Skip to content

Commit 539395e

Browse files
committed
ci: make package signing optional
1 parent a264049 commit 539395e

6 files changed

Lines changed: 64 additions & 51 deletions

File tree

.github/workflows/publish-artifacts.yml

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ name: Publish Artifacts
22

33
on:
44
workflow_call:
5+
outputs:
6+
signing_enabled:
7+
description: "Whether package signing was enabled for this run."
8+
value: ${{ jobs.package.outputs.signing_enabled }}
59
inputs:
610
package_version:
711
description: "Optional package version, usually the release tag without the leading v."
@@ -36,13 +40,13 @@ on:
3640
default: true
3741
secrets:
3842
NUGET_SIGN_CERTIFICATE_BASE64:
39-
required: true
43+
required: false
4044
NUGET_SIGN_CERTIFICATE_PASSWORD:
41-
required: true
45+
required: false
4246
NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT:
43-
required: true
47+
required: false
4448
NUGET_SIGN_TIMESTAMP_URL:
45-
required: true
49+
required: false
4650

4751
permissions:
4852
contents: read
@@ -51,6 +55,8 @@ jobs:
5155
package:
5256
name: Pack packages
5357
runs-on: ubuntu-latest
58+
outputs:
59+
signing_enabled: ${{ steps.signing.outputs.enabled }}
5460

