Skip to content

Commit 620fc69

Browse files
improvement(cli): automate npm package version bumps
1 parent ea6a6c2 commit 620fc69

5 files changed

Lines changed: 344 additions & 16 deletions

File tree

.github/workflows/publish-sim-cli.yml

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ permissions:
1111

1212
concurrency:
1313
group: publish-sim-cli-${{ github.ref }}
14-
cancel-in-progress: true
14+
cancel-in-progress: false
1515

1616
jobs:
1717
publish-npm:
@@ -50,6 +50,9 @@ jobs:
5050
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
5151
run: bun pm whoami
5252

53+
- name: Auto-bump package version
54+
run: bun run bump:npm-packages sim-cli
55+
5356
- name: Run tests
5457
working-directory: packages/sim-cli
5558
run: bun run test
@@ -115,35 +118,25 @@ jobs:
115118
tar -xzf "$PACKAGE_PATH" -C "$SMOKE_DIR"
116119
"$SMOKE_DIR/package/dist/index.js" --version
117120
118-
- name: Check if version already exists
119-
id: version_check
121+
- name: Verify version is unpublished
120122
working-directory: packages/sim-cli
121123
env:
122124
VERSION: ${{ steps.release.outputs.version }}
123125
run: |
124126
if bun pm view "sim@$VERSION" version > /dev/null 2>&1; then
125-
echo "exists=true" >> "$GITHUB_OUTPUT"
126-
else
127-
echo "exists=false" >> "$GITHUB_OUTPUT"
127+
echo "sim@$VERSION is already published. The automatic version bump did not produce a unique release." >&2
128+
exit 1
128129
fi
129130
130131
- name: Publish to npm
131-
if: steps.version_check.outputs.exists == 'false'
132132
working-directory: packages/sim-cli
133133
env:
134134
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
135135
NPM_TAG: ${{ steps.release.outputs.tag }}
136136
run: bun publish --access public --tag "$NPM_TAG" --no-save
137137

138138
- name: Summarize release
139-
if: steps.version_check.outputs.exists == 'false'
140139
env:
141140
VERSION: ${{ steps.release.outputs.version }}
142141
NPM_TAG: ${{ steps.release.outputs.tag }}
143142
run: echo "Published sim@$VERSION with the '$NPM_TAG' tag."
144-
145-
- name: Summarize skipped release
146-
if: steps.version_check.outputs.exists == 'true'
147-
env:
148-
VERSION: ${{ steps.release.outputs.version }}
149-
run: echo "Skipped sim@$VERSION because that version is already published."

.github/workflows/publish-sim-setup.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ jobs:
5555
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
5656
run: bun pm whoami
5757

58+
- name: Auto-bump package version
59+
run: bun run bump:npm-packages sim-setup
60+
5861
- name: Check generated deployment config
5962
run: bun run deployment-config:check
6063

