Skip to content

Commit 2367883

Browse files
committed
feat: prepare v5 release candidate
- make snippet generation deterministic and persistence atomic - fix generated snippets, search behavior, settings, and documentation - add release gates, artifact checks, and prerelease migration guidance
1 parent adec087 commit 2367883

38 files changed

Lines changed: 1755 additions & 835 deletions

‎.github/workflows/release.yml‎

Lines changed: 126 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,25 @@ on:
44
workflow_dispatch:
55
inputs:
66
version:
7-
description: 'Version bump (or explicit semver, e.g. 5.0.0-rc.2)'
7+
description: 'Version bump (major/minor/patch) or explicit x.y.z version'
88
required: true
9-
default: 'prerelease'
9+
default: 'patch'
1010
type: string
11+
prerelease:
12+
description: 'Publish this numeric version to the prerelease channel'
13+
required: true
14+
default: false
15+
type: boolean
1116
target:
1217
description: 'Where to publish'
1318
required: true
14-
default: 'both'
19+
default: 'vsce'
1520
type: choice
1621
options:
1722
- both
1823
- vsce
1924
- ovsx
2025
- dry-run
21-
push:
22-
tags:
23-
- 'v*'
24-
2526
permissions:
2627
contents: write
2728

@@ -31,7 +32,8 @@ concurrency:
3132

3233
jobs:
3334
release:
34-
runs-on: r5n-m2-ultra
35+
if: github.ref_type == 'branch' && github.ref_name == 'develop'
36+
runs-on: ubuntu-latest
3537
steps:
3638
- uses: actions/checkout@v6
3739
with:
@@ -40,128 +42,183 @@ jobs:
4042

4143
- uses: oven-sh/setup-bun@v2
4244
with:
43-
bun-version: latest
45+
bun-version: 1.3.14
4446

4547
- name: Install
4648
run: bun install --frozen-lockfile
4749

50+
- name: Verify VS Code Marketplace credentials
51+
if: github.event.inputs.target == 'both' || github.event.inputs.target == 'vsce'
52+
env:
53+
VSCE_PAT: ${{ secrets.VSCE_PAT }}
54+
run: |
55+
set -euo pipefail
56+
if [ -z "$VSCE_PAT" ]; then
57+
echo "::error::VSCE_PAT is required for VS Code Marketplace publishing"
58+
exit 1
59+
fi
60+
bunx vsce verify-pat r5n
61+
62+
- name: Verify Open VSX credentials
63+
if: github.event.inputs.target == 'both' || github.event.inputs.target == 'ovsx'
64+
env:
65+
OVSX_PAT: ${{ secrets.OVSX_PAT }}
66+
run: |
67+
set -euo pipefail
68+
if [ -z "$OVSX_PAT" ]; then
69+
echo "::error::OVSX_PAT is required for Open VSX publishing"
70+
exit 1
71+
fi
72+
bunx ovsx verify-pat r5n
73+
74+
- name: Audit release dependencies
75+
run: bun run audit
76+
4877
- name: Lint
4978
run: bun run lint
5079

5180
- name: Typescript
5281
run: bun run typescript
5382

