diff --git a/.github/workflows/build-native.yml b/.github/workflows/build-native.yml index 3b409d83d..3fb4e9412 100644 --- a/.github/workflows/build-native.yml +++ b/.github/workflows/build-native.yml @@ -166,11 +166,28 @@ jobs: fi echo "All platform packages verified." + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + + - name: Verify dist exists + run: test -f dist/loader.js || { echo "::error::dist/loader.js missing after build"; exit 1; } + + - name: Verify tarball contents + run: | + npm pack --dry-run 2>&1 | tee /tmp/pack-output.txt + grep -q "dist/loader.js" /tmp/pack-output.txt || { + echo "::error::dist/loader.js not in tarball" + exit 1 + } + - name: Publish main package env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - # Skip prepublishOnly (build already done upstream) — just publish the tarball + # --ignore-scripts: skip prepublishOnly since we built explicitly above OUTPUT=$(npm publish --ignore-scripts 2>&1) && echo "$OUTPUT" || { if echo "$OUTPUT" | grep -q "cannot publish over the previously published\|You cannot publish over"; then echo "Already published, skipping" @@ -179,3 +196,14 @@ jobs: exit 1 fi } + + - name: Post-publish smoke test + run: | + VERSION=$(node -p "require('./package.json').version") + sleep 15 + TMPDIR=$(mktemp -d) + cd "$TMPDIR" + npm init -y + npm install "gsd-pi@${VERSION}" + npx gsd --version + echo "Published package is functional" diff --git a/src/resources/extensions/gsd/git-service.ts b/src/resources/extensions/gsd/git-service.ts index f561cc651..a55c74adb 100644 --- a/src/resources/extensions/gsd/git-service.ts +++ b/src/resources/extensions/gsd/git-service.ts @@ -151,6 +151,13 @@ export function writeIntegrationBranch(basePath: string, milestoneId: string, br // ─── Git Helper ──────────────────────────────────────────────────────────── +/** Env overlay that suppresses all interactive git credential prompts. */ +const GIT_NO_PROMPT_ENV = { + ...process.env, + GIT_TERMINAL_PROMPT: "0", + GIT_ASKPASS: "", +}; + /** * Run a git command in the given directory. * Returns trimmed stdout. Throws on non-zero exit unless allowFailure is set. @@ -162,6 +169,7 @@ export function runGit(basePath: string, args: string[], options: { allowFailure cwd: basePath, stdio: [options.input != null ? "pipe" : "ignore", "pipe", "pipe"], encoding: "utf-8", + env: GIT_NO_PROMPT_ENV, ...(options.input != null ? { input: options.input } : {}), }).trim(); } catch (error) { diff --git a/src/resources/extensions/gsd/worktree-manager.ts b/src/resources/extensions/gsd/worktree-manager.ts index 217826d9c..b1207f07f 100644 --- a/src/resources/extensions/gsd/worktree-manager.ts +++ b/src/resources/extensions/gsd/worktree-manager.ts @@ -46,12 +46,20 @@ export interface WorktreeDiffSummary { // ─── Git Helpers ─────────────────────────────────────────────────────────── +/** Env overlay that suppresses all interactive git credential prompts. */ +const GIT_NO_PROMPT_ENV = { + ...process.env, + GIT_TERMINAL_PROMPT: "0", + GIT_ASKPASS: "", +}; + function runGit(cwd: string, args: string[], opts: { allowFailure?: boolean } = {}): string { try { return execSync(`git ${args.join(" ")}`, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8", + env: GIT_NO_PROMPT_ENV, }).trim(); } catch (error) { if (opts.allowFailure) return "";