Skip to content

Build, pack, and publish #808

Build, pack, and publish

Build, pack, and publish #808

name: Build, pack, and publish
on:
workflow_dispatch:
push:
tags:
- 'Exporter.*-*'
- 'Extensions.*-*'
- 'Extensions-*'
- 'Instrumentation.*-*'
- 'OpAmp.*-*'
- 'PersistentStorage-*'
- 'Resources.*-*'
- 'Sampler.*-*'
- 'SemanticConventions-*'
schedule:
- cron: '0 0 * * *' # once in a day at 00:00
permissions:
contents: read
jobs:
automation:
uses: ./.github/workflows/automation.yml
secrets:
OTELBOT_DOTNET_CONTRIB_PRIVATE_KEY: ${{ secrets.OTELBOT_DOTNET_CONTRIB_PRIVATE_KEY }}
build-pack-publish:
permissions:
attestations: write
contents: read
id-token: write
runs-on: windows-latest
outputs:
artifact-url: ${{ steps.upload-artifacts.outputs.artifact-url }}
artifact-id: ${{ steps.upload-artifacts.outputs.artifact-id }}
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
# Note: By default GitHub only fetches 1 commit. MinVer needs to find
# the version tag which is typically NOT on the first commit so we
# retrieve them all.
fetch-depth: 0
- name: Resolve project
id: resolve-project
shell: pwsh
env:
TAG: ${{ github.ref_type == 'tag' && github.ref_name || '' }}
run: |
Import-Module .\build\scripts\build.psm1
# Note: The ResolveProjectForTag call here figures out the .proj file to
# use for the build. It will be either opentelemetry-dotnet-contrib.proj
# (for manual/scheduled builds), a .proj file in .\build\Projects\ (if
# one is defined with MinVerTagPrefix matching the tag), or
# Component.proj for simple projects (where a single csproj has
# MinVerTagPrefix matching the tag).
$title = '' # Used for friendly names in action UI
$project = '' # Actual project passed to dotnet
$component = '' # Used to tell Component.proj what to build
ResolveProjectForTag `
-tag ${env:TAG} `
-title ([ref]$title) `
-project ([ref]$project) `
-component ([ref]$component)
echo "title=$title" >> ${env:GITHUB_OUTPUT}
echo "PROJECT_PATH=$project" >> ${env:GITHUB_ENV}
# Note: BUILD_COMPONENT envvar tells Component.proj what to build. Only
# used if $project ends up Component.proj.
echo "BUILD_COMPONENT=$component" >> ${env:GITHUB_ENV}
- name: Setup dotnet
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
- name: dotnet restore ${{ steps.resolve-project.outputs.title }}
run: dotnet restore ${env:PROJECT_PATH}
- name: dotnet build ${{ steps.resolve-project.outputs.title }}
run: dotnet build ${env:PROJECT_PATH} --configuration Release --no-restore -p:"BuildNumber=${env:GITHUB_RUN_NUMBER}"
- name: dotnet test ${{ steps.resolve-project.outputs.title }}
run: dotnet test ${env:PROJECT_PATH} --configuration Release --no-restore --no-build
- name: Create GitHub attestations for DLLs
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
with:
subject-path: |
./artifacts/bin/*/release_*/OpenTelemetry*.dll
!./artifacts/bin/*/**/OpenTelemetry.dll
!./artifacts/bin/*/**/OpenTelemetry.Api.dll
!./artifacts/bin/*/**/OpenTelemetry.Api.ProviderBuilderExtensions.dll
!./artifacts/bin/*/**/*Benchmark*.dll
!./artifacts/bin/*/**/*Example*.dll
!./artifacts/bin/*/**/*Stress*.dll
!./artifacts/bin/*/**/*Test*.dll
- name: dotnet pack ${{ steps.resolve-project.outputs.title }}
shell: pwsh
run: dotnet pack ${env:PROJECT_PATH} --configuration Release --no-restore --no-build -p:"PackTag=${env:TAG}"
- name: Publish Artifacts
id: upload-artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ${{ github.ref_name }}-packages
path: ./artifacts/package/release
if-no-files-found: error
- name: Install NuGet package validation tools
env:
# renovate: datasource=nuget depName=dotnet-validate
DOTNET_VALIDATE_VERSION: '0.0.1-preview.537'
# renovate: datasource=nuget depName=Meziantou.Framework.NuGetPackageValidation.Tool
MEZIANTOU_VALIDATE_NUGET_PACKAGE_VERSION: '1.0.37'
run: |
dotnet tool install --global dotnet-validate --version ${env:DOTNET_VALIDATE_VERSION} --allow-roll-forward
dotnet tool install --global Meziantou.Framework.NuGetPackageValidation.Tool --version ${env:MEZIANTOU_VALIDATE_NUGET_PACKAGE_VERSION} --allow-roll-forward
- name: Validate NuGet packages
shell: pwsh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
$packages = Get-ChildItem -Path artifacts/package/release/*.nupkg -File | ForEach-Object { $_.FullName }
$invalidPackages = 0
foreach ($package in $packages) {
$isValid = $true
dotnet validate package local $package
if ($LASTEXITCODE -ne 0) {
Write-Output "::error::validate package local failed for $package."
$isValid = $false
}
meziantou.validate-nuget-package $package --github-token ${env:GH_TOKEN}
if ($LASTEXITCODE -ne 0) {
Write-Output "::error::meziantou.validate-nuget-package failed for $package."
$isValid = $false
}
if (-Not $isValid) {
$invalidPackages++
}
}
if ($invalidPackages -gt 0) {
Write-Output "::error::$invalidPackages NuGet package(s) failed validation."
exit 1
}
- name: Publish to MyGet
working-directory: ./artifacts/package/release
env:
MYGET_TOKEN_EXISTS: ${{ secrets.MYGET_TOKEN != '' }}
API_KEY: ${{ secrets.MYGET_TOKEN }}
SOURCE: https://www.myget.org/F/opentelemetry/api/v2/package
if: env.MYGET_TOKEN_EXISTS == 'true' # Skip MyGet publish if run on a fork without the secret
shell: pwsh
run: dotnet nuget push *.nupkg --api-key ${env:API_KEY} --skip-duplicate --source ${env:SOURCE}
- name: NuGet log in
uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544 # v1.1.0
env:
NUGET_USER_EXISTS: ${{ secrets.NUGET_USER != '' }}
id: nuget-login
if: github.ref_type == 'tag' && env.NUGET_USER_EXISTS == 'true' # Skip NuGet publish for scheduled nightly builds or if run on a fork without the secret
with:
user: ${{ secrets.NUGET_USER }}
- name: Publish to NuGet
working-directory: ./artifacts/package/release
env:
NUGET_TOKEN_EXISTS: ${{ steps.nuget-login.outputs.NUGET_API_KEY != '' }}
API_KEY: ${{ steps.nuget-login.outputs.NUGET_API_KEY }}
SOURCE: https://api.nuget.org/v3/index.json
if: github.ref_type == 'tag' && env.NUGET_TOKEN_EXISTS == 'true' # Skip NuGet publish for scheduled nightly builds or if run on a fork without the secret
shell: pwsh
run: dotnet nuget push *.nupkg --api-key ${env:API_KEY} --skip-duplicate --source ${env:SOURCE}
post-build:
runs-on: ubuntu-24.04
needs:
- automation
- build-pack-publish
if: needs.automation.outputs.enabled && github.event_name == 'push'
steps:
- uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
id: otelbot-token
with:
app-id: ${{ vars.OTELBOT_DOTNET_CONTRIB_APP_ID }}
private-key: ${{ secrets.OTELBOT_DOTNET_CONTRIB_PRIVATE_KEY }}
- name: Check out code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
token: ${{ steps.otelbot-token.outputs.token }}
- name: Download Artifacts
env:
ARTIFACT_ID: ${{ needs.build-pack-publish.outputs.artifact-id }}
ARTIFACT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token ${ARTIFACT_TOKEN}" \
-L \
-o "${GITHUB_WORKSPACE}/artifacts/${GITHUB_REF_NAME}-packages.zip" \
--create-dirs \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/actions/artifacts/${ARTIFACT_ID}/zip"
- name: Create GitHub Release
if: github.ref_type == 'tag'
shell: pwsh
env:
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
run: |
Import-Module .\build\scripts\post-release.psm1
CreateRelease `
-gitRepository ${env:GITHUB_REPOSITORY} `
-tag ${env:GITHUB_REF_NAME} `
-releaseFiles "${env:GITHUB_WORKSPACE}/artifacts/${env:GITHUB_REF_NAME}-packages.zip"
- name: Post notice when packages are ready
shell: pwsh
env:
GH_TOKEN: ${{ steps.otelbot-token.outputs.token }}
EXPECTED_PR_AUTHOR_USER_NAME: ${{ needs.automation.outputs.application-name }}
PACKAGES_URL: ${{ needs.build-pack-publish.outputs.artifact-url }}
run: |
Import-Module .\build\scripts\post-release.psm1
TryPostPackagesReadyNoticeOnPrepareReleasePullRequest `
-gitRepository ${env:GITHUB_REPOSITORY} `
-tag ${env:GITHUB_REF_NAME} `
-tagSha ${env:GITHUB_SHA} `
-packagesUrl ${env:PACKAGES_URL} `
-expectedPrAuthorUserName ${env:EXPECTED_PR_AUTHOR_USER_NAME}