From 1291af0b7276f658fbe257f34a97b18658229959 Mon Sep 17 00:00:00 2001 From: James Griffin Date: Thu, 20 Aug 2026 13:27:22 -0300 Subject: [PATCH] Authenticate setup-php against the GitHub API setup-php resolves its tools through the GitHub API, unauthenticated at 60 requests an hour per source address. A CI fan-out across the fleet exhausts that bucket, and the step then retries for several minutes before reporting only "Could not setup PHP 8.3". It reads as a hang rather than a throttle, and it took out both a main CI run and a release build. Each cluster has its own egress address and so its own bucket, which is why the same job passed on one runner and failed on another in the same minute. The token comes from 1Password through the Connect instance in whichever cluster picked up the job, matching the pattern in thatguygriff/infra. That repository's composite action is not reachable from here, so it is mirrored locally. It stays a step output rather than being exported to the job environment, to keep it away from the package scripts composer install runs. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0133tYSQoZhoKebKZV8o2GPs --- .gitea/actions/op-github-token/action.yml | 80 +++++++++++++++++++++++ .gitea/workflows/ci.yml | 48 ++++++++++++++ .gitea/workflows/release.yml | 15 +++++ 3 files changed, 143 insertions(+) create mode 100644 .gitea/actions/op-github-token/action.yml diff --git a/.gitea/actions/op-github-token/action.yml b/.gitea/actions/op-github-token/action.yml new file mode 100644 index 0000000..a2944b8 --- /dev/null +++ b/.gitea/actions/op-github-token/action.yml @@ -0,0 +1,80 @@ +name: GitHub API token from 1Password +description: > + Resolve the GitHub API token that setup-php authenticates with, via the + 1Password Connect instance running inside whichever cluster picked up this + job. Mirrors thatguygriff/infra .gitea/actions/op-connect, which is not + reachable from this repository. + +inputs: + connect-host: + description: 1Password Connect host + required: true + op-connect-token-eris: + description: 1Password Connect token for the eris cluster + required: true + op-connect-token-kallone: + description: 1Password Connect token for the kallone cluster + required: true + op-connect-token-nemesis: + description: 1Password Connect token for the nemesis cluster + required: true + +outputs: + token: + description: GitHub API token, for the GITHUB_TOKEN env of a setup-php step + value: ${{ steps.load.outputs.GH_API_TOKEN }} + +runs: + using: composite + steps: + # Connect is addressed at a cluster-local Service, so the token has to match + # the cluster the job landed on. A value with no match would configure no + # host at all and fail somewhere less obvious. + - name: Check RUNNER_CLUSTER is recognised + shell: bash + run: | + case "${RUNNER_CLUSTER:-}" in + eris|kallone|nemesis) echo "Runner cluster: $RUNNER_CLUSTER" ;; + "") echo "::error::RUNNER_CLUSTER is unset; no 1Password Connect token can be selected"; exit 1 ;; + *) echo "::error::RUNNER_CLUSTER='$RUNNER_CLUSTER' has no matching 1Password Connect token"; exit 1 ;; + esac + + - name: Configure Connect (eris) + if: env.RUNNER_CLUSTER == 'eris' + uses: 1password/load-secrets-action/configure@v2 + with: + connect-host: ${{ inputs.connect-host }} + connect-token: ${{ inputs.op-connect-token-eris }} + + - name: Configure Connect (kallone) + if: env.RUNNER_CLUSTER == 'kallone' + uses: 1password/load-secrets-action/configure@v2 + with: + connect-host: ${{ inputs.connect-host }} + connect-token: ${{ inputs.op-connect-token-kallone }} + + - name: Configure Connect (nemesis) + if: env.RUNNER_CLUSTER == 'nemesis' + uses: 1password/load-secrets-action/configure@v2 + with: + connect-host: ${{ inputs.connect-host }} + connect-token: ${{ inputs.op-connect-token-nemesis }} + + # export-env stays false so the token surfaces as a step output rather than + # entering the job environment, where `composer install` would run third + # party package scripts alongside it. + - name: Load GitHub API token + id: load + uses: 1password/load-secrets-action@v2 + with: + export-env: false + env: + GH_API_TOKEN: "op://Unsupervised/GitHub Personal Access Token for Gitea/token" + + - name: Verify token loaded + shell: bash + env: + GH_API_TOKEN: ${{ steps.load.outputs.GH_API_TOKEN }} + run: | + test -n "$GH_API_TOKEN" || { echo "::error::GitHub API token is empty after loading from 1Password"; exit 1; } + echo "GitHub API token loaded" diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index c14788b..e96414f 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -14,11 +14,26 @@ jobs: steps: - uses: actions/checkout@v4 + # setup-php resolves its tools through the GitHub API, which allows 60 + # requests an hour per source address unauthenticated. A CI fan-out across + # the fleet exhausts that, and the step then retries for minutes before + # reporting only "Could not setup PHP". + - name: Load GitHub API token + id: gh-token + uses: ./.gitea/actions/op-github-token + with: + connect-host: ${{ vars.OP_CONNECT_HOST }} + op-connect-token-eris: ${{ secrets.OP_CONNECT_TOKEN_ERIS }} + op-connect-token-kallone: ${{ secrets.OP_CONNECT_TOKEN_KALLONE }} + op-connect-token-nemesis: ${{ secrets.OP_CONNECT_TOKEN_NEMESIS }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' tools: composer:v2 + env: + GITHUB_TOKEN: ${{ steps.gh-token.outputs.token }} - name: Cache Composer packages uses: actions/cache@v3 @@ -39,11 +54,22 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load GitHub API token + id: gh-token + uses: ./.gitea/actions/op-github-token + with: + connect-host: ${{ vars.OP_CONNECT_HOST }} + op-connect-token-eris: ${{ secrets.OP_CONNECT_TOKEN_ERIS }} + op-connect-token-kallone: ${{ secrets.OP_CONNECT_TOKEN_KALLONE }} + op-connect-token-nemesis: ${{ secrets.OP_CONNECT_TOKEN_NEMESIS }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' tools: composer:v2 + env: + GITHUB_TOKEN: ${{ steps.gh-token.outputs.token }} - name: Cache Composer packages uses: actions/cache@v3 @@ -70,6 +96,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load GitHub API token + id: gh-token + uses: ./.gitea/actions/op-github-token + with: + connect-host: ${{ vars.OP_CONNECT_HOST }} + op-connect-token-eris: ${{ secrets.OP_CONNECT_TOKEN_ERIS }} + op-connect-token-kallone: ${{ secrets.OP_CONNECT_TOKEN_KALLONE }} + op-connect-token-nemesis: ${{ secrets.OP_CONNECT_TOKEN_NEMESIS }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -77,6 +112,8 @@ jobs: extensions: mbstring, intl coverage: none tools: composer:v2 + env: + GITHUB_TOKEN: ${{ steps.gh-token.outputs.token }} - name: Cache Composer packages uses: actions/cache@v3 @@ -113,11 +150,22 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load GitHub API token + id: gh-token + uses: ./.gitea/actions/op-github-token + with: + connect-host: ${{ vars.OP_CONNECT_HOST }} + op-connect-token-eris: ${{ secrets.OP_CONNECT_TOKEN_ERIS }} + op-connect-token-kallone: ${{ secrets.OP_CONNECT_TOKEN_KALLONE }} + op-connect-token-nemesis: ${{ secrets.OP_CONNECT_TOKEN_NEMESIS }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' tools: composer:v2 + env: + GITHUB_TOKEN: ${{ steps.gh-token.outputs.token }} - name: Build plugin zip run: composer build diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index ff7e6b9..a5a06ce 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -18,11 +18,26 @@ jobs: steps: - uses: actions/checkout@v4 + # setup-php resolves its tools through the GitHub API, which allows 60 + # requests an hour per source address unauthenticated. A CI fan-out across + # the fleet exhausts that, and the step then retries for minutes before + # reporting only "Could not setup PHP". + - name: Load GitHub API token + id: gh-token + uses: ./.gitea/actions/op-github-token + with: + connect-host: ${{ vars.OP_CONNECT_HOST }} + op-connect-token-eris: ${{ secrets.OP_CONNECT_TOKEN_ERIS }} + op-connect-token-kallone: ${{ secrets.OP_CONNECT_TOKEN_KALLONE }} + op-connect-token-nemesis: ${{ secrets.OP_CONNECT_TOKEN_NEMESIS }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.3' tools: composer:v2 + env: + GITHUB_TOKEN: ${{ steps.gh-token.outputs.token }} # A tag that disagrees with the plugin header would make sites see a # phantom update forever (or never see a real one), so fail fast. -- 2.54.0