5561
steps:
5662
- name: Checkout
@@ -137,32 +143,38 @@ jobs:
137143
-o nupkg
138144
-p:PackageVersion=${{ steps.version.outputs.redis_version }}
139145
140-
- name: Import signing certificate
146+
- name: Resolve signing mode
147+
id: signing
141148
env:
142149
NUGET_SIGN_CERTIFICATE_BASE64: ${{ secrets.NUGET_SIGN_CERTIFICATE_BASE64 }}
150+
NUGET_SIGN_CERTIFICATE_PASSWORD: ${{ secrets.NUGET_SIGN_CERTIFICATE_PASSWORD }}
151+
NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT: ${{ secrets.NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT }}
152+
NUGET_SIGN_TIMESTAMP_URL: ${{ secrets.NUGET_SIGN_TIMESTAMP_URL }}
143153
run: |
144-
if [ -z "$NUGET_SIGN_CERTIFICATE_BASE64" ]; then
145-
echo "NUGET_SIGN_CERTIFICATE_BASE64 secret is required for package signing." >&2
146-
exit 1
154+
if [ -n "$NUGET_SIGN_CERTIFICATE_BASE64" ] \
155+
&& [ -n "$NUGET_SIGN_CERTIFICATE_PASSWORD" ] \
156+
&& [ -n "$NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT" ] \
157+
&& [ -n "$NUGET_SIGN_TIMESTAMP_URL" ]; then
158+
echo "enabled=true" >> "$GITHUB_OUTPUT"
159+
echo "Package signing enabled."
160+
else
161+
echo "enabled=false" >> "$GITHUB_OUTPUT"
162+
echo "Package signing disabled. Continuing with unsigned packages."
147163
fi
148164
165+
- name: Import signing certificate
166+
if: ${{ steps.signing.outputs.enabled == 'true' }}
167+
env:
168+
NUGET_SIGN_CERTIFICATE_BASE64: ${{ secrets.NUGET_SIGN_CERTIFICATE_BASE64 }}
169+
run: |
149170
printf '%s' "$NUGET_SIGN_CERTIFICATE_BASE64" | base64 --decode > signing-cert.pfx
150171
151172
- name: Sign packages
173+
if: ${{ steps.signing.outputs.enabled == 'true' }}
152174
env:
153175
NUGET_SIGN_CERTIFICATE_PASSWORD: ${{ secrets.NUGET_SIGN_CERTIFICATE_PASSWORD }}
154176
NUGET_SIGN_TIMESTAMP_URL: ${{ secrets.NUGET_SIGN_TIMESTAMP_URL }}
155177
run: |
156-
if [ -z "$NUGET_SIGN_CERTIFICATE_PASSWORD" ]; then
157-
echo "NUGET_SIGN_CERTIFICATE_PASSWORD secret is required for package signing." >&2
158-
exit 1
159-
fi
160-
161-
if [ -z "$NUGET_SIGN_TIMESTAMP_URL" ]; then
162-
echo "NUGET_SIGN_TIMESTAMP_URL secret is required for package signing." >&2
163-
exit 1
164-
fi
165-
166178
for package in nupkg/*.nupkg; do
167179
dotnet nuget sign "$package" \
168180
--certificate-path signing-cert.pfx \
@@ -174,14 +186,10 @@ jobs:
174186
done
175187
176188
- name: Verify signed packages
189+
if: ${{ steps.signing.outputs.enabled == 'true' }}
177190
env:
178191
NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT: ${{ secrets.NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT }}
179192
run: |
180-
if [ -z "$NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT" ]; then
181-
echo "NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT secret is required for package verification." >&2
182-
exit 1
183-
fi
184-
185193
for package in nupkg/*.nupkg; do
186194
dotnet nuget verify "$package" \
187195
--all \

.github/workflows/publish-attested.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ on:
1515
type: string
1616
secrets:
1717
NUGET_SIGN_CERTIFICATE_BASE64:
18-
required: true
18+
required: false
1919
NUGET_SIGN_CERTIFICATE_PASSWORD:
20-
required: true
20+
required: false
2121
NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT:
22-
required: true
22+
required: false
2323
NUGET_SIGN_TIMESTAMP_URL:
24-
required: true
24+
required: false
2525

2626
permissions:
2727
contents: write
@@ -56,6 +56,11 @@ jobs:
5656
path: dist
5757
merge-multiple: true
5858

59+
- name: Attest package artifacts
60+
uses: actions/attest-build-provenance@v2
61+
with:
62+
subject-path: dist/*.nupkg
63+
5964
- name: Create or update draft release
6065
env:
6166
GITHUB_TOKEN: ${{ github.token }}

.github/workflows/publish-packages.yml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,10 @@ jobs:
130130
merge-multiple: true
131131

132132
- name: Verify signed packages
133+
if: ${{ needs.package.outputs.signing_enabled == 'true' }}
133134
env:
134135
NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT: ${{ secrets.NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT }}
135136
run: |
136-
if [ -z "$NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT" ]; then
137-
echo "NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT secret is required for package verification." >&2
138-
exit 1
139-
fi
140-
141137
for package in dist/*.nupkg; do
142138
dotnet nuget verify "$package" \
143139
--all \
@@ -184,14 +180,10 @@ jobs:
184180
merge-multiple: true
185181

186182
- name: Verify signed packages
183+
if: ${{ needs.package.outputs.signing_enabled == 'true' }}
187184
env:
188185
NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT: ${{ secrets.NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT }}
189186
run: |
190-
if [ -z "$NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT" ]; then
191-
echo "NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT secret is required for package verification." >&2
192-
exit 1
193-
fi
194-
195187
for package in dist/*.nupkg; do
196188
dotnet nuget verify "$package" \
197189
--all \

.github/workflows/release-drafter.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ jobs:
3434
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3535

3636
publish-attested:
37-
if: ${{ secrets.NUGET_SIGN_CERTIFICATE_BASE64 != '' && secrets.NUGET_SIGN_CERTIFICATE_PASSWORD != '' && secrets.NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT != '' && secrets.NUGET_SIGN_TIMESTAMP_URL != '' }}
3837
needs: update-release-draft
3938
uses: ./.github/workflows/publish-attested.yml
4039
with:

Docs/Package-Signing.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Package Signing
22

3-
`ModularityKit.Mutator` release packages are signed as part of the standard package publish path.
3+
`ModularityKit.Mutator` can sign release packages as part of the standard package publish path.
44

5-
The repository signs generated `.nupkg` artifacts before they are uploaded or pushed to package feeds.
6-
Unsigned release packages are treated as a validation failure.
5+
When signing material is configured, the repository signs generated `.nupkg` artifacts before they
6+
are uploaded or pushed to package feeds. When signing material is not configured, the release path
7+
continues with unsigned packages and relies on GitHub artifact attestations for provenance.
78

89
## Signing approach
910

@@ -21,21 +22,28 @@ This keeps signing explicit, auditable, and integrated with the existing `pack`
2122
The standard package release path is:
2223

2324
1. pack packages in `.github/workflows/publish-artifacts.yml`
24-
2. sign every `.nupkg`
25-
3. verify every signed `.nupkg`
26-
4. upload signed artifacts
27-
5. download and verify signed artifacts again before pushing to NuGet.org or GitHub Packages
25+
2. sign every `.nupkg` when signing secrets are configured
26+
3. verify every signed `.nupkg` when signing is enabled
27+
4. upload artifacts
28+
5. generate GitHub artifact attestations in `.github/workflows/publish-attested.yml`
29+
6. download and verify signed artifacts again before pushing to NuGet.org or GitHub Packages when signing is enabled
2830

2931
The signing step changes package contents only by adding signature metadata.
3032

31-
## Required GitHub secrets
33+
## GitHub secrets
3234

33-
Configure these repository secrets before using the package publish workflows:
35+
Package signing is optional. Configure these repository secrets to enable signed package output:
3436

3537
- `NUGET_SIGN_CERTIFICATE_BASE64`
3638
- `NUGET_SIGN_CERTIFICATE_PASSWORD`
3739
- `NUGET_SIGN_CERTIFICATE_SHA256_FINGERPRINT`
3840
- `NUGET_SIGN_TIMESTAMP_URL`
41+
42+
Without those secrets, the workflows still pack packages and the attested release path still emits
43+
GitHub provenance attestations.
44+
45+
NuGet.org publishing still requires:
46+
3947
- `NUGET_USERNAME`
4048

4149
Notes:
@@ -55,7 +63,7 @@ Contributors can still:
5563
- pack projects locally
5664
- run tests and smoke tests
5765

58-
Signing is enforced in the repository release workflows, not for ordinary local development.
66+
Signing is optional in the repository release workflows and not required for ordinary local development.
5967

6068
If you have access to the signing certificate locally, you can validate package signatures with:
6169

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ https://modularitykit.github.io/ModularityKit.Mutator/
7171

7272
## Package signing
7373

74-
Release packages are signed and verified in the standard package publish workflow. See
75-
[`Docs/Package-Signing.md`](Docs/Package-Signing.md) for the signing approach, required secrets, and
76-
local verification expectations.
74+
Release packages can be signed and verified in the standard package publish workflow when signing
75+
secrets are configured. Without signing secrets, the attested release path still emits GitHub
76+
artifact attestations. See [`Docs/Package-Signing.md`](Docs/Package-Signing.md) for the signing
77+
approach, optional secrets, and local verification expectations.

0 commit comments

Comments
 (0)