Repository navigation
Feat: serve cortex installer at /cortex/install.sh - #130
Conversation
sync-docs.sh now also copies rossoctl/cortex:scripts/install.sh to a git-ignored cortex/ directory (from CORTEX_SRC_REPO if set, else a sparse clone of CORTEX_REPO_URL). A postBuild plugin copies cortex/ into build/cortex/, so the script is served as a real file rather than the SPA's HTML fallback. A missing install.sh fails the sync, so the URL can't go live without the script. Refs rossoctl/cortex#1354 Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Ed Snible <snible@us.ibm.com>
✅ Deploy Preview for animated-crumble-fb8862 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
- Log the cortex commit that cortex/install.sh came from, so the deploy log records exactly what went live. - Don't pass rm an empty operand when TMP is unset. - Update comments in sync-docs.sh, deploy.yaml and netlify.toml that still described only the rossoctl/rossoctl sync. Refs rossoctl/cortex#1354 Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Ed Snible <snible@us.ibm.com>
Alan-Cha
left a comment
There was a problem hiding this comment.
Clean, well-scoped change with unusually good comment hygiene — the "why not static/" note in docusaurus.config.ts and the "fatal if missing" rationale in sync-docs.sh both answer exactly the questions a reviewer would ask. The fail-closed design (hard error if install.sh is absent) is the right call, since the failure mode it prevents is piping an HTML 404 page into sh.
Verified the core claim end-to-end against the Netlify deploy preview:
HTTP/2 200
content-type: application/x-sh
content-length: 64952
First line is #!/bin/sh, and 64952 bytes matches rossoctl/cortex:scripts/install.sh upstream exactly. GitHub Actions are all SHA-pinned, DCO passes, both commits signed off, and fs/path are properly imported for the new postBuild plugin.
I also checked the ${TMP:+"$TMP"} idiom from bd8b5c4 — that's the correct set -u-safe form and expands to nothing when TMP is unset. Not a bug.
Three non-blocking comments below, all in sync-docs.sh. Approving — none of them block merge.
One thing outside the diff, not a review comment: production www.rossoctl.dev is GitHub Pages, while the verified preview is Netlify, and the two don't necessarily agree on Content-Type for .sh. GitHub Pages does map .sh to application/x-sh, so I expect this to work, but the preview doesn't technically prove the production path. Worth a single curl -fsSI https://www.rossoctl.dev/cortex/install.sh after merge — it currently 404s, as expected pre-merge.
Areas reviewed: Shell, TypeScript/config, CI/GitHub Actions, TOML, security
CI status: passing
Assisted-By: Claude Code
| fi | ||
| mkdir -p "$SITE_DIR/cortex" | ||
| rsync -a "$CORTEX_SRC/scripts/install.sh" "$SITE_DIR/cortex/install.sh" | ||
| echo "==> cortex/install.sh copied from ${CORTEX_SRC_REPO:-$CORTEX_REPO_URL}@$(git -C "$CORTEX_SRC" rev-parse --short HEAD)." |
There was a problem hiding this comment.
suggestion — rev-parse fails when CORTEX_SRC_REPO isn't a git repo.
This runs git rev-parse --short HEAD unconditionally. Under set -euo pipefail, if a contributor points CORTEX_SRC_REPO at a plain directory (an extracted tarball, a vendored copy), this exits 128 and fails the whole sync after the file was already copied successfully. I confirmed the exit code locally.
The remote path is always a real clone, so this only affects local users — but it fails the step for what is just a log line. Suggest tolerating it:
CORTEX_REV="$(git -C "$CORTEX_SRC" rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
echo "==> cortex/install.sh copied from ${CORTEX_SRC_REPO:-$CORTEX_REPO_URL}@${CORTEX_REV}."| CORTEX_SRC="$CORTEX_SRC_REPO" | ||
| else | ||
| CORTEX_SRC="$(mktemp -d)" | ||
| trap 'rm -rf ${TMP:+"$TMP"} "$CORTEX_SRC"' EXIT |
There was a problem hiding this comment.
suggestion — this trap ... EXIT replaces the earlier one rather than appending.
In the common CI path both clones happen, so the earlier trap 'rm -rf "$TMP"' EXIT is discarded and this becomes the only handler. The ${TMP:+...} guard correctly compensates, so the current code is fine — but that correctness now depends on this trap remembering to re-list every earlier temp dir. A third synced repo would silently reintroduce the leak.
Registering one cleanup function would make that structural rather than something to remember:
CLEANUP_DIRS=()
cleanup() { [[ ${#CLEANUP_DIRS[@]} -gt 0 ]] && rm -rf "${CLEANUP_DIRS[@]}"; }
trap cleanup EXIT
# then: CLEANUP_DIRS+=("$TMP") / CLEANUP_DIRS+=("$CORTEX_SRC")Low real impact — the leak is a temp dir in a runner that gets destroyed anyway. Raised for maintainability.
| git -C "$CORTEX_SRC" sparse-checkout set scripts | ||
| fi | ||
| mkdir -p "$SITE_DIR/cortex" | ||
| rsync -a "$CORTEX_SRC/scripts/install.sh" "$SITE_DIR/cortex/install.sh" |
There was a problem hiding this comment.
nit — rsync -a on a single file gains nothing over cp -p here: no --delete, no exclusions, no directory recursion. rsync also isn't present in every minimal container image, though ubuntu-latest has it.
The existing rsync further up genuinely needs --delete/--exclude; this one doesn't.
rossoctl/.github#130 serves scripts/install.sh at https://www.rossoctl.dev/cortex/install.sh, synced from main on every site deploy. Make that the documented one-liner: install.sh's header and --help, the README quick start, CONTRIBUTING's release-candidate example, agentop's "nothing is installed" fix, the release notes, and the README animation (regenerated from demo.yaml). The raw.githubusercontent.com URL stays in the README as the one alternate, and wherever the repo must not depend on the site being current: install.sh's own re-exec fetches and its no-setup recovery hint, and CONTRIBUTING's --ref=main example, which runs the piped copy itself and so would run the site's possibly day-old one. agentop's one-liner also stops naming authbridge/install.sh, which only worked through the v0.7.0 redirect script. Refs #1354 Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Ed Snible <snible@us.ibm.com>
Summary
Serves the Cortex one-line installer from the site, so it can be installed with:
curl -fsSL https://www.rossoctl.dev/cortex/install.sh | shscripts/sync-docs.shcopiesrossoctl/cortex:scripts/install.shinto a git-ignoredcortex/directory. It reads fromCORTEX_SRC_REPOif set; otherwise it does a sparse clone ofCORTEX_REPO_URL, which defaults tohttps://github.com/rossoctl/cortex.git. Ifinstall.shis missing the sync fails, so the URL can't go live serving HTML.docusaurus.config.ts: a smallpostBuildplugin copiescortex/intobuild/cortex/, so the script is served as a real file (application/x-sh) and not as the SPA fallback page.static/wasn't used because that folder is committed and this file is synced at build time..gitignore: adds/cortex.The installer is synced from cortex
mainon each deploy (pushes here, the daily 06:17 UTC rebuild, or a manual run). The installer re-downloads itself from the newest release anyway, so this URL is only the front door.Related issue(s)
Part of rossoctl/cortex#1354. A follow-up PR in rossoctl/cortex will update the hard-coded
raw.githubusercontent.comURLs ininstall.shand the README.(Optional) Testing Instructions
Checked locally: the served file matches
cortex/scripts/install.shbyte-for-byte, andcurl … | sh -s -- --helpprints the installer usage. The default path withoutCORTEX_SRC_REPO(cloning from GitHub) was also tested, and its temp clone is cleaned up.Assisted-By: Claude Code