diff --git a/.github/workflows/lockfile-maintenance.yml b/.github/workflows/lockfile-maintenance.yml new file mode 100644 index 0000000..05b4c4d --- /dev/null +++ b/.github/workflows/lockfile-maintenance.yml @@ -0,0 +1,92 @@ +# Compensates for pnpm 11.x ignoring targeted updates of transitive-only +# dependencies (https://github.com/pnpm/pnpm/issues/12744), which makes +# Dependabot's transitive security updates a silent no-op. Refreshes every +# in-range transitive resolution with workspace overrides untouched. Run it +# from the Actions tab when a security alert fires; the cron covers drift. +# Retire path: bump packageManager once a stable pnpm ships the upstream fix. +name: Lockfile maintenance + +on: + schedule: + - cron: "0 6 1 * *" + workflow_dispatch: + +permissions: {} + +jobs: + refresh: + name: Refresh lockfile + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + timeout-minutes: 15 + concurrency: + group: lockfile-maintenance-${{ github.repository }} + cancel-in-progress: false + environment: + name: release + deployment: false + permissions: + contents: read + + steps: + - name: Create release bot token + id: release-bot + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ vars.PUTIO_RELEASE_BOT_CLIENT_ID }} + private-key: ${{ secrets.PUTIO_RELEASE_BOT_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write + + - name: Resolve release bot identity + id: release-bot-identity + env: + GH_TOKEN: ${{ steps.release-bot.outputs.token }} + APP_SLUG: ${{ steps.release-bot.outputs.app-slug }} + run: | + set -euo pipefail + user_id="$(gh api "/users/${APP_SLUG}%5Bbot%5D" --jq .id)" + if [[ ! "$user_id" =~ ^[0-9]+$ ]]; then + echo "failed to resolve numeric bot user id for ${APP_SLUG}[bot]" >&2 + exit 1 + fi + echo "user_id=${user_id}" >> "$GITHUB_OUTPUT" + + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Set up Node + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: .node-version + + - name: Refresh transitive lockfile resolutions + run: corepack pnpm update --lockfile-only -r + + - name: Open or update pull request + env: + GH_TOKEN: ${{ steps.release-bot.outputs.token }} + APP_SLUG: ${{ steps.release-bot.outputs.app-slug }} + BOT_USER_ID: ${{ steps.release-bot-identity.outputs.user_id }} + run: | + set -euo pipefail + if git diff --quiet -- pnpm-lock.yaml; then + echo "lockfile already current" + exit 0 + fi + branch="chore/lockfile-maintenance" + git config user.name "${APP_SLUG}[bot]" + git config user.email "${BOT_USER_ID}+${APP_SLUG}[bot]@users.noreply.github.com" + git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git checkout -B "$branch" + git add pnpm-lock.yaml + git commit -m "chore(deps): refresh transitive lockfile resolutions" + git push --force origin "HEAD:refs/heads/${branch}" + if [ -z "$(gh pr list --head "$branch" --state open --json number --jq '.[].number')" ]; then + gh pr create \ + --head "$branch" \ + --title "chore(deps): refresh transitive lockfile resolutions" \ + --body "Scheduled lockfile maintenance. Re-resolves transitive dependencies within existing ranges because pnpm 11.x ignores targeted transitive updates (pnpm/pnpm#12744), so Dependabot security updates cannot land them. Workspace overrides are untouched." + fi