mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-12 16:08:59 +02:00
Merge origin/main (v1.64.0.0) into garrytan/time-attack-fork-review
Both waves fixed several of the same bugs; resolutions keep whichever shape this branch's tests pin (#2018 jq bind, #1798 set-- pattern, stop-ack, lock errors, polyfill windowsHide) and take main's richer codex Step 2A (it absorbed the same mktemp fix). True unions: memory- ingest keeps main's capability-probed --include-gitignored inside our GIT_CEILING defense; setup wraps main's Playwright platform override in our stale-healing install lock; package.json takes main's diff@^9 and the combined test glob (design/test + ios-qa/daemon/test, 30s timeout). Generated SKILL.md files regenerated from resolved templates, never hand-picked. Ship goldens refreshed; parity/carve budgets re-measured for the summed preamble growth of both waves (itemized per entry).
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { TemplateContext } from './types';
|
||||
import { type TemplateContext, toShellPath } from './types';
|
||||
import { COMMAND_DESCRIPTIONS } from '../../browse/src/commands';
|
||||
import { SNAPSHOT_FLAGS } from '../../browse/src/snapshot';
|
||||
|
||||
@@ -106,7 +106,7 @@ export function generateBrowseSetup(ctx: TemplateContext): string {
|
||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
B=""
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse" ] && B="$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse"
|
||||
[ -z "$B" ] && B="$HOME${ctx.paths.browseDir.replace(/^~/, '')}/browse"
|
||||
[ -z "$B" ] && B="${toShellPath(ctx.paths.browseDir)}/browse"
|
||||
if [ -x "$B" ]; then
|
||||
echo "READY: $B"
|
||||
else
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TemplateContext } from './types';
|
||||
import { type TemplateContext, toShellPath } from './types';
|
||||
import { AI_SLOP_BLACKLIST, OPENAI_HARD_REJECTIONS, OPENAI_LITMUS_CHECKS } from './constants';
|
||||
|
||||
export function generateDesignReviewLite(ctx: TemplateContext): string {
|
||||
@@ -792,7 +792,7 @@ export function generateDesignSetup(ctx: TemplateContext): string {
|
||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
D=""
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design" ] && D="$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design"
|
||||
[ -z "$D" ] && D="$HOME${ctx.paths.designDir.replace(/^~/, '')}/design"
|
||||
[ -z "$D" ] && D="${toShellPath(ctx.paths.designDir)}/design"
|
||||
if [ -x "$D" ]; then
|
||||
echo "DESIGN_READY: $D"
|
||||
else
|
||||
@@ -800,7 +800,7 @@ else
|
||||
fi
|
||||
B=""
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse" ] && B="$_ROOT/${ctx.paths.localSkillRoot}/browse/dist/browse"
|
||||
[ -z "$B" ] && B="$HOME${ctx.paths.browseDir.replace(/^~/, '')}/browse"
|
||||
[ -z "$B" ] && B="${toShellPath(ctx.paths.browseDir)}/browse"
|
||||
if [ -x "$B" ]; then
|
||||
echo "BROWSE_READY: $B"
|
||||
else
|
||||
@@ -837,7 +837,7 @@ export function generateDesignMockup(ctx: TemplateContext): string {
|
||||
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
D=""
|
||||
[ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design" ] && D="$_ROOT/${ctx.paths.localSkillRoot}/design/dist/design"
|
||||
[ -z "$D" ] && D="$HOME${ctx.paths.designDir.replace(/^~/, '')}/design"
|
||||
[ -z "$D" ] && D="${toShellPath(ctx.paths.designDir)}/design"
|
||||
[ -x "$D" ] && echo "DESIGN_READY" || echo "DESIGN_NOT_AVAILABLE"
|
||||
\`\`\`
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TemplateContext } from './types';
|
||||
import { type TemplateContext, toShellPath } from './types';
|
||||
|
||||
/**
|
||||
* {{MAKE_PDF_SETUP}} — emits the shell preamble that resolves $P to the
|
||||
@@ -19,7 +19,7 @@ _ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
P=""
|
||||
[ -n "$MAKE_PDF_BIN" ] && [ -x "$MAKE_PDF_BIN" ] && P="$MAKE_PDF_BIN"
|
||||
[ -z "$P" ] && [ -n "$_ROOT" ] && [ -x "$_ROOT/${ctx.paths.localSkillRoot}/make-pdf/dist/pdf" ] && P="$_ROOT/${ctx.paths.localSkillRoot}/make-pdf/dist/pdf"
|
||||
[ -z "$P" ] && P="$HOME${ctx.paths.makePdfDir.replace(/^~/, '')}/pdf"
|
||||
[ -z "$P" ] && P="${toShellPath(ctx.paths.makePdfDir)}/pdf"
|
||||
if [ -x "$P" ]; then
|
||||
echo "MAKE_PDF_READY: $P"
|
||||
alias _p_="$P" # shellcheck alias helper (not exported)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* to `gstack-brain-sync --discover-new` + `--once`.
|
||||
*/
|
||||
import type { TemplateContext } from '../types';
|
||||
import { quoteSafePath } from '../types';
|
||||
|
||||
export function generateBrainSyncBlock(ctx: TemplateContext): string {
|
||||
const isBrainHost = ctx.host === 'gbrain' || ctx.host === 'hermes';
|
||||
@@ -42,8 +43,8 @@ if [ -f "$HOME/.gstack-artifacts-remote.txt" ]; then
|
||||
else
|
||||
_BRAIN_REMOTE_FILE="$HOME/.gstack-brain-remote.txt"
|
||||
fi
|
||||
_BRAIN_SYNC_BIN="${ctx.paths.binDir}/gstack-brain-sync"
|
||||
_BRAIN_CONFIG_BIN="${ctx.paths.binDir}/gstack-config"
|
||||
_BRAIN_SYNC_BIN="${quoteSafePath(ctx.paths.binDir)}/gstack-brain-sync"
|
||||
_BRAIN_CONFIG_BIN="${quoteSafePath(ctx.paths.binDir)}/gstack-config"
|
||||
|
||||
# /sync-gbrain context-load: teach the agent to use gbrain when it's available.
|
||||
# Per-worktree pin: post-spike redesign uses kubectl-style \`.gbrain-source\` in the
|
||||
@@ -152,8 +153,8 @@ If A/B and \`~/.gstack/.git\` is missing, ask whether to run \`gstack-artifacts-
|
||||
At skill END before telemetry:
|
||||
|
||||
\`\`\`bash
|
||||
"${ctx.paths.binDir}/gstack-brain-sync" --discover-new 2>/dev/null || true
|
||||
"${ctx.paths.binDir}/gstack-brain-sync" --once 2>/dev/null || true
|
||||
"${quoteSafePath(ctx.paths.binDir)}/gstack-brain-sync" --discover-new 2>/dev/null || true
|
||||
"${quoteSafePath(ctx.paths.binDir)}/gstack-brain-sync" --once 2>/dev/null || true
|
||||
\`\`\`
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -73,11 +73,15 @@ fi
|
||||
if [ "$_TEL" != "off" ] && [ -x ~/.claude/skills/gstack/bin/gstack-telemetry-log ]; then
|
||||
~/.claude/skills/gstack/bin/gstack-telemetry-log \\
|
||||
--skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \\
|
||||
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &
|
||||
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" \\
|
||||
--error-message "ERROR_MESSAGE" --failed-step "FAILED_STEP" 2>/dev/null &
|
||||
fi
|
||||
\`\`\`
|
||||
|
||||
Replace \`SKILL_NAME\`, \`OUTCOME\`, and \`USED_BROWSE\` before running.
|
||||
Replace \`ERROR_MESSAGE\` with a short description of the error (if outcome is error,
|
||||
otherwise use empty string ""), and \`FAILED_STEP\` with the step name or number where
|
||||
the failure occurred (if outcome is error, otherwise use empty string "").
|
||||
|
||||
## Plan Status Footer
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { TemplateContext } from '../types';
|
||||
import { quoteSafePath } from '../types';
|
||||
import { getHostConfig } from '../../../hosts/index';
|
||||
|
||||
export function generatePreambleBash(ctx: TemplateContext): string {
|
||||
@@ -67,13 +68,15 @@ if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then
|
||||
echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL"
|
||||
_QUESTION_TUNING=$(${ctx.paths.binDir}/gstack-config get question_tuning 2>/dev/null || echo "false")
|
||||
echo "QUESTION_TUNING: $_QUESTION_TUNING"
|
||||
_UPDATE_CHECK=$(${ctx.paths.binDir}/gstack-config get update_check 2>/dev/null || echo "true")
|
||||
echo "UPDATE_CHECK: $_UPDATE_CHECK"
|
||||
mkdir -p ~/.gstack/analytics
|
||||
if [ "$_TEL" != "off" ]; then
|
||||
echo '{"skill":"${ctx.skillName}","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null | tr -cd 'a-zA-Z0-9._-'); echo "\${_repo:-unknown}")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
|
||||
fi
|
||||
for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do
|
||||
if [ -f "$_PF" ]; then
|
||||
if [ "$_TEL" != "off" ] && [ -x "${ctx.paths.binDir}/gstack-telemetry-log" ]; then
|
||||
if [ "$_TEL" != "off" ] && [ -x "${quoteSafePath(ctx.paths.binDir)}/gstack-telemetry-log" ]; then
|
||||
${ctx.paths.binDir}/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true
|
||||
fi
|
||||
rm -f "$_PF" 2>/dev/null || true
|
||||
|
||||
@@ -5,6 +5,8 @@ export function generateUpgradeCheck(ctx: TemplateContext): string {
|
||||
|
||||
If \`SKILL_PREFIX\` is \`"true"\`, suggest/invoke \`/gstack-*\` names. Disk paths stay \`${ctx.paths.skillRoot}/[skill-name]/SKILL.md\`.
|
||||
|
||||
If \`UPDATE_CHECK\` is \`"false"\`, skip the next two lines — the update-check binary emits nothing in that mode, so there is no \`UPGRADE_AVAILABLE\` / \`JUST_UPGRADED\` output to act on.
|
||||
|
||||
If output shows \`UPGRADE_AVAILABLE <old> <new>\`: read \`${ctx.paths.skillRoot}/gstack-upgrade/SKILL.md\` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined).
|
||||
|
||||
If output shows \`JUST_UPGRADED <from> <to>\`: print "Running gstack v{to} (just updated!)". If \`SPAWNED_SESSION\` is true, skip feature discovery.
|
||||
|
||||
@@ -129,7 +129,7 @@ CHECKLIST:
|
||||
|
||||
**Subagent configuration:**
|
||||
- Use \`subagent_type: "general-purpose"\`
|
||||
- Do NOT use \`run_in_background\` — all specialists must complete before merge
|
||||
- Pass \`run_in_background: false\` on every specialist Agent call — subagents run in the BACKGROUND by default since Claude Code v2.1.198, and all specialists must complete before merge. (Merely omitting the flag no longer produces a foreground run; it must be explicitly false.)
|
||||
- If any specialist subagent fails or times out, log the failure and continue with results from successful specialists. Specialists are additive — partial results are better than no results.`;
|
||||
}
|
||||
|
||||
|
||||
@@ -350,7 +350,7 @@ If B: skip Phase 3.5 entirely. Remember that the second opinion did NOT run (aff
|
||||
2. **Write the assembled prompt to a temp file** (prevents shell injection from user-derived content):
|
||||
|
||||
\`\`\`bash
|
||||
CODEX_PROMPT_FILE=$(mktemp /tmp/gstack-codex-oh-XXXXXXXX.txt)
|
||||
CODEX_PROMPT_FILE=$(mktemp /tmp/gstack-codex-oh-XXXXXXXX)
|
||||
\`\`\`
|
||||
|
||||
Write the full prompt to this file. **Always start with the filesystem boundary:**
|
||||
@@ -526,10 +526,14 @@ If \`CODEX_MODE\` is \`ready\`:
|
||||
\`\`\`bash
|
||||
TMPERR_ADV=$(mktemp /tmp/codex-adv-XXXXXXXX)
|
||||
_REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; }
|
||||
codex exec "${CODEX_BOUNDARY}Review the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/<base> HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format \`Recommendation: <action> because <one-line reason naming the most exploitable finding>\`. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_ADV"
|
||||
# Shell functions do not survive between Bash blocks, so re-source the probe
|
||||
# here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout ->
|
||||
# unwrapped fallback), added in #1056 but never wired into this call site.
|
||||
source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true
|
||||
_gstack_codex_timeout_wrapper 540 codex exec "${CODEX_BOUNDARY}Review the changes on this branch against the base branch. Run DIFF_BASE=$(git merge-base origin/<base> HEAD) && git diff "$DIFF_BASE" to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems. End your output with ONE line in the canonical format \`Recommendation: <action> because <one-line reason naming the most exploitable finding>\`. Generic reasons like 'because it's safer' do not qualify; the reason must point to a specific finding or no-fix rationale." -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR_ADV"
|
||||
\`\`\`
|
||||
|
||||
Set the Bash tool's \`timeout\` parameter to \`300000\` (5 minutes). Do NOT use the \`timeout\` shell command — it doesn't exist on macOS. After the command completes, read stderr:
|
||||
Set the Bash tool's \`timeout\` parameter to \`600000\` (10 minutes). It sits ABOVE the 540s wrapper deliberately, so the wrapper fires first and a stall surfaces as a diagnosable exit 124 instead of a harness kill that returns nothing. The wrapper resolves \`gtimeout\`, then \`timeout\`, then runs unwrapped, so it is safe on a macOS without coreutils. After the command completes, read stderr:
|
||||
\`\`\`bash
|
||||
cat "$TMPERR_ADV"
|
||||
\`\`\`
|
||||
@@ -538,7 +542,7 @@ Present the full output verbatim. This is informational — it never blocks ship
|
||||
|
||||
**Error handling:** All errors are non-blocking — adversarial review is a quality enhancement, not a prerequisite.
|
||||
- **Auth failure:** If stderr contains "auth", "login", "unauthorized", or "API key": "Codex authentication failed. Run \\\`codex login\\\` to authenticate."
|
||||
- **Timeout:** "Codex timed out after 5 minutes."
|
||||
- **Timeout (exit 124):** "Codex exceeded 9 minutes and was terminated; this pass produced NO findings." A timed-out pass is MISSING COVERAGE, not a clean bill — say so explicitly rather than continuing as if Codex had reviewed. Whatever it produced before the cut is recoverable from that run's rollout log under \`~/.codex/sessions/<YYYY>/<MM>/<DD>/\`.
|
||||
- **Empty response:** "Codex returned no response. Stderr: <paste relevant error>."
|
||||
|
||||
**Cleanup:** Run \`rm -f "$TMPERR_ADV"\` after processing.
|
||||
@@ -555,10 +559,16 @@ If \`DIFF_TOTAL >= 200\` AND \`CODEX_MODE\` is \`ready\`:
|
||||
TMPERR=$(mktemp /tmp/codex-review-XXXXXXXX)
|
||||
_REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; }
|
||||
cd "$_REPO_ROOT"
|
||||
codex review "${CODEX_BOUNDARY}Review the changes on this branch against the base branch <base>. Run git diff origin/<base>...HEAD 2>/dev/null || git diff <base>...HEAD to see the diff and review only those changes." -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR"
|
||||
# Shell functions do not survive between Bash blocks, so re-source the probe
|
||||
# here. It defines _gstack_codex_timeout_wrapper (gtimeout -> timeout ->
|
||||
# unwrapped fallback), added in #1056 but never wired into this call site.
|
||||
source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true
|
||||
_gstack_codex_timeout_wrapper 540 codex review --base <base> -c 'model_reasoning_effort="high"' --enable web_search_cached < /dev/null 2>"$TMPERR"
|
||||
\`\`\`
|
||||
|
||||
Set the Bash tool's \`timeout\` parameter to \`300000\` (5 minutes). Do NOT use the \`timeout\` shell command — it doesn't exist on macOS. Present output under \`CODEX SAYS (code review):\` header.
|
||||
**No prompt argument.** \`--base\` is what scopes the review, and the positional \`[PROMPT]\` is mutually exclusive with it — passing both fails at argv parsing. Do NOT "fix" that error by dropping \`--base\` and keeping the prompt: a prompt-only \`codex review\` silently falls back to the **uncommitted working-tree** scope (\`git status --short; git diff\`), so it reviews the wrong changes and reports "no changes" on a clean tree. Prompt text describing the diff range does not change what the CLI feeds the reviewer. Unlike the adversarial pass above, which uses \`codex exec\` and really does run the git command it's told to, this path gets a pre-computed diff from the CLI — which is also why it needs no filesystem boundary.
|
||||
|
||||
Set the Bash tool's \`timeout\` parameter to \`600000\` (10 minutes). It sits ABOVE the 540s wrapper deliberately, so the wrapper fires first and a stall surfaces as a diagnosable exit 124 instead of a harness kill that returns nothing. The wrapper resolves \`gtimeout\`, then \`timeout\`, then runs unwrapped, so it is safe on a macOS without coreutils. Present output under \`CODEX SAYS (code review):\` header.
|
||||
Check for \`[P1]\` markers: found → \`GATE: FAIL\`, not found → \`GATE: PASS\`.
|
||||
|
||||
If GATE is FAIL, use AskUserQuestion:
|
||||
|
||||
@@ -258,7 +258,7 @@ git ls-files | grep -cE '(^|/)(tests?|spec|__tests__)/|(^|/)tests?\\.py$|(^|/)te
|
||||
|
||||
\`\`\`bash
|
||||
# Count test files before any generation
|
||||
find . -name '*.test.*' -o -name '*.spec.*' -o -name '*_test.*' -o -name '*_spec.*' | grep -v node_modules | wc -l
|
||||
git ls-files 2>/dev/null | grep -E '(\\.test\\.|\\.spec\\.|_test\\.|_spec\\.)' | wc -l
|
||||
\`\`\`
|
||||
|
||||
Store this number for the PR body.`);
|
||||
@@ -466,7 +466,7 @@ If no test framework AND user declined bootstrap → diagram only, no generation
|
||||
|
||||
\`\`\`bash
|
||||
# Count test files after generation
|
||||
find . -name '*.test.*' -o -name '*.spec.*' -o -name '*_test.*' -o -name '*_spec.*' | grep -v node_modules | wc -l
|
||||
git ls-files 2>/dev/null | grep -E '(\\.test\\.|\\.spec\\.|_test\\.|_spec\\.)' | wc -l
|
||||
\`\`\`
|
||||
|
||||
For PR body: \`Tests: {before} → {after} (+{delta} new)\`
|
||||
|
||||
@@ -16,6 +16,27 @@ export interface HostPaths {
|
||||
makePdfDir: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a host path safe to interpolate INSIDE DOUBLE QUOTES in generated bash.
|
||||
*
|
||||
* Tilde-based hosts (Claude, factory) resolve to paths like
|
||||
* `~/.claude/skills/gstack/bin`. Bash only performs tilde expansion when the
|
||||
* `~` is UNQUOTED, so `"~/.claude/..."` is a literal relative path that never
|
||||
* resolves. A `[ -x "~/..." ]` test is therefore always false and a
|
||||
* `"~/..." --flag` invocation always fails — the surrounding block silently
|
||||
* becomes dead code rather than erroring.
|
||||
*
|
||||
* Env-var hosts already use `$GSTACK_BIN`, which expands correctly when
|
||||
* quoted, so they pass through untouched.
|
||||
*
|
||||
* Use this ONLY where the path lands inside double quotes. Unquoted
|
||||
* interpolations (`${ctx.paths.binDir}/gstack-slug`) expand fine as-is and are
|
||||
* left alone so generated docs keep the more readable `~`.
|
||||
*/
|
||||
export function quoteSafePath(hostPath: string): string {
|
||||
return hostPath.startsWith('~/') ? `$HOME/${hostPath.slice(2)}` : hostPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* HOST_PATHS — derived from host configs.
|
||||
* Each config's globalRoot/localSkillRoot determines the path structure.
|
||||
@@ -50,6 +71,16 @@ function buildHostPaths(): Record<string, HostPaths> {
|
||||
|
||||
export const HOST_PATHS: Record<string, HostPaths> = buildHostPaths();
|
||||
|
||||
/**
|
||||
* Render a HostPaths binary dir as a shell-expandable absolute path.
|
||||
* Claude-style dirs are `~`-rooted (e.g. `~/.claude/skills/gstack/browse/dist`)
|
||||
* and expand via `$HOME`; env-var hosts already carry an absolute `$GSTACK_*`
|
||||
* value, so they pass through untouched — prepending `$HOME` would double it.
|
||||
*/
|
||||
export function toShellPath(dir: string): string {
|
||||
return dir.startsWith('~') ? `$HOME${dir.slice(1)}` : dir;
|
||||
}
|
||||
|
||||
import type { Model } from '../models';
|
||||
export type { Model } from '../models';
|
||||
|
||||
|
||||
@@ -57,8 +57,11 @@ echo "$DEPLOY_CONFIG"
|
||||
|
||||
# If config exists, parse it
|
||||
if [ "$DEPLOY_CONFIG" != "NO_CONFIG" ]; then
|
||||
PROD_URL=$(echo "$DEPLOY_CONFIG" | grep -i "production.*url" | head -1 | sed 's/.*: *//')
|
||||
PLATFORM=$(echo "$DEPLOY_CONFIG" | grep -i "platform" | head -1 | sed 's/.*: *//')
|
||||
# Cut at the FIRST ": ", not the last. A greedy 's/.*: *//' ate the scheme of
|
||||
# any URL: "Production URL: https://x.com" became "//x.com", because the last
|
||||
# ":" belongs to "https:".
|
||||
PROD_URL=$(echo "$DEPLOY_CONFIG" | grep -i "production.*url" | head -1 | sed 's/^[^:]*: *//')
|
||||
PLATFORM=$(echo "$DEPLOY_CONFIG" | grep -i "platform" | head -1 | sed 's/^[^:]*: *//')
|
||||
echo "PERSISTED_PLATFORM:$PLATFORM"
|
||||
echo "PERSISTED_URL:$PROD_URL"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user