Просмотр исходного кода

CI: install Railway CLI from a checksum-verified release; show Vercel errors

- npm's @railway/cli needs its install script to fetch the binary
  (Sonar S6505). Download the pinned v5.35.0 release with gh, check the
  published SHA-256, then install it.
- domains.sh printed only curl's "403"; print Vercel's error message
  so token scope problems are visible in the log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Andrey Yasko 2 недель назад
Родитель
Сommit
244d1e9fb8
2 измененных файлов с 47 добавлено и 10 удалено
  1. 36 6
      .github/workflows/ci.yml
  2. 11 4
      scripts/railway/domains.sh

+ 36 - 6
.github/workflows/ci.yml

@@ -126,8 +126,18 @@ jobs:
         chmod +x deploy/entrypoint.sh
 
     - name: Install Railway CLI
-      # Pinned npm package instead of piping an install script into sh.
-      run: npm install --global @railway/cli@5.35.0
+      # Pinned release, checked against its published SHA-256 before it is run.
+      env:
+        GH_TOKEN: ${{ github.token }}
+        RAILWAY_CLI_VERSION: v5.35.0
+        RAILWAY_CLI_SHA256: fb675d282e613ae9868b25be1ad4567d37b9c13901785f636dd0a13837f8ecf0
+      run: |
+        asset="railway-${RAILWAY_CLI_VERSION}-x86_64-unknown-linux-musl.tar.gz"
+        gh release download "$RAILWAY_CLI_VERSION" --repo railwayapp/cli --pattern "$asset" --dir /tmp/railway-cli
+        echo "${RAILWAY_CLI_SHA256}  /tmp/railway-cli/${asset}" | sha256sum -c -
+        tar -xzf "/tmp/railway-cli/${asset}" -C /tmp/railway-cli railway
+        sudo install -m 0755 /tmp/railway-cli/railway /usr/local/bin/railway
+        railway --version
 
     - name: Provision PR environment
       run: |
@@ -263,8 +273,18 @@ jobs:
         chmod +x deploy/entrypoint.sh
 
     - name: Install Railway CLI
-      # Pinned npm package instead of piping an install script into sh.
-      run: npm install --global @railway/cli@5.35.0
+      # Pinned release, checked against its published SHA-256 before it is run.
+      env:
+        GH_TOKEN: ${{ github.token }}
+        RAILWAY_CLI_VERSION: v5.35.0
+        RAILWAY_CLI_SHA256: fb675d282e613ae9868b25be1ad4567d37b9c13901785f636dd0a13837f8ecf0
+      run: |
+        asset="railway-${RAILWAY_CLI_VERSION}-x86_64-unknown-linux-musl.tar.gz"
+        gh release download "$RAILWAY_CLI_VERSION" --repo railwayapp/cli --pattern "$asset" --dir /tmp/railway-cli
+        echo "${RAILWAY_CLI_SHA256}  /tmp/railway-cli/${asset}" | sha256sum -c -
+        tar -xzf "/tmp/railway-cli/${asset}" -C /tmp/railway-cli railway
+        sudo install -m 0755 /tmp/railway-cli/railway /usr/local/bin/railway
+        railway --version
 
     - name: Configure production
       run: |
@@ -326,8 +346,18 @@ jobs:
         scripts/railway/domains.sh dns-remove "api-pr-${{ github.event.pull_request.number }}.unacms.app"
 
     - name: Install Railway CLI
-      # Pinned npm package instead of piping an install script into sh.
-      run: npm install --global @railway/cli@5.35.0
+      # Pinned release, checked against its published SHA-256 before it is run.
+      env:
+        GH_TOKEN: ${{ github.token }}
+        RAILWAY_CLI_VERSION: v5.35.0
+        RAILWAY_CLI_SHA256: fb675d282e613ae9868b25be1ad4567d37b9c13901785f636dd0a13837f8ecf0
+      run: |
+        asset="railway-${RAILWAY_CLI_VERSION}-x86_64-unknown-linux-musl.tar.gz"
+        gh release download "$RAILWAY_CLI_VERSION" --repo railwayapp/cli --pattern "$asset" --dir /tmp/railway-cli
+        echo "${RAILWAY_CLI_SHA256}  /tmp/railway-cli/${asset}" | sha256sum -c -
+        tar -xzf "/tmp/railway-cli/${asset}" -C /tmp/railway-cli railway
+        sudo install -m 0755 /tmp/railway-cli/railway /usr/local/bin/railway
+        railway --version
 
     - name: Delete PR environment
       run: |

+ 11 - 4
scripts/railway/domains.sh

@@ -26,11 +26,18 @@ vercel() { # vercel <METHOD> <path> [json-body]
     local method=$1 path=$2 body=${3:-}
     local sep='?'; case "$path" in *\?*) sep='&' ;; esac
     local url="$VERCEL_API$path${TEAM_ID:+${sep}teamId=$TEAM_ID}${TEAM_SLUG:+${sep}slug=$TEAM_SLUG}"
-    if [ -n "$body" ]; then
-        curl -fsS -X "$method" -H "Authorization: Bearer $VERCEL_TOKEN" -H 'Content-Type: application/json' -d "$body" "$url"
-    else
-        curl -fsS -X "$method" -H "Authorization: Bearer $VERCEL_TOKEN" "$url"
+    local out code
+    out=$(mktemp)
+    code=$(curl -sS -o "$out" -w '%{http_code}' -X "$method" -H "Authorization: Bearer $VERCEL_TOKEN" \
+        ${body:+-H 'Content-Type: application/json' -d "$body"} "$url") || code=000
+    if [ "${code:0:1}" != 2 ]; then
+        # Vercel explains 403s (token scope, team access) in the body; show it.
+        echo "vercel: $method ${path%%\?*} -> HTTP $code: $(jq -r '.error.message // .error.code // empty' "$out" 2>/dev/null)" >&2
+        rm -f "$out"
+        return 1
     fi
+    cat "$out"
+    rm -f "$out"
 }
 
 # The Vercel team (or personal account) that owns DNS_ZONE; it also owns the client project.