Skip to content

Commit e3625d3

Browse files
committed
feat(release): automate GitHub Releases for LSP binaries and VSIX; refresh docs
1 parent e30f9c8 commit e3625d3

4 files changed

Lines changed: 442 additions & 200 deletions

File tree

.github/workflows/release.yml

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: "Release tag to publish (example: v0.1.9)"
11+
type: string
12+
required: true
13+
pre_release:
14+
description: "Mark GitHub release + VSIX as pre-release"
15+
type: boolean
16+
required: true
17+
default: true
18+
draft:
19+
description: "Create draft release"
20+
type: boolean
21+
required: true
22+
default: false
23+
24+
permissions:
25+
contents: write
26+
27+
jobs:
28+
prepare:
29+
runs-on: ubuntu-latest
30+
outputs:
31+
tag: ${{ steps.meta.outputs.tag }}
32+
prerelease: ${{ steps.meta.outputs.prerelease }}
33+
draft: ${{ steps.meta.outputs.draft }}
34+
steps:
35+
- name: Checkout (for tag validation)
36+
uses: actions/checkout@v4
37+
with:
38+
fetch-depth: 0
39+
40+
- id: meta
41+
shell: bash
42+
run: |
43+
set -euo pipefail
44+
45+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
46+
TAG="${{ inputs.tag }}"
47+
PRERELEASE="${{ inputs.pre_release }}"
48+
DRAFT="${{ inputs.draft }}"
49+
else
50+
TAG="${{ github.ref_name }}"
51+
if [[ "$TAG" == *"-"* ]]; then
52+
PRERELEASE="true"
53+
else
54+
PRERELEASE="false"
55+
fi
56+
DRAFT="false"
57+
fi
58+
59+
if [[ -z "$TAG" ]]; then
60+
echo "Release tag is required." >&2
61+
exit 1
62+
fi
63+
64+
if [[ ! "$TAG" =~ ^v ]]; then
65+
echo "Release tag must start with 'v' (received: $TAG)." >&2
66+
exit 1
67+
fi
68+
69+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
70+
if ! git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
71+
echo "Tag '$TAG' does not exist in the repository. Create and push it before running this workflow." >&2
72+
exit 1
73+
fi
74+
fi
75+
76+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
77+
echo "prerelease=$PRERELEASE" >> "$GITHUB_OUTPUT"
78+
echo "draft=$DRAFT" >> "$GITHUB_OUTPUT"
79+
80+
build-language-server:
81+
needs: prepare
82+
strategy:
83+
fail-fast: false
84+
matrix:
85+
include:
86+
- os: windows-latest
87+
rid: win-x64
88+
archive_ext: zip
89+
- os: ubuntu-latest
90+
rid: linux-x64
91+
archive_ext: tar.gz
92+
- os: macos-13
93+
rid: osx-x64
94+
archive_ext: tar.gz
95+
- os: macos-14
96+
rid: osx-arm64
97+
archive_ext: tar.gz
98+
runs-on: ${{ matrix.os }}
99+
steps:
100+
- name: Checkout
101+
uses: actions/checkout@v4
102+
103+
- name: Set up .NET
104+
uses: actions/setup-dotnet@v4
105+
with:
106+
dotnet-version: "10.0.x"
107+
108+
- name: Publish language server
109+
run: dotnet publish src/VbNet.LanguageServer.Vb/VbNet.LanguageServer.Vb.vbproj -c Release -r ${{ matrix.rid }} --self-contained false -o out/lsp/${{ matrix.rid }}
110+
111+
- name: Archive language server (Windows)
112+
if: runner.os == 'Windows'
113+
shell: pwsh
114+
run: |
115+
$ErrorActionPreference = 'Stop'
116+
New-Item -ItemType Directory -Path out/release -Force | Out-Null
117+
$archive = "out/release/vbnet-language-server-${{ matrix.rid }}.zip"
118+
Compress-Archive -Path "out/lsp/${{ matrix.rid }}/*" -DestinationPath $archive -Force
119+
120+
- name: Archive language server (Linux/macOS)
121+
if: runner.os != 'Windows'
122+
shell: bash
123+
run: |
124+
set -euo pipefail
125+
mkdir -p out/release
126+
tar -czf "out/release/vbnet-language-server-${{ matrix.rid }}.tar.gz" -C "out/lsp/${{ matrix.rid }}" .
127+
128+
- name: Upload language server artifact
129+
uses: actions/upload-artifact@v4
130+
with:
131+
name: vbnet-language-server-${{ matrix.rid }}
132+
path: out/release/vbnet-language-server-${{ matrix.rid }}.${{ matrix.archive_ext }}
133+
134+
build-vsix:
135+
needs: prepare
136+
runs-on: windows-latest
137+
steps:
138+
- name: Checkout
139+
uses: actions/checkout@v4
140+
141+
- name: Set up .NET
142+
uses: actions/setup-dotnet@v4
143+
with:
144+
dotnet-version: "10.0.x"
145+
146+
- name: Set up Node
147+
uses: actions/setup-node@v4
148+
with:
149+
node-version: "20"
150+
cache: npm
151+
cache-dependency-path: src/extension/package-lock.json
152+
153+
- name: Install extension dependencies
154+
working-directory: src/extension
155+
run: npm ci
156+
157+
- name: Cache Roslyn downloads
158+
uses: actions/cache@v4
159+
with:
160+
path: src/extension/.roslyn-downloads
161+
key: roslyn-downloads-${{ runner.os }}-${{ hashFiles('src/extension/scripts/copy-roslyn-server.js') }}
162+
163+
- name: Package VSIX files
164+
working-directory: src/extension
165+
shell: pwsh
166+
run: |
167+
$ErrorActionPreference = 'Stop'
168+
169+
npm run bundle-server
170+
npm run package
171+
172+
$targets = @("win32-x64", "linux-x64", "darwin-x64", "darwin-arm64")
173+
174+
foreach ($target in $targets) {
175+
npm run "bundle-roslyn:$target"
176+
npm run validate-roslyn
177+
npm run bundle-debugger -- --target "$target"
178+
179+
$vsix = "vbnet-language-support-$target.vsix"
180+
$vsceArgs = @("package", "--target", $target, "--out", $vsix)
181+
if ('${{ needs.prepare.outputs.prerelease }}' -eq 'true') {
182+
$vsceArgs += "--pre-release"
183+
}
184+
npx vsce @vsceArgs
185+
186+
if (-not (Test-Path $vsix)) {
187+
throw "VSIX not found at $vsix"
188+
}
189+
190+
$extract = Join-Path $env:TEMP ("vbnet-vsix-" + [guid]::NewGuid().ToString("N"))
191+
Expand-Archive -Path $vsix -DestinationPath $extract -Force
192+
$root = Join-Path $extract "extension"
193+
if (-not (Test-Path (Join-Path $root ".roslyn"))) { throw "Missing .roslyn in $vsix" }
194+
if (-not (Test-Path (Join-Path $root ".roslyn-vb"))) { throw "Missing .roslyn-vb in $vsix" }
195+
Remove-Item -Recurse -Force $extract
196+
}
197+
198+
- name: Upload VSIX artifacts
199+
uses: actions/upload-artifact@v4
200+
with:
201+
name: vsix-packages
202+
path: src/extension/vbnet-language-support-*.vsix
203+
204+
publish-release:
205+
needs:
206+
- prepare
207+
- build-language-server
208+
- build-vsix
209+
runs-on: ubuntu-latest
210+
steps:
211+
- name: Download language server artifacts
212+
uses: actions/download-artifact@v4
213+
with:
214+
pattern: vbnet-language-server-*
215+
merge-multiple: true
216+
path: out/release
217+
218+
- name: Download VSIX artifacts
219+
uses: actions/download-artifact@v4
220+
with:
221+
name: vsix-packages
222+
path: out/release
223+
224+
- name: Create GitHub release
225+
uses: softprops/action-gh-release@v2
226+
with:
227+
tag_name: ${{ needs.prepare.outputs.tag }}
228+
name: ${{ needs.prepare.outputs.tag }}
229+
draft: ${{ needs.prepare.outputs.draft == 'true' }}
230+
prerelease: ${{ needs.prepare.outputs.prerelease == 'true' }}
231+
generate_release_notes: true
232+
files: |
233+
out/release/*

0 commit comments

Comments
 (0)