Repository navigation
147 lines (131 loc) · 6.4 KB
/
Copy pathrelease.yml
File metadata and controls
147 lines (131 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Publishes SheetStream to nuget.org when a version tag is pushed, e.g. `git tag v0.1.0 && git push --tags`.
# The tag must match the <Version> in src/SheetStream/SheetStream.csproj; the build job fails early if it
# does not, so a stale csproj version can never ship under the wrong tag.
#
# Publishing uses nuget.org Trusted Publishing: a policy on the P4Software nuget.org account trusts this
# repository's release.yml, so the publish job exchanges its GitHub OIDC token for a short-lived API key.
# No long-lived key is stored anywhere.
#
# The work is split into four jobs so each holds only the permission it needs: building and testing run
# our own and third-party code with a read-only token; the attest job alone can sign provenance, only the publish job can mint a NuGet key,
# and only the release job can write to the repository.
name: Release
on:
push:
tags: ['v*']
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read # this job runs third-party test code, so it never holds a signing token
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: |
8.0.x
10.0.x
- name: Check tag matches both package versions
run: |
TAG="${GITHUB_REF_NAME#v}"
for P in src/SheetStream/SheetStream.csproj src/SheetStream.AspNetCore/SheetStream.AspNetCore.csproj; do
V=$(grep -oPm1 '(?<=<Version>)[^<]+' "$P")
echo "tag=$TAG $P=$V"
test "$TAG" = "$V" || { echo "Tag v$TAG does not match <Version>$V</Version> in $P; bump it first."; exit 1; }
done
- name: Restore
run: dotnet restore
- name: Build
run: dotnet build --no-restore -c Release -p:ContinuousIntegrationBuild=true
- name: Test
run: dotnet test --no-build -c Release
- name: Pack
run: |
dotnet pack src/SheetStream/SheetStream.csproj --no-build -c Release -o artifacts
dotnet pack src/SheetStream.AspNetCore/SheetStream.AspNetCore.csproj --no-build -c Release -o artifacts
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: built-packages
path: artifacts/*
# Runs after the build with nothing but the finished packages: no project code or tests execute here,
# so the signing token cannot be reached by anything a dependency might run.
attest:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # sign the build provenance attestation
attestations: write # store the attestation on GitHub
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: built-packages
path: artifacts
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: 10.0.x
# A software bill of materials (SPDX 2.2) listing exactly what is inside the packages and what they
# were built from, attached to every release so procurement and security teams can check it.
# The tool version is pinned so the SBOM format cannot change under us.
- name: Generate SBOM
run: |
dotnet tool install --global Microsoft.Sbom.DotNetTool --version 4.1.13
mkdir -p sbom # sbom-tool refuses to create its manifest directory itself
sbom-tool generate -b artifacts -bc . -m sbom -pn SheetStream.NET -pv "${GITHUB_REF_NAME#v}" -ps "P4 Software" -nsb https://p4.software/sbom -V Warning
cp sbom/_manifest/spdx_2.2/manifest.spdx.json "artifacts/SheetStream.NET-${GITHUB_REF_NAME#v}.spdx.json"
# Signed statement that these exact package files were produced by this workflow from this commit.
# Anyone can verify it with `gh attestation verify SheetStream.NET.x.y.z.nupkg --owner P4Software`.
- name: Attest build provenance
id: attest
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: artifacts/*.nupkg
# The same signed provenance, attached to the release as a Sigstore bundle so it can be checked
# offline (and so scanners that look for a signature file next to the assets find one).
- name: Attach the provenance bundle to the release assets
run: cp "${{ steps.attest.outputs.bundle-path }}" "artifacts/SheetStream.NET-${GITHUB_REF_NAME#v}.intoto.jsonl"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: packages
path: artifacts/*
publish:
needs: attest
runs-on: ubuntu-latest
permissions:
id-token: write # request the OIDC token NuGet exchanges for a short-lived key
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: packages
path: artifacts
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: 10.0.x
# Official NuGet action, pinned to the v1.2.0 commit so a moved tag cannot change what runs.
- name: NuGet login (Trusted Publishing)
id: nuget-login
uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1.2.0
with:
user: P4Software
- name: Push to nuget.org
run: dotnet nuget push "artifacts/*.nupkg" --api-key "${{ steps.nuget-login.outputs.NUGET_API_KEY }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
release:
needs: publish
runs-on: ubuntu-latest
permissions:
contents: write # create the GitHub release
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: packages
path: artifacts
# The runner's built-in gh CLI avoids a third-party action holding a contents:write token.
- name: Create GitHub release with the package attached
env:
GH_TOKEN: ${{ github.token }}
run: gh release create "$GITHUB_REF_NAME" artifacts/* --repo "$GITHUB_REPOSITORY" --generate-notes --verify-tag