mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 04:10:47 +02:00
Use an allowed local file URL for the browser smoke test, centralize keyless archive signing after native builds so Windows ARM64 does not require an unavailable Cosign binary, and advance the immutable bootstrap channel to RC2.
202 lines
8.8 KiB
YAML
202 lines
8.8 KiB
YAML
name: Release runtime artifacts
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- v2.0.0
|
|
- v2.0.0-rc.*
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: runtime-release-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
build:
|
|
name: Build ${{ matrix.target }}
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
attestations: write
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- os: macos-15
|
|
target: darwin-arm64
|
|
capabilities: browser,browser-visible,design,pdf,diagram,ios
|
|
- os: macos-15-intel
|
|
target: darwin-x64
|
|
capabilities: browser,browser-visible,design,pdf,diagram,ios
|
|
- os: ubuntu-24.04-arm
|
|
target: linux-arm64
|
|
capabilities: browser,browser-visible,design,pdf,diagram
|
|
- os: ubuntu-24.04
|
|
target: linux-x64
|
|
capabilities: browser,browser-visible,design,pdf,diagram
|
|
- os: windows-11-arm
|
|
target: windows-arm64
|
|
capabilities: browser,browser-visible,design,pdf,diagram
|
|
- os: windows-2025
|
|
target: windows-x64
|
|
capabilities: browser,browser-visible,design,pdf,diagram
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 35
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
with:
|
|
bun-version: 1.3.14
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
|
with:
|
|
node-version: 22.23.1
|
|
- name: Install frozen dependencies
|
|
run: bun install --frozen-lockfile --ignore-scripts
|
|
shell: bash
|
|
|
|
- name: Build and stage the complete managed runtime
|
|
env:
|
|
GSTACK_HOME: ${{ runner.temp }}/gstack-release-home
|
|
TARGET: ${{ matrix.target }}
|
|
CAPABILITIES: ${{ matrix.capabilities }}
|
|
run: |
|
|
set -euo pipefail
|
|
node runtime/install.js \
|
|
--source "$GITHUB_WORKSPACE" \
|
|
--home "$GSTACK_HOME" \
|
|
--version 2.0.0 \
|
|
--install-now \
|
|
--yes \
|
|
--capabilities "$CAPABILITIES"
|
|
active_slot=$(node -e 'const fs=require("fs"),p=process.argv[1];const v=JSON.parse(fs.readFileSync(p,"utf8")).current;if(typeof v!=="string"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(v))process.exit(1);process.stdout.write(v)' "$GSTACK_HOME/versions/current.json")
|
|
active="$GSTACK_HOME/versions/$active_slot"
|
|
test -f "$active/.gstack-bundle.json"
|
|
case "$TARGET" in
|
|
windows-*) managed_bun_rel=".gstack-runtime-tools/bun.exe" ;;
|
|
*) managed_bun_rel=".gstack-runtime-tools/bun" ;;
|
|
esac
|
|
managed_bun="$active/$managed_bun_rel"
|
|
test -f "$managed_bun"
|
|
test "$("$managed_bun" --version)" = "1.3.14"
|
|
test -f "$active/runtime/licenses/BUN-LICENSE-1.3.14.md"
|
|
test -f "$active/runtime/licenses/BUN-SOURCE.md"
|
|
node -e 'const fs=require("fs"),c=require("crypto"),root=process.argv[1],rel=process.argv[2];const m=JSON.parse(fs.readFileSync(root+"/.gstack-bundle.json","utf8"));if(m.tools?.bun?.path!==rel||m.tools?.bun?.version!=="1.3.14")process.exit(1);const license=fs.readFileSync(root+"/runtime/licenses/BUN-LICENSE-1.3.14.md");if(c.createHash("sha256").update(license).digest("hex")!=="2cb858b2db8fc793bca2093489c5bc8eee615d002cc4924254904044c27a0afa")process.exit(1)' "$active" "$managed_bun_rel"
|
|
test -d "$active/.gstack-runtime-browsers"
|
|
(
|
|
cd "$active"
|
|
PLAYWRIGHT_BROWSERS_PATH="$active/.gstack-runtime-browsers" \
|
|
node --input-type=module --eval \
|
|
'const { chromium } = await import("./node_modules/playwright/index.mjs"); for (const options of [{ headless: true }, { headless: true, channel: "chromium" }]) { const browser = await chromium.launch(options); await browser.close(); }'
|
|
)
|
|
node_command=$(node -p 'process.execPath')
|
|
host_bun=$(command -v bun)
|
|
host_bun_dir=$(cd "$(dirname "$host_bun")" && pwd -P)
|
|
clean_path=""
|
|
IFS=: read -r -a path_parts <<< "$PATH"
|
|
for part in "${path_parts[@]}"; do
|
|
physical=$(cd "$part" 2>/dev/null && pwd -P || printf '%s' "$part")
|
|
if [ "$physical" != "$host_bun_dir" ]; then
|
|
clean_path="${clean_path:+$clean_path:}$part"
|
|
fi
|
|
done
|
|
if (PATH="$clean_path"; command -v bun >/dev/null 2>&1); then
|
|
echo "Host-global Bun remained available after removing setup-bun from PATH" >&2
|
|
exit 1
|
|
fi
|
|
test "$(PATH="$clean_path" GSTACK_NODE="$node_command" "$GSTACK_HOME/bin/bun" --version)" = "1.3.14"
|
|
browser_cleanup() {
|
|
PATH="$clean_path" GSTACK_NODE="$node_command" BROWSE_PARENT_PID=0 \
|
|
"$GSTACK_HOME/bin/browse" stop >/dev/null 2>&1 || true
|
|
}
|
|
trap browser_cleanup EXIT
|
|
smoke_url=$(node -e 'const fs=require("fs"),p=require("path").join(process.env.RUNNER_TEMP,"gstack-runtime-smoke.html");fs.writeFileSync(p,"<!doctype html><title>GStack runtime smoke</title>\n");process.stdout.write(require("url").pathToFileURL(p).href)')
|
|
PATH="$clean_path" GSTACK_NODE="$node_command" BROWSE_PARENT_PID=0 \
|
|
"$GSTACK_HOME/bin/browse" goto "$smoke_url"
|
|
PATH="$clean_path" GSTACK_NODE="$node_command" BROWSE_PARENT_PID=0 \
|
|
"$GSTACK_HOME/bin/browse" status
|
|
browser_cleanup
|
|
trap - EXIT
|
|
stage="$RUNNER_TEMP/runtime-components"
|
|
mkdir -p "$stage" "$GITHUB_WORKSPACE/release-output"
|
|
node .github/scripts/stage-runtime-components.mjs "$active" "$stage"
|
|
for component_dir in "$stage"/*; do
|
|
test -d "$component_dir" || continue
|
|
component=$(basename "$component_dir")
|
|
archive="$GITHUB_WORKSPACE/release-output/gstack-runtime-2.0.0-$TARGET-$component.tar.gz"
|
|
tar -czf "$archive" -C "$component_dir" gstack
|
|
node -e 'const fs=require("fs"),c=require("crypto"),p=process.argv[1];const b=fs.readFileSync(p);fs.writeFileSync(p+".sha256",c.createHash("sha256").update(b).digest("hex")+" "+require("path").basename(p)+"\n")' "$archive"
|
|
done
|
|
shell: bash
|
|
|
|
- name: Attest component archive provenance
|
|
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
|
|
with:
|
|
subject-path: release-output/*.tar.gz
|
|
|
|
- name: Upload signed archive
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
with:
|
|
name: runtime-${{ matrix.target }}
|
|
path: release-output/*
|
|
if-no-files-found: error
|
|
retention-days: 14
|
|
|
|
manifest:
|
|
name: Assemble manifest and GitHub Release
|
|
needs: build
|
|
runs-on: ubuntu-24.04
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
permissions:
|
|
contents: write
|
|
id-token: write
|
|
attestations: write
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
with:
|
|
pattern: runtime-*
|
|
path: release-output
|
|
merge-multiple: true
|
|
- uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
|
|
|
|
- name: Keyless-sign component archives
|
|
run: |
|
|
set -euo pipefail
|
|
for archive in release-output/*.tar.gz; do
|
|
cosign sign-blob --yes --bundle "$archive.sigstore.json" "$archive"
|
|
done
|
|
shell: bash
|
|
|
|
- name: Create strict six-target manifest
|
|
run: node .github/scripts/create-runtime-release-manifest.mjs release-output "$GITHUB_REPOSITORY" 2.0.0 "$GITHUB_REF_NAME"
|
|
|
|
- name: Checksum and keyless-sign manifest
|
|
run: |
|
|
set -euo pipefail
|
|
cd release-output
|
|
sha256sum gstack-runtime-manifest.json > gstack-runtime-manifest.json.sha256
|
|
cosign sign-blob --yes --bundle gstack-runtime-manifest.json.sigstore.json gstack-runtime-manifest.json
|
|
shell: bash
|
|
|
|
- name: Attest manifest provenance
|
|
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
|
|
with:
|
|
subject-path: release-output/gstack-runtime-manifest.json
|
|
|
|
- name: Publish immutable release assets
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
PRERELEASE_FLAG: ${{ contains(github.ref_name, '-rc.') && '--prerelease' || '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
gh release create "$GITHUB_REF_NAME" \
|
|
--verify-tag \
|
|
$PRERELEASE_FLAG \
|
|
--title "GStack runtime $GITHUB_REF_NAME" \
|
|
--notes "Signed optional runtime artifacts for the six portable GStack skills." \
|
|
release-output/*
|
|
shell: bash
|