From 52b912c3a03920f3854f5a9a999170f96515d57d Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Thu, 11 Jun 2026 08:49:18 +0000 Subject: [PATCH] chore(ci): add update-lockfiles automation wf --- .github/workflows/update_lockfiles.yml | 118 +++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/update_lockfiles.yml diff --git a/.github/workflows/update_lockfiles.yml b/.github/workflows/update_lockfiles.yml new file mode 100644 index 00000000..d1faff4a --- /dev/null +++ b/.github/workflows/update_lockfiles.yml @@ -0,0 +1,118 @@ +name: Update lockfiles + +on: + workflow_dispatch: + schedule: + - cron: "0 4 * * 1" + +permissions: + contents: write + pull-requests: write + +jobs: + update-lockfiles: + name: Refresh mix.lock files + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Get auth token + id: token + uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0 + with: + app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} + private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} + + - name: Check out this repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + token: ${{ steps.token.outputs.token }} + + - name: Setup Elixir and Erlang + uses: erlef/setup-beam@fc68ffb90438ef2936bbb3251622353b3dcb2f93 # v1.24.0 + with: + elixir-version: "1.18" + otp-version: "27.2" + + - name: Refresh lockfiles + run: | + for lock in mix.lock test_integrations/*/mix.lock; do + dir=$(dirname "$lock") + echo "==> Refreshing mix.lock in $dir" + (cd "$dir" && mix deps.update --all) + done + + - name: Configure git + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + + - name: Create branch + id: create-branch + run: | + # Stage first, then diff the index against HEAD: plain `git diff` ignores + # untracked files, so a brand-new project's lock would look unchanged. + git add mix.lock 'test_integrations/*/mix.lock' + + if git diff --cached --quiet; then + echo "No lockfile changes; nothing to do." + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + COMMIT_TITLE="chore(deps): Refresh mix.lock files" + BRANCH_NAME="deps/lockfiles-update-$(date +%Y-%m-%d)" + + git checkout -B "$BRANCH_NAME" + git commit -m "$COMMIT_TITLE" + git push origin "$BRANCH_NAME" --force + + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT" + echo "commit_title=$COMMIT_TITLE" >> "$GITHUB_OUTPUT" + + - name: Create pull request + if: steps.create-branch.outputs.changed == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + BRANCH_NAME: ${{ steps.create-branch.outputs.branch_name }} + COMMIT_TITLE: ${{ steps.create-branch.outputs.commit_title }} + with: + github-token: ${{ steps.token.outputs.token }} + script: | + const branchName = process.env.BRANCH_NAME; + const commitTitle = process.env.COMMIT_TITLE; + const prBody = `Automated weekly refresh of the committed \`mix.lock\` files via \`mix deps.update --all\`, keeping dependency pins current with the latest security patches allowed by each project's version constraints. + + #skip-changelog + + ## Action required + - If CI passes on this PR, it's safe to approve and merge. + - If CI fails, a dependency update broke something — investigate before merging. + + _🤖 Automatically created by [.github/workflows/update_lockfiles.yml](https://github.com/getsentry/sentry-elixir/blob/master/.github/workflows/update_lockfiles.yml)._`.replace(/^ {12}/gm, ''); + + // Close superseded lockfile PRs — they're now obsolete. + const existingPRs = await github.paginate(github.rest.pulls.list, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + }); + for (const pr of existingPRs) { + if (pr.head.ref.startsWith('deps/lockfiles-update-')) { + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + state: 'closed', + }); + } + } + + await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: commitTitle, + head: branchName, + base: 'master', + body: prBody, + });