@@ -6,9 +6,22 @@ name: Release
66# notes from CHANGELOG.md). Each subproject's publish step is gated
77# on its own verify step.
88#
9- # Required secrets (set per subproject's environment):
9+ # Build vs. publish: the build/package steps always run and produce
10+ # universal artifacts — a fat VSIX bundling all 6 platform LSP binaries
11+ # and a single IntelliJ plugin zip that loads on every JetBrains IDE on
12+ # every OS. Publishing is OFF for tag pushes — a `git push origin v*`
13+ # only builds artifacts and attaches them to the GH Release. Registry
14+ # publishes run ONLY on a manual `workflow_dispatch` with `publish: true`
15+ # (re-run the same tag once tokens are configured, version unchanged).
16+ # Even then each publish is BEST-EFFORT: skipped when its token is unset
17+ # and marked `continue-on-error`, so a missing token, an Open VSX read-
18+ # only window, or a pending JetBrains first-upload moderation never
19+ # blocks the run or the artifact upload.
20+ #
21+ # Optional secrets (set per subproject's environment). Absent → that
22+ # registry publish is skipped, artifacts still ship to the GH Release:
1023# • crates-io → CARGO_REGISTRY_TOKEN
11- # • npm-vscode → VSCE_PAT, OVSX_PAT
24+ # • npm-vscode → VSCE_PAT (VS Code Marketplace) , OVSX_PAT (Open VSX)
1225# • intellij → INTELLIJ_PUBLISH_TOKEN
1326
1427on :
1831 workflow_dispatch :
1932 inputs :
2033 tag :
21- description : " Tag to publish (e.g. v0.1.0). Must already exist."
34+ description : " Tag to build/ publish (e.g. v0.1.0). Must already exist."
2235 required : true
36+ publish :
37+ description : " Publish to registries (crates.io / Marketplace / Open VSX / JetBrains). Tag pushes NEVER publish — they only build artifacts."
38+ type : boolean
39+ default : true
2340
2441permissions :
2542 contents : read
7592 needs : [verify-versions, lsp-binaries]
7693 runs-on : ubuntu-latest
7794 environment : crates-io
95+ env :
96+ # Job-level so the publish step's `if:` can detect whether the token
97+ # is configured (secrets are only visible to `if:` via the env context).
98+ CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
7899 defaults :
79100 run :
80101 working-directory : lsp
@@ -90,8 +111,12 @@ jobs:
90111 - run : cargo clippy --release --all-targets -- -D warnings
91112 - run : cargo test --release
92113 - name : cargo publish
93- env :
94- CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
114+ # Publishes only on a manual dispatch with publish=true; tag pushes
115+ # build only. Best-effort: skip without a token, and don't fail the
116+ # run if this version was already published. fmt/clippy/test above
117+ # still gate the build, so a genuinely broken crate blocks the run.
118+ if : ${{ github.event_name == 'workflow_dispatch' && inputs.publish && env.CARGO_REGISTRY_TOKEN != '' }}
119+ continue-on-error : true
95120 run : cargo publish
96121
97122 # ------------------------------------------------------------------
@@ -183,6 +208,11 @@ jobs:
183208 needs : [verify-versions, lsp-binaries]
184209 runs-on : ubuntu-latest
185210 environment : npm-vscode
211+ env :
212+ # Job-level so each publish step's `if:` can detect whether the token
213+ # is configured (secrets reach `if:` only through the env context).
214+ VSCE_PAT : ${{ secrets.VSCE_PAT }}
215+ OVSX_PAT : ${{ secrets.OVSX_PAT }}
186216 defaults :
187217 run :
188218 working-directory : vscode
@@ -202,14 +232,25 @@ jobs:
202232 - name : Organize binaries
203233 shell : bash
204234 run : |
205- mkdir -p ../vscode/bin/{linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64}
206- [ -d "binaries/ktav-lsp-linux-amd64" ] && cp binaries/ktav-lsp-linux-amd64/ktav-lsp ../vscode/bin/linux-x64/
207- [ -d "binaries/ktav-lsp-linux-arm64" ] && cp binaries/ktav-lsp-linux-arm64/ktav-lsp ../vscode/bin/linux-arm64/
208- [ -d "binaries/ktav-lsp-darwin-amd64" ] && cp binaries/ktav-lsp-darwin-amd64/ktav-lsp ../vscode/bin/darwin-x64/
209- [ -d "binaries/ktav-lsp-darwin-arm64" ] && cp binaries/ktav-lsp-darwin-arm64/ktav-lsp ../vscode/bin/darwin-arm64/
210- [ -d "binaries/ktav-lsp-windows-amd64.exe" ] && cp binaries/ktav-lsp-windows-amd64.exe/ktav-lsp.exe ../vscode/bin/win32-x64/
211- [ -d "binaries/ktav-lsp-windows-arm64.exe" ] && cp binaries/ktav-lsp-windows-arm64.exe/ktav-lsp.exe ../vscode/bin/win32-arm64/
212- ls -lhR ../vscode/bin/
235+ # `download-artifact` placed the artifacts at $GITHUB_WORKSPACE/binaries
236+ # (workspace-root relative — NOT relative to this step's vscode
237+ # working-directory). Each artifact dir holds ONE file named after the
238+ # asset (lsp-binaries stages it as `$asset`, not `ktav-lsp`). Copy each
239+ # into the platform dir the extension probes, renamed to `ktav-lsp[.exe]`.
240+ # Absolute $GITHUB_WORKSPACE paths avoid any cwd ambiguity; no `[ -d ]`
241+ # guards so a missing binary fails the release loudly instead of
242+ # silently shipping a partial (Windows-only) VSIX.
243+ B="$GITHUB_WORKSPACE/binaries"
244+ D="$GITHUB_WORKSPACE/vscode/bin"
245+ mkdir -p "$D"/{linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64}
246+ cp "$B/ktav-lsp-linux-amd64/ktav-lsp-linux-amd64" "$D/linux-x64/ktav-lsp"
247+ cp "$B/ktav-lsp-linux-arm64/ktav-lsp-linux-arm64" "$D/linux-arm64/ktav-lsp"
248+ cp "$B/ktav-lsp-darwin-amd64/ktav-lsp-darwin-amd64" "$D/darwin-x64/ktav-lsp"
249+ cp "$B/ktav-lsp-darwin-arm64/ktav-lsp-darwin-arm64" "$D/darwin-arm64/ktav-lsp"
250+ cp "$B/ktav-lsp-windows-amd64.exe/ktav-lsp-windows-amd64.exe" "$D/win32-x64/ktav-lsp.exe"
251+ cp "$B/ktav-lsp-windows-arm64.exe/ktav-lsp-windows-arm64.exe" "$D/win32-arm64/ktav-lsp.exe"
252+ chmod +x "$D/linux-x64/ktav-lsp" "$D/linux-arm64/ktav-lsp" "$D/darwin-x64/ktav-lsp" "$D/darwin-arm64/ktav-lsp"
253+ ls -lhR "$D"
213254
214255 - uses : actions/setup-node@v6
215256 with :
@@ -227,13 +268,25 @@ jobs:
227268 - name : Package .vsix
228269 run : npx vsce package --no-dependencies
229270 - name : Publish to VS Code Marketplace
230- env :
231- VSCE_PAT : ${{ secrets.VSCE_PAT }}
271+ # Publishes only on a manual dispatch with publish=true; tag pushes
272+ # build only. The Marketplace PAT requires an Azure DevOps org (behind
273+ # an Azure subscription wall) — when VSCE_PAT is unset the step skips
274+ # and the fat VSIX still ships as a GH Release artifact for manual
275+ # upload. continue-on-error keeps a failed publish from blocking the run.
276+ if : ${{ github.event_name == 'workflow_dispatch' && inputs.publish && env.VSCE_PAT != '' }}
277+ continue-on-error : true
232278 run : npx vsce publish --no-dependencies --pat "$VSCE_PAT"
233279 - name : Publish to Open VSX
234- env :
235- OVSX_PAT : ${{ secrets.OVSX_PAT }}
280+ # Publishes only on a manual dispatch with publish=true; tag pushes
281+ # build only. Skipped when OVSX_PAT is unset. continue-on-error so an
282+ # Open VSX read-only maintenance window, or a namespace not yet
283+ # created, doesn't fail the run — re-run later with
284+ # `ovsx publish ktav-<ver>.vsix --pat <token>` (no rebuild needed).
285+ if : ${{ github.event_name == 'workflow_dispatch' && inputs.publish && env.OVSX_PAT != '' }}
286+ continue-on-error : true
236287 run : npx ovsx publish --pat "$OVSX_PAT" *.vsix
288+ # The universal VSIX always ships, regardless of whether either publish
289+ # ran — this is the artifact for manual Marketplace / Open VSX upload.
237290 - uses : actions/upload-artifact@v5
238291 with :
239292 name : vscode-vsix
@@ -248,6 +301,10 @@ jobs:
248301 needs : [verify-versions, lsp-binaries]
249302 runs-on : ubuntu-latest
250303 environment : intellij
304+ env :
305+ # Job-level so the publish step's `if:` can detect whether the token
306+ # is configured (secrets reach `if:` only through the env context).
307+ INTELLIJ_PUBLISH_TOKEN : ${{ secrets.INTELLIJ_PUBLISH_TOKEN }}
251308 defaults :
252309 run :
253310 working-directory : intellij
@@ -267,14 +324,21 @@ jobs:
267324 - name : Organize binaries
268325 shell : bash
269326 run : |
270- mkdir -p ../intellij/bin/{linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64}
271- [ -d "binaries/ktav-lsp-linux-amd64" ] && cp binaries/ktav-lsp-linux-amd64/ktav-lsp ../intellij/bin/linux-x64/
272- [ -d "binaries/ktav-lsp-linux-arm64" ] && cp binaries/ktav-lsp-linux-arm64/ktav-lsp ../intellij/bin/linux-arm64/
273- [ -d "binaries/ktav-lsp-darwin-amd64" ] && cp binaries/ktav-lsp-darwin-amd64/ktav-lsp ../intellij/bin/darwin-x64/
274- [ -d "binaries/ktav-lsp-darwin-arm64" ] && cp binaries/ktav-lsp-darwin-arm64/ktav-lsp ../intellij/bin/darwin-arm64/
275- [ -d "binaries/ktav-lsp-windows-amd64.exe" ] && cp binaries/ktav-lsp-windows-amd64.exe/ktav-lsp.exe ../intellij/bin/win32-x64/
276- [ -d "binaries/ktav-lsp-windows-arm64.exe" ] && cp binaries/ktav-lsp-windows-arm64.exe/ktav-lsp.exe ../intellij/bin/win32-arm64/
277- ls -lhR ../intellij/bin/
327+ # Same as vscode-publish: artifacts live at $GITHUB_WORKSPACE/binaries
328+ # (workspace-root relative), each dir holding one file named after the
329+ # asset. Copy into the per-platform dir as `ktav-lsp[.exe]`. Absolute
330+ # paths avoid cwd ambiguity; fail loudly on any missing binary.
331+ B="$GITHUB_WORKSPACE/binaries"
332+ D="$GITHUB_WORKSPACE/intellij/bin"
333+ mkdir -p "$D"/{linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64}
334+ cp "$B/ktav-lsp-linux-amd64/ktav-lsp-linux-amd64" "$D/linux-x64/ktav-lsp"
335+ cp "$B/ktav-lsp-linux-arm64/ktav-lsp-linux-arm64" "$D/linux-arm64/ktav-lsp"
336+ cp "$B/ktav-lsp-darwin-amd64/ktav-lsp-darwin-amd64" "$D/darwin-x64/ktav-lsp"
337+ cp "$B/ktav-lsp-darwin-arm64/ktav-lsp-darwin-arm64" "$D/darwin-arm64/ktav-lsp"
338+ cp "$B/ktav-lsp-windows-amd64.exe/ktav-lsp-windows-amd64.exe" "$D/win32-x64/ktav-lsp.exe"
339+ cp "$B/ktav-lsp-windows-arm64.exe/ktav-lsp-windows-arm64.exe" "$D/win32-arm64/ktav-lsp.exe"
340+ chmod +x "$D/linux-x64/ktav-lsp" "$D/linux-arm64/ktav-lsp" "$D/darwin-x64/ktav-lsp" "$D/darwin-arm64/ktav-lsp"
341+ ls -lhR "$D"
278342
279343 - uses : actions/setup-java@v5
280344 with :
@@ -283,9 +347,18 @@ jobs:
283347 - uses : gradle/actions/setup-gradle@v4
284348 - run : ./gradlew test verifyPlugin buildPlugin --no-daemon
285349 - name : Publish to JetBrains Marketplace
286- env :
287- INTELLIJ_PUBLISH_TOKEN : ${{ secrets.INTELLIJ_PUBLISH_TOKEN }}
350+ # Publishes only on a manual dispatch with publish=true; tag pushes
351+ # build only. The FIRST version must be uploaded manually via
352+ # https://plugins.jetbrains.com/plugin/add and pass moderation before
353+ # token publishing works. Skipped when the token is unset, and
354+ # continue-on-error so a rejected/blocked publishPlugin doesn't fail
355+ # the run — the universal plugin zip ships as a GH Release artifact
356+ # for that manual first upload.
357+ if : ${{ github.event_name == 'workflow_dispatch' && inputs.publish && env.INTELLIJ_PUBLISH_TOKEN != '' }}
358+ continue-on-error : true
288359 run : ./gradlew publishPlugin --no-daemon
360+ # The universal plugin zip (loads on all JetBrains IDEs / all OSes,
361+ # bundling every platform LSP binary) always ships.
289362 - uses : actions/upload-artifact@v5
290363 with :
291364 name : intellij-zip
0 commit comments