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-
2526permissions :
2627 contents : write
2728
@@ -31,7 +32,8 @@ concurrency:
3132
3233jobs :
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 }}
0 commit comments