-
Notifications
You must be signed in to change notification settings - Fork 12
188 lines (162 loc) · 7.07 KB
/
Copy pathdeploy.yml
File metadata and controls
188 lines (162 loc) · 7.07 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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
name: Deploy
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
# Dry run: exchange the OIDC token for a nuget.org key and stop, without
# packing or publishing. Lives here rather than in its own workflow because
# the trusted publishing policy matches on the workflow filename and the
# environment — a separate workflow would fail to match even when correct.
workflow_dispatch:
inputs:
nuget_user:
description: "nuget.org profile name to exchange as (defaults to the NUGET_USER secret)"
required: false
type: string
permissions:
id-token: write
contents: read
env:
ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }}
jobs:
verify:
runs-on: ubuntu-x64
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Get tag
if: ${{ github.event_name == 'push' }}
id: tag
run: echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
- name: Verify tag matches package version
if: ${{ github.event_name == 'push' }}
env:
TAG: ${{ steps.tag.outputs.version }}
run: |
set -euo pipefail
VERSION=$(sed -nE 's@.*<Version>(.*)</Version>.*@\1@p' Analytics-CSharp/Analytics-CSharp.csproj)
# SegmentVersion is what the library reports at runtime — Analytics.Version
# and the library version on every event context. A stale value here
# publishes a correctly numbered package that misreports itself.
RUNTIME=$(sed -nE 's@.*SegmentVersion *= *"([^"]+)".*@\1@p' Analytics-CSharp/Segment/Analytics/Version.cs)
for pair in "csproj:$VERSION" "Version.cs:$RUNTIME"; do
name="${pair%%:*}"; value="${pair#*:}"
if [ -z "$value" ]; then
echo "::error::Could not read the version from $name"; exit 1
fi
if [ "$TAG" != "$value" ]; then
echo "::error::Tag $TAG does not match $name ($value)"; exit 1
fi
done
echo "Releasing $TAG"
- name: Setup .NET SDK
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4
with:
# Tests target net10.0 and net6.0, so both runtimes are needed to
# execute them. Keep in step with ci.yml.
dotnet-version: |
6.0.x
10.0.x
- name: Configure Artifactory NuGet source
uses: twilio/sdk-actions/artifactory-oidc@c94e420aa64ea686ff25bb03d4c66cdaf8e523e4 # main
with:
ecosystem: dotnet
provider-name: github-actions-segmentio
- name: Restore dependencies
run: dotnet restore Analytics-CSharp.slnf --locked-mode
- name: Build
run: dotnet build Analytics-CSharp.slnf --no-restore
- name: Test
run: dotnet test Analytics-CSharp.slnf --no-build
publish:
needs: verify
runs-on: ubuntu-x64
# `deployment` exists and carries the required reviewers. Naming an
# environment that does not exist silently creates an unprotected one, so
# this must match a real environment and the nuget.org policy.
environment: deployment
permissions:
# id-token for the nuget.org OIDC exchange; contents:write because the
# last step creates the GitHub release. The workflow default is
# contents: read, which 403s there.
id-token: write
contents: write
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Setup .NET SDK
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4
with:
# Tests target net10.0 and net6.0, so both runtimes are needed to
# execute them. Keep in step with ci.yml.
dotnet-version: |
6.0.x
10.0.x
- name: Configure Artifactory NuGet source
uses: twilio/sdk-actions/artifactory-oidc@c94e420aa64ea686ff25bb03d4c66cdaf8e523e4 # main
with:
ecosystem: dotnet
provider-name: github-actions-segmentio
- name: Restore dependencies
run: dotnet restore Analytics-CSharp.slnf --locked-mode
# Only the library is packable. A solution-wide pack would also produce
# packages for the sample projects, and the push glob below would send them.
- name: Pack
if: ${{ github.event_name == 'push' }}
run: dotnet pack Analytics-CSharp/Analytics-CSharp.csproj --no-restore -c Release -o artifacts
# NuGet trusted publishing: exchange the GitHub OIDC token for an API key
# that lives one hour. Done inline rather than with NuGet/login, which is
# not on the org's allow-list. One OIDC token mints exactly one key, so
# this sits immediately before the push.
- name: Push to NuGet.org (trusted publishing)
env:
NUGET_USER: ${{ inputs.nuget_user || secrets.NUGET_USER }}
run: |
set -euo pipefail
if [ -z "${NUGET_USER:-}" ]; then
echo "::error::NUGET_USER is not set. It is the nuget.org profile name that owns the trusted publishing policy, not an email address."
exit 1
fi
OIDC_JWT=$(curl -sS \
-H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=https://www.nuget.org" \
| jq -r '.value')
if [ -z "$OIDC_JWT" ] || [ "$OIDC_JWT" = "null" ]; then
echo "::error::No GitHub OIDC token. The job needs 'permissions: id-token: write'."
exit 1
fi
RESP=$(curl -sS -X POST https://www.nuget.org/api/v2/token \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${OIDC_JWT}" \
-d "{\"username\": \"${NUGET_USER}\", \"tokenType\": \"ApiKey\"}")
API_KEY=$(echo "$RESP" | jq -r '.apiKey // empty')
if [ -z "$API_KEY" ]; then
echo "::error::nuget.org token exchange failed."
echo "$RESP" | jq 'del(.apiKey)' 2>/dev/null || echo "::error::(response withheld - not valid JSON)"
exit 1
fi
echo "::add-mask::$API_KEY"
echo "Exchange succeeded as '${NUGET_USER}' — nuget.org issued a key."
if [ "${GITHUB_EVENT_NAME}" != "push" ]; then
echo "Dry run: not packing or publishing."
exit 0
fi
dotnet nuget push "artifacts/*.nupkg" \
--source https://api.nuget.org/v3/index.json \
--api-key "$API_KEY"
- name: Create GitHub release
if: ${{ github.event_name == 'push' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REF_NAME: ${{ github.ref_name }}
run: |
# Guarded so a re-run after a partial failure does not error with
# "release already exists".
if gh release view "$REF_NAME" >/dev/null 2>&1; then
echo "Release $REF_NAME already exists; leaving it as is."
else
gh release create "$REF_NAME" \
--title "$REF_NAME" \
--generate-notes
fi