diff --git a/.github/workflows/housekeeping-dependencies.yml b/.github/workflows/housekeeping-dependencies.yml index bac4442..cfd5446 100644 --- a/.github/workflows/housekeeping-dependencies.yml +++ b/.github/workflows/housekeeping-dependencies.yml @@ -67,22 +67,26 @@ on: type: string default: disabled -permissions: - actions: read - contents: read - id-token: write +permissions: {} jobs: - renovate: - name: Renovate + # The only job that may hold `id-token: write` and see the App private key. + # Every step here must therefore stay a SHA-pinned third-party action or an + # inline `run`: a local `uses: ./...` resolves from the caller's checked-out + # tree, which any token with `contents: write` can rewrite, and that would + # undo the split. + # + # Renovate gets an installation token instead — an hour long, scoped to the + # calling repo, revocable, where the key is permanent and covers the whole + # installation. + token: + name: Mint installation token runs-on: ubuntu-24.04 - concurrency: - cancel-in-progress: false - group: renovate - env: - is_pr: ${{ github.event_name == 'pull_request' }} - dry_run: ${{ github.event_name == 'pull_request' && 'extract' || inputs.dryRun || 'disabled' }} - repo_cache: ${{ inputs.repoCache || 'enabled' }} + permissions: + id-token: write + outputs: + workflow-ref: ${{ steps.workflow-ref.outputs.ref }} + installation-token: ${{ steps.app-token.outputs.token }} steps: - name: Resolve reusable workflow ref @@ -96,15 +100,6 @@ jobs: const ref = job_workflow_ref.split('@')[1]; core.setOutput('ref', ref); - - name: Checkout .github repo for the Renovate lockfile - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - repository: hashintel/.github - ref: ${{ steps.workflow-ref.outputs.ref }} - sparse-checkout: | - package.json - package-lock.json - - name: Authenticate Vault id: secrets uses: hashicorp/vault-action@892a26828f195e65540a40b4768ae4571f51ebfc # v4 @@ -129,6 +124,38 @@ jobs: owner: ${{ github.repository_owner }} repositories: ${{ steps.repo.outputs.name }} + renovate: + name: Renovate + needs: token + runs-on: ubuntu-24.04 + permissions: + actions: read + contents: read + concurrency: + cancel-in-progress: false + group: renovate + env: + is_pr: ${{ github.event_name == 'pull_request' }} + dry_run: ${{ github.event_name == 'pull_request' && 'extract' || inputs.dryRun || 'disabled' }} + repo_cache: ${{ inputs.repoCache || 'enabled' }} + + steps: + # Job outputs are not masked the way secrets are, so register the value + # before anything else in this job runs. + - name: Mask the installation token + env: + INSTALLATION_TOKEN: ${{ needs.token.outputs.installation-token }} + run: echo "::add-mask::$INSTALLATION_TOKEN" + + - name: Checkout .github repo for the Renovate lockfile + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + repository: hashintel/.github + ref: ${{ needs.token.outputs.workflow-ref }} + sparse-checkout: | + package.json + package-lock.json + - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: @@ -164,7 +191,7 @@ jobs: - name: Run Renovate env: LOG_LEVEL: ${{ inputs.logLevel || 'info' }} - RENOVATE_TOKEN: ${{ steps.app-token.outputs.token }} + RENOVATE_TOKEN: ${{ needs.token.outputs.installation-token }} RENOVATE_FORCE: ${{ inputs.overrideSchedule && '{"schedule":null}' || '' }} RENOVATE_DRY_RUN: ${{ env.dry_run == 'disabled' && 'null' || env.dry_run }} RENOVATE_PLATFORM_COMMIT: enabled