Skip to content

Commit 930d543

Browse files
authored
Automatically publish extension and add pre-release version (#624)
- Automatically publish the pre-release when pushing a `v*-pre` tag to `main`. - Automatically publish the stable release when pushing a `v*` tag to `main`. - Package VSIX on every PR and merge to main. For PRs, it is retained for 7 days, but for main it's retained indefinitely. - Skips publishing if the secret for that platform is not set. Closes #97
1 parent 9c884df commit 930d543

File tree

4 files changed

+317
-12
lines changed

4 files changed

+317
-12
lines changed

.github/workflows/ci.yaml

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: ci
1+
name: CI
22

33
on:
44
push:
@@ -11,6 +11,7 @@ on:
1111

1212
jobs:
1313
lint:
14+
name: Lint
1415
runs-on: ubuntu-22.04
1516

1617
steps:
@@ -19,6 +20,7 @@ jobs:
1920
- uses: actions/setup-node@v6
2021
with:
2122
node-version: "22"
23+
cache: "yarn"
2224

2325
- run: yarn
2426

@@ -29,6 +31,7 @@ jobs:
2931
- run: yarn build
3032

3133
test:
34+
name: Test
3235
runs-on: ubuntu-22.04
3336

3437
steps:
@@ -37,7 +40,61 @@ jobs:
3740
- uses: actions/setup-node@v6
3841
with:
3942
node-version: "22"
43+
cache: "yarn"
4044

4145
- run: yarn
4246

4347
- run: yarn test:ci
48+
49+
package:
50+
name: Package
51+
runs-on: ubuntu-22.04
52+
needs: [lint, test]
53+
steps:
54+
- uses: actions/checkout@v5
55+
56+
- uses: actions/setup-node@v6
57+
with:
58+
node-version: "22"
59+
cache: "yarn"
60+
61+
- name: Install dependencies
62+
run: |
63+
yarn
64+
npm install -g @vscode/vsce
65+
66+
- name: Get version from package.json
67+
id: version
68+
run: |
69+
VERSION=$(node -e "console.log(require('./package.json').version)")
70+
echo "version=$VERSION" >> $GITHUB_OUTPUT
71+
echo "Version: $VERSION"
72+
73+
- name: Setup package path
74+
id: setup
75+
run: |
76+
EXTENSION_NAME=$(node -e "console.log(require('./package.json').name)")
77+
# Add commit SHA for CI builds
78+
SHORT_SHA=$(git rev-parse --short HEAD)
79+
PACKAGE_NAME="${EXTENSION_NAME}-${{ steps.version.outputs.version }}-${SHORT_SHA}.vsix"
80+
echo "packageName=$PACKAGE_NAME" >> $GITHUB_OUTPUT
81+
82+
- name: Package extension
83+
run: vsce package --out "${{ steps.setup.outputs.packageName }}"
84+
85+
- name: Upload artifact (PR)
86+
if: github.event_name == 'pull_request'
87+
uses: actions/upload-artifact@v4
88+
with:
89+
name: extension-pr-${{ github.event.pull_request.number }}
90+
path: ${{ steps.setup.outputs.packageName }}
91+
if-no-files-found: error
92+
retention-days: 7
93+
94+
- name: Upload artifact (main)
95+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
96+
uses: actions/upload-artifact@v4
97+
with:
98+
name: extension-main-${{ github.sha }}
99+
path: ${{ steps.setup.outputs.packageName }}
100+
if-no-files-found: error

.github/workflows/pre-release.yaml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Pre-Release
2+
on:
3+
push:
4+
tags:
5+
- "v*-pre"
6+
7+
permissions:
8+
# Required to publish a release
9+
contents: write
10+
pull-requests: read
11+
12+
jobs:
13+
package:
14+
name: Package
15+
runs-on: ubuntu-22.04
16+
outputs:
17+
version: ${{ steps.version.outputs.version }}
18+
steps:
19+
- uses: actions/checkout@v5
20+
21+
- uses: actions/setup-node@v6
22+
with:
23+
node-version: "22"
24+
25+
- name: Extract version from tag
26+
id: version
27+
run: |
28+
# Extract version from tag (remove 'v' prefix and '-pre' suffix)
29+
TAG_NAME=${GITHUB_REF#refs/tags/v}
30+
VERSION=${TAG_NAME%-pre}
31+
echo "version=$VERSION" >> $GITHUB_OUTPUT
32+
echo "Pre-release version: $VERSION"
33+
34+
- name: Validate version matches package.json
35+
run: |
36+
TAG_VERSION="${{ steps.version.outputs.version }}"
37+
PACKAGE_VERSION=$(node -e "console.log(require('./package.json').version)")
38+
39+
if [ "$TAG_VERSION" != "$PACKAGE_VERSION" ]; then
40+
echo "Error: Tag version ($TAG_VERSION) does not match package.json version ($PACKAGE_VERSION)"
41+
echo "Please ensure the tag version matches the version in package.json"
42+
exit 1
43+
fi
44+
45+
echo "Version validation successful: $TAG_VERSION"
46+
47+
- name: Install dependencies
48+
run: |
49+
yarn
50+
npm install -g @vscode/vsce
51+
52+
- name: Setup package path
53+
id: setup
54+
run: |
55+
EXTENSION_NAME=$(node -e "console.log(require('./package.json').name)")
56+
PACKAGE_NAME="${EXTENSION_NAME}-${{ steps.version.outputs.version }}-pre.vsix"
57+
echo "packageName=$PACKAGE_NAME" >> $GITHUB_OUTPUT
58+
59+
- name: Package extension
60+
run: vsce package --pre-release --out "${{ steps.setup.outputs.packageName }}"
61+
62+
- name: Upload artifact
63+
uses: actions/upload-artifact@v4
64+
with:
65+
name: extension-${{ steps.version.outputs.version }}
66+
path: ${{ steps.setup.outputs.packageName }}
67+
if-no-files-found: error
68+
69+
publish:
70+
name: Publish Extension and Create Pre-Release
71+
needs: package
72+
uses: ./.github/workflows/publish-extension.yaml
73+
with:
74+
version: ${{ needs.package.outputs.version }}
75+
isPreRelease: true
76+
secrets:
77+
VSCE_PAT: ${{ secrets.VSCE_PAT }}
78+
OVSX_PAT: ${{ secrets.OVSX_PAT }}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: Publish Extension
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
version:
7+
required: true
8+
type: string
9+
description: "Version to publish"
10+
isPreRelease:
11+
required: false
12+
type: boolean
13+
default: false
14+
description: "Whether this is a pre-release"
15+
secrets:
16+
VSCE_PAT:
17+
required: false
18+
OVSX_PAT:
19+
required: false
20+
21+
jobs:
22+
setup:
23+
name: Setup
24+
runs-on: ubuntu-22.04
25+
outputs:
26+
packageName: ${{ steps.package.outputs.packageName }}
27+
hasVscePat: ${{ steps.check-secrets.outputs.hasVscePat }}
28+
hasOvsxPat: ${{ steps.check-secrets.outputs.hasOvsxPat }}
29+
steps:
30+
- uses: actions/checkout@v5
31+
32+
- uses: actions/setup-node@v6
33+
with:
34+
node-version: "22"
35+
36+
- name: Construct package name
37+
id: package
38+
run: |
39+
EXTENSION_NAME=$(node -e "console.log(require('./package.json').name)")
40+
if [ "${{ inputs.isPreRelease }}" = "true" ]; then
41+
PACKAGE_NAME="${EXTENSION_NAME}-${{ inputs.version }}-pre.vsix"
42+
else
43+
PACKAGE_NAME="${EXTENSION_NAME}-${{ inputs.version }}.vsix"
44+
fi
45+
echo "packageName=$PACKAGE_NAME" >> $GITHUB_OUTPUT
46+
echo "Package name: $PACKAGE_NAME"
47+
48+
- name: Check secrets
49+
id: check-secrets
50+
env:
51+
VSCE_PAT: ${{ secrets.VSCE_PAT }}
52+
OVSX_PAT: ${{ secrets.OVSX_PAT }}
53+
run: |
54+
echo "hasVscePat=$([ -n "$VSCE_PAT" ] && echo true || echo false)" >> $GITHUB_OUTPUT
55+
echo "hasOvsxPat=$([ -n "$OVSX_PAT" ] && echo true || echo false)" >> $GITHUB_OUTPUT
56+
57+
publishMS:
58+
name: Publish to VS Marketplace
59+
needs: setup
60+
runs-on: ubuntu-22.04
61+
if: ${{ needs.setup.outputs.hasVscePat == 'true' }}
62+
steps:
63+
- uses: actions/setup-node@v6
64+
with:
65+
node-version: "22"
66+
67+
- name: Install vsce
68+
run: npm install -g @vscode/vsce
69+
70+
- uses: actions/download-artifact@v5
71+
with:
72+
name: extension-${{ inputs.version }}
73+
74+
- name: Publish to VS Marketplace
75+
run: |
76+
echo "Publishing version ${{ inputs.version }} to VS Marketplace"
77+
if [ "${{ inputs.isPreRelease }}" = "true" ]; then
78+
vsce publish --pre-release --packagePath "./${{ needs.setup.outputs.packageName }}" -p ${{ secrets.VSCE_PAT }}
79+
else
80+
vsce publish --packagePath "./${{ needs.setup.outputs.packageName }}" -p ${{ secrets.VSCE_PAT }}
81+
fi
82+
83+
publishOVSX:
84+
name: Publish to Open VSX
85+
needs: setup
86+
runs-on: ubuntu-22.04
87+
if: ${{ needs.setup.outputs.hasOvsxPat == 'true' }}
88+
steps:
89+
- uses: actions/setup-node@v6
90+
with:
91+
node-version: "22"
92+
93+
- name: Install ovsx
94+
run: npm install -g ovsx
95+
96+
- uses: actions/download-artifact@v5
97+
with:
98+
name: extension-${{ inputs.version }}
99+
100+
- name: Publish to Open VSX
101+
run: |
102+
echo "Publishing version ${{ inputs.version }} to Open VSX"
103+
if [ "${{ inputs.isPreRelease }}" = "true" ]; then
104+
ovsx publish "./${{ needs.setup.outputs.packageName }}" --pre-release -p ${{ secrets.OVSX_PAT }}
105+
else
106+
ovsx publish "./${{ needs.setup.outputs.packageName }}" -p ${{ secrets.OVSX_PAT }}
107+
fi
108+
109+
publishGH:
110+
name: Create GitHub ${{ inputs.isPreRelease && 'Pre-' || '' }}Release
111+
needs: setup
112+
runs-on: ubuntu-22.04
113+
steps:
114+
- uses: actions/download-artifact@v5
115+
with:
116+
name: extension-${{ inputs.version }}
117+
118+
- name: Create ${{ inputs.isPreRelease && 'Pre-' || '' }}Release
119+
uses: marvinpinto/action-automatic-releases@latest
120+
with:
121+
repo_token: ${{ secrets.GITHUB_TOKEN }}
122+
prerelease: ${{ inputs.isPreRelease }}
123+
draft: true
124+
title: "${{ inputs.isPreRelease && 'Pre-' || '' }}Release v${{ inputs.version }}"
125+
files: ${{ needs.setup.outputs.packageName }}

.github/workflows/release.yaml

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,78 @@
1+
name: Release
12
on:
23
push:
34
tags:
45
- "v*"
5-
6-
name: release
6+
- "!v*-pre"
77

88
permissions:
99
# Required to publish a release
1010
contents: write
11-
pull-requests: "read"
11+
pull-requests: read
1212

1313
jobs:
1414
package:
15+
name: Package
1516
runs-on: ubuntu-22.04
17+
outputs:
18+
version: ${{ steps.version.outputs.version }}
1619
steps:
1720
- uses: actions/checkout@v5
1821

1922
- uses: actions/setup-node@v6
2023
with:
2124
node-version: "22"
2225

23-
- run: yarn
26+
- name: Extract version from tag
27+
id: version
28+
run: |
29+
# Extract version from tag (remove 'v' prefix)
30+
VERSION=${GITHUB_REF#refs/tags/v}
31+
echo "version=$VERSION" >> $GITHUB_OUTPUT
32+
echo "Release version: $VERSION"
33+
34+
- name: Validate version matches package.json
35+
run: |
36+
TAG_VERSION="${{ steps.version.outputs.version }}"
37+
PACKAGE_VERSION=$(node -e "console.log(require('./package.json').version)")
38+
39+
if [ "$TAG_VERSION" != "$PACKAGE_VERSION" ]; then
40+
echo "Error: Tag version ($TAG_VERSION) does not match package.json version ($PACKAGE_VERSION)"
41+
echo "Please ensure the tag version matches the version in package.json"
42+
exit 1
43+
fi
44+
45+
echo "Version validation successful: $TAG_VERSION"
2446
25-
- run: npx @vscode/vsce package
47+
- name: Install dependencies
48+
run: |
49+
yarn
50+
npm install -g @vscode/vsce
2651
27-
- uses: "marvinpinto/action-automatic-releases@latest"
52+
- name: Setup package path
53+
id: setup
54+
run: |
55+
EXTENSION_NAME=$(node -e "console.log(require('./package.json').name)")
56+
PACKAGE_NAME="${EXTENSION_NAME}-${{ steps.version.outputs.version }}.vsix"
57+
echo "packageName=$PACKAGE_NAME" >> $GITHUB_OUTPUT
58+
59+
- name: Package extension
60+
run: vsce package --out "${{ steps.setup.outputs.packageName }}"
61+
62+
- name: Upload artifact
63+
uses: actions/upload-artifact@v4
2864
with:
29-
repo_token: "${{ secrets.GITHUB_TOKEN }}"
30-
prerelease: false
31-
draft: true
32-
files: |
33-
*.vsix
65+
name: extension-${{ steps.version.outputs.version }}
66+
path: ${{ steps.setup.outputs.packageName }}
67+
if-no-files-found: error
68+
69+
publish:
70+
name: Publish Extension and Create Release
71+
needs: package
72+
uses: ./.github/workflows/publish-extension.yaml
73+
with:
74+
version: ${{ needs.package.outputs.version }}
75+
isPreRelease: false
76+
secrets:
77+
VSCE_PAT: ${{ secrets.VSCE_PAT }}
78+
OVSX_PAT: ${{ secrets.OVSX_PAT }}

0 commit comments

Comments
 (0)