From 717387f665b8a1ca0e248cdc9c49a36c69ef6d32 Mon Sep 17 00:00:00 2001 From: "benjamin.baker" Date: Wed, 2 Sep 2026 07:33:30 -0400 Subject: [PATCH] authenticate the web launcher against the private repo raw.githubusercontent.com returns 404 for a private repo without a token, so the anonymous iex one-liner could never fetch get.ps1, and even once fetched its git clone of the same private repo would fail. get.ps1 now reads a GitHub PAT from SHOPDB_TOKEN (or GITHUB_TOKEN) and uses it for the clone/fetch; the raw fetch is authenticated by irm -Headers in the one-liner. The token is kept off disk: origin is reset to the clean URL after clone, and the update path fetches by explicit URL rather than a tokenized origin. --- scripts/get.ps1 | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/scripts/get.ps1 b/scripts/get.ps1 index 398b877d..0003aa5c 100644 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -12,11 +12,17 @@ Channel is chosen by an environment variable so a pure `iex` pipe (which cannot pass parameters) still selects stable vs edge: - # Stable (main): - $env:SHOPDB_CHANNEL='stable'; iex (irm https://raw.githubusercontent.com/ge-aero/shopdb-flask/wilm/scripts/get.ps1) - # Bleeding edge (dev-be): - $env:SHOPDB_CHANNEL='edge'; iex (irm https://raw.githubusercontent.com/ge-aero/shopdb-flask/wilm/scripts/get.ps1) + $env:SHOPDB_CHANNEL='edge' + $env:SHOPDB_TOKEN='ghp_yourtoken' + $h=@{ Authorization="token $env:SHOPDB_TOKEN" } + iex (irm -Headers $h https://raw.githubusercontent.com/ge-aero/shopdb-flask/wilm/scripts/get.ps1) + + ge-aero/shopdb-flask is a PRIVATE repo, so both the raw fetch of this + launcher AND the git clone it performs need a GitHub token. The raw fetch is + authenticated by the -Headers on irm above; the clone is authenticated here + by reading the same token from the environment (SHOPDB_TOKEN, or GITHUB_TOKEN + as a fallback) and using it in the clone URL. Anonymous access returns 404. SHOPDB_DIR overrides the clone location (default %USERPROFILE%\shopdb-dev). @@ -28,7 +34,18 @@ $ErrorActionPreference = 'Stop' -$repoUrl = 'https://github.com/ge-aero/shopdb-flask.git' +# Private-repo access token, used for the git clone/fetch below. The same token +# authenticated the raw fetch of this script (via irm -Headers). Prefer the +# ShopDB-specific var so a pilot can keep an unrelated GITHUB_TOKEN in place. +$token = if ($env:SHOPDB_TOKEN) { $env:SHOPDB_TOKEN } elseif ($env:GITHUB_TOKEN) { $env:GITHUB_TOKEN } else { '' } +if (-not $token) { + throw 'No token found. Set $env:SHOPDB_TOKEN (a GitHub PAT with repo read) before running; the repo is private.' +} + +# x-access-token is GitHub's documented username for token-in-URL auth; it works +# for classic PATs and fine-grained tokens alike. Kept out of any Write-Host so +# the secret never lands in the transcript. +$repoUrl = "https://x-access-token:$token@github.com/ge-aero/shopdb-flask.git" $channel = if ($env:SHOPDB_CHANNEL) { $env:SHOPDB_CHANNEL } else { 'stable' } if ($channel -notin @('stable', 'edge')) { throw "SHOPDB_CHANNEL must be 'stable' or 'edge' (got '$channel')." @@ -46,16 +63,27 @@ if (-not (Get-Command git -ErrorAction SilentlyContinue)) { if (Test-Path (Join-Path $target '.git')) { Write-Host "==> Updating existing clone" -ForegroundColor Cyan - git -C $target fetch origin $branch + # Fetch by explicit tokenized URL, not `origin`: origin is deliberately the + # clean tokenless URL (see the clone path below), so a bare `fetch origin` + # would 404 against the private repo. Passing the URL keeps the token off + # disk while still authenticating this pull. + git -C $target fetch $repoUrl $branch if ($LASTEXITCODE -ne 0) { throw "git fetch failed ($LASTEXITCODE)." } git -C $target checkout $branch if ($LASTEXITCODE -ne 0) { throw "git checkout failed ($LASTEXITCODE)." } - git -C $target pull --ff-only origin $branch - if ($LASTEXITCODE -ne 0) { throw "git pull failed ($LASTEXITCODE)." } + git -C $target merge --ff-only FETCH_HEAD + if ($LASTEXITCODE -ne 0) { throw "git merge --ff-only failed ($LASTEXITCODE)." } } else { Write-Host "==> Cloning $branch" -ForegroundColor Cyan git clone --branch $branch $repoUrl $target if ($LASTEXITCODE -ne 0) { throw "git clone failed ($LASTEXITCODE)." } + # Scrub the token out of the persisted remote: `git clone` writes the full + # URL (token included) into .git/config. Reset origin to the clean URL so the + # secret does not sit on disk. Fetch/pull above still work because this only + # runs on the fresh-clone path; a returning pilot re-fetches with a clean + # origin and their own credential helper / token as usual. + git -C $target remote set-url origin 'https://github.com/ge-aero/shopdb-flask.git' + if ($LASTEXITCODE -ne 0) { throw "git remote set-url failed ($LASTEXITCODE)." } } $bootstrap = Join-Path $target 'scripts\dev-bootstrap.ps1'