Skip to content

Installer installs main (or GRAPHDONE_REF), never a deleted branch - #247

Merged
mvalancy merged 2 commits into
devfrom
fix/installer-ref-243
Nov 7, 2026
Merged

mvalancy merged 2 commits into
devfrom
fix/installer-ref-243

Conversation

@mvalancy

@mvalancy mvalancy commented Nov 7, 2026

Copy link
Copy Markdown
Member

Closes #243

Problem

scripts/install.sh pinned fix/first-start, a branch that no longer exists, in two places: git clone --branch fix/first-start and the base of the raw.githubusercontent.com fallback URLs for scripts/setup_*.sh. Every fresh one-line install failed at the clone. It also exited silently, because wait $clone_pid under set -e exits before the error message prints. Re-running on an existing install also failed: git pull had no upstream left to pull.

Change

  • One ref, GRAPHDONE_REF, default main. main is the branch the installer is served from. The fresh clone, the update of ~/graphdone and the setup-script fallback URLs (setup_script_url) all read this one variable. Option-like or unsafe values (-…, spaces, ..) are rejected before anything runs.
  • Update path. For an installer-managed checkout, the installer now runs git fetch origin "$GRAPHDONE_REF", checks the ref out and fast-forwards it (or detaches, for a tag). It no longer pulls the current branch. Installs stranded on fix/first-start move to main. A developer checkout that the installer is run from keeps its branch and still does git pull.
  • Failures print their log. A failed clone or update now shows its log and a clear error, instead of exiting silently at wait.
  • sh install.sh sources. Prints the repository, ref and setup-script URLs the installer will use. The tests use it, and it helps when debugging an install.
  • Image tags. The web image pre-pull and deployment/docker-compose.registry.yml now use :latest instead of :fix-first-start. These are the same lines Real tag-gated releases, promotion gates on dev, no fake deploys #241 changes, so the two PRs merge cleanly in either order.
  • Docs. docs/deployment.md documents GRAPHDONE_REF. tests/README.md and npm run test:installer cover the new tests.

