Skip to content

Verifiable .NET build #2134

Verifiable .NET build

Verifiable .NET build #2134

Workflow file for this run

name: Verifiable .NET build
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
paths-ignore:
- "**.md"
release:
types:
- published
schedule:
# A daily build to check all is still functioning.
- cron: "0 0 * * *"
env:
# This environment variable is checked in tests.
# For TPM either a Windows simulator or a platform TPM is used.
# Tests check that platform TPM tests must be run on Windows or Linux,
# MacOS tests are skipped.
USE_PLATFORM_TPM: true
DOTNET_ENVIRONMENT: CI
BUILD_CONFIGURATION: Release
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_NOLOGO: true
NUGET_XMLDOC_MODE: skip
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
NUGET_FEED: https://api.nuget.org/v3/index.json
GITHUB_USER: ${{ github.repository_owner }}
GITHUB_FEED: https://nuget.pkg.github.com/lumoin/
# These are the Nuget packages that will be packed and uploaded.
VERIFIABLE: Verifiable
VERIFIABLE_BOUNCYCASTLE: Verifiable.BouncyCastle
VERIFIABLE_CORE: Verifiable.Core
VERIFIABLE_DECENTRALIZEDWEBNODE: Verifiable.DecentralizedWebNode
VERIFIABLE_JWT: Verifiable.Jwt
VERIFIABLE_NSEC: Verifiable.NSec
VERIFIABLE_MICROSOFT: Verifiable.Microsoft
VERIFIABLE_SIDETREE: Verifiable.Sidetree
VERIFIABLE_TPM: Verifiable.Tpm
# These are the test projects that will be reported.
VERIFIABLE_TESTS: Verifiable.Tests
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
steps:
- name: Harden Runner
if: ${{ matrix.os == 'ubuntu-latest' }}
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
dotnetbuilds.azureedge.net:443
aka.ms:443
api.github.com:443
api.nuget.org:443
pkgs.dev.azure.com:443
dashboard.stryker-mutator.io:443
dotnetcli.azureedge.net:443
github.com:443
nuget.pkg.github.com:443
api.clearlydefined.io:443
cacerts.digicert.com:80
ts-crl.ws.symantec.com:80
crl3.digicert.com:80
crl4.digicert.com:80
s.symcb.com:80
ocsp.digicert.com:80
# Windows builds may have insufficient resource limits, so they're increased.
- name: Configure Windows Pagefile
if: ${{ matrix.os == 'windows-latest' }}
uses: al-cheb/configure-pagefile-action@a3b6ebd6b634da88790d9c58d4b37a7f4a7b8708
with:
minimum-size: 8GB
maximum-size: 32GB
disk-root: "D:"
# This needs to run always. Only when there is a problem that could
# be because of system changes.
# - name: Windows system information
# if: ${{ matrix.os == 'windows-latest' }}
# run: Get-ComputerInfo
# - name: Get Windows TPM information
# if: ${{ matrix.os == 'windows-latest' }}
# run: Get-Tpm
# This follows instructions at https://wiki.ubuntu.com/TPM/Testing.
# - name: Install Linux TPM 2.0 module (tpm2-abrmd)
# if: ${{ matrix.os == 'ubuntu-latest' }}
# run: |
# sudo apt-get update
# sudo apt-get install tpm2-abrmd
# sudo apt-get install libtss2-tcti-tabrmd-dev
#- name: Check Linux TPM 2.0 module functionality
# if: ${{ matrix.os == 'ubuntu-latest' }}
# run: |
# sudo service tpm2-abrmd start
# sudo tpm2-abrmd --tcti=mssim --allow-root --logger=stdout
- name: Checkout code
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0
fetch-tags: true
- name: Cache Nuget packages '${{ matrix.os }}'
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a
with:
path: ${{ env.NUGET_PACKAGES }}
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{runner.os}}-nuget-
- name: Setup .NET SDK
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25
with:
global-json-file: global.json
- name: Install dependencies
run: dotnet restore --locked-mode
- name: Restore local .NET tools
run: dotnet tool restore
- name: Add Problem Matcher for dotnet-format
uses: xt0rted/dotnet-format-problem-matcher@b90c4f18e3daa4f8fd266e41eba4f351b2e00b75
# - name: Run dotnet format
# run: dotnet format --check
# The version numbers are determined and set here so it can be set appropriately to code and NuGet packages.
# See explanation at https://dusted.codes/github-actions-for-dotnet-core-nuget-packages.
- name: Set NuGet packages and suffix version
run: |
# Bash script to determine the version and version suffix for CI/CD
# Use git to find the latest tag; if none are found, default to "0.0.1".
latestTag=$(git describe --tags --abbrev=0 2>/dev/null || echo 0.0.1)
# Case 1: A release is being created.
# Extract the version from the tag and add a suffix with the short SHA.
if [[ $GITHUB_EVENT_NAME == 'release' ]]; then
# Extract the version number from the release tag and remove any 'v' prefix.
arrTag=(${GITHUB_REF//\// })
VERSION="${arrTag[2]}"
VERSION="${VERSION//v}"
# Set PACKAGE_VERSION and VERSION, and add a VERSION_SUFFIX for clarity in identifying the release and commit.
echo "PACKAGE_VERSION=${VERSION}+${GITHUB_SHA::7}" >> "$GITHUB_ENV"
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
echo "TAG_VERSION=${VERSION}" >> "$GITHUB_ENV"
# Case 2: The 'develop' branch.
# Use the latestTag as the base version and add a suffix with "develop", the run_id, and the short SHA.
elif [[ $GITHUB_REF == 'refs/heads/develop' ]]; then
# Set PACKAGE_VERSION and PACKAGE, and add a VERSION_SUFFIX for clarity in identifying the development build, run, and commit.
echo "PACKAGE_VERSION=${latestTag//v}-develop.${GITHUB_RUN_ID}+${GITHUB_SHA::7}" >> "$GITHUB_ENV"
echo "VERSION=${latestTag//v}-develop.${GITHUB_RUN_ID}+${GITHUB_SHA::7}" >> "$GITHUB_ENV"
echo "TAG_VERSION=${latestTag//v}" >> "$GITHUB_ENV"
# Case 3: Any other build (e.g., feature branches).
# Use the latestTag as the base version and add a suffix with "build", the run_id, and the short SHA.
else
# Set PACKAGE_VERSION and VERSION, and add a VERSION_SUFFIX for clarity in identifying the build, run, and commit.
echo "PACKAGE_VERSION=${latestTag//v}-build.${GITHUB_RUN_ID}+${GITHUB_SHA::7}" >> "$GITHUB_ENV"
echo "VERSION=${latestTag//v}-build.${GITHUB_RUN_ID}+${GITHUB_SHA::7}" >> "$GITHUB_ENV"
echo "TAG_VERSION=${latestTag//v}" >> "$GITHUB_ENV"
fi
shell: bash
- name: Build
# At the moment Verifiable.Tests cannot be built with -isolate alone due to Coverlet.
run: dotnet build --binaryLogger --tl --graphBuild -isolate:MessageUponIsolationViolation --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore --property:ContinuousIntegrationBuild=true --property:Version=${{ env.VERSION }} --property:InformationalVersion=${{ env.PACKAGE_VERSION }} --property:AssemblyVersion=${{ env.TAG_VERSION }} --property:FileVersion=${{ env.TAG_VERSION }}
timeout-minutes: 5
# - name: Set PR markdown title name
# run: |
# echo "title=Test Run (${{ github.run_number }})" >> $GITHUB_ENV
# echo "file_name=TestReport.${{ github.run_number }}.md" >> $GITHUB_ENV
# shell: bash
# MacOS is skipped at the moment due to issues with some .NET crypto libraries.
# Until tests are a fixed a bit. The coverage from the executable does not have a file suffix in Linux.
- name: Test
if: runner.os != 'macOS'
run: dotnet tool run dotnet-coverage collect --output '${{ github.workspace }}/reports/coverage.cobertura.xml' --output-format cobertura '${{ github.workspace }}/test/${{ env.VERIFIABLE_TESTS }}/bin/${{ env.BUILD_CONFIGURATION }}/net9.0/${{ env.VERIFIABLE_TESTS }}' --report-trx --report-trx-filename testresults.trx --results-directory '${{ github.workspace }}/reports'
timeout-minutes: 5
# Mutation tests skipped for now due to CI limits and temporarily reduced test coverage...
# This either requires cd to test directory or --solution-path Verifiable.sln (which may not work).
# - name: Stryker.NET mutation Tests for Verifiable.Core.csproj
# if: ${{ matrix.os == 'ubuntu-latest' }}
# run: dotnet stryker --config-file stryker-config.json --reporter progress --reporter html --reporter dashboard --dashboard-api-key ${{ secrets.STRYKER_API_KEY }} --project Verifiable.Core.csproj
# timeout-minutes: 15
#- name: Upload Stryker output artefacts
# if: ${{ matrix.os == 'ubuntu-latest' }}
# uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
# with:
# name: 'Stryker output artefacts'
# path: ${{ github.workspace }}/StrykerOutput/
# - name: Publish
# run: dotnet publish -c Release --verbosity normal -o ./publish/
# - name: Archive publish results
# uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
# with:
# name: Verifiable.Benchmarks
# path: ./publish/*
# - name: Run Benchmarks
# run: dotnet "./publish/Verifiable.Benchmarks.dll" -f "Verifiable.Benchmarks.*"
# - name: Upload benchmark results
# uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
# with:
# name: Benchmark_Results
# path: ./BenchmarkDotNet.Artifacts/results/*
# This step is run always (e.g. also for non-PRs) so the results can be inspected on the command line too.
- name: ReportGenerator
if: ${{ matrix.os == 'ubuntu-latest' }}
run: dotnet reportgenerator -filefilters:'-**/obj/**;-**/*.g.cs' -assemblyfilters:'+Verifiable*' -reports:'${{ github.workspace }}/reports/coverage.cobertura.xml' -targetdir:'${{ github.workspace }}/reports/coverage/' -reporttypes:'HtmlInline;Cobertura;MarkdownSummary'
# - name: Publish coverage report
# if: ${{ matrix.os == 'ubuntu-latest' }}
# uses: 5monkeys/cobertura-action@master
# with:
# path: '${{ github.workspace }}/reports/coverage/Cobertura.xml'
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# minimum_coverage: 75
- name: Create test summary
if: ${{ matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' }}
uses: EnricoMi/publish-unit-test-result-action@170bf24d20d201b842d7a52403b73ed297e6645b
with:
trx_files: '${{ github.workspace }}/reports/**/*.trx'
- name: Publish coverage summary
if: ${{ matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' }}
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31
with:
header: Report
path: '${{ github.workspace }}/reports/coverage/Summary.md'
recreate: true
# - name: Comment PR with the generated test Markdown
# if: ${{ matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' }}
# uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31
# with:
# path: ${{ env.file_name }}
# - name: Upload PR build information artefact
# if: ${{ matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' }}
# uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
# with:
# name: 'Test Run'
# path: ${{ github.workspace }}/${{ env.file_name }}
# - name: Comment PR with the generated test Markdown
# if: ${{ matrix.os == 'ubuntu-latest' }}
# uses: machine-learning-apps/pr-comment@78e77cd435e0f9706512ea294d846058ae46f7ff
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# path: ${{ env.file_name }}
# - name: The sbom-tool does not generate the output directory and fails if it not present.
- name: Create SBOM output directory
run: mkdir -p "${{ github.workspace }}/${{ matrix.os }}/sbom/"
# There may a difference in libraries between platforms, so the tool is being run on all platforms.
- name: Run BOM analysis
run: dotnet tool run sbom-tool generate -DeleteManifestDirIfPresent true -BuildDropPath "${{ github.workspace }}/${{ matrix.os }}/sbom/" -FetchLicenseInformation true -EnablePackageMetadataParsing true -BuildComponentPath . -PackageName "Verifiable" -PackageSupplier "Lumoin" -NamespaceUriBase "https://lumoin.com/verifiable" -PackageVersion ${{ env.PACKAGE_VERSION }} -Verbosity Verbose
- name: Pack NuGet files
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE/$VERIFIABLE.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_BOUNCYCASTLE/$VERIFIABLE_BOUNCYCASTLE.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:NoWarn=NU5104 -property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_CORE/$VERIFIABLE_CORE.csproj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_DECENTRALIZEDWEBNODE/$VERIFIABLE_DECENTRALIZEDWEBNODE.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_JWT/$VERIFIABLE_JWT.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:NoWarn=NU5104 -property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_NSEC/$VERIFIABLE_NSEC.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_MICROSOFT/$VERIFIABLE_MICROSOFT.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_SIDETREE/$VERIFIABLE_SIDETREE.*proj
dotnet pack --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output nupkgs --property:PackageVersion=$PACKAGE_VERSION src/$VERIFIABLE_TPM/$VERIFIABLE_TPM.*proj
# Note that on Windows this would be simply "dotnet dotnet-validate package local ./snupkgs/*.nupkg", the handling of an array of paths works directly.
- name: Validate generated NuGet files
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
for file in ./nupkgs/*.nupkg; do
dotnet dotnet-validate package local "$file"
done
- name: Upload Verifiable NuGet packages
if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: nupkg
path: ./nupkgs/*.*
# The release idea is inspired by https://dusted.codes/github-actions-for-dotnet-core-nuget-packages.
prerelease:
permissions:
# For setup-dotnet to create package.
packages: write
needs: build
if: ${{ github.ref == 'refs/heads/develop' && github.repository_owner == 'lumoin' }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
aka.ms:443
api.github.com:443
api.nuget.org:443
dashboard.stryker-mutator.io:443
dotnetcli.azureedge.net:443
github.com:443
nuget.pkg.github.com:443
api.clearlydefined.io:443
- name: Download NuGet artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: nupkg
- name: Push to GitHub developer feed
run: dotnet nuget push "**/*.nupkg" --source $GITHUB_FEED --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
deploy:
permissions:
# For setup-dotnet to create package.
packages: write
needs: build
if: ${{ github.event_name == 'release' && github.repository_owner == 'lumoin' }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7
with:
disable-sudo: true
egress-policy: audit
allowed-endpoints: >
aka.ms:443
api.github.com:443
api.nuget.org:443
dashboard.stryker-mutator.io:443
dotnetcli.azureedge.net:443
github.com:443
nuget.pkg.github.com:443
- name: Download NuGet artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: nupkg
- name: Push to GitHub developer feed
run: dotnet nuget push "**/*.nupkg" --source $GITHUB_FEED --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
- name: Push to NuGet feed
run: dotnet nuget push "**/*.nupkg" --source $NUGET_FEED --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate