Build, pack, and publish to MyGet #387
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ################################################# | |
| ################### IMPORTANT ################### | |
| # DON'T RENAME THIS FILE UNLESS WE START | |
| # RELEASING THE VERSION 2.* | |
| ################### IMPORTANT ################### | |
| ################################################# | |
| name: Build, pack, and publish to MyGet | |
| on: | |
| workflow_dispatch: | |
| push: | |
| tags: | |
| - 'core-*' | |
| - 'coreunstable-*' | |
| schedule: | |
| - cron: '0 0 * * *' # once in a day at 00:00 | |
| permissions: | |
| contents: read | |
| jobs: | |
| automation: | |
| uses: ./.github/workflows/automation.yml | |
| secrets: | |
| OTELBOT_DOTNET_PRIVATE_KEY: ${{ secrets.OTELBOT_DOTNET_PRIVATE_KEY }} | |
| build-pack-publish: | |
| runs-on: windows-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| COSIGN_YES: "yes" | |
| outputs: | |
| artifact-url: ${{ steps.upload-artifacts.outputs.artifact-url }} | |
| artifact-id: ${{ steps.upload-artifacts.outputs.artifact-id }} | |
| steps: | |
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| 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: Setup dotnet | |
| uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 | |
| - name: Install Cosign | |
| uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0 | |
| - name: dotnet restore | |
| run: dotnet restore ./build/OpenTelemetry.proj -p:RunningDotNetPack=true | |
| - name: dotnet build | |
| shell: pwsh | |
| run: dotnet build ./build/OpenTelemetry.proj --configuration Release --no-restore -p:Deterministic=true -p:"BuildNumber=${env:GITHUB_RUN_NUMBER}" -p:RunningDotNetPack=true | |
| - name: Sign DLLs with Cosign Keyless | |
| shell: pwsh | |
| run: | | |
| $projectFiles = Get-ChildItem -Path src/*/*.csproj -File | |
| foreach ($projectFile in $projectFiles) { | |
| $projectName = [System.IO.Path]::GetFileNameWithoutExtension($projectFile) | |
| Get-ChildItem -Path artifacts/bin/$projectName/release_*/$projectName.dll -File | ForEach-Object { | |
| $fileFullPath = $_.FullName | |
| Write-Output "Signing $fileFullPath" | |
| cosign.exe sign-blob $fileFullPath --yes --output-signature $fileFullPath-keyless.sig --output-certificate $fileFullPath-keyless.pem | |
| } | |
| } | |
| - name: dotnet pack | |
| shell: pwsh | |
| env: | |
| PACK_TAG: ${{ github.ref_type == 'tag' && github.ref_name || '' }} | |
| run: dotnet pack ./build/OpenTelemetry.proj --configuration Release --no-restore --no-build -p:"PackTag=${env:PACK_TAG}" | |
| - 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.31' | |
| 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: Verify package DLL Cosign Keyless signatures | |
| shell: pwsh | |
| run: | | |
| $nupkgFiles = Get-ChildItem -Path artifacts/package/release/*.nupkg -File | |
| # Copy the NuGet packages to a temporary directory and extract them | |
| $tempDir = New-Item -ItemType Directory -Path (Join-Path -Path ${env:RUNNER_TEMP} -ChildPath ([System.Guid]::NewGuid().ToString())) | |
| foreach ($nupkgFile in $nupkgFiles) { | |
| $nupkgFilePath = $nupkgFile.FullName | |
| $packageName = [System.IO.Path]::GetFileNameWithoutExtension($nupkgFilePath) | |
| Write-Output "Extracting $nupkgFilePath" | |
| Expand-Archive -Path $nupkgFilePath -DestinationPath (Join-Path $tempDir.FullName $packageName) | |
| } | |
| # Iterate over all DLL files in the extracted packages and verify their signatures | |
| $dllFiles = Get-ChildItem -Path $tempDir.FullName -Recurse -Filter *.dll -File | |
| foreach ($dllFile in $dllFiles) { | |
| $dllFilePath = $dllFile.FullName | |
| Write-Output "Verifying $dllFilePath" | |
| cosign.exe verify-blob ` | |
| --signature $dllFilePath-keyless.sig ` | |
| --certificate $dllFilePath-keyless.pem ` | |
| --certificate-identity "${env:GITHUB_SERVER_URL}/${env:GITHUB_REPOSITORY}/.github/workflows/publish-packages-1.0.yml@${env:GITHUB_REF}" ` | |
| --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ` | |
| $dllFilePath | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Output "::error::Signature verification failed for $dllFilePath." | |
| exit 1 | |
| } | |
| Write-Output "Signature verification succeeded for $dllFilePath" | |
| } | |
| - name: Publish Artifacts | |
| id: upload-artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: ${{ github.ref_name }}-packages | |
| path: ./artifacts/package/release | |
| if-no-files-found: error | |
| - name: Publish 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} | |
| 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_APP_ID }} | |
| private-key: ${{ secrets.OTELBOT_DOTNET_PRIVATE_KEY }} | |
| - name: Check out code | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| 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 draft | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ steps.otelbot-token.outputs.token }} | |
| run: | | |
| Import-Module .\build\scripts\post-release.psm1 | |
| CreateDraftRelease ` | |
| -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} |