-
Notifications
You must be signed in to change notification settings - Fork 2
205 lines (182 loc) · 8.26 KB
/
Copy pathpublish.yml
File metadata and controls
205 lines (182 loc) · 8.26 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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
name: Publish to npm
# Every run publishes a dev build. A run also publishes a release when
# the push changed the root `version`, or a dispatch asked for one. The
# two are not alternatives: when they were, the release commit never
# reached the dev channel and `dev` sat on an older version than the
# release. See docs/oss/versioning.md.
#
# The version is always what the root `package.json` says at this ref.
# Dev suffixes are stamped in CI and never committed.
on:
push:
branches: [main]
tags: ["!**"]
workflow_dispatch:
inputs:
dist-tag:
description: "npm dist-tag. Empty = the version's canonical tag (next on the RC line, latest for stable). Pass latest explicitly to move latest onto an RC — that is the deliberate cutover act."
required: false
default: ""
type: string
dry-run:
description: "Dry-run only (build + pack, no npm publish, no GitHub Release)."
required: false
default: true
type: boolean
concurrency:
group: npm-publish
cancel-in-progress: false
jobs:
publish:
name: Publish packages to npm
runs-on: ubuntu-latest
# Only `main` publishes; a dry-run dispatch may validate the pipeline
# from any branch.
if: ${{ github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry-run == 'true') }}
permissions:
contents: write # Required to create the GitHub Release + tag for latest publishes
id-token: write # Required for npm OIDC Trusted Publishing
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
# determine-version.ts reads package.json at `before`, which a
# multi-commit push can place arbitrarily far back.
fetch-depth: 0
- name: Set up pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .node-version
cache: pnpm
- name: Configure npm
run: pnpm config set registry https://registry.npmjs.org
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Determine version
id: version
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
INPUT_DIST_TAG: ${{ github.event.inputs.dist-tag }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
run: node scripts/determine-version.ts
# --- The dev build: every run, no conditions. ---
# The lockfile refresh is part of the stamp: pnpm verifies
# manifests against the lockfile before running any script.
- name: Stamp the dev version
env:
DEV_VERSION: ${{ steps.version.outputs.devVersion }}
run: |
node scripts/set-version.ts "$DEV_VERSION"
node scripts/update-product-versions.mjs --channel dev
pnpm install --lockfile-only --no-frozen-lockfile
- name: Build the dev version
run: pnpm build
- name: Check the dev version
env:
PUBLISH_CHANNEL: dev
run: |
pnpm check:grammar
pnpm test:scripts
pnpm check:conformance
- name: Publish the dev version
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.dry-run != 'true' }}
env:
NPM_CONFIG_PROVENANCE: "true"
run: bash scripts/publish-packages.sh dev @prisma/cli-engine @prisma/cli prisma
- name: Verify the dev version resolves
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.dry-run != 'true' }}
env:
DEV_VERSION: ${{ steps.version.outputs.devVersion }}
run: |
node scripts/verify-published.mjs "@prisma/cli@$DEV_VERSION" "prisma@$DEV_VERSION"
# --- The release: only when the committed version changed. ---
- name: Restore the committed versions
if: ${{ steps.version.outputs.release == 'true' }}
run: |
git checkout -- .
pnpm install --frozen-lockfile
pnpm build
- name: Check the release
if: ${{ steps.version.outputs.release == 'true' }}
env:
PUBLISH_CHANNEL: release
run: |
pnpm check:grammar
pnpm check:conformance
- name: Upload tarball artifacts
if: ${{ steps.version.outputs.release == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: npm-tarballs
path: artifacts/tarballs/*.tgz
if-no-files-found: error
# NODE_AUTH_TOKEN is intentionally NOT set: npm authenticates over
# OIDC, and setting it to any value — even empty — blocks that.
# `pnpm publish`, not `npm publish`, or `workspace:` specifiers
# survive into the published manifest.
- name: Publish the release
if: ${{ steps.version.outputs.release == 'true' && (github.event_name != 'workflow_dispatch' || github.event.inputs.dry-run != 'true') }}
env:
NPM_CONFIG_PROVENANCE: "true"
DIST_TAG: ${{ steps.version.outputs.releaseTag }}
run: bash scripts/publish-packages.sh "$DIST_TAG" @prisma/cli-engine @prisma/cli prisma
- name: Verify the release resolves
if: ${{ steps.version.outputs.release == 'true' && (github.event_name != 'workflow_dispatch' || github.event.inputs.dry-run != 'true') }}
env:
RELEASE_VERSION: ${{ steps.version.outputs.releaseVersion }}
run: |
engine=$(node -p "require('./packages/cli-engine/package.json').version")
node scripts/verify-published.mjs \
"@prisma/cli-engine@$engine" \
"@prisma/cli@$RELEASE_VERSION" \
"prisma@$RELEASE_VERSION"
# Draft first, assets, then publish: a published release is
# immutable, so a later upload answers 422. Created through the API
# for the id — searching the releases listing for a draft races its
# eventual consistency.
- name: Create GitHub Release
if: ${{ steps.version.outputs.githubRelease == 'true' && (github.event_name != 'workflow_dispatch' || github.event.inputs.dry-run != 'true') }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.releaseVersion }}
run: |
# The by-tag endpoints do not see drafts, so search the listing.
existing=$(gh api --paginate "repos/$GITHUB_REPOSITORY/releases" \
| jq -c --arg tag "v$VERSION" '.[] | select(.tag_name == $tag)' | head -n 1)
if [ -n "$existing" ]; then
if [ "$(jq -r .draft <<<"$existing")" = "false" ]; then
echo "Release v$VERSION is already published and releases are immutable — nothing to repair."
exit 0
fi
# A draft from a failed attempt never reached anyone; replace it.
gh api -X DELETE "repos/$GITHUB_REPOSITORY/releases/$(jq -r .id <<<"$existing")"
fi
PRERELEASE=false
case "$VERSION" in
*-rc.*) PRERELEASE=true ;;
esac
release_id=$(gh api "repos/$GITHUB_REPOSITORY/releases" \
-f tag_name="v$VERSION" \
-f target_commitish="$GITHUB_SHA" \
-f name="v$VERSION" \
-F draft=true \
-F prerelease=$PRERELEASE \
-F generate_release_notes=true \
--jq .id)
if [ -z "$release_id" ]; then
echo "Creating the draft release for v$VERSION returned no id" >&2
exit 1
fi
# By id, not tag: uploads to a fresh draft race the by-tag lookup.
for tarball in artifacts/tarballs/*.tgz; do
gh api -X POST \
-H "Content-Type: application/gzip" \
"https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$release_id/assets?name=$(basename "$tarball")" \
--input "$tarball" >/dev/null
done
gh api -X PATCH "repos/$GITHUB_REPOSITORY/releases/$release_id" \
-F draft=false >/dev/null
echo "Published release v$VERSION with $(find artifacts/tarballs -name '*.tgz' | wc -l | tr -d ' ') asset(s)."