Skip to content

chore: release main (#3615) #5019

chore: release main (#3615)

chore: release main (#3615) #5019

name: Profiler Build / Unit Test / Deploy
on:
pull_request:
branches:
- main
- "feature/**"
# needs to run on every push to main to keep CodeCov in sync
push:
branches:
- main
# this workflow can be invoked manually
workflow_dispatch:
inputs:
deploy:
description: 'Deploy NuGet Package'
required: true
default: false
type: boolean
permissions:
contents: read
id-token: write
# only allow one instance of this workflow to be running per PR or branch, cancels any that are already running
concurrency:
group: build-profiler-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
scripts_path: ${{ github.workspace }}\build\scripts
tools_path: ${{ github.workspace }}\build\Tools
DOTNET_NOLOGO: true
jobs:
check-modified-files:
name: Check for source file changes
uses: ./.github/workflows/check_modified_files.yml
permissions:
contents: read
pull-requests: read
build-windows-profiler:
name: Build Windows Profiler & Run Unit Tests / Code Coverage
runs-on: windows-2025-vs2026
needs: check-modified-files
# only run this job if source files were modified, or if triggered by a manual execution
if: ${{ needs.check-modified-files.outputs.source-files-changed == 'true' || github.event_name == 'workflow_dispatch' }}
env:
tests_base_path: ${{ github.workspace }}\src\Agent\NewRelic
profiler_solution_path: ${{ github.workspace }}\src\Agent\NewRelic\Profiler\NewRelic.Profiler.sln
output_path: ${{ github.workspace }}\src\Agent\_profilerBuild
test_results_path: ${{ github.workspace }}\src\Agent\NewRelic\TestResults
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
filter: blob:none
- name: Cache NuGet packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }}
restore-keys: ${{ runner.os }}-nuget-
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0
- name: Clean out _profilerBuild directory
run: |
Remove-Item -Path "${{ github.workspace }}\src\Agent\_profilerBuild\*.*" -Force -Recurse -ErrorAction SilentlyContinue
shell: powershell
- name: Build x64
run: |
Write-Host "List NuGet Sources"
dotnet nuget list source # For unknown reasons, this step is necessary to avoid subsequent problems with NuGet package restore
Write-Host "MSBuild.exe -restore -m -p:Platform=x64 -p:Configuration=Release ${{ env.profiler_solution_path }}"
MSBuild.exe -restore -m -p:Platform=x64 -p:Configuration=Release -p:NativeToolset=v145 ${{ env.profiler_solution_path }}
shell: powershell
- name: Build x86
run: |
Write-Host "MSBuild.exe -restore -m -p:Platform=Win32 -p:Configuration=Release ${{ env.profiler_solution_path }}"
MSBuild.exe -restore -m -p:Platform=Win32 -p:Configuration=Release -p:NativeToolset=v145 ${{ env.profiler_solution_path }}
shell: powershell
- name: Setup VSTest and add to PATH
shell: powershell
run: |
$vswhere = "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
if (-not (Test-Path $vswhere)) {
Write-Error "vswhere.exe not found at $vswhere"
exit 1
}
$vsInstallPath = & $vswhere -latest -property installationPath
if (-not $vsInstallPath) {
Write-Error "vswhere did not return a Visual Studio installation path"
exit 1
}
$vstestDir = Join-Path $vsInstallPath "Common7\IDE\CommonExtensions\Microsoft\TestWindow"
if (-not (Test-Path (Join-Path $vstestDir "vstest.console.exe"))) {
Write-Error "vstest.console.exe not found at $vstestDir"
exit 1
}
Write-Host "Adding $vstestDir to PATH"
Add-Content -Path $env:GITHUB_PATH -Value $vstestDir
- name: Setup OpenCppCoverage and add to PATH
id: setup_opencppcoverage
run: |
choco install OpenCppCoverage -y
echo "C:\Program Files\OpenCppCoverage" >> $env:GITHUB_PATH
- name: Generate Report
id: generate_test_report
shell: cmd
run: |
cd ${{ env.tests_base_path }}
OpenCppCoverage.exe --sources Profiler --excluded_sources rapidxml --excluded_sources Profiler\SystemCalls.h --excluded_sources test --modules NewRelic\Profiler --export_type cobertura:${{ env.test_results_path }}\profilerx86.xml -- "vstest.console.exe" /Platform:x86 "Profiler\CommonTest\bin\x86\Release\CommonTest.dll" "Profiler\ConfigurationTest\bin\x86\Release\ConfigurationTest.dll" "Profiler\LoggingTest\bin\x86\Release\LoggingTest.dll" "Profiler\MethodRewriterTest\bin\x86\Release\MethodRewriterTest.dll" "Profiler\SignatureParserTest\bin\x86\Release\SignatureParserTest.dll" "Profiler\Sicily\SicilyTest\bin\x86\Release\SicilyTest.dll"
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
mv ${{ env.tests_base_path}}\LastCoverageResults.log ${{ env.tests_base_path}}\LastCoverageResults_x86.log
OpenCppCoverage.exe --sources Profiler --cover_children --excluded_sources rapidxml --excluded_sources Profiler\SystemCalls.h --excluded_sources test --modules NewRelic\Profiler --export_type cobertura:${{ env.test_results_path }}\profilerx64.xml -- "vstest.console.exe" /Platform:x64 "Profiler\CommonTest\bin\x64\Release\CommonTest.dll" "Profiler\ConfigurationTest\bin\x64\Release\ConfigurationTest.dll" "Profiler\LoggingTest\bin\x64\Release\LoggingTest.dll" "Profiler\MethodRewriterTest\bin\x64\Release\MethodRewriterTest.dll" "Profiler\SignatureParserTest\bin\x64\Release\SignatureParserTest.dll" "Profiler\Sicily\SicilyTest\bin\x64\Release\SicilyTest.dll"
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
mv ${{ env.tests_base_path}}\LastCoverageResults.log ${{ env.tests_base_path}}\LastCoverageResults_x64.log
- name: Upload coverage reports to Codecov.io
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
flags: Profiler
files: ${{ env.test_results_path }}/profilerx86.xml,${{ env.test_results_path }}/profilerx64.xml
token: ${{ secrets.CODECOV_TOKEN }}
- name: Archive Build Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: profiler-windows
path: ${{ github.workspace }}\src\Agent\_profilerBuild\**\*
if-no-files-found: error
- name: Archive Code Coverage Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: profiler-code-coverage
path: |
${{ env.test_results_path }}\*.xml
${{ env.tests_base_path }}\*.log
if-no-files-found: error
build-linux-x64-profiler:
name: Build Linux x64 Profiler
runs-on: ubuntu-22.04
needs: check-modified-files
# only run this job if source files were modified, or if triggered by a manual execution
if: ${{ needs.check-modified-files.outputs.source-files-changed == 'true' || github.event_name == 'workflow_dispatch' }}
permissions:
contents: read
env:
profiler_path: ${{ github.workspace }}/src/Agent/NewRelic/Profiler
CORECLR_NEW_RELIC_HOME: ${{ github.workspace }}/src/Agent/NewRelic/newrelichome_x64_coreclr_linux # not used but required by Profiler/docker-compose.yml
steps:
# intentionally disabled for this job, when enabled it causes a failure in the Build Linux Profiler step
# - name: Harden Runner
# uses: step-security/harden-runner@03bee3930647ebbf994244c21ddbc0d4933aab4f # v2.3.0
# with:
# egress-policy: audit
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clean out _profilerBuild directory
run: |
rm -f ${{ github.workspace }}/src/Agent/_profilerBuild/*.* || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/linux-x64-release || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/linux-arm64-release || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/x64-Release || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/x86-Release || true
shell: bash
- name: Build Linux Profiler
run: |
cd ${{ env.profiler_path }}
docker compose build build
docker compose run build
shell: bash
- name: Move Profiler to staging folder
run: |
mkdir --parents ${{ github.workspace }}/src/Agent/_profilerBuild/linux-x64-release/
mv -f ${{ env.profiler_path }}/libNewRelicProfiler.so ${{ github.workspace }}/src/Agent/_profilerBuild/linux-x64-release/libNewRelicProfiler.so
shell: bash
- name: Archive Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: profiler-amd64
path: ${{ github.workspace }}/src/Agent/_profilerBuild/
if-no-files-found: error
build-linux-arm64-profiler:
name: Build Linux ARM64 Profiler
runs-on: ubuntu-24.04-arm
needs: check-modified-files
# only run this job if source files were modified, or if triggered by a manual execution
if: ${{ needs.check-modified-files.outputs.source-files-changed == 'true' || github.event_name == 'workflow_dispatch' }}
permissions:
contents: read # for actions/checkout to fetch code
env:
profiler_path: ${{ github.workspace }}/src/Agent/NewRelic/Profiler
CORECLR_NEW_RELIC_HOME: ${{ github.workspace }}/src/Agent/NewRelic/newrelichome_arm64_coreclr_linux # not used but required by Profiler/docker-compose.yml
steps:
- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clean out _profilerBuild directory
run: |
rm -f ${{ github.workspace }}/src/Agent/_profilerBuild/*.* || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/linux-x64-release || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/linux-arm64-release || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/x64-Release || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/x86-Release || true
shell: bash
- name: Build Linux ARM64 Profiler
run: |
cd ${{ env.profiler_path }}
docker compose build build_arm64
docker compose run build_arm64
shell: bash
- name: Move Profiler to staging folder
run: |
mkdir --parents ${{ github.workspace }}/src/Agent/_profilerBuild/linux-arm64-release/
mv -f ${{ env.profiler_path }}/libNewRelicProfiler.so ${{ github.workspace }}/src/Agent/_profilerBuild/linux-arm64-release/libNewRelicProfiler.so
shell: bash
- name: Archive Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: profiler-arm64
path: ${{ github.workspace }}/src/Agent/_profilerBuild/
if-no-files-found: error
build-linux-musl-x64-profiler:
name: Build Linux musl x64 Profiler
runs-on: ubuntu-22.04
needs: check-modified-files
# only run this job if source files were modified, or if triggered by a manual execution
if: ${{ needs.check-modified-files.outputs.source-files-changed == 'true' || github.event_name == 'workflow_dispatch' }}
permissions:
contents: read
env:
profiler_path: ${{ github.workspace }}/src/Agent/NewRelic/Profiler
CORECLR_NEW_RELIC_HOME: ${{ github.workspace }}/src/Agent/NewRelic/newrelichome_x64_coreclr_linux # not used but required by Profiler/docker-compose.yml
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clean out _profilerBuild directory
run: |
rm -f ${{ github.workspace }}/src/Agent/_profilerBuild/*.* || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/linux-musl-x64-release || true
shell: bash
- name: Build Linux musl x64 Profiler
run: |
cd ${{ env.profiler_path }}
docker compose build build_musl_x64
docker compose run build_musl_x64
shell: bash
- name: Move Profiler to staging folder
run: |
mkdir --parents ${{ github.workspace }}/src/Agent/_profilerBuild/linux-musl-x64-release/
mv -f ${{ env.profiler_path }}/libNewRelicProfiler.so ${{ github.workspace }}/src/Agent/_profilerBuild/linux-musl-x64-release/libNewRelicProfiler.so
shell: bash
- name: Archive Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: profiler-musl-amd64
path: ${{ github.workspace }}/src/Agent/_profilerBuild/
if-no-files-found: error
build-linux-musl-arm64-profiler:
name: Build Linux musl ARM64 Profiler
runs-on: ubuntu-24.04-arm
needs: check-modified-files
# only run this job if source files were modified, or if triggered by a manual execution
if: ${{ needs.check-modified-files.outputs.source-files-changed == 'true' || github.event_name == 'workflow_dispatch' }}
permissions:
contents: read
env:
profiler_path: ${{ github.workspace }}/src/Agent/NewRelic/Profiler
CORECLR_NEW_RELIC_HOME: ${{ github.workspace }}/src/Agent/NewRelic/newrelichome_arm64_coreclr_linux # not used but required by Profiler/docker-compose.yml
steps:
- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Clean out _profilerBuild directory
run: |
rm -f ${{ github.workspace }}/src/Agent/_profilerBuild/*.* || true
rm -rf ${{ github.workspace }}/src/Agent/_profilerBuild/linux-musl-arm64-release || true
shell: bash
- name: Build Linux musl ARM64 Profiler
run: |
cd ${{ env.profiler_path }}
docker compose build build_musl_arm64
docker compose run build_musl_arm64
shell: bash
- name: Move Profiler to staging folder
run: |
mkdir --parents ${{ github.workspace }}/src/Agent/_profilerBuild/linux-musl-arm64-release/
mv -f ${{ env.profiler_path }}/libNewRelicProfiler.so ${{ github.workspace }}/src/Agent/_profilerBuild/linux-musl-arm64-release/libNewRelicProfiler.so
shell: bash
- name: Archive Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: profiler-musl-arm64
path: ${{ github.workspace }}/src/Agent/_profilerBuild/
if-no-files-found: error
package-and-deploy:
needs:
[
build-windows-profiler,
build-linux-x64-profiler,
build-linux-arm64-profiler,
]
if: ${{ inputs.deploy }}
name: Package and Deploy Profiler NuGet
runs-on: windows-2025-vs2026
permissions:
id-token: write
env:
nuget_source: https://www.nuget.org
outputs:
package_version: ${{ steps.agentVersion.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
filter: blob:none
- name: Download Windows Profiler Artifacts to working Directory
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: profiler-windows
path: ${{ github.workspace }}/_workingDir
- name: Download Linux amd64 Profiler Artifacts to working Directory
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: profiler-amd64
path: ${{ github.workspace }}/_workingDir
- name: Download Linux arm64 Profiler Artifacts to working Directory
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: profiler-arm64
path: ${{ github.workspace }}/_workingDir
- name: Determine Package Version from Git history
id: agentVersion
run: |
# get latest agent version tag
$agentVersion = git describe --match v* --abbrev=0 HEAD --tags
# get commit count since that tag
$getRevCmd = "git rev-list $agentVersion..HEAD --count HEAD"
$agentRev = Invoke-Expression $getRevCmd
# if count is > 0, add the rev to the version
if ($agentRev -gt 0) { $agentVersion = $agentVersion + "." + $agentRev}
# remove the leading "v" from the version number
$agentVersion = $agentVersion.substring(1)
echo "version=$agentVersion" >> $env:GITHUB_OUTPUT
shell: powershell
- name: Stage files in working directory
run: |
New-Item "${{ github.workspace }}/_workingDir/images" -Type "directory"
Copy-Item -Path "${{ github.workspace }}/build/Packaging/NugetProfiler/images/*.*" -Destination "${{ github.workspace }}/_workingDir/images"
New-Item "${{ github.workspace }}/_workingDir/build" -Type "directory"
Copy-Item -Path "${{ github.workspace }}/build/Packaging/NugetProfiler/build/*.*" -Destination "${{ github.workspace }}/_workingDir/build"
Copy-Item -Path "${{ github.workspace }}/build/Packaging/NugetProfiler/readme.md" -Destination "${{ github.workspace }}/_workingDir"
- name: Pack Profiler NuGet Package
run: |
New-Item "${{ github.workspace }}/_workingDir/NugetProfiler" -Type "directory"
nuget pack ${{ github.workspace }}/build/Packaging/NugetProfiler/NewRelic.Profiler.nuspec -BasePath ${{ github.workspace }}/_workingDir -OutputDirectory ${{ github.workspace }}/_workingDir/NugetProfiler -Version ${{ steps.agentVersion.outputs.version }} -Verbosity detailed
shell: powershell
# Get a short-lived NuGet API key
- name: NuGet login (OIDC → temp API key)
uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1.2.0
id: login
with:
user: ${{ secrets.NUGET_TRUSTED_PUBLISH_POLICY_USER }}
- name: Deploy Profiler Package to Nuget
run: |
$packageName = Get-ChildItem ${{ github.workspace }}/_workingDir/NugetProfiler/NewRelic.Agent.Internal.Profiler.*.nupkg -Name
$packagePath = Convert-Path ${{ github.workspace }}//_workingDir/NugetProfiler/$packageName
$version = $packageName.TrimStart('NewRelic.Agent.Internal.Profiler').TrimStart('.').TrimEnd('.nupkg')
dotnet nuget push $packagePath --api-key "${{ steps.login.outputs.NUGET_API_KEY }}" --source ${{ env.nuget_source }}
shell: powershell
update-nuget-reference:
name: Update Profiler Nuget Reference
runs-on: ubuntu-22.04
needs: package-and-deploy
if: ${{ inputs.deploy }}
permissions:
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- name: Install xmlstarlet
run: |
sudo apt-get install -y xmlstarlet
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Update Profiler Package Reference to Latest Version
run: |
cat ${{ github.workspace }}/src/Agent/NewRelic/Home/Home.csproj | \
xmlstarlet edit --pf --omit-decl \
--update "//PackageReference[@Include='NewRelic.Agent.Internal.Profiler']/@Version" \
--value "${{ needs.package-and-deploy.outputs.package_version }}" > ${{ github.workspace }}/src/Agent/NewRelic/Home/_temp &&
cat ${{ github.workspace }}/src/Agent/NewRelic/Home/_temp > ${{ github.workspace }}/src/Agent/NewRelic/Home/Home.csproj &&
rm -f ${{ github.workspace }}/src/Agent/NewRelic/Home/_temp
- name: Create Pull Request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.DOTNET_AGENT_GH_TOKEN}}
commit-message: "chore: Update Profiler NuGet Package Reference to v${{ needs.package-and-deploy.outputs.package_version }} (built from ${{ github.sha }}).\n\nBuilt from commit: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}"
title: "chore: Update Profiler NuGet Package Reference to v${{ needs.package-and-deploy.outputs.package_version }} (built from ${{ github.sha }})"
branch: profiler-nuget-updates/${{ github.ref_name }}
labels: |
profiler nuget
automated pr
delete-branch: true
add-paths: |
src/Agent/NewRelic/Home/Home.csproj