diff --git a/prepare_assets.sh b/prepare_assets.sh index 1b75c5f1..ec1aaa80 100755 --- a/prepare_assets.sh +++ b/prepare_assets.sh @@ -41,6 +41,20 @@ if [[ "${OS_NAME}" == "osx" ]]; then echo "+ signing" export CODESIGN_IDENTITY AGENT_TEMPDIRECTORY + # sign.ts gates main() behind `import.meta.main`, which is undefined in + # Node 22 (only available in Node 23+ behind a flag / Node 24 unflagged). + # When run on Node 22 the entrypoint never executes, sign() is never + # called, and the resulting .app is unsigned — codesign --verify then + # fails with "code object is not signed at all" (see release run + # 26356902456). Force the guard to true: we only ever invoke this + # file directly via `node sign.ts ...`, never import it as a module. + SIGN_TS="vscode/build/darwin/sign.ts" + if [[ -f "${SIGN_TS}" ]] && grep -q 'import\.meta\.main' "${SIGN_TS}"; then + echo "+ patching sign.ts entrypoint guard for Node 22 compatibility" + sed -i.bak 's|import\.meta\.main|true /* import.meta.main (Node 22 polyfill) */|g' "${SIGN_TS}" + rm -f "${SIGN_TS}.bak" + fi + DEBUG="electron-osx-sign*" node --experimental-strip-types vscode/build/darwin/sign.ts "$( pwd )" # Verify code signing succeeded diff --git a/release.sh b/release.sh index 0d79795b..0ece3e28 100755 --- a/release.sh +++ b/release.sh @@ -18,6 +18,29 @@ REPOSITORY_NAME="${ASSETS_REPOSITORY/*\//}" npm install -g github-release-cli +# Probe the binaries repo with the active token BEFORE doing any work. +# Without this check, an expired/revoked RELEASE_GITHUB_TOKEN slips past +# `gh release view` (whose 401 body doesn't contain "release not found"), +# we skip release creation, then hit the upload retry loop and burn ~50min +# per job pretending a network blip will fix bad credentials. See: +# stable-linux 26356903381, stable-windows 26356902896 — both 401. +echo "+ verifying token has write access to ${ASSETS_REPOSITORY}" +PROBE_HTTP_CODE=$( gh api -i "repos/${ASSETS_REPOSITORY}" --jq '.permissions.push // false' 2>&1 | head -n 1 | awk '{print $2}' || true ) +PROBE_PUSH=$( gh api "repos/${ASSETS_REPOSITORY}" --jq '.permissions.push // false' 2>/dev/null || echo "auth_failed" ) +if [[ "${PROBE_PUSH}" == "auth_failed" ]]; then + echo "::error::Cannot authenticate to ${ASSETS_REPOSITORY}." + echo " The token in GITHUB_TOKEN/RELEASE_GITHUB_TOKEN was rejected (HTTP ${PROBE_HTTP_CODE:-unknown})." + echo " Rotate the RELEASE_GITHUB_TOKEN repo secret with a PAT that has 'contents: write'" + echo " on both ${ASSETS_REPOSITORY} and ${VERSIONS_REPOSITORY}, then re-dispatch the workflow." + exit 1 +fi +if [[ "${PROBE_PUSH}" != "true" ]]; then + echo "::error::Token authenticated but lacks push access to ${ASSETS_REPOSITORY}." + echo " permissions.push=${PROBE_PUSH}. Grant write access or use a PAT with 'contents: write'." + exit 1 +fi +echo "+ token OK" + if [[ $( gh release view "${RELEASE_VERSION}" --repo "${ASSETS_REPOSITORY}" 2>&1 ) =~ "release not found" ]]; then echo "Creating release '${RELEASE_VERSION}'" diff --git a/update_version.sh b/update_version.sh index e49ce4a1..96a503fc 100755 --- a/update_version.sh +++ b/update_version.sh @@ -23,6 +23,25 @@ fi # Support for GitHub Enterprise GH_HOST="${GH_HOST:-github.com}" +# Probe the versions repo with the active token before doing any work. +# Same rationale as release.sh: surface auth failures up front with an +# actionable message instead of dying mid-git-push after several minutes. +echo "+ verifying token has write access to ${VERSIONS_REPOSITORY}" +PROBE_PUSH=$( GH_TOKEN="${GITHUB_TOKEN}" gh api "repos/${VERSIONS_REPOSITORY}" --jq '.permissions.push // false' 2>/dev/null || echo "auth_failed" ) +if [[ "${PROBE_PUSH}" == "auth_failed" ]]; then + echo "::error::Cannot authenticate to ${VERSIONS_REPOSITORY}." + echo " The token in GITHUB_TOKEN/RELEASE_GITHUB_TOKEN was rejected." + echo " Rotate the RELEASE_GITHUB_TOKEN repo secret with a PAT that has 'contents: write'" + echo " on both ${ASSETS_REPOSITORY} and ${VERSIONS_REPOSITORY}, then re-dispatch the workflow." + exit 1 +fi +if [[ "${PROBE_PUSH}" != "true" ]]; then + echo "::error::Token authenticated but lacks push access to ${VERSIONS_REPOSITORY}." + echo " permissions.push=${PROBE_PUSH}. Grant write access or use a PAT with 'contents: write'." + exit 1 +fi +echo "+ token OK" + if [[ "${FORCE_UPDATE}" == "true" ]]; then . version.sh fi