Skip to content

Feat: serve cortex installer at /cortex/install.sh - #130

Merged
esnible merged 2 commits into
rossoctl:mainfrom
esnible:feat/serve-cortex-install-sh
Oct 14, 2026
Merged

esnible merged 2 commits into
rossoctl:mainfrom
esnible:feat/serve-cortex-install-sh

Conversation

@esnible

@esnible esnible commented Oct 14, 2026

Copy link
Copy Markdown
Member

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 | sh
  • scripts/sync-docs.sh copies rossoctl/cortex:scripts/install.sh into a git-ignored cortex/ directory. It reads from CORTEX_SRC_REPO if set; otherwise it does a sparse clone of CORTEX_REPO_URL, which defaults to https://github.com/rossoctl/cortex.git. If install.sh is missing the sync fails, so the URL can't go live serving HTML.
  • docusaurus.config.ts: a small postBuild plugin copies cortex/ into build/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 main on 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.com URLs in install.sh and the README.

(Optional) Testing Instructions

CORTEX_SRC_REPO=~/src/cortex SRC_REPO=~/src/rossoctl npm run sync-docs && npm run build && npm run serve
curl -fsSI http://localhost:3000/cortex/install.sh   # 200, Content-Type: application/x-sh
curl -fsSL http://localhost:3000/cortex/install.sh | head -1   # #!/bin/sh

Checked locally: the served file matches cortex/scripts/install.sh byte-for-byte, and curl … | sh -s -- --help prints the installer usage. The default path without CORTEX_SRC_REPO (cloning from GitHub) was also tested, and its temp clone is cleaned up.

Assisted-By: Claude Code

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>
@netlify

netlify Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for animated-crumble-fb8862 ready!

Name Link
🔨 Latest commit bd8b5c4
🔍 Latest deploy log https://app.netlify.com/projects/animated-crumble-fb8862/deploys/6acf8b780fdfc25e819ff525
😎 Deploy Preview https://deploy-preview-130--animated-crumble-fb8862.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

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 Alan-Cha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread scripts/sync-docs.sh
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)."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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}."

Comment thread scripts/sync-docs.sh
CORTEX_SRC="$CORTEX_SRC_REPO"
else
CORTEX_SRC="$(mktemp -d)"
trap 'rm -rf ${TMP:+"$TMP"} "$CORTEX_SRC"' EXIT

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread scripts/sync-docs.sh
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"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@esnible
esnible merged commit ec0afad into rossoctl:main Oct 14, 2026
5 checks passed
@esnible
esnible deleted the feat/serve-cortex-install-sh branch October 14, 2026 14:45
@github-project-automation github-project-automation Bot moved this from New/ToDo to Done in Rossoctl Issue Prioritization Oct 14, 2026
esnible added a commit to rossoctl/cortex that referenced this pull request Oct 14, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants