From f663becad570ae6b6b03d39f5d04c90fda49714d Mon Sep 17 00:00:00 2001 From: Jayson Grace Date: Sun, 10 May 2026 12:18:02 -0600 Subject: [PATCH 1/2] ci: enable autofix and autocommit of pre-commit failures on renovate PRs **Added:** - Added step to generate a GitHub app token for autocommit on Renovate bot PRs - Added logic to commit and push pre-commit autofixes back to the PR if pre-commit fails and files are modified - Set up dynamic checkout and token usage to allow bot-authenticated pushes during CI **Changed:** - Updated permissions from `contents: read` to `contents: write` to allow commits - Modified checkout step to use PR head ref and app token when available --- .github/workflows/pre-commit.yaml | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 3449a1ca..9311a98c 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -23,7 +23,7 @@ concurrency: group: pre-commit-${{ github.workflow }}-${{ github.ref }} permissions: - contents: read + contents: write env: GO_VERSION: "1.26.3" @@ -35,8 +35,22 @@ jobs: name: Update pre-commit hooks and run pre-commit runs-on: ubuntu-latest steps: + - name: Generate app token for autocommit + if: >- + github.event_name == 'pull_request' && + github.event.pull_request.user.login == 'dreadnode-renovate-bot[bot]' && + !github.event.pull_request.head.repo.fork + uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 + id: app-token + with: + app-id: "${{ secrets.BOT_APP_ID }}" + private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" + - name: Checkout git repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.pull_request.head.ref || github.ref }} + token: ${{ steps.app-token.outputs.token || github.token }} - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 @@ -118,5 +132,23 @@ jobs: install-only: true - name: Run pre-commit + id: precommit run: | pre-commit run --show-diff-on-failure --color=always --all-files + + - name: Commit pre-commit autofixes back to bot PR + if: ${{ failure() && steps.precommit.outcome == 'failure' && steps.app-token.outputs.token != '' }} + env: + HEAD_REF: ${{ github.event.pull_request.head.ref }} + GIT_AUTHOR_NAME: "${{ secrets.BOT_USERNAME }}[bot]" + GIT_AUTHOR_EMAIL: "${{ secrets.BOT_USER_ID }}+${{ secrets.BOT_USERNAME }}[bot]@users.noreply.github.com" + GIT_COMMITTER_NAME: "${{ secrets.BOT_USERNAME }}[bot]" + GIT_COMMITTER_EMAIL: "${{ secrets.BOT_USER_ID }}+${{ secrets.BOT_USERNAME }}[bot]@users.noreply.github.com" + run: | + if [[ -z "$(git status --porcelain)" ]]; then + echo "pre-commit failed but did not modify any files; nothing to autofix." + exit 1 + fi + git add -A + git commit -m "chore: apply pre-commit autofixes" + git push origin "HEAD:${HEAD_REF}" From 9b8f0f53edc3af5e50b9f86773493d6eff015514 Mon Sep 17 00:00:00 2001 From: Jayson Grace Date: Sun, 10 May 2026 13:06:06 -0600 Subject: [PATCH 2/2] ci: improve pre-commit workflow automation and codeowner protections **Added:** - Introduced CODEOWNERS file to require maintainer review for changes to .github/* - Added dedicated autocommit job to apply pre-commit autofixes to Renovate bot PRs - Implemented artifact upload and download for pre-commit autofix patch sharing between jobs **Changed:** - Updated permissions for pre-commit workflow jobs to use read-only access for contents - Refactored checkout steps to avoid persisting credentials in both jobs - Moved GitHub App token generation and usage to the autocommit job for better security - Streamlined logic to detect and handle pre-commit autofixes using patch files and explicit outputs - Improved clarity and reliability of conditionals for autofix application and artifact handling **Removed:** - Removed in-line autocommit logic from pre-commit job in favor of a separate autocommit job - Eliminated unnecessary checkout token override and redundant status checks in pre-commit job --- .github/CODEOWNERS | 4 ++ .github/workflows/pre-commit.yaml | 84 +++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..e737dcb8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# Workflow and CI configuration changes require maintainer review, +# since these files run with repo secrets (incl. the renovate bot's +# GitHub App private key). +.github/** @l50 diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 9311a98c..3ee20e8a 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -23,7 +23,7 @@ concurrency: group: pre-commit-${{ github.workflow }}-${{ github.ref }} permissions: - contents: write + contents: read env: GO_VERSION: "1.26.3" @@ -34,23 +34,14 @@ jobs: pre-commit: name: Update pre-commit hooks and run pre-commit runs-on: ubuntu-latest + outputs: + has-fixes: ${{ steps.capture.outputs.has-fixes }} steps: - - name: Generate app token for autocommit - if: >- - github.event_name == 'pull_request' && - github.event.pull_request.user.login == 'dreadnode-renovate-bot[bot]' && - !github.event.pull_request.head.repo.fork - uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 - id: app-token - with: - app-id: "${{ secrets.BOT_APP_ID }}" - private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" - - name: Checkout git repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.event.pull_request.head.ref || github.ref }} - token: ${{ steps.app-token.outputs.token || github.token }} + persist-credentials: false - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 @@ -136,19 +127,70 @@ jobs: run: | pre-commit run --show-diff-on-failure --color=always --all-files - - name: Commit pre-commit autofixes back to bot PR - if: ${{ failure() && steps.precommit.outcome == 'failure' && steps.app-token.outputs.token != '' }} + - name: Capture autofix patch + id: capture + if: ${{ failure() && steps.precommit.outcome == 'failure' }} + run: | + if git diff --quiet HEAD; then + echo "pre-commit failed without modifying tracked files; no autofix possible" + echo "has-fixes=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + git diff --binary HEAD > autofix.patch + echo "has-fixes=true" >> "$GITHUB_OUTPUT" + + - name: Upload autofix patch + if: ${{ steps.capture.outputs.has-fixes == 'true' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: autofix-patch + path: autofix.patch + retention-days: 1 + if-no-files-found: error + + autocommit: + name: Apply pre-commit autofixes to bot PR + needs: pre-commit + if: >- + failure() && + needs.pre-commit.outputs.has-fixes == 'true' && + github.event_name == 'pull_request' && + github.event.pull_request.user.login == 'dreadnode-renovate-bot[bot]' && + !github.event.pull_request.head.repo.fork + runs-on: ubuntu-latest + environment: pre-commit-autofix + permissions: + contents: read + steps: + - name: Generate app token + uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 + id: app-token + with: + app-id: "${{ secrets.BOT_APP_ID }}" + private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" + + - name: Checkout PR head + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.pull_request.head.ref }} + persist-credentials: false + + - name: Download autofix patch + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: autofix-patch + + - name: Apply patch and push env: HEAD_REF: ${{ github.event.pull_request.head.ref }} + APP_TOKEN: ${{ steps.app-token.outputs.token }} GIT_AUTHOR_NAME: "${{ secrets.BOT_USERNAME }}[bot]" GIT_AUTHOR_EMAIL: "${{ secrets.BOT_USER_ID }}+${{ secrets.BOT_USERNAME }}[bot]@users.noreply.github.com" GIT_COMMITTER_NAME: "${{ secrets.BOT_USERNAME }}[bot]" GIT_COMMITTER_EMAIL: "${{ secrets.BOT_USER_ID }}+${{ secrets.BOT_USERNAME }}[bot]@users.noreply.github.com" run: | - if [[ -z "$(git status --porcelain)" ]]; then - echo "pre-commit failed but did not modify any files; nothing to autofix." - exit 1 - fi - git add -A + git apply --index autofix.patch git commit -m "chore: apply pre-commit autofixes" - git push origin "HEAD:${HEAD_REF}" + AUTH_HEADER="AUTHORIZATION: basic $(printf 'x-access-token:%s' "${APP_TOKEN}" | base64 -w0)" + git -c http.https://github.com/.extraheader="${AUTH_HEADER}" \ + push "https://github.com/${GITHUB_REPOSITORY}.git" "HEAD:${HEAD_REF}"