Skip to content

Commit 5b4e63d

Browse files
authored
chore: add rc workflow (#3815)
1 parent c85c8fd commit 5b4e63d

1 file changed

Lines changed: 287 additions & 0 deletions

File tree

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
name: Publish @solana/web3.js (v3.x)
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
dry-run:
7+
description: 'Dry run (unchecked will publish to npm, push git tag, and create GitHub release)'
8+
required: true
9+
default: true
10+
type: boolean
11+
12+
permissions:
13+
contents: write
14+
id-token: write
15+
16+
# Prevent concurrent publishes
17+
concurrency:
18+
group: web3js-v3-publish
19+
cancel-in-progress: false
20+
21+
jobs:
22+
guard-branch:
23+
name: Guard allowed source branch for publish
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Fail if workflow_dispatch is not on v3.x
27+
run: |
28+
if [ "${{ github.ref }}" != "refs/heads/v3.x" ]; then
29+
echo "::error::Publish must be run from v3.x. Current ref: ${{ github.ref }}"
30+
exit 1
31+
fi
32+
33+
publish:
34+
name: Publish @solana/web3.js
35+
runs-on: ubuntu-latest
36+
needs: guard-branch
37+
env:
38+
NPM_CONFIG_PROVENANCE: true
39+
40+
steps:
41+
- name: Checkout repository
42+
uses: actions/checkout@v4
43+
with:
44+
fetch-depth: 0
45+
token: ${{ secrets.GITHUB_TOKEN }}
46+
47+
- name: Setup Git user
48+
run: |
49+
git config user.name "github-actions[bot]"
50+
git config user.email "github-actions[bot]@users.noreply.github.com"
51+
52+
- name: Setup pnpm
53+
uses: pnpm/action-setup@v4
54+
with:
55+
version: 9.1.0
56+
run_install: false
57+
58+
- name: Setup Node.js
59+
uses: actions/setup-node@v4
60+
with:
61+
node-version: 'lts/*'
62+
registry-url: 'https://registry.npmjs.org'
63+
cache: 'pnpm'
64+
65+
- name: Install dependencies
66+
run: pnpm install --frozen-lockfile
67+
68+
- name: Get version
69+
id: version
70+
run: |
71+
VERSION=$(node -p "require('./package.json').version")
72+
echo "version=$VERSION" >> $GITHUB_OUTPUT
73+
echo "Publishing version: $VERSION"
74+
75+
- name: Resolve npm dist-tag from version
76+
id: prerelease
77+
env:
78+
VERSION: ${{ steps.version.outputs.version }}
79+
run: |
80+
# SemVer: MAJOR.MINOR.PATCH[-IDENTIFIER[.N]]. Use the prerelease identifier
81+
# as the npm dist-tag (e.g. 3.0.0-rc.1 -> rc, 1.0.0-maintenance -> maintenance).
82+
# Stable versions publish under 'latest'.
83+
if [[ "$VERSION" == *"-"* ]]; then
84+
PRERELEASE="${VERSION#*-}"
85+
NPM_TAG="${PRERELEASE%%.*}"
86+
IS_PRERELEASE=true
87+
else
88+
NPM_TAG=latest
89+
IS_PRERELEASE=false
90+
fi
91+
92+
if [ -z "$NPM_TAG" ]; then
93+
echo "::error::Could not derive npm dist-tag from version '$VERSION'"
94+
exit 1
95+
fi
96+
97+
echo "npm_tag=$NPM_TAG" >> $GITHUB_OUTPUT
98+
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
99+
echo "Version: $VERSION | npm tag: $NPM_TAG | prerelease: $IS_PRERELEASE"
100+
101+
- name: Enforce code formatting
102+
run: pnpm test:prettier
103+
104+
- name: Compile types
105+
run: pnpm compile:typedefs
106+
107+
- name: Lint
108+
run: pnpm test:lint
109+
110+
- name: Build
111+
run: pnpm compile:js
112+
113+
- name: Run unit tests
114+
run: pnpm test:unit
115+
116+
- name: Pack tarball
117+
run: |
118+
mkdir -p .npm-pack
119+
# Mirror prepublishOnly: drop devDependencies before pack so tarball is clean.
120+
# pnpm pack does not run prepublishOnly, and we publish from the tarball below.
121+
pnpm pkg delete devDependencies
122+
pnpm pack --pack-destination .npm-pack
123+
echo ""
124+
echo "Packed tarball:"
125+
ls -la .npm-pack/
126+
# Restore package.json so later steps and the working tree are unaffected.
127+
git checkout -- package.json
128+
129+
- name: Guard - tarball contains required build artifacts
130+
run: |
131+
echo "Checking tarball for lib/ artifacts..."
132+
FAILED=0
133+
for tarball in .npm-pack/*.tgz; do
134+
CONTENTS=$(tar -tzf "$tarball")
135+
for f in \
136+
package/lib/index.cjs.js \
137+
package/lib/index.esm.js \
138+
package/lib/index.browser.cjs.js \
139+
package/lib/index.browser.esm.js \
140+
package/lib/index.native.js \
141+
package/lib/index.d.ts; do
142+
if ! echo "$CONTENTS" | grep -q "^${f}$"; then
143+
echo " ✗ ${tarball} missing ${f}"
144+
FAILED=1
145+
fi
146+
done
147+
done
148+
if [ "$FAILED" -eq 1 ]; then
149+
echo ""
150+
echo "Make sure 'pnpm compile:js' and 'pnpm compile:typedefs' ran successfully."
151+
exit 1
152+
fi
153+
echo " ✓ tarball contains all required lib/ artifacts"
154+
155+
- name: Guard - tarball does not include devDependencies
156+
run: |
157+
for tarball in .npm-pack/*.tgz; do
158+
tar -xzf "$tarball" package/package.json -O > /tmp/pkg.json
159+
if node -e "const p=require('/tmp/pkg.json'); process.exit(p.devDependencies && Object.keys(p.devDependencies).length ? 1 : 0)"; then
160+
echo " ✓ ${tarball} has no devDependencies"
161+
else
162+
echo " ✗ ${tarball} contains devDependencies"
163+
exit 1
164+
fi
165+
done
166+
167+
- name: Pre-flight - npm publish dry-run
168+
run: |
169+
VERSION="${{ steps.version.outputs.version }}"
170+
NPM_TAG="${{ steps.prerelease.outputs.npm_tag }}"
171+
TARBALL=".npm-pack/solana-web3.js-${VERSION}.tgz"
172+
173+
if [ ! -f "$TARBALL" ]; then
174+
echo "::error::Tarball not found: ${TARBALL}"
175+
ls -la .npm-pack/ || true
176+
exit 1
177+
fi
178+
179+
# Refuse to overwrite a published version.
180+
NPM_RC=0
181+
NPM_OUT=$(npm view "@solana/web3.js@${VERSION}" version 2>&1) || NPM_RC=$?
182+
if [ "$NPM_RC" -eq 0 ] && [ -n "$NPM_OUT" ]; then
183+
echo "::error::@solana/web3.js@${VERSION} is already published. Bump the version in package.json."
184+
exit 1
185+
fi
186+
if [ "$NPM_RC" -ne 0 ] && ! echo "$NPM_OUT" | grep -q "E404"; then
187+
echo "::error::npm registry error (not 404):"
188+
echo "$NPM_OUT"
189+
exit 1
190+
fi
191+
192+
echo "Running publish dry-run for ${TARBALL} (tag '${NPM_TAG}')..."
193+
npm publish "$TARBALL" --access public --tag "$NPM_TAG" --dry-run
194+
echo "✓ pre-flight passed"
195+
196+
- name: Publish to npm
197+
if: ${{ github.event.inputs.dry-run != 'true' }}
198+
run: |
199+
VERSION="${{ steps.version.outputs.version }}"
200+
NPM_TAG="${{ steps.prerelease.outputs.npm_tag }}"
201+
TARBALL=".npm-pack/solana-web3.js-${VERSION}.tgz"
202+
echo "Publishing ${TARBALL} with tag '${NPM_TAG}'..."
203+
npm publish "$TARBALL" --access public --tag "$NPM_TAG"
204+
echo "✓ published @solana/web3.js@${VERSION}"
205+
206+
- name: Create and push tag
207+
if: ${{ github.event.inputs.dry-run != 'true' }}
208+
run: |
209+
TAG="v${{ steps.version.outputs.version }}"
210+
if git rev-parse "$TAG" >/dev/null 2>&1; then
211+
echo "Tag $TAG already exists, skipping"
212+
else
213+
git tag "$TAG"
214+
git push origin "$TAG"
215+
echo "Created tag $TAG"
216+
fi
217+
218+
- name: Create GitHub Release
219+
if: ${{ github.event.inputs.dry-run != 'true' }}
220+
uses: actions/github-script@v7
221+
with:
222+
github-token: ${{ secrets.GITHUB_TOKEN }}
223+
script: |
224+
const version = `${{ steps.version.outputs.version }}`;
225+
const tagName = `v${version}`;
226+
const releaseName = `@solana/web3.js v${version}`;
227+
const isPrerelease = '${{ steps.prerelease.outputs.is_prerelease }}' === 'true';
228+
229+
const body = [
230+
`## @solana/web3.js v${version}`,
231+
'',
232+
'### Installation',
233+
'',
234+
'```bash',
235+
`pnpm add @solana/web3.js@${version}`,
236+
'```',
237+
'',
238+
`https://www.npmjs.com/package/@solana/web3.js/v/${version}`,
239+
].join('\n');
240+
241+
try {
242+
await github.rest.repos.getReleaseByTag({
243+
owner: context.repo.owner,
244+
repo: context.repo.repo,
245+
tag: tagName,
246+
});
247+
console.log(`Release ${tagName} already exists, skipping`);
248+
return;
249+
} catch (e) {
250+
if (e.status !== 404) throw e;
251+
}
252+
253+
await github.rest.repos.createRelease({
254+
owner: context.repo.owner,
255+
repo: context.repo.repo,
256+
tag_name: tagName,
257+
name: releaseName,
258+
body: body.trim(),
259+
draft: false,
260+
prerelease: isPrerelease,
261+
});
262+
console.log(`Created release: ${releaseName}`);
263+
264+
- name: Publish summary
265+
run: |
266+
VERSION="${{ steps.version.outputs.version }}"
267+
NPM_TAG="${{ steps.prerelease.outputs.npm_tag }}"
268+
DRY_RUN="${{ github.event.inputs.dry-run }}"
269+
270+
{
271+
echo "## @solana/web3.js v${VERSION}"
272+
echo ""
273+
echo "**Package**: \`@solana/web3.js\`"
274+
echo "**Version**: \`${VERSION}\`"
275+
echo "**npm tag**: \`${NPM_TAG}\`"
276+
echo ""
277+
} >> $GITHUB_STEP_SUMMARY
278+
279+
if [ "$DRY_RUN" == "true" ]; then
280+
echo "Mode: **dry run** (OIDC + tarball validated, nothing published)" >> $GITHUB_STEP_SUMMARY
281+
else
282+
{
283+
echo "Published to npm: https://www.npmjs.com/package/@solana/web3.js/v/${VERSION}"
284+
echo ""
285+
echo "GitHub release: https://github.com/${{ github.repository }}/releases/tag/v${VERSION}"
286+
} >> $GITHUB_STEP_SUMMARY
287+
fi

0 commit comments

Comments
 (0)