83+
- name: Test
84+
run: bun test
85+
86+
- name: Verify generated snippets
87+
run: bun run generate:check
88+
5489
- name: Configure git
55-
if: github.event_name == 'workflow_dispatch'
5690
run: |
5791
git config user.name "github-actions[bot]"
5892
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
5993
6094
- name: Bump version
61-
if: github.event_name == 'workflow_dispatch'
6295
id: bump
6396
env:
97+
RELEASE_BRANCH: ${{ github.ref_name }}
6498
VERSION_INPUT: ${{ github.event.inputs.version }}
6599
run: |
66100
set -euo pipefail
67-
if ! [[ "$VERSION_INPUT" =~ ^(major|minor|patch|prerelease|premajor|preminor|prepatch)$ ]] \
68-
&& ! [[ "$VERSION_INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
101+
if [ "${{ github.ref_type }}" != "branch" ] || [ "$RELEASE_BRANCH" != "develop" ]; then
102+
echo "::error::Releases must be dispatched from the develop branch"
103+
exit 1
104+
fi
105+
if ! [[ "$VERSION_INPUT" =~ ^(major|minor|patch)$ ]] \
106+
&& ! [[ "$VERSION_INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
69107
echo "::error::Invalid version input: $VERSION_INPUT"
70108
exit 1
71109
fi
110+
CURRENT_VERSION=$(node -p "require('./package.json').version")
72111
case "$VERSION_INPUT" in
73-
major|minor|patch|prerelease|premajor|preminor|prepatch)
74-
NEW_VERSION=$(npm version "$VERSION_INPUT" --no-git-tag-version --preid=rc | tr -d 'v')
112+
major|minor|patch)
113+
NEW_VERSION=$(npm version "$VERSION_INPUT" --no-git-tag-version | tr -d 'v')
75114
;;
76115
*)
77-
NEW_VERSION=$(npm version "$VERSION_INPUT" --no-git-tag-version | tr -d 'v')
116+
if [ "$VERSION_INPUT" = "$CURRENT_VERSION" ]; then
117+
NEW_VERSION="$CURRENT_VERSION"
118+
else
119+
NEW_VERSION=$(npm version "$VERSION_INPUT" --no-git-tag-version | tr -d 'v')
120+
fi
78121
;;
79122
esac
80123
printf 'version=%s\n' "$NEW_VERSION" >> "$GITHUB_OUTPUT"
81124
printf 'tag=v%s\n' "$NEW_VERSION" >> "$GITHUB_OUTPUT"
82-
git add package.json
83-
git commit -m "chore(release): v${NEW_VERSION}"
84-
git tag "v${NEW_VERSION}"
85-
86-
- name: Resolve version (tag push)
87-
if: github.event_name == 'push'
88-
id: tag
89-
run: |
90-
set -euo pipefail
91-
TAG="${GITHUB_REF#refs/tags/}"
92-
if ! [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
93-
echo "::error::Tag $TAG does not match v<semver>"
94-
exit 1
125+
if ! git diff --quiet -- package.json; then
126+
git add package.json
127+
git commit -m "chore(release): v${NEW_VERSION}"
95128
fi
96-
printf 'version=%s\n' "${TAG#v}" >> "$GITHUB_OUTPUT"
97-
printf 'tag=%s\n' "$TAG" >> "$GITHUB_OUTPUT"
98-
99-
- name: Set version output
100-
id: version
101-
env:
102-
DISPATCH_VERSION: ${{ steps.bump.outputs.version }}
103-
DISPATCH_TAG: ${{ steps.bump.outputs.tag }}
104-
TAG_VERSION: ${{ steps.tag.outputs.version }}
105-
TAG_TAG: ${{ steps.tag.outputs.tag }}
106-
run: |
107-
set -euo pipefail
108-
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
109-
printf 'version=%s\n' "$DISPATCH_VERSION" >> "$GITHUB_OUTPUT"
110-
printf 'tag=%s\n' "$DISPATCH_TAG" >> "$GITHUB_OUTPUT"
129+
if git rev-parse -q --verify "refs/tags/v${NEW_VERSION}" >/dev/null; then
130+
if [ "$(git rev-list -n 1 "v${NEW_VERSION}")" != "$(git rev-parse HEAD)" ]; then
131+
echo "::error::Tag v${NEW_VERSION} already points to another commit"
132+
exit 1
133+
fi
111134
else
112-
printf 'version=%s\n' "$TAG_VERSION" >> "$GITHUB_OUTPUT"
113-
printf 'tag=%s\n' "$TAG_TAG" >> "$GITHUB_OUTPUT"
135+
git tag "v${NEW_VERSION}"
114136
fi
115137
116-
- name: Compile
117-
run: bun run compile
118-
119-
- name: Package vsix
120-
run: bun run package
121-
122138
- name: Detect prerelease
123139
id: prerelease
124140
env:
125-
VERSION: ${{ steps.version.outputs.version }}
141+
DISPATCH_PRERELEASE: ${{ github.event.inputs.prerelease }}
126142
run: |
127143
set -euo pipefail
128-
if [[ "$VERSION" == *-* ]]; then
144+
if [ "$DISPATCH_PRERELEASE" = "true" ]; then
129145
printf 'flag=--pre-release\n' >> "$GITHUB_OUTPUT"
130146
printf 'is_prerelease=true\n' >> "$GITHUB_OUTPUT"
131147
else
132148
printf 'flag=\n' >> "$GITHUB_OUTPUT"
133149
printf 'is_prerelease=false\n' >> "$GITHUB_OUTPUT"
134150
fi
135151
152+
- name: Package vsix
153+
id: package
154+
env:
155+
PRERELEASE_FLAG: ${{ steps.prerelease.outputs.flag }}
156+
VERSION: ${{ steps.bump.outputs.version }}
157+
run: |
158+
set -euo pipefail
159+
VSIX_PATH="es-js-snippets-${VERSION}.vsix"
160+
if [ -n "$PRERELEASE_FLAG" ]; then
161+
bunx vsce package --pre-release --no-dependencies --out "$VSIX_PATH"
162+
else
163+
bunx vsce package --no-dependencies --out "$VSIX_PATH"
164+
fi
165+
test -f "$VSIX_PATH"
166+
sha256sum "$VSIX_PATH" > "${VSIX_PATH}.sha256"
167+
printf 'path=%s\n' "$VSIX_PATH" >> "$GITHUB_OUTPUT"
168+
printf 'checksum_path=%s.sha256\n' "$VSIX_PATH" >> "$GITHUB_OUTPUT"
169+
170+
- name: Upload packaged artifact
171+
uses: actions/upload-artifact@v7
172+
with:
173+
name: es-js-snippets-${{ steps.bump.outputs.version }}
174+
path: |
175+
${{ steps.package.outputs.path }}
176+
${{ steps.package.outputs.checksum_path }}
177+
if-no-files-found: error
178+
179+
- name: Push release commit and tag
180+
if: github.event.inputs.target != 'dry-run'
181+
env:
182+
BRANCH: ${{ github.ref_name }}
183+
RELEASE_TAG: ${{ steps.bump.outputs.tag }}
184+
run: |
185+
set -euo pipefail
186+
git push --atomic origin "HEAD:refs/heads/${BRANCH}" "refs/tags/${RELEASE_TAG}:refs/tags/${RELEASE_TAG}"
187+
136188
- name: Publish to VS Code Marketplace
137-
if: github.event_name == 'push' || github.event.inputs.target == 'both' || github.event.inputs.target == 'vsce'
189+
if: github.event.inputs.target == 'both' || github.event.inputs.target == 'vsce'
138190
env:
139191
VSCE_PAT: ${{ secrets.VSCE_PAT }}
140192
PRERELEASE_FLAG: ${{ steps.prerelease.outputs.flag }}
141-
run: bunx vsce publish $PRERELEASE_FLAG --no-dependencies
193+
VSIX_PATH: ${{ steps.package.outputs.path }}
194+
run: |
195+
if [ -n "$PRERELEASE_FLAG" ]; then
196+
bunx vsce publish --pre-release --packagePath "$VSIX_PATH" --skip-duplicate
197+
else
198+
bunx vsce publish --packagePath "$VSIX_PATH" --skip-duplicate
199+
fi
142200
143201
- name: Publish to Open VSX
144-
if: github.event_name == 'push' || github.event.inputs.target == 'both' || github.event.inputs.target == 'ovsx'
202+
if: github.event.inputs.target == 'both' || github.event.inputs.target == 'ovsx'
145203
env:
146204
OVSX_PAT: ${{ secrets.OVSX_PAT }}
147205
PRERELEASE_FLAG: ${{ steps.prerelease.outputs.flag }}
148-
run: bunx ovsx publish $PRERELEASE_FLAG --no-dependencies
149-
150-
- name: Push commit + tag
151-
if: github.event_name == 'workflow_dispatch' && github.event.inputs.target != 'dry-run'
152-
env:
153-
RELEASE_TAG: ${{ steps.version.outputs.tag }}
206+
VSIX_PATH: ${{ steps.package.outputs.path }}
154207
run: |
155-
set -euo pipefail
156-
git push origin HEAD
157-
git push origin "$RELEASE_TAG"
208+
if [ -n "$PRERELEASE_FLAG" ]; then
209+
bunx ovsx publish "$VSIX_PATH" --pre-release --skip-duplicate
210+
else
211+
bunx ovsx publish "$VSIX_PATH" --skip-duplicate
212+
fi
158213
159214
- name: Create GitHub Release
160215
if: github.event.inputs.target != 'dry-run'
161216
uses: softprops/action-gh-release@v3
162217
with:
163-
tag_name: ${{ steps.version.outputs.tag }}
164-
name: ${{ steps.version.outputs.tag }}
218+
tag_name: ${{ steps.bump.outputs.tag }}
219+
name: ${{ steps.bump.outputs.tag }}
165220
prerelease: ${{ steps.prerelease.outputs.is_prerelease }}
166221
generate_release_notes: true
167-
files: '*.vsix'
222+
files: |
223+
${{ steps.package.outputs.path }}
224+
${{ steps.package.outputs.checksum_path }}

‎.github/workflows/typescript_and_lint.yml‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: Typescript & lint
22

3+
permissions:
4+
contents: read
5+
36
on:
47
push:
58
branches:
@@ -14,7 +17,7 @@ concurrency:
1417

1518
jobs:
1619
lint:
17-
runs-on: r5n-m2-ultra
20+
runs-on: ubuntu-latest
1821
steps:
1922
- uses: actions/checkout@v6
2023

@@ -25,8 +28,17 @@ jobs:
2528
- name: Install
2629
run: bun install --frozen-lockfile
2730

31+
- name: Audit dependencies
32+
run: bun run audit
33+
2834
- name: Lint
2935
run: bun run lint
3036

3137
- name: Typescript
3238
run: bun run typescript
39+
40+
- name: Test
41+
run: bun test
42+
43+
- name: Verify generated snippets
44+
run: bun run generate:check

‎.oxfmtrc.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"ignorePatterns": [
1313
"lib/**",
1414
"node_modules/**",
15-
"src/snippets/generated.json",
15+
"src/snippets/generated.code-snippets",
1616
"*.vsix",
1717
"bun.lock",
1818
"yarn.lock"

‎.oxlintrc.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@
5050
"lib/",
5151
"node_modules/",
5252
"*.vsix",
53-
"src/snippets/generated.json"
53+
"src/snippets/generated.code-snippets"
5454
]
5555
}

‎.vscode/extensions.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"recommendations": ["ms-vscode.vscode-typescript-tslint-plugin"]
2+
"recommendations": ["oxc.oxc-vscode"]
33
}

