From 59a93d945c83c9f240d1faf66c38a79c9679490e Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Mon, 5 Oct 2026 11:28:09 +0000 Subject: [PATCH] fix(cli): Install nightlies from Toolkit GHCR Co-Authored-By: GPT-6 Sol --- packages/cli/install | 16 ++++--- packages/cli/test/lib/install-script.test.ts | 45 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/packages/cli/install b/packages/cli/install index 7ee7d6264..6a7063aa0 100755 --- a/packages/cli/install +++ b/packages/cli/install @@ -202,18 +202,22 @@ if [[ "$requested_version" == "nightly" ]]; then echo -e "${MUTED}Fetching nightly build from GHCR...${NC}" # Step 1: Get anonymous pull token - GHCR_TOKEN=$(curl -sf \ - "https://ghcr.io/token?scope=repository:getsentry/cli:pull" \ - | awk -F'"' '{for(i=1;i<=NF;i++) if($i=="token"){print $(i+2);exit}}') + if ! GHCR_TOKEN=$(curl -sf \ + "https://ghcr.io/token?scope=repository:getsentry/toolkit:pull" \ + | awk -F'"' '{for(i=1;i<=NF;i++) if($i=="token"){print $(i+2);exit}}'); then + die "Failed to get GHCR token" "ghcr-token" + fi if [[ -z "$GHCR_TOKEN" ]]; then die "Failed to get GHCR token" "ghcr-token" fi # Step 2: Fetch the OCI manifest for the :nightly tag - MANIFEST=$(curl -sf \ + if ! MANIFEST=$(curl -sf \ -H "Authorization: Bearer $GHCR_TOKEN" \ -H "Accept: application/vnd.oci.image.manifest.v1+json" \ - "https://ghcr.io/v2/getsentry/cli/manifests/nightly") + "https://ghcr.io/v2/getsentry/toolkit/manifests/nightly"); then + die "Failed to fetch nightly manifest from GHCR" "ghcr-manifest" + fi if [[ -z "$MANIFEST" ]]; then die "Failed to fetch nightly manifest from GHCR" "ghcr-manifest" fi @@ -248,7 +252,7 @@ if [[ "$requested_version" == "nightly" ]]; then # the redirect target. if ! blob_status=$(curl -sS -D "$blob_headers" -o "$blob_file" -w '%{http_code}' \ -H "Authorization: Bearer $GHCR_TOKEN" \ - "https://ghcr.io/v2/getsentry/cli/blobs/${digest}"); then + "https://ghcr.io/v2/getsentry/toolkit/blobs/${digest}"); then die "Failed to fetch nightly blob from GHCR" "ghcr-blob" fi diff --git a/packages/cli/test/lib/install-script.test.ts b/packages/cli/test/lib/install-script.test.ts index e3ec7e3a1..e3b9eb7b0 100644 --- a/packages/cli/test/lib/install-script.test.ts +++ b/packages/cli/test/lib/install-script.test.ts @@ -287,11 +287,18 @@ esac `#!/usr/bin/env bash set -euo pipefail url="\${!#}" +printf '%s\\n' "$url" >> "$SENTRY_TEST_DIR/curl-urls" case "$url" in *"/token?"*) + if [[ "\${SENTRY_TEST_NIGHTLY_TOKEN_FAIL:-0}" != "0" ]]; then + exit 22 + fi printf '{"token":"test-token"}' ;; *"/manifests/nightly") + if [[ "\${SENTRY_TEST_NIGHTLY_MANIFEST_FAIL:-0}" != "0" ]]; then + exit 22 + fi cat <<'JSON' ${manifest} JSON @@ -450,6 +457,44 @@ process.exitCode = result.status ?? 1; ]); expect(existsSync(join(installDir, "sentry"))).toBe(true); expect(installerTempFiles()).toEqual([]); + expect(recorded("curl-urls").slice(0, 3)).toEqual([ + "https://ghcr.io/token?scope=repository:getsentry/toolkit:pull", + "https://ghcr.io/v2/getsentry/toolkit/manifests/nightly", + "https://ghcr.io/v2/getsentry/toolkit/blobs/sha256:test", + ]); + }); + + test.each([ + { failure: "token", flag: "SENTRY_TEST_NIGHTLY_TOKEN_FAIL" }, + { failure: "manifest", flag: "SENTRY_TEST_NIGHTLY_MANIFEST_FAIL" }, + ])("does not fall back to legacy GHCR when Toolkit $failure fails", ({ + flag, + }) => { + configureNightlyDownload(false); + env[flag] = "1"; + const result = spawnSync("bash", [installScript, "--version", "nightly"], { + env, + encoding: "utf8", + timeout: 10_000, + }); + + expect(result.status).not.toBe(0); + expect(result.stderr).toContain( + flag === "SENTRY_TEST_NIGHTLY_TOKEN_FAIL" + ? "Failed to get GHCR token" + : "Failed to fetch nightly manifest from GHCR" + ); + expect(result.stderr).not.toContain("Unexpected failure at line"); + expect(recorded("curl-urls")).toEqual( + flag === "SENTRY_TEST_NIGHTLY_TOKEN_FAIL" + ? ["https://ghcr.io/token?scope=repository:getsentry/toolkit:pull"] + : [ + "https://ghcr.io/token?scope=repository:getsentry/toolkit:pull", + "https://ghcr.io/v2/getsentry/toolkit/manifests/nightly", + ] + ); + expect(recorded("setup-args")).toEqual([]); + expect(existsSync(join(installDir, "sentry"))).toBe(false); }); test("uses the legacy release only after a Toolkit tag returns HTTP 404", () => {