Skip to content

Build, pack, and publish to MyGet #387

Build, pack, and publish to MyGet

Build, pack, and publish to MyGet #387

#################################################
################### 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}