‎.vscode/launch.json‎

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,8 @@
77
"request": "launch",
88
"runtimeExecutable": "${execPath}",
99
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
10-
"outFiles": ["${workspaceFolder}/out/**/*.js"],
11-
"preLaunchTask": "npm: watch"
12-
},
13-
{
14-
"name": "Extension Tests",
15-
"type": "extensionHost",
16-
"request": "launch",
17-
"runtimeExecutable": "${execPath}",
18-
"args": [
19-
"--extensionDevelopmentPath=${workspaceFolder}",
20-
"--extensionTestsPath=${workspaceFolder}/out/test"
21-
],
22-
"outFiles": ["${workspaceFolder}/out/test/**/*.js"],
23-
"preLaunchTask": "npm: watch"
10+
"outFiles": ["${workspaceFolder}/lib/**/*.js"],
11+
"preLaunchTask": "watch"
2412
}
2513
]
2614
}

‎.vscode/tasks.json‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
"version": "2.0.0",
33
"tasks": [
44
{
5-
"type": "npm",
6-
"script": "watch",
5+
"label": "watch",
6+
"type": "process",
7+
"command": "bun",
8+
"args": ["run", "watch"],
79
"problemMatcher": "$tsc-watch",
810
"isBackground": true,
911
"presentation": {

‎.vscodeignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
.gitignore
55
.vscode/**
66
docs/**
7+
scripts/**
78
src/**
9+
tests/**
810

911
# package manager / lockfiles
1012
bun.lock

0 commit comments

Comments
 (0)