Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 123 additions & 28 deletions .github/workflows/nuget-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,129 @@ on:
branches: [main]
workflow_dispatch:

# No token scopes by default. The Publish job grants the ceiling the reusable
# workflow's jobs run under; each of its jobs narrows it further.
permissions: {}
# Published with nuget.org Trusted Publishing: GitHub's OIDC token is traded for an API key that
# lasts an hour, so there is no stored key to expire (the SWNUGETKEY secret had expired). nuget.org
# takes the workflow file from the token's job_workflow_ref and requires it to be in this
# repository, so the login can't run in simplify9/.github's reusable-nuget-publish.yml. Its jobs
# are therefore written out here, using the same shared actions. The nuget.org policy: owner
# simplify9, repository SW-CloudFiles, workflow nuget-publish.yml. NUGET_USER (a repository or
# organisation variable) is the nuget.org user who created the policy.

permissions:
contents: read

# Serialize runs per ref so concurrent pushes can't race the tag-based version.
concurrency:
group: nuget-publish-${{ github.ref }}
cancel-in-progress: false

jobs:
Publish:
version:
name: Version
runs-on: ubuntu-24.04
timeout-minutes: 10
outputs:
git-tag: ${{ steps.semver.outputs.git-tag }}
is-release: ${{ steps.semver.outputs.is-release }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # every tag, to compute the next version
persist-credentials: false
- name: Determine semantic version
id: semver
uses: simplify9/.github/.github/actions/determine-semver@main
with:
major: '10'
minor: '0'
# Only the default branch gets a release version; others get a prerelease.
release-branch: ${{ github.event.repository.default_branch }}
current-ref: ${{ github.ref_name }}
build-id: ${{ github.run_number }}

critical-vuln-gate:
name: Dependabot Check
needs: version
if: ${{ needs.version.outputs.is-release == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
contents: read
security-events: read
steps:
- name: Check for open critical Dependabot alerts
uses: simplify9/.github/.github/actions/check-critical-vulns@main
with:
dependabot-alerts-token: ${{ secrets.DEPENDABOT_ALERTS_TOKEN }}
repository: ${{ github.repository }}

nuget:
name: NuGet
needs: [version, critical-vuln-gate]
# The gate is skipped on non-release runs, so allow 'skipped' explicitly.
if: >-
${{ !cancelled()
&& needs.version.result == 'success'
&& (needs.critical-vuln-gate.result == 'success'
|| needs.critical-vuln-gate.result == 'skipped') }}
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
contents: read
id-token: write # the OIDC token NuGet/login trades for a short-lived API key
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Restore and build
uses: simplify9/.github/.github/actions/dotnet-build@main
with:
projects: '**/*.csproj'
configuration: Release
dotnet-version: '10.0.x'
run-tests: false
test-projects: '**/*UnitTests/*.csproj'
- name: NuGet login (OIDC to a one-hour API key)
id: login
uses: NuGet/login@v1
with:
user: ${{ vars.NUGET_USER }}
- name: Pack and push
uses: simplify9/.github/.github/actions/dotnet-pack-push@main
with:
projects: >-
SW.CloudFiles.S3/SW.CloudFiles.S3.csproj
SW.CloudFiles.S3.Extensions/SW.CloudFiles.S3.Extensions.csproj
SW.CloudFiles.AS/SW.CloudFiles.AS.csproj
SW.CloudFiles.OC/SW.CloudFiles.OC.csproj
SW.CloudFiles.AS.Extensions/SW.CloudFiles.AS.Extensions.csproj
SW.CloudFiles.OC.Extensions/SW.CloudFiles.OC.Extensions.csproj
SW.CloudFiles.GC/SW.CloudFiles.GC.csproj
SW.CloudFiles.GC.Extensions/SW.CloudFiles.GC.Extensions.csproj
SW.CloudFiles.LocalTests/SW.CloudFiles.LocalTests.csproj
SW.CloudFiles.LocalTests.Extensions/SW.CloudFiles.LocalTests.Extensions.csproj
configuration: Release
version: ${{ needs.version.outputs.git-tag }}
api-key: ${{ steps.login.outputs.NUGET_API_KEY }}
nuget-source: 'https://api.nuget.org/v3/index.json'

tag:
name: Tag
needs: [version, nuget]
# Only after a successful push, so a tag never names an unpublished version.
if: >-
${{ !cancelled()
&& needs.version.result == 'success'
&& needs.nuget.result == 'success' }}
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: write # tag job: create the git tag
packages: write # nuget job: only used when pushing to a GitHub Packages feed
security-events: read # critical-vuln gate job
uses: simplify9/.github/.github/workflows/reusable-nuget-publish.yml@main
with:
nuget-projects: >-
SW.CloudFiles.S3/SW.CloudFiles.S3.csproj
SW.CloudFiles.S3.Extensions/SW.CloudFiles.S3.Extensions.csproj
SW.CloudFiles.AS/SW.CloudFiles.AS.csproj
SW.CloudFiles.OC/SW.CloudFiles.OC.csproj
SW.CloudFiles.AS.Extensions/SW.CloudFiles.AS.Extensions.csproj
SW.CloudFiles.OC.Extensions/SW.CloudFiles.OC.Extensions.csproj
SW.CloudFiles.GC/SW.CloudFiles.GC.csproj
SW.CloudFiles.GC.Extensions/SW.CloudFiles.GC.Extensions.csproj
SW.CloudFiles.LocalTests/SW.CloudFiles.LocalTests.csproj
SW.CloudFiles.LocalTests.Extensions/SW.CloudFiles.LocalTests.Extensions.csproj
major-version: '10'
minor-version: '0'
dotnet-version: '10.0.x'
run-tests: false
test-projects: '**/*UnitTests/*.csproj'
secrets:
nuget-api-key: ${{ secrets.SWNUGETKEY }}
dependabot-alerts-token: ${{ secrets.DEPENDABOT_ALERTS_TOKEN }}
contents: write
steps:
- name: Tag the version
uses: simplify9/.github/.github/actions/tag-github-origin@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
tag: ${{ needs.version.outputs.git-tag }}
sha: ${{ github.sha }}
Loading