-
Notifications
You must be signed in to change notification settings - Fork 139
170 lines (147 loc) · 6.33 KB
/
Copy pathnuget.yml
File metadata and controls
170 lines (147 loc) · 6.33 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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
name: Publish Nuget
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to pack (e.g. 1.4.6). Required when running manually.'
required: true
type: string
dry_run:
description: 'Skip the nuget push step.'
type: boolean
default: true
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
# Gate real publishes behind the 'release' environment (required reviewer); leave dry-runs ungated.
environment: ${{ (github.event_name == 'push' || inputs.dry_run == false) && 'release' || '' }}
permissions:
contents: write # create GitHub Release
id-token: write # Sigstore OIDC
attestations: write # GitHub attestations API
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # MinVer needs full history + tags to derive the version
- name: Setup .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: |
6.0.x
8.0.x
- name: Resolve version
id: get_version
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
# On a tag push MinVer derives the version from the checked-out v* tag.
# On a manual run there is no tag, so override MinVer with the requested version.
if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then
VERSION="$INPUT_VERSION"
echo "MINVER_OVERRIDE=-p:MinVerVersionOverride=$VERSION" >> "$GITHUB_OUTPUT"
else
VERSION="${GITHUB_REF#refs/tags/v}"
echo "MINVER_OVERRIDE=" >> "$GITHUB_OUTPUT"
fi
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
echo "Resolved version: $VERSION"
- name: Restore .NET tools
run: dotnet tool restore
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore ${{ steps.get_version.outputs.MINVER_OVERRIDE }}
- name: Pack
run: dotnet pack --configuration Release --no-build --output . ${{ steps.get_version.outputs.MINVER_OVERRIDE }}
- name: Generate SBOM
env:
VERSION: ${{ steps.get_version.outputs.VERSION }}
run: |
set -euo pipefail
# Generate from temporary consumers that restore the freshly packed local .nupkg files.
# That keeps project references represented as the NuGet dependencies consumers install.
SBOM_INPUT_DIR="$(mktemp -d)"
LOCAL_NUGET_SOURCE="$PWD"
create_sbom_input() {
local package_id="$1"
local project_path="$SBOM_INPUT_DIR/${package_id}.SbomInput.csproj"
cat > "$project_path" <<EOF
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0;net10.0</TargetFrameworks>
<RestoreSources>${LOCAL_NUGET_SOURCE};https://api.nuget.org/v3/index.json</RestoreSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="${package_id}" Version="${VERSION}" />
</ItemGroup>
</Project>
EOF
}
normalize_sbom() {
local package_id="$1"
local raw_path="$2"
local output_path="$3"
local root_ref="pkg:nuget/${package_id}@${VERSION}"
jq --arg root_ref "$root_ref" '
.components = ((.components // []) | map(select(.purl != $root_ref and ."bom-ref" != $root_ref))) |
.dependencies = (
(.dependencies // [])
| group_by(.ref)
| map({
ref: .[0].ref,
dependsOn: ([.[].dependsOn[]?] | unique | map(select(. != $root_ref)))
})
)
' "$raw_path" > "$output_path"
}
generate_package_sbom() {
local package_id="$1"
local output_path="$2"
local raw_filename="${package_id}.raw.bom.json"
local project_path="$SBOM_INPUT_DIR/${package_id}.SbomInput.csproj"
create_sbom_input "$package_id"
dotnet CycloneDX "$project_path" \
--output "$SBOM_INPUT_DIR" --filename "$raw_filename" \
--output-format Json --exclude-dev \
--set-name "$package_id" --set-version "$VERSION" --set-type Library --set-nuget-purl
normalize_sbom "$package_id" "$SBOM_INPUT_DIR/$raw_filename" "$output_path"
}
generate_package_sbom GoogleMapsApi GoogleMapsApi.bom.json
generate_package_sbom GoogleMapsApi.Extensions.DependencyInjection GoogleMapsApi.Extensions.DependencyInjection.bom.json
- name: Attest build provenance
if: github.event_name == 'push' || inputs.dry_run == false
id: attest
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: '*.nupkg'
- name: Upload nupkg artifact
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: nupkg-${{ steps.get_version.outputs.VERSION }}
path: |
*.nupkg
*.bom.json
- name: Publish NuGet
if: github.event_name == 'push' || inputs.dry_run == false
run: dotnet nuget push *.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
- name: Create or update GitHub Release
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.dry_run == false)
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.get_version.outputs.VERSION }}
ATTESTATION_BUNDLE: ${{ steps.attest.outputs.bundle-path }}
run: |
if gh release view "v${VERSION}" >/dev/null 2>&1; then
gh release upload "v${VERSION}" ./*.nupkg ./*.bom.json "${ATTESTATION_BUNDLE}" --clobber
else
gh release create "v${VERSION}" \
--title "v${VERSION}" \
--generate-notes \
./*.nupkg ./*.bom.json "${ATTESTATION_BUNDLE}"
fi