From 881debb22b3f9d5b5ad2753892c7e8ff2131ec34 Mon Sep 17 00:00:00 2001 From: Q Bera Date: Fri, 22 May 2026 12:28:36 -0400 Subject: [PATCH 1/8] security: split secrets from fork-processing workflow rebasing 392 to main after merge of 391 --- .github/workflows/post-validate.yml | 105 ++++++++++++++ .github/workflows/validate.yml | 210 +++++++++++----------------- 2 files changed, 188 insertions(+), 127 deletions(-) create mode 100644 .github/workflows/post-validate.yml diff --git a/.github/workflows/post-validate.yml b/.github/workflows/post-validate.yml new file mode 100644 index 00000000..60802303 --- /dev/null +++ b/.github/workflows/post-validate.yml @@ -0,0 +1,105 @@ +# This workflow handles the secret-dependent upload step. +# It runs AFTER the Validate workflow completes and never checks out fork code. +# Secrets (Cloudflare creds) only exist in this workflow, isolated from +# any fork-controlled input. +# +# The artifact bridge: +# Validate (pull_request_target, no secrets) +# └── packages asset files + PR metadata as artifacts +# Post-Validate (workflow_run, has secrets) +# └── downloads artifacts, uploads to Cloudflare using base branch scripts + +name: Post-Validate + +on: + workflow_run: + workflows: ["Validate"] + types: [completed] + +jobs: + upload-assets: + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion == 'success' + environment: cloudflare-uploads + permissions: + contents: read + pull-requests: write + actions: read + + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version-file: '.nvmrc' + + - name: Setup pnpm + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + with: + version: 9.15.9 + + - name: Get pnpm store directory + shell: bash + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Setup pnpm cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + # Read PR metadata from artifact saved by Validate workflow. + # We use artifacts instead of workflow_run.pull_requests[] because + # that array is empty for fork PRs (known GitHub limitation). + - name: Download PR info + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: pr-info + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ github.token }} + + - name: Read PR metadata + id: pr + run: | + echo "number=$(cat pr_number.txt)" >> $GITHUB_OUTPUT + echo "head_repo=$(cat pr_head_repo.txt)" >> $GITHUB_OUTPUT + echo "head_sha=$(cat pr_head_sha.txt)" >> $GITHUB_OUTPUT + + # Try to download the asset artifact. If no assets changed in the PR, + # the Validate workflow skipped the package-assets job and this artifact + # won't exist — that's expected, so continue-on-error. + - name: Download asset files + id: download-assets + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: pr-assets + path: ./head/src/assets/ + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ github.token }} + continue-on-error: true + + - name: Upload changed images to Cloudflare Images + if: steps.download-assets.outcome == 'success' + env: + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + CLOUDFLARE_IMAGES_API_TOKEN: ${{ secrets.CLOUDFLARE_IMAGES_API_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository }} + PR_NUMBER: ${{ steps.pr.outputs.number }} + run: pnpm upload:assets ./head + + - name: Post summary comment + if: always() && steps.download-assets.outcome == 'success' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR: ${{ steps.pr.outputs.number }} + run: | + if [ -s "$GITHUB_STEP_SUMMARY" ]; then + gh pr comment "$PR" --body-file "$GITHUB_STEP_SUMMARY" + fi diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 4cf12faf..3d8ab978 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -9,13 +9,11 @@ permissions: jobs: schema: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -23,44 +21,40 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 with: version: 9.15.9 - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install dependencies - run: pnpm install - + run: pnpm install + - name: Validate JSON files - run: | - pnpm validate:json head + run: pnpm validate:json head format: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -68,25 +62,24 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 with: version: 9.15.9 - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- @@ -99,13 +92,11 @@ jobs: data-consistency: needs: schema runs-on: ubuntu-latest - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -113,35 +104,33 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 with: version: 9.15.9 - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install dependencies run: pnpm install - + + # BERACHAIN_HUB_API_TOKEN and BERACHAIN_HUB_API_BASE_URL removed — + # not referenced by any script (confirmed via code audit May 2026) - name: Validate consistency with on-chain data - env: - BERACHAIN_HUB_API_TOKEN: ${{ secrets.BERACHAIN_HUB_API_TOKEN }} - BERACHAIN_HUB_API_BASE_URL: ${{ secrets.BERACHAIN_HUB_API_BASE_URL }} run: pnpm validate:data head detect-changes: @@ -149,12 +138,11 @@ jobs: outputs: assets-changed: ${{ steps.filter.outputs.assets }} steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - id: filter - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 + uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3.0.3 with: base: ${{ github.event.pull_request.base.sha }} ref: ${{ github.event.pull_request.head.sha }} @@ -162,83 +150,59 @@ jobs: assets: - 'src/assets/**' - upload-assets: + # Save PR metadata as artifact for the post-validate workflow. + # workflow_run.pull_requests[] is empty for fork PRs (known GitHub bug), + # so we pass it explicitly via artifact. + save-pr-info: + runs-on: ubuntu-latest + steps: + - name: Save PR number and head info + run: | + echo "${{ github.event.pull_request.number }}" > pr_number.txt + echo "${{ github.event.pull_request.head.repo.full_name }}" > pr_head_repo.txt + echo "${{ github.event.pull_request.head.sha }}" > pr_head_sha.txt + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: pr-info + path: | + pr_number.txt + pr_head_repo.txt + pr_head_sha.txt + retention-days: 1 + + # Package changed asset files for the post-validate upload job. + # This runs in the no-secrets context; the actual Cloudflare upload + # happens in post-validate.yml which has secrets but never checks out fork code. + package-assets: needs: [schema, detect-changes] if: needs.detect-changes.outputs.assets-changed == 'true' runs-on: ubuntu-latest - environment: cloudflare-uploads - permissions: - contents: read - pull-requests: write - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} path: ./head persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 - with: - node-version-file: '.nvmrc' - - - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - with: - version: 9.15.9 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install - - - name: Upload changed images to Cloudflare Images - env: - CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - CLOUDFLARE_IMAGES_API_TOKEN: ${{ secrets.CLOUDFLARE_IMAGES_API_TOKEN }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPOSITORY: ${{ github.repository }} - PR_NUMBER: ${{ github.event.pull_request.number }} - run: pnpm upload:assets ./head - - - name: Post summary comment - if: always() - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR: ${{ github.event.pull_request.number }} - run: | - if [ -s "$GITHUB_STEP_SUMMARY" ]; then - gh pr comment "$PR" --body-file "$GITHUB_STEP_SUMMARY" - fi + name: pr-assets + path: ./head/src/assets/ + retention-days: 1 images: - needs: [schema, upload-assets] - if: always() && needs.schema.result == 'success' && (needs.upload-assets.result == 'success' || needs.upload-assets.result == 'skipped') + needs: [schema, package-assets] + if: always() && needs.schema.result == 'success' && (needs.package-assets.result == 'success' || needs.package-assets.result == 'skipped') runs-on: ubuntu-latest - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -246,25 +210,24 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 with: version: 9.15.9 - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- @@ -272,19 +235,16 @@ jobs: run: pnpm install - name: Validate images - run: | - pnpm validate:images head + run: pnpm validate:images head coingecko: needs: schema runs-on: ubuntu-latest - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -292,25 +252,24 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 with: version: 9.15.9 - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- @@ -323,13 +282,11 @@ jobs: pyth: needs: schema runs-on: ubuntu-latest - steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -337,25 +294,24 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 with: version: 9.15.9 - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- From f7a363e25338f30612201f1056af93e1d0de9ecf Mon Sep 17 00:00:00 2001 From: qtipbera <194121515+qtipbera@users.noreply.github.com> Date: Fri, 22 May 2026 13:15:31 -0400 Subject: [PATCH 2/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: qtipbera <194121515+qtipbera@users.noreply.github.com> --- .github/workflows/post-validate.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/post-validate.yml b/.github/workflows/post-validate.yml index 60802303..220ed6f9 100644 --- a/.github/workflows/post-validate.yml +++ b/.github/workflows/post-validate.yml @@ -28,6 +28,8 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 From c303f3f9274501360f58f1e3025b3642318f4caf Mon Sep 17 00:00:00 2001 From: Q Bera Date: Mon, 25 May 2026 11:06:33 -0400 Subject: [PATCH 3/8] fix: upgrade all actions to node24, pin base checkouts, fix pnpm v2 --- .github/workflows/post-validate.yml | 13 ++--- .github/workflows/validate.yml | 80 ++++++++++++++++------------- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/.github/workflows/post-validate.yml b/.github/workflows/post-validate.yml index 220ed6f9..a7091757 100644 --- a/.github/workflows/post-validate.yml +++ b/.github/workflows/post-validate.yml @@ -27,17 +27,18 @@ jobs: actions: read steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.workflow_run.head_sha }} persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -46,7 +47,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} @@ -60,7 +61,7 @@ jobs: # We use artifacts instead of workflow_run.pull_requests[] because # that array is empty for fork PRs (known GitHub limitation). - name: Download PR info - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: name: pr-info run-id: ${{ github.event.workflow_run.id }} @@ -78,7 +79,7 @@ jobs: # won't exist — that's expected, so continue-on-error. - name: Download asset files id: download-assets - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: name: pr-assets path: ./head/src/assets/ diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 3d8ab978..1581fdd3 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -10,10 +10,11 @@ jobs: schema: runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -21,12 +22,12 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -35,7 +36,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} @@ -51,10 +52,11 @@ jobs: format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -62,12 +64,12 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -76,7 +78,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} @@ -93,10 +95,11 @@ jobs: needs: schema runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -104,12 +107,12 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -118,7 +121,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} @@ -138,11 +141,12 @@ jobs: outputs: assets-changed: ${{ steps.filter.outputs.assets }} steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - id: filter - uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3.0.3 + uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 with: base: ${{ github.event.pull_request.base.sha }} ref: ${{ github.event.pull_request.head.sha }} @@ -161,7 +165,7 @@ jobs: echo "${{ github.event.pull_request.number }}" > pr_number.txt echo "${{ github.event.pull_request.head.repo.full_name }}" > pr_head_repo.txt echo "${{ github.event.pull_request.head.sha }}" > pr_head_sha.txt - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: pr-info path: | @@ -178,17 +182,18 @@ jobs: if: needs.detect-changes.outputs.assets-changed == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} path: ./head persist-credentials: false - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: pr-assets path: ./head/src/assets/ @@ -199,10 +204,11 @@ jobs: if: always() && needs.schema.result == 'success' && (needs.package-assets.result == 'success' || needs.package-assets.result == 'skipped') runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -210,12 +216,12 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -224,7 +230,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} @@ -241,10 +247,11 @@ jobs: needs: schema runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -252,12 +259,12 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -266,7 +273,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} @@ -283,10 +290,11 @@ jobs: needs: schema runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: + ref: ${{ github.event.pull_request.base.sha }} persist-credentials: false - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -294,12 +302,12 @@ jobs: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' - name: Setup pnpm - uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1 + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 9.15.9 @@ -308,7 +316,7 @@ jobs: run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} From c82e23d623acfdef3e820ac0d3fd1e019b997f84 Mon Sep 17 00:00:00 2001 From: Q Bera Date: Mon, 25 May 2026 11:14:09 -0400 Subject: [PATCH 4/8] fix: remove workflow_run.head_sha ref from post-validate checkout --- .github/workflows/post-validate.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/post-validate.yml b/.github/workflows/post-validate.yml index a7091757..ffc158f2 100644 --- a/.github/workflows/post-validate.yml +++ b/.github/workflows/post-validate.yml @@ -29,7 +29,6 @@ jobs: steps: - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: - ref: ${{ github.event.workflow_run.head_sha }} persist-credentials: false - name: Setup Node.js From 9503ebaf8541a9308c9052377e514cbbb2df51e6 Mon Sep 17 00:00:00 2001 From: Q Bera Date: Tue, 26 May 2026 06:32:37 -0400 Subject: [PATCH 5/8] chore: trigger CI From fe2cffd4db02d8eee57bb90eefe7167382972755 Mon Sep 17 00:00:00 2001 From: Q Bera Date: Tue, 26 May 2026 13:32:44 -0400 Subject: [PATCH 6/8] chore: trigger CI From 2d85abc0a6771e4eab22a1f2ceee007882e919d2 Mon Sep 17 00:00:00 2001 From: Q Bera Date: Wed, 27 May 2026 11:17:44 -0400 Subject: [PATCH 7/8] fix: disable setup-node v5 auto-cache --- .github/workflows/post-validate.yml | 1 + .github/workflows/validate.yml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/post-validate.yml b/.github/workflows/post-validate.yml index ffc158f2..00bfab66 100644 --- a/.github/workflows/post-validate.yml +++ b/.github/workflows/post-validate.yml @@ -35,6 +35,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 1581fdd3..3a9d29a7 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -25,6 +25,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 @@ -67,6 +68,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 @@ -110,6 +112,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 @@ -219,6 +222,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 @@ -262,6 +266,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 @@ -305,6 +310,7 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: '.nvmrc' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 From 60e0ccb1c6a204f99c9fbe263cd1f6a656e318d7 Mon Sep 17 00:00:00 2001 From: Q Bera Date: Tue, 2 Jun 2026 10:22:45 -0400 Subject: [PATCH 8/8] fixing broken validate workflow --- .github/workflows/validate.yml | 189 ++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 84 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 7385352c..0c1ebd61 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -1,8 +1,26 @@ +# Validate runs on pull_request_target so it can validate fork PRs, BUT it holds +# NO secrets and never executes fork code. Every job runs the trusted base-branch +# scripts against the PR head, which is checked out into ./head as DATA only. +# +# Anything that needs a secret (the Cloudflare upload) is handed off to +# post-validate.yml (workflow_run), which never checks out fork code. +# +# Artifact bridge: +# Validate (pull_request_target, NO secrets) +# ├── validates PR head data (schema / format / images / coingecko / pyth / on-chain) +# ├── publishes PR metadata as the `pr-info` artifact +# └── publishes the changed asset files as the `pr-assets` artifact +# Post-Validate (workflow_run, HAS secrets, no fork checkout) +# └── downloads those artifacts and uploads to Cloudflare Images +# +# Pinned action SHAs and persist-credentials:false are retained from #391. + name: Validate on: pull_request_target: +# Minimal token, read-only. There are NO secrets in this workflow. permissions: contents: read @@ -35,23 +53,23 @@ jobs: - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + # Key on the BASE lockfile only (not **/), so the fork's lockfile + # cannot influence the cache key. + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install dependencies - run: pnpm install - + run: pnpm install + - name: Validate JSON files - run: | - pnpm validate:json head + run: pnpm validate:json head format: runs-on: ubuntu-latest @@ -81,14 +99,13 @@ jobs: - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- @@ -127,30 +144,35 @@ jobs: - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install dependencies run: pnpm install - - - name: Validate consistency with on-chain data - env: - BERACHAIN_HUB_API_TOKEN: ${{ secrets.BERACHAIN_HUB_API_TOKEN }} - BERACHAIN_HUB_API_BASE_URL: ${{ secrets.BERACHAIN_HUB_API_BASE_URL }} + + # NO secret here. validate:data runs two kinds of check: + # - validateTokens/validateVaults read ./head's JSON and raise ERRORS + # (blocking). These are the PR-relevant checks and need no secret. + # - validateApiMetadata queries the Berachain Hub API for on-chain items + # missing metadata and only raises WARNINGS; it already catches its own + # failures and skips. Without the token it degrades to a no-op warning. + # If you want those API warnings back, run that check from post-validate.yml + # (workflow_run, where the token lives) or a scheduled job — never here. + - name: Validate consistency with on-chain data (head data only) run: pnpm validate:data head detect-changes: runs-on: ubuntu-latest outputs: assets-changed: ${{ steps.filter.outputs.assets }} + assets-files: ${{ steps.filter.outputs.assets_files }} steps: - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: @@ -161,80 +183,83 @@ jobs: with: base: ${{ github.event.pull_request.base.sha }} ref: ${{ github.event.pull_request.head.sha }} + list-files: json filters: | assets: - 'src/assets/**' - upload-assets: - needs: [schema, detect-changes] - if: needs.detect-changes.outputs.assets-changed == 'true' + package-pr-context: + # Publishes the inputs post-validate.yml needs. The PR head is checked out + # as DATA only here: no install, no scripts run against it. + needs: detect-changes runs-on: ubuntu-latest - environment: cloudflare-uploads - permissions: - contents: read - pull-requests: write steps: - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - with: - ref: ${{ github.event.pull_request.base.sha }} - persist-credentials: false - - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - name: Checkout PR head (untrusted, data only) + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} path: ./head persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 - with: - node-version-file: '.nvmrc' - package-manager-cache: false - - - name: Setup pnpm - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - with: - version: 9.15.9 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install - - - name: Upload changed images to Cloudflare Images + # workflow_run's pull_requests[] is empty for fork PRs, so post-validate + # reads PR identity from this artifact instead. PR-controlled values are + # passed through env (never interpolated directly into the script body). + - name: Write PR metadata env: - CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - CLOUDFLARE_IMAGES_API_TOKEN: ${{ secrets.CLOUDFLARE_IMAGES_API_TOKEN }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPOSITORY: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} - run: pnpm upload:assets ./head - - - name: Post summary comment - if: always() + PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: | + mkdir -p pr-info + printf '%s' "$PR_NUMBER" > pr-info/pr_number.txt + printf '%s' "$PR_HEAD_REPO" > pr-info/pr_head_repo.txt + printf '%s' "$PR_HEAD_SHA" > pr-info/pr_head_sha.txt + + - name: Upload PR info artifact + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: pr-info + path: pr-info/ + if-no-files-found: error + retention-days: 1 + + # Stage ONLY the changed asset files, preserving their path under src/assets, + # so post-validate uploads exactly the files this PR touched. + - name: Stage changed asset files + if: needs.detect-changes.outputs.assets-changed == 'true' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR: ${{ github.event.pull_request.number }} + CHANGED_FILES: ${{ needs.detect-changes.outputs.assets-files }} run: | - if [ -s "$GITHUB_STEP_SUMMARY" ]; then - gh pr comment "$PR" --body-file "$GITHUB_STEP_SUMMARY" - fi + mkdir -p pr-assets + printf '%s' "$CHANGED_FILES" | jq -r '.[]' | while IFS= read -r f; do + if [ -z "$f" ]; then continue; fi + case "$f" in + src/assets/*) ;; + *) continue ;; + esac + case "$f" in + *..*) continue ;; + esac + rel="${f#src/assets/}" + if [ -f "head/$f" ]; then + mkdir -p "pr-assets/$(dirname "$rel")" + cp "head/$f" "pr-assets/$rel" + fi + done + + - name: Upload changed assets artifact + if: needs.detect-changes.outputs.assets-changed == 'true' + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: pr-assets + path: pr-assets/ + if-no-files-found: ignore + retention-days: 1 images: - needs: [schema, upload-assets] - if: always() && needs.schema.result == 'success' && (needs.upload-assets.result == 'success' || needs.upload-assets.result == 'skipped') + needs: schema runs-on: ubuntu-latest steps: @@ -262,14 +287,13 @@ jobs: - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- @@ -277,8 +301,7 @@ jobs: run: pnpm install - name: Validate images - run: | - pnpm validate:images head + run: pnpm validate:images head coingecko: needs: schema @@ -309,14 +332,13 @@ jobs: - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- @@ -355,14 +377,13 @@ jobs: - name: Get pnpm store directory shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store-