Skip to content

fix(git-id-switcher): replace broken Snyk badge with static shield (#… #159

fix(git-id-switcher): replace broken Snyk badge with static shield (#…

fix(git-id-switcher): replace broken Snyk badge with static shield (#… #159

Workflow file for this run

name: Publish Extension
on:
push:
tags:
- 'git-id-switcher-v*'
permissions: {}
jobs:
publish:
runs-on: ubuntu-latest
environment: production
# Prevent forks from publishing
if: github.repository == 'nullvariant/nullvariant-vscode-extensions'
permissions:
contents: write
id-token: write
attestations: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: block
allowed-endpoints: >
api.cloudflare.com:443
api.github.com:443
fulcio.sigstore.dev:443
ghcr.io:443
github.com:443
marketplace.visualstudio.com:443
oauth2.sigstore.dev:443
objects.githubusercontent.com:443
raw.githubusercontent.com:443
release-assets.githubusercontent.com:443
open-vsx.org:443
pkg-containers.githubusercontent.com:443
registry.npmjs.org:443
rekor.sigstore.dev:443
timestamp.sigstore.dev:443
tuf-repo-cdn.sigstore.dev:443
uploads.github.com:443
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: package-lock.json
# Install at root level for npm workspaces
- name: Install dependencies
run: npm ci
- name: Compile
run: npm run compile
working-directory: extensions/git-id-switcher
- name: Package extension
run: npm run package
working-directory: extensions/git-id-switcher
- name: Get version from tag
id: version
run: echo "version=${GITHUB_REF#refs/tags/git-id-switcher-v}" >> $GITHUB_OUTPUT
# Supply Chain Security: Trivy VSIX scan (post-package, pre-publish)
# Scans the packaged VSIX for known CVEs before any publishing step
# Downloads Trivy directly from GitHub Releases to avoid get.trivy.dev
# dependency (blocked by harden-runner egress policy)
- name: Scan VSIX with Trivy
env:
TRIVY_VERSION: '0.69.3'
run: |
curl -sfL -o trivy.tar.gz \
"https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
tar -xzf trivy.tar.gz trivy
chmod +x trivy
./trivy fs extensions/git-id-switcher \
--severity CRITICAL,HIGH \
--exit-code 1 \
--db-repository ghcr.io/aquasecurity/trivy-db:2
rm -f trivy trivy.tar.gz
# Supply Chain Security: Cosign keyless signing for VSIX
# Uses GitHub OIDC token (no secret key management required)
- name: Install Cosign
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
# SECURITY: Cosign signing failure aborts the entire release.
# Sigstore infrastructure is mature — failure indicates an anomaly.
- name: Sign VSIX with Cosign (keyless)
id: cosign-sign
run: |
VSIX_FILE="extensions/git-id-switcher/git-id-switcher-${{ steps.version.outputs.version }}.vsix"
VSIX_BASENAME=$(basename "$VSIX_FILE")
cosign sign-blob "$VSIX_FILE" \
--yes \
--bundle "extensions/git-id-switcher/${VSIX_BASENAME}.bundle"
echo "vsix_file=$VSIX_FILE" >> $GITHUB_OUTPUT
echo "bundle_file=extensions/git-id-switcher/${VSIX_BASENAME}.bundle" >> $GITHUB_OUTPUT
# Supply Chain Security: SBOM generation (CycloneDX via Syft)
- name: Generate SBOM (CycloneDX)
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
path: extensions/git-id-switcher
artifact-name: sbom-cyclonedx.json
output-file: extensions/git-id-switcher/sbom-cyclonedx.json
format: cyclonedx-json
# Supply Chain Security: SBOM attestation (signed with GitHub Attestation API)
- name: Attest SBOM
id: sbom-attest
continue-on-error: true
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: extensions/git-id-switcher/*.vsix
sbom-path: extensions/git-id-switcher/sbom-cyclonedx.json
- name: Warn if SBOM attestation failed
if: steps.sbom-attest.outcome == 'failure'
run: echo "::warning::SBOM attestation failed. The SBOM will be included in the release without attestation."
# SLSA Provenance: Generate attestation via GitHub Attestation API
# This creates verifiable build provenance for supply chain security
- name: Generate SLSA Provenance attestation
id: provenance
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-path: extensions/git-id-switcher/*.vsix
# Copy the provenance bundle to release assets for OpenSSF Scorecard detection
# The bundle is also stored in GitHub Attestation API for `gh attestation verify`
- name: Prepare provenance for release
run: |
BUNDLE_PATH="${{ steps.provenance.outputs.bundle-path }}"
DEST_PATH="extensions/git-id-switcher/git-id-switcher-${{ steps.version.outputs.version }}.vsix.intoto.jsonl"
if [ -z "$BUNDLE_PATH" ]; then
echo "::error::Provenance bundle path is empty"
exit 1
fi
if [ ! -f "$BUNDLE_PATH" ]; then
echo "::error::Provenance bundle file not found: $BUNDLE_PATH"
exit 1
fi
cp "$BUNDLE_PATH" "$DEST_PATH"
echo "Provenance bundle copied to: $DEST_PATH"
ls -la "$DEST_PATH"
- name: Upload VSIX artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: git-id-switcher-${{ steps.version.outputs.version }}.vsix
path: extensions/git-id-switcher/*.vsix
- name: Create GitHub Release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
files: |
extensions/git-id-switcher/*.vsix
extensions/git-id-switcher/*.intoto.jsonl
extensions/git-id-switcher/sbom-cyclonedx.json
extensions/git-id-switcher/*.vsix.bundle
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to VS Code Marketplace
if: ${{ vars.PUBLISH_TO_MARKETPLACE == 'true' }}
run: npx vsce publish --packagePath git-id-switcher-${{ steps.version.outputs.version }}.vsix -p ${{ secrets.VSCE_PAT }}
working-directory: extensions/git-id-switcher
- name: Publish to Open VSX
if: ${{ vars.PUBLISH_TO_OPENVSX == 'true' }}
run: npx ovsx publish git-id-switcher-${{ steps.version.outputs.version }}.vsix -p ${{ secrets.OVSX_PAT }}
working-directory: extensions/git-id-switcher
- name: Deploy documentation to R2
run: |
R2_BASE="kura/nullvariant.com/nullvariant-vscode-extensions"
EXT_PATH="extensions/git-id-switcher"
# Upload all language READMEs from docs/i18n/ (including en/)
for lang_dir in ${EXT_PATH}/docs/i18n/*/; do
lang=$(basename "$lang_dir")
echo "Deploying ${lang}/README.md..."
npx wrangler@4.54.0 r2 object put "${R2_BASE}/${EXT_PATH}/docs/i18n/${lang}/README.md" \
--file "${lang_dir}README.md" \
--content-type "text/markdown; charset=utf-8" \
--remote
done
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}