mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 04:10:47 +02:00
Merge codex/gstack-2 into gstack2-runtime-integration
Reconcile the four integrated v2 runtime implementations (unified execution result contract, execution profiles, capability readiness, GitHub security) with main's browser-provider hardening. Conflict resolutions: - runtimeContract() generator: keep new execution-result + doctor-capability paragraphs, adopt main's `[matching browser flags]` fallback wording; regenerate the six RUNTIME.md. - package.json: keep the strict isolated test:gstack2 runner and marked 18.0.6 security bump; adopt main's playwright-core alias. - bun.lock: regenerated via bun install. - release-hardening.test.ts: adopt main's browser-provider assertions (resolveServerLaunchTarget, --browser managed smoke loop). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -70,11 +70,11 @@ RUN curl --retry 5 --retry-delay 5 --retry-connrefused -fsSL https://bun.sh/inst
|
||||
RUN npm i -g @anthropic-ai/claude-code
|
||||
|
||||
# Playwright system deps (Chromium) — needed for browse E2E tests
|
||||
RUN npx playwright install-deps chromium
|
||||
RUN npx playwright-core install-deps chromium
|
||||
|
||||
# Linux has neither Helvetica nor Arial. make-pdf's print CSS stacks fall back
|
||||
# to Liberation Sans (metric-compatible Arial clone, SIL OFL 1.1) so PDFs don't
|
||||
# render in DejaVu Sans. playwright install-deps happens to pull this in today,
|
||||
# render in DejaVu Sans. playwright-core install-deps happens to pull this in today,
|
||||
# but the dep is implicit and could change — install explicitly so upgrades
|
||||
# can't silently regress rendering.
|
||||
#
|
||||
@@ -100,12 +100,12 @@ RUN bun install --frozen-lockfile && rm -rf /tmp/*
|
||||
|
||||
# Install Playwright Chromium to a shared location accessible by all users
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers
|
||||
RUN npx playwright install chromium \
|
||||
RUN npx playwright-core install chromium \
|
||||
&& chmod -R a+rX /opt/playwright-browsers
|
||||
|
||||
# Verify everything works
|
||||
RUN bun --version && node --version && claude --version && jq --version && gh --version \
|
||||
&& npx playwright --version \
|
||||
&& npx playwright-core --version \
|
||||
&& fc-match "Liberation Sans" | grep -qi "Liberation" \
|
||||
|| (echo "ERROR: fonts-liberation not installed — make-pdf PDFs will render in DejaVu Sans" && exit 1)
|
||||
|
||||
|
||||
@@ -2,11 +2,19 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const [directory, repository = process.env.GITHUB_REPOSITORY, version = "2.0.0"] = process.argv.slice(2);
|
||||
const [
|
||||
directory,
|
||||
repository = process.env.GITHUB_REPOSITORY,
|
||||
version = "2.0.0",
|
||||
releaseTag = `v${version}`,
|
||||
] = process.argv.slice(2);
|
||||
if (!directory || !repository) {
|
||||
console.error("Usage: create-runtime-release-manifest.mjs <artifact-dir> <owner/repo> [version]");
|
||||
console.error("Usage: create-runtime-release-manifest.mjs <artifact-dir> <owner/repo> [version] [release-tag]");
|
||||
process.exit(2);
|
||||
}
|
||||
if (!/^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(releaseTag)) {
|
||||
throw new Error(`Invalid runtime release tag: ${releaseTag}`);
|
||||
}
|
||||
|
||||
const targets = [
|
||||
"darwin-arm64",
|
||||
@@ -35,8 +43,8 @@ const capabilityComponents = {
|
||||
ios: ["ios"],
|
||||
};
|
||||
const commonComponents = ["core", "browser-code", "browser-headless", "browser-visible", "design", "diagram", "pdf"];
|
||||
const release = `https://github.com/${repository}/releases/download/v${version}`;
|
||||
const certificateIdentity = `https://github.com/${repository}/.github/workflows/release-artifacts.yml@refs/tags/v${version}`;
|
||||
const release = `https://github.com/${repository}/releases/download/${releaseTag}`;
|
||||
const certificateIdentity = `https://github.com/${repository}/.github/workflows/release-artifacts.yml@refs/tags/${releaseTag}`;
|
||||
const targetRecords = {};
|
||||
|
||||
for (const target of targets) {
|
||||
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
fc-match -f '%{family[0]}\t%{color}\n' ':lang=und-zsye:charset=1F600' || true
|
||||
|
||||
- name: Install Playwright Chromium
|
||||
run: bunx playwright install chromium
|
||||
run: bunx playwright-core install chromium
|
||||
|
||||
- name: Build binaries
|
||||
run: bun run build
|
||||
|
||||
@@ -2,7 +2,9 @@ name: Release runtime artifacts
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [v2.0.0]
|
||||
tags:
|
||||
- v2.0.0
|
||||
- v2.0.0-rc.*
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -51,8 +53,6 @@ jobs:
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: 22.23.1
|
||||
- uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
|
||||
|
||||
- name: Install frozen dependencies
|
||||
run: bun install --frozen-lockfile --ignore-scripts
|
||||
shell: bash
|
||||
@@ -70,6 +70,7 @@ jobs:
|
||||
--version 2.0.0 \
|
||||
--install-now \
|
||||
--yes \
|
||||
--browser managed \
|
||||
--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"
|
||||
@@ -112,32 +113,28 @@ jobs:
|
||||
"$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.GITHUB_WORKSPACE,".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 about:blank
|
||||
"$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"
|
||||
# GNU tar treats a Windows drive colon in an archive path as a
|
||||
# remote-host separator. Keep archive output in Git Bash's POSIX view.
|
||||
release_dir="$(pwd -P)/release-output"
|
||||
mkdir -p "$stage" "$release_dir"
|
||||
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"
|
||||
archive="$release_dir/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: 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: Attest component archive provenance
|
||||
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
|
||||
with:
|
||||
@@ -169,8 +166,16 @@ jobs:
|
||||
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
|
||||
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: |
|
||||
@@ -188,11 +193,13 @@ jobs:
|
||||
- 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 \
|
||||
--title "GStack runtime 2.0.0" \
|
||||
--notes "Signed optional runtime artifacts for the six portable GStack skills." \
|
||||
$PRERELEASE_FLAG \
|
||||
--title "GStack runtime $GITHUB_REF_NAME" \
|
||||
--notes "Signed optional runtime artifacts for the six portable GStack skills. This release adds an explicit managed-versus-installed Chromium consent gate before browser preview or installation." \
|
||||
release-output/*
|
||||
shell: bash
|
||||
|
||||
@@ -65,14 +65,14 @@ jobs:
|
||||
- name: Preview without mutating state
|
||||
run: |
|
||||
set -e
|
||||
bash ./setup --dry-run --capabilities browser
|
||||
bash ./setup --dry-run --capabilities browser --browser managed
|
||||
test ! -e "$GSTACK_HOME" || (echo "dry-run mutated GSTACK_HOME" && exit 1)
|
||||
shell: bash
|
||||
|
||||
- name: Explicitly install the browser capability
|
||||
run: |
|
||||
set -e
|
||||
bash ./setup --install-now --yes --capabilities browser
|
||||
bash ./setup --install-now --yes --capabilities browser --browser managed
|
||||
test -f "$GSTACK_HOME/versions/current.json"
|
||||
test -f "$GSTACK_HOME/bin/gstack.cmd"
|
||||
shell: bash
|
||||
|
||||
Reference in New Issue
Block a user