From aefe96db517d938d86dd3a8b60514395cd5c6084 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:09:08 +0000 Subject: [PATCH] Revert "ci(deps): Dedupe lockfile on Dependabot PRs (#25911)" pnpm autoDedupe (#25961) makes Dependabot write an already-deduped lockfile, so the dedupe workflow no longer has anything to push. This reverts commit bc8fdf170009cd3c474b158d9dcf169f1acb9741. Co-Authored-By: Charly Gomez --- .github/workflows/build.yml | 7 +- .github/workflows/dependabot-dedupe-push.yml | 134 ------------------- .github/workflows/dependabot-dedupe.yml | 63 --------- 3 files changed, 2 insertions(+), 202 deletions(-) delete mode 100644 .github/workflows/dependabot-dedupe-push.yml delete mode 100644 .github/workflows/dependabot-dedupe.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d470f273e39..a546292a32ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1141,16 +1141,13 @@ jobs: # them. optional-e2e.yml reports the results in a PR comment. job_optional_e2e_tests: name: E2E Tests (optional) - # We only run E2E tests for non-fork PRs because the E2E tests require secrets to work and they can't be accessed from forks. - # Dependabot PRs are skipped by author, not by `github.actor`: once the Gitflow app pushes the deduped lockfile - # (dependabot-dedupe-push.yml), the actor is the app and the run would otherwise get the E2E secrets. + # We only run E2E tests for non-fork PRs because the E2E tests require secrets to work and they can't be accessed from forks # We need to add the `always()` check here because the previous step has this as well :( # See: https://github.com/actions/runner/issues/2205 if: always() && needs.job_get_metadata.outputs.is_release != 'true' && needs.job_build_tarballs.result == 'success' && needs.job_build.outputs.e2e-matrix-optional != '{"include":[]}' && (github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository) && github.event.pull_request.user.login != - 'dependabot[bot]' + github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' needs: [job_get_metadata, job_build, job_build_tarballs] # This job only waits for optional-e2e.yml, which can take most of an hour. GitHub runners are free for public # repos and Namespace runners are paid per minute, so the wait runs here and the tests run on Namespace. diff --git a/.github/workflows/dependabot-dedupe-push.yml b/.github/workflows/dependabot-dedupe-push.yml deleted file mode 100644 index 3fce5447b7ba..000000000000 --- a/.github/workflows/dependabot-dedupe-push.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: 'Dependabot: Push deduped lockfile' - -# Pushes the lockfile from `dependabot-dedupe.yml` to the Dependabot PR branch. -# -# This workflow holds the Gitflow app token, so it never runs code from the PR. Everything it -# receives is untrusted: anyone with write access can push to a Dependabot branch, and the run that -# produced the artifact used the PR's version of `dependabot-dedupe.yml`. So it looks the PR up -# through the API, accepts only a single regular `pnpm-lock.yaml` file and commits nothing else. -# -# The app token is limited to `contents: write` on this repository, not to `dependabot/**` branches, so -# nothing from the PR may run before it is minted. Pushing as the app also changes `github.actor` on the -# PR's next CI run, so jobs that keep secrets away from Dependabot must check the PR author, not the actor. - -on: - workflow_run: - workflows: ['Dependabot: Dedupe lockfile'] - types: [completed] - -permissions: - actions: read - contents: read - pull-requests: read - -concurrency: - group: dependabot-dedupe-push-${{ github.event.workflow_run.head_sha }} - cancel-in-progress: false - -jobs: - push: - name: Push deduped lockfile - if: | - github.event.workflow_run.conclusion == 'success' - && github.event.workflow_run.event == 'pull_request' - && github.event.workflow_run.head_repository.full_name == github.repository - runs-on: namespace-profile-sentry-javascript-small - timeout-minutes: 5 - env: - GH_TOKEN: ${{ github.token }} - RUN_ID: ${{ github.event.workflow_run.id }} - HEAD_SHA: ${{ github.event.workflow_run.head_sha }} - steps: - - name: Find artifact and Dependabot PR - id: pr - run: | - artifacts=$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID}/artifacts" \ - --jq '[.artifacts[] | select(.name == "pnpm-lock")] | length') - if [ "$artifacts" != "1" ]; then - echo "No deduped lockfile to push." - exit 0 - fi - - head_ref=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${HEAD_SHA}/pulls" | - jq -r --arg repo "$GITHUB_REPOSITORY" --arg sha "$HEAD_SHA" ' - [.[] | select(.state == "open" - and .base.ref == "develop" - and .user.login == "dependabot[bot]" - and .head.repo.full_name == $repo - and .head.sha == $sha)] - | if length == 1 then .[0].head.ref else empty end') - if [[ ! "$head_ref" =~ ^dependabot/[A-Za-z0-9._/@+-]+$ ]]; then - echo "::error::No open Dependabot PR into develop has head commit ${HEAD_SHA}." - exit 1 - fi - echo "head_ref=${head_ref}" >> "$GITHUB_OUTPUT" - - - name: Download deduped lockfile - if: steps.pr.outputs.head_ref - uses: actions/download-artifact@v8 - with: - name: pnpm-lock - path: ${{ runner.temp }}/pnpm-lock - run-id: ${{ github.event.workflow_run.id }} - github-token: ${{ github.token }} - - - name: Check out PR branch - if: steps.pr.outputs.head_ref - uses: actions/checkout@v7 - with: - ref: ${{ github.event.workflow_run.head_sha }} - persist-credentials: false - - # Replace the file instead of writing through it, so a symlinked lockfile in the PR cannot redirect the write. - - name: Apply deduped lockfile - if: steps.pr.outputs.head_ref - id: apply - env: - LOCKFILE_DIR: ${{ runner.temp }}/pnpm-lock - run: | - if [ "$(find "$LOCKFILE_DIR" -mindepth 1 | wc -l)" != "1" ] || [ ! -f "$LOCKFILE_DIR/pnpm-lock.yaml" ] || [ -L "$LOCKFILE_DIR/pnpm-lock.yaml" ]; then - echo "::error::The artifact must contain exactly one regular file named pnpm-lock.yaml." - exit 1 - fi - if [ "$(git ls-files --stage -- pnpm-lock.yaml | cut -d' ' -f1)" != "100644" ]; then - echo "::error::pnpm-lock.yaml in the PR is not a regular file." - exit 1 - fi - rm pnpm-lock.yaml - cp "$LOCKFILE_DIR/pnpm-lock.yaml" pnpm-lock.yaml - - changes=$(git status --porcelain) - if [ -z "$changes" ]; then - echo "Lockfile is already deduped." - exit 0 - fi - if [ "$changes" != " M pnpm-lock.yaml" ]; then - echo "::error::Unexpected changes:" - echo "$changes" - exit 1 - fi - echo "changed=true" >> "$GITHUB_OUTPUT" - - # An app token is needed so the push triggers CI again; pushes made with GITHUB_TOKEN do not. - - name: Generate GitHub App token - if: steps.apply.outputs.changed == 'true' - id: app-token - uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 - with: - client-id: ${{ vars.GITFLOW_APP_ID }} - private-key: ${{ secrets.GITFLOW_APP_PRIVATE_KEY }} - permission-contents: write - - # `[dependabot skip]` lets Dependabot keep rebasing the PR over this commit. - # The push is not forced, so it fails if the branch moved past HEAD_SHA in the meantime. - - name: Commit and push - if: steps.apply.outputs.changed == 'true' - env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} - APP_SLUG: ${{ steps.app-token.outputs.app-slug }} - HEAD_REF: ${{ steps.pr.outputs.head_ref }} - run: | - git config user.name "${APP_SLUG}[bot]" - git config user.email "${APP_SLUG}[bot]@users.noreply.github.com" - git commit -m "chore(deps): Dedupe pnpm-lock.yaml [dependabot skip]" -- pnpm-lock.yaml - git push "https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "HEAD:refs/heads/${HEAD_REF}" diff --git a/.github/workflows/dependabot-dedupe.yml b/.github/workflows/dependabot-dedupe.yml deleted file mode 100644 index 05fcf2f42448..000000000000 --- a/.github/workflows/dependabot-dedupe.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: 'Dependabot: Dedupe lockfile' - -# Dependabot updates pnpm-lock.yaml without deduping it, so `Check lockfile` (`pnpm dedupe --check`) -# fails on most of its PRs. This job dedupes the lockfile and uploads it as an artifact. It runs on -# `pull_request`, so it has no secrets, a read-only token and PR-scoped caches. -# `dependabot-dedupe-push.yml` validates the result and pushes it to the PR branch. - -on: - pull_request: - types: [opened, synchronize, reopened] - branches: - - develop - paths: - - 'pnpm-lock.yaml' - -permissions: - contents: read - -concurrency: - group: dependabot-dedupe-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - dedupe: - name: Dedupe lockfile - # Only run on pushes made by Dependabot itself. The deduped commit pushed by `dependabot-dedupe-push.yml` - # also triggers `synchronize`, and a second full `pnpm dedupe` on it would only confirm there is nothing left to do. - if: | - github.event.pull_request.user.login == 'dependabot[bot]' - && github.actor == 'dependabot[bot]' - && github.event.pull_request.head.repo.full_name == github.repository - # PR code runs here, so keep its cache writes away from the cache used by develop, like the PR jobs in build.yml. - runs-on: namespace-profile-sentry-javascript;overrides.cache-tag=sentry-javascript-pr - # `pnpm dedupe` fetches metadata for every package from npm. - timeout-minutes: 20 - steps: - - name: Check out PR branch - uses: actions/checkout@v7 - with: - ref: ${{ github.event.pull_request.head.sha }} - persist-credentials: false - - - name: Install pnpm - uses: ./.github/actions/install-pnpm - - - name: Set up Node - uses: actions/setup-node@v7 - with: - node-version-file: 'package.json' - - - name: Dedupe lockfile - id: dedupe - run: | - pnpm dedupe --ignore-scripts --ignore-pnpmfile - git diff --quiet pnpm-lock.yaml || echo "changed=true" >> "$GITHUB_OUTPUT" - - - name: Upload deduped lockfile - if: steps.dedupe.outputs.changed == 'true' - uses: actions/upload-artifact@v7 - with: - name: pnpm-lock - path: pnpm-lock.yaml - retention-days: 1