@@ -156,7 +159,7 @@ jobs:
156159
VERSION: ${{ steps.release.outputs.version }}
157160
run: |
158161
if bun pm view "sim-setup@$VERSION" version > /dev/null 2>&1; then
159-
echo "sim-setup@$VERSION is already published. Bump packages/sim-setup/package.json before releasing another build." >&2
162+
echo "sim-setup@$VERSION is already published. The automatic version bump did not produce a unique release." >&2
160163
exit 1
161164
fi
162165

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
"dev:sockets": "cd apps/realtime && bun run dev",
1515
"dev:full": "bunx concurrently -n \"App,Realtime\" -c \"cyan,magenta\" \"cd apps/sim && bun run dev\" \"cd apps/realtime && bun run dev\"",
1616
"dev:full:capped": "bunx concurrently -n \"App,Realtime\" -c \"cyan,magenta\" \"cd apps/sim && bun run dev:capped\" \"cd apps/realtime && bun run dev\"",
17-
"test": "bun run test:setup && bun run test:icon-path-precision && bun run test:tool-registry-boundary && bun run test:tool-request-boundary && bun run test:generators && turbo run test",
17+
"test": "bun run test:setup && bun run test:npm-package-versions && bun run test:icon-path-precision && bun run test:tool-registry-boundary && bun run test:tool-request-boundary && bun run test:generators && turbo run test",
1818
"test:setup": "bun run --cwd packages/sim-setup test",
19+
"test:npm-package-versions": "bunx vitest run scripts/bump-npm-package-versions.test.ts",
1920
"test:icon-path-precision": "bunx vitest run scripts/check-icon-path-precision.test.ts",
2021
"test:tool-registry-boundary": "bunx vitest run scripts/check-tool-registry-boundary.test.ts",
2122
"test:tool-request-boundary": "bunx vitest run scripts/check-tool-request-boundary.test.ts",
@@ -93,6 +94,7 @@
9394
"library:covers": "bun run scripts/generate-library-covers.tsx",
9495
"library:covers:check": "bun run scripts/generate-library-covers.tsx --check",
9596
"skills:sync": "bun run scripts/sync-skills.ts",
97+
"bump:npm-packages": "bun run scripts/bump-npm-package-versions.ts",
9698
"sim": "bun run packages/sim-cli/src/index.ts",
9799
"sim-setup": "bun run packages/sim-setup/src/index.ts",
98100
"agent-stream-docs:generate": "bun run scripts/sync-agent-stream-docs.ts",
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { describe, expect, it } from 'vitest'
2+
import {
3+
resolveNextStableVersion,
4+
updateLockfileWorkspaceVersion,
5+
} from './bump-npm-package-versions'
6+
7+
describe('resolveNextStableVersion', () => {
8+
it('increments the highest published stable patch and ignores prereleases', () => {
9+
expect(
10+
resolveNextStableVersion('2.1.2', [
11+
'2.1.3-preview.10.1',
12+
'1.9.9',
13+
'2.1.2',
14+
'2.1.3-dev.11.1',
15+
'2.0.8',
16+
])
17+
).toBe('2.1.3')
18+
})
19+
20+
it('preserves a higher unpublished manifest version', () => {
21+
expect(resolveNextStableVersion('3.0.0', ['2.1.2', '2.1.3-preview.10.1'])).toBe('3.0.0')
22+
})
23+
24+
it('advances from the registry when the manifest is stale', () => {
25+
expect(resolveNextStableVersion('1.5.0', ['2.0.0', '2.1.2'])).toBe('2.1.3')
26+
})
27+
28+
it('fails on a prerelease manifest or a registry without a stable version', () => {
29+
expect(() => resolveNextStableVersion('2.1.3-preview.1', ['2.1.2'])).toThrow(
30+
"Manifest version must be a stable X.Y.Z version, got '2.1.3-preview.1'"
31+
)
32+
expect(() => resolveNextStableVersion('2.1.3', ['2.1.3-preview.1'])).toThrow(
33+
'npm returned no published stable versions'
34+
)
35+
})
36+
})
37+
38+
describe('updateLockfileWorkspaceVersion', () => {
39+
const lockfile = `{
40+
"workspaces": {
41+
"packages/sim-cli": {
42+
"name": "sim",
43+
"version": "2.1.2",
44+
},
45+
"packages/sim-setup": {
46+
"name": "sim-setup",
47+
"version": "1.0.2",
48+
},
49+
},
50+
}`
51+
52+
it('updates only the selected workspace', () => {
53+
const next = updateLockfileWorkspaceVersion(
54+
lockfile,
55+
'packages/sim-cli',
56+
'sim',
57+
'2.1.2',
58+
'2.1.3'
59+
)
60+
61+
expect(next).toContain('"version": "2.1.3"')
62+
expect(next).toContain('"version": "1.0.2"')
63+
expect(next).not.toContain('"version": "2.1.2"')
64+
})
65+
66+
it('fails when the lockfile disagrees with the manifest', () => {
67+
expect(() =>
68+
updateLockfileWorkspaceVersion(lockfile, 'packages/sim-cli', 'sim', '2.1.1', '2.1.3')
69+
).toThrow("bun.lock must contain exactly one sim@2.1.1 entry in 'packages/sim-cli'")
70+
})
71+
})

0 commit comments

Comments
 (0)