From f8720d83be9a2397ff5b9c81f09e8bba422a39d7 Mon Sep 17 00:00:00 2001 From: Dmitrii Smirnov Date: Mon, 19 Oct 2026 19:47:38 +0300 Subject: [PATCH 1/2] Build darwin-x64 releases on the macos-15-intel runner The commented-out leg pointed at macos-13, which GitHub retired on 2025-12-04, so it queued forever. macos-15-intel is the standard-runner Intel label for public repos: the leg builds natively (can_execute runs the real smoke test) with a longer per-leg timeout for the slower 4-core Intel release build. PLATFORM_COUNT rises to 6 to match. Publish-side jobs (marketplace, open-vsx, brew, scoop, pages) are guarded to the canonical repo so fork releases stay green without the publish secrets; the GitHub Release assets upload unchanged. Homebrew rendering still excludes darwin-x64 deliberately (verify-package-manifests.mjs) and only runs on the canonical repo. --- .github/workflows/release.yml | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0a38cb32..110b12ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,7 +80,7 @@ jobs: name: Build VSIX (${{ matrix.platform }}) needs: version runs-on: "${{ matrix.os }}" - timeout-minutes: 45 + timeout-minutes: "${{ matrix.timeout_minutes || 45 }}" strategy: fail-fast: false matrix: @@ -97,11 +97,16 @@ jobs: os: macos-15 rust_target: aarch64-apple-darwin can_execute: true - # This just spins forever on GitHub's hosted runners - # - platform: darwin-x64 - # os: macos-13 - # rust_target: x86_64-apple-darwin - # can_execute: true + # macos-13 was retired 2025-12-04, so the old leg queued forever; + # macos-15-intel is GitHub's standard-runner Intel label for public + # repos, making this a NATIVE build (can_execute: true runs the real + # smoke test). 4 Intel cores compile the Rust release build slower + # than the ARM runners, hence the longer per-leg timeout. + - platform: darwin-x64 + os: macos-15-intel + rust_target: x86_64-apple-darwin + can_execute: true + timeout_minutes: 60 - platform: win32-x64 os: windows-latest rust_target: x86_64-pc-windows-msvc @@ -319,7 +324,7 @@ jobs: env: # Kept beside the build-vsix matrix: adding a platform there without # updating this count fails the release loudly instead of shipping short. - PLATFORM_COUNT: '5' + PLATFORM_COUNT: '6' # Hyphenated SemVer tags (v0.2.0-rc.1, v0.2.0-beta) are marked prerelease so # they never become the "Latest release". [DIST-RELEASE] [DIST-RELEASE] - name: Create GitHub release @@ -346,6 +351,11 @@ jobs: deploy-pages: name: Deploy website to GitHub Pages needs: release + # Publish-side jobs run ONLY on the canonical repo: forks carry neither the + # publish secrets nor the Pages setup, and the GitHub Release assets (the + # part forks DO want) are already uploaded by `release`. Guarding instead of + # deleting keeps this workflow upstream-compatible. + if: github.repository == 'Nimblesite/SharpLsp' permissions: contents: read pages: write @@ -358,6 +368,7 @@ jobs: needs: - version - release + if: github.repository == 'Nimblesite/SharpLsp' runs-on: ${{ vars.UBUNTU_RUNNER || 'ubuntu-latest' }} # 20m: allows retry-with-backoff on transient Marketplace 5xx failures. timeout-minutes: 20 @@ -479,7 +490,7 @@ jobs: needs: - version - release - if: "${{ !contains(github.ref_name, '-') }}" + if: "${{ github.repository == 'Nimblesite/SharpLsp' && !contains(github.ref_name, '-') }}" runs-on: ${{ vars.UBUNTU_RUNNER || 'ubuntu-latest' }} timeout-minutes: 10 permissions: @@ -539,7 +550,7 @@ jobs: needs: - version - release - if: "${{ !contains(github.ref_name, '-') }}" + if: "${{ github.repository == 'Nimblesite/SharpLsp' && !contains(github.ref_name, '-') }}" runs-on: ${{ vars.UBUNTU_RUNNER || 'ubuntu-latest' }} timeout-minutes: 10 permissions: @@ -597,6 +608,7 @@ jobs: needs: - version - release + if: github.repository == 'Nimblesite/SharpLsp' runs-on: ${{ vars.UBUNTU_RUNNER || 'ubuntu-latest' }} # 20m: allows retry-with-backoff on transient Open VSX 5xx failures # (observed: 503 Service Unavailable mid-batch on 2026-08-29). From 5d488f7ab02e7a4b81b4ab811e769ac14f43e67d Mon Sep 17 00:00:00 2001 From: Dmitrii Smirnov Date: Mon, 19 Oct 2026 20:22:12 +0300 Subject: [PATCH 2/2] Scope fork publish guards to steps, not jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit security-gates.test.mjs implements [DIST-CI-AUDIT]: publish-marketplace and publish-openvsx must carry no job-level if, so publishing can never bypass the audited release dependency. Move the canonical-repo scoping onto the credential-holding steps instead — on forks the jobs still run and still require the audited release, but sign in to nothing and publish nothing. All 14 gate tests pass locally. --- .github/workflows/release.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 110b12ba..b6048aea 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -368,7 +368,6 @@ jobs: needs: - version - release - if: github.repository == 'Nimblesite/SharpLsp' runs-on: ${{ vars.UBUNTU_RUNNER || 'ubuntu-latest' }} # 20m: allows retry-with-backoff on transient Marketplace 5xx failures. timeout-minutes: 20 @@ -396,6 +395,12 @@ jobs: # authorization is Marketplace publisher membership — hence # allow-no-subscriptions. - uses: azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906 # v3.1.0 + # STEP-level repo scoping, never job-level: security-gates.test.mjs + # asserts this job has no job-level `if`, so publishing can never bypass + # its audited `release` dependency. On forks the job still runs (and + # still requires the audited release) but has no Entra credentials, so + # only the credential-holding steps are scoped to the canonical repo. + if: github.repository == 'Nimblesite/SharpLsp' with: client-id: "${{ secrets.AZURE_CLIENT_ID }}" tenant-id: "${{ secrets.AZURE_TENANT_ID }}" @@ -412,6 +417,7 @@ jobs: # hyphenated tag is published with --pre-release (the VSIX is packaged with # --pre-release in the Makefile for hyphenated versions). - name: Publish each platform VSIX (Entra OIDC, no PAT) + if: github.repository == 'Nimblesite/SharpLsp' shell: bash run: | set -euo pipefail @@ -608,7 +614,6 @@ jobs: needs: - version - release - if: github.repository == 'Nimblesite/SharpLsp' runs-on: ${{ vars.UBUNTU_RUNNER || 'ubuntu-latest' }} # 20m: allows retry-with-backoff on transient Open VSX 5xx failures # (observed: 503 Service Unavailable mid-batch on 2026-08-29). @@ -630,6 +635,10 @@ jobs: # latest release at publish time, inside the job that holds the token — a # supply-chain risk. Bump deliberately. Secret: OPEN_VSX_PAT. - name: Publish to Open VSX Registry + # Step-level repo scoping, same invariant as publish-marketplace: the + # job keeps its unconditional audited-release gating, only the + # PAT-holding step is scoped to the canonical repo. + if: github.repository == 'Nimblesite/SharpLsp' env: OVSX_PAT: "${{ secrets.OPEN_VSX_PAT }}" shell: bash