-
Notifications
You must be signed in to change notification settings - Fork 3
190 lines (173 loc) · 7.89 KB
/
Copy pathpublish.yml
File metadata and controls
190 lines (173 loc) · 7.89 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
# Publishes `@comfyorg/sdk` to npm.
#
# Tag-driven versioning: the release tag (vX.Y.Z) is the single source of truth
# for the published version. It is injected into package.json at build time, so
# the committed version there is just a placeholder — to release a version,
# create a GitHub Release with the tag you want; no version-bump commit needed.
#
# Trigger: a GitHub Release being published (tag vX.Y.Z). That's the only
# path that reaches the `publish` job below. `workflow_dispatch` is a dry
# run only — it exercises `build` (compile + `pnpm pack` + a dry-run
# `npm publish`) but never reaches `publish`, so it's safe to run against
# any branch to sanity-check the pipeline before cutting a real release.
#
# Auth: npm Trusted Publishing (OIDC) — no NPM_TOKEN / API-token secret is
# stored in this repo. A trusted publisher configured on npmjs.com (for this
# repo + this workflow + the `npm` environment) lets `npm publish`
# authenticate with a short-lived OIDC token, and generates a public SLSA
# provenance attestation automatically. `id-token: write` on the publish job
# is what enables it. OIDC trusted publishing requires a recent npm CLI
# (>= 11.5.1), so the publish job upgrades npm before publishing.
name: Publish to npm
on:
release:
types: [published]
workflow_dispatch:
inputs:
ref:
description: "Git ref to build for a dry run (build + pack + npm publish --dry-run only — this input never reaches the publish job)"
required: false
type: string
default: ""
permissions:
contents: read
concurrency:
group: publish-${{ github.workflow }}-${{ github.event.release.tag_name || github.sha }}
cancel-in-progress: false
jobs:
# Runs for every trigger. Builds and packs the exact tarball `publish` will
# upload, and dry-run-publishes it (no auth, nothing is uploaded) as an
# extra check. This IS the workflow_dispatch dry run: trigger this
# workflow manually via the Actions tab and you get this job (and nothing
# else, since `publish` requires a `release` event).
build:
name: Build and pack (dry-run check)
runs-on: ubuntu-latest
outputs:
tarball: ${{ steps.pack.outputs.tarball }}
version: ${{ steps.setver.outputs.version }}
steps:
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.inputs.ref || github.ref }}
- name: Set up pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
# Tag-driven versioning: the release tag (vX.Y.Z) is the source of truth.
# Inject it into package.json before build/pack so the published tarball
# carries the tag's version. (On a workflow_dispatch dry run there is no
# release tag; the committed placeholder version is packed as-is.)
- name: Set version from release tag
id: setver
if: github.event_name == 'release'
shell: bash
env:
TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
VERSION="${TAG#v}"
# Full SemVer 2.0: X.Y.Z, with an optional -prerelease and an
# optional +build-metadata segment (both may be present together).
if ! printf '%s' "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
echo "::error::Release tag '${TAG}' is not a valid version (expected vX.Y.Z)."
exit 1
fi
npm pkg set version="$VERSION"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Set package.json version = $VERSION"
- name: Build
run: pnpm build
- name: Pack and verify the published file set
id: pack
run: |
set -euo pipefail
pnpm pack --pack-destination /tmp/pack-check
tarball="$(ls /tmp/pack-check/*.tgz)"
echo "Packed: $tarball"
tar tzf "$tarball" | tee /tmp/pack-check/contents.txt
for f in package/dist/index.js package/dist/index.d.ts; do
if ! grep -qx "$f" /tmp/pack-check/contents.txt; then
echo "ERROR: expected file missing from published package: $f" >&2
exit 1
fi
done
echo "tarball=$(basename "$tarball")" >> "$GITHUB_OUTPUT"
- name: Dry-run publish (no auth, nothing uploaded)
run: npm publish "/tmp/pack-check/${{ steps.pack.outputs.tarball }}" --access public --dry-run
- name: Upload packed tarball
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: npm-tarball
path: /tmp/pack-check/${{ steps.pack.outputs.tarball }}
retention-days: 7
publish:
name: Publish to npm
needs: [build]
if: github.event_name == 'release'
runs-on: ubuntu-latest
# Manual approval gate: create this environment in
# Settings -> Environments with required reviewers, so every publish
# needs a human click even though the trigger (release published) is
# automatic. See "Maintainer setup" for the one-time steps.
environment: npm
permissions:
id-token: write # OIDC trusted publishing + provenance (no stored token)
contents: read
steps:
- name: Download packed tarball
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: npm-tarball
path: dist-pack/
- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
registry-url: "https://registry.npmjs.org"
# OIDC trusted publishing needs npm >= 11.5.1; Node 22 still ships 10.x.
- name: Upgrade npm for OIDC trusted publishing
run: npm install -g npm@latest
- name: Check if this version is already on npm
id: check_npm
shell: bash
run: |
set -euo pipefail
# Update this if the package is ever renamed — kept as a literal to
# avoid trusting the downloaded artifact's contents for this check.
NAME="@comfyorg/sdk"
# Use the exact version the build job injected into the packed
# tarball, not a second independent derivation from the ref — a
# divergence would let this "already published?" check test the
# wrong version and silently skip the real publish.
VER="${{ needs.build.outputs.version }}"
STATUS=0
OUTPUT=$(npm view "${NAME}@${VER}" --json 2>&1) || STATUS=$?
if [ "$STATUS" -eq 0 ]; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "::warning title=Already published::${NAME}@${VER} already exists on npm. Skipping publish."
elif echo "$OUTPUT" | grep -q "E404"; then
echo "exists=false" >> "$GITHUB_OUTPUT"
else
echo "::error title=Registry lookup failed::$OUTPUT" >&2
exit "$STATUS"
fi
# No NODE_AUTH_TOKEN: authentication is via npm Trusted Publishing (OIDC).
# `--provenance` is implied by trusted publishing but kept explicit.
- name: Publish to npm
if: steps.check_npm.outputs.exists == 'false'
shell: bash
run: |
set -euo pipefail
tarball="$(ls dist-pack/*.tgz)"
# Prefix with ./ so npm treats this as a local file path. Without it,
# "dist-pack/<file>.tgz" matches npm's "<owner>/<repo>" GitHub
# shorthand, so npm tries to git-fetch "github:dist-pack/<file>" and
# fails with EALLOWGIT instead of publishing the packed tarball.
npm publish "./${tarball}" --access public --provenance