Tests

  • tests/toolchain/installer-contract.mjs (node:test, no network, about 0.1 s). It checks that:

    • every git clone/checkout/fetch/pull ref and every raw GitHub URL in the installer is $GRAPHDONE_REF, and that the variable defaults to main;
    • the installer has no hard-coded fix/…, feat/… or similar branch names;
    • every ghcr.io/graphdone/* tag in the installer and in deployment/*.yml is latest or a version;
    • every run_setup_script target is listed and exists;
    • sources reports main, honours the override and rejects option-like refs;
    • the documented one-line URLs use /main/scripts/install.sh.

    It also includes a self-test proving that the old pinned lines are rejected. The test:toolchain glob picks the file up as well.

  • tests/integration/installer-container.sh (about 70 s). It runs the real installer non-interactively in a disposable node:22.18.0-trixie-slim container. With GRAPHDONE_INSTALL_STOP_AFTER=clone it stops once the code is in place, so nothing is installed or started. A stub docker inside the container reports a running daemon; host Docker only runs the container. It checks that:

    1. the ref exists on the remote;
    2. the fresh install exits 0 and ~/graphdone is on the remote's commit for the ref;
    3. a re-run takes the update path and stays on that commit;
    4. a checkout moved onto a local fix/first-start branch (one commit behind, upstream deleted) is brought back to the ref;
    5. every setup-script URL from sources returns HTTP 200.
  • CI wiring. Both tests now run in the required Installer & Deploy Config job, which also validates docker-compose.registry.yml. The job has a 15-minute timeout.

Evidence (local, Node 22)

  • npm run test:unified:lib: 208/208 pass
  • npm run lint: pass
  • node --test tests/toolchain/*.mjs: 11/11 pass, including the new contract tests
  • sh tests/integration/installer-container.sh: 18/18 PASS for main. With GRAPHDONE_REF=dev it also passes 18/18.
  • Negative controls:
    • Contract test against the old dev installer and registry compose: tests 2–4 fail. The failures report GRAPHDONE_REF must be defined once with default main, hard-coded branch name 'fix/first-start' (lines 285 and 3371), raw GitHub URL pins '${GITHUB_BRANCH}', git clone must use --branch "$GRAPHDONE_REF", and image tag 'fix-first-start' (install.sh:3735 and registry.yml lines 6, 42 and 77).
    • Container test with GRAPHDONE_REF=fix/first-start: exit 1. The ref does not exist, the clone log shows fatal: Remote branch fix/first-start not found in upstream origin, and all three setup-script URLs return HTTP 404.
    • Container test with INSTALLER_UNDER_TEST=<old dev install.sh>: exit 1. The fresh install fails at "Downloading GraphDone" and exits without any error message, which is the silent set -e exit described above.

🤖 Generated with Claude Code

scripts/install.sh pinned fix/first-start, which no longer exists, for the
fresh clone and the setup-script fallback URLs, so every one-line install
failed at git clone (#243).

- One ref drives the clone, the update of ~/graphdone and the
  raw.githubusercontent setup-script fallbacks: GRAPHDONE_REF, default main
  (the branch the installer is served from). Option-like or unsafe values are
  rejected.
- Updating an installer-managed checkout fetches GRAPHDONE_REF and checks it
  out instead of pulling the current branch, so installs stranded on
  fix/first-start move to main. A developer checkout keeps its branch.
- Clone and update failures now print their log instead of exiting silently
  under set -e at `wait`.
- `sh install.sh sources` prints the repository, ref and setup-script URLs.
- Web image pre-pull and the registry compose use :latest instead of
  :fix-first-start (same lines as #241).

Tests:
- tests/toolchain/installer-contract.mjs: every git ref and raw URL in the
  installer is GRAPHDONE_REF (default main), no hard-coded branch names,
  ghcr.io/graphdone image tags are latest or versions, setup scripts exist,
  documented install URLs use main. Includes a self-test that the old pin
  is rejected.
- tests/integration/installer-container.sh: runs the installer in a
  node:22.18.0-trixie-slim container (GRAPHDONE_INSTALL_STOP_AFTER=clone):
  fresh clone lands on the remote commit for the ref, re-run updates, a
  checkout stranded on fix/first-start moves to the ref, and every
  setup-script URL returns HTTP 200. About a minute.
- Both run in the required "Installer & Deploy Config" job, which now also
  validates the registry compose file.

Closes #243

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 22.18.0 & 24.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy

mvalancy commented Nov 7, 2026

Copy link
Copy Markdown
Member Author

Maintainer verification of cc9a667 (owner-delegated merge approval)

  • CI on this head, after merging dev with Real tag-gated releases, promotion gates on dev, no fake deploys #241: 18 pass, including the 4 required checks; the main-only prod job is skipped. The installer contract and container test run inside the required Installer & Deploy Config job.
  • I re-ran these locally on a fresh clone:
    • tests/integration/installer-container.sh against main passes: fresh clone at GitHub's commit for the ref, the update path, recovery of a checkout parked on a deleted branch, and HTTP 200 for every setup-script URL.
    • Negative control: GRAPHDONE_REF=fix/first-start fails: the clone fails and all three setup-script URLs return 404. This is the outage in Installer pins deleted branch fix/first-start: fresh installs fail at clone #243.
    • installer-contract.mjs 5/5. On the merged tree, test:unified:lib 289/289 and tests/toolchain/*.mjs 11/11. The Mermaid and Vite contracts needed the Playwright headless shell installed locally; CI has it.
    • GRAPHDONE_REF='--upload-pack=x' sh scripts/install.sh sources is rejected, exit 1.
  • Code read:
    • One source of truth (GRAPHDONE_REF, default main) for the clone, the update and the setup-script fallback.
    • The update path is non-destructive: explicit fetch, then a checkout plus --ff-only merge, or a detached checkout for tags. There is no reset or force; a dirty or diverged checkout stops with a clear error.
    • A developer checkout keeps its own branch with git pull.
    • The silent set -e exit after a failed clone or update now prints its log.

Merging. The installer on main stays broken until the next dev→main release ships this fix.

@mvalancy
mvalancy merged commit 90db67d into dev Nov 7, 2026
19 checks passed
@mvalancy
mvalancy deleted the fix/installer-ref-243 branch November 7, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant