fix: allow auto-fix workflow to run on dependabot PRs #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto-fix License Files | ||
| # Automatically create/update/close PRs to fix license files on failing PRs | ||
| # Creates: main <- PR:feature <- PR:license-fix | ||
| # Only targets PRs against main, not stacked PRs | ||
| on: | ||
| pull_request: | ||
| types: [synchronize, opened, reopened, ready_for_review] | ||
| paths: | ||
| - "**.go" | ||
| - go.mod | ||
| - go.sum | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| jobs: | ||
| auto-fix-licenses: | ||
| runs-on: ubuntu-latest | ||
| # Only run on PRs targeting main, from same repo, not drafts | ||
| if: | | ||
| github.event.pull_request.base.ref == 'main' && | ||
| github.event.pull_request.head.repo.full_name == github.repository && | ||
| github.event.pull_request.draft == false | ||
| steps: | ||
| - name: Check out base PR branch | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.ref }} | ||
| fetch-depth: 0 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v6 | ||
| with: | ||
| go-version-file: "go.mod" | ||
| - name: Regenerate licenses | ||
| id: regen | ||
| env: | ||
| CI: "true" | ||
| run: | | ||
| export GOROOT=$(go env GOROOT) | ||
| export PATH=${GOROOT}/bin:$PATH | ||
| ./script/licenses | ||
| # Check if licenses changed | ||
| if git diff --exit-code --quiet third-party-licenses.*.md third-party/; then | ||
| echo "needs_fix=false" >> $GITHUB_OUTPUT | ||
| echo "✅ License files are up to date" | ||
| else | ||
| echo "needs_fix=true" >> $GITHUB_OUTPUT | ||
| echo "📝 License files need updating" | ||
| # Compute hash of license changes only | ||
| LICENSE_HASH=$(git diff third-party-licenses.*.md third-party/ | sha256sum | cut -c1-8) | ||
| echo "license_hash=${LICENSE_HASH}" >> $GITHUB_OUTPUT | ||
| echo "License changes hash: ${LICENSE_HASH}" | ||
| fi | ||
| - name: Find existing license fix PR | ||
| id: find_pr | ||
| if: steps.regen.outputs.needs_fix == 'true' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const basePR = context.payload.pull_request.number; | ||
| const baseBranch = context.payload.pull_request.head.ref; | ||
| // Search for existing auto-fix PR | ||
| const { data: prs } = await github.rest.pulls.list({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| state: 'open', | ||
| base: baseBranch, | ||
| sort: 'created', | ||
| direction: 'desc' | ||
| }); | ||
| // Find PR with our marker in the title or body | ||
| const existingPR = prs.find(pr => | ||
| pr.title.includes('🤖 Auto-fix licenses') && | ||
| pr.body?.includes(`<!-- auto-fix-for-pr:${basePR} -->`) | ||
| ); | ||
| if (existingPR) { | ||
| core.setOutput('exists', 'true'); | ||
| core.setOutput('pr_number', existingPR.number); | ||
| core.setOutput('pr_branch', existingPR.head.ref); | ||
| // Extract hash from PR body | ||
| const hashMatch = existingPR.body?.match(/<!-- license-hash:(\w+) -->/); | ||
| const oldHash = hashMatch ? hashMatch[1] : ''; | ||
| core.setOutput('old_hash', oldHash); | ||
| core.info(`Found existing PR #${existingPR.number} with hash ${oldHash}`); | ||
| } else { | ||
| core.setOutput('exists', 'false'); | ||
| core.info('No existing auto-fix PR found'); | ||
| } | ||
| - name: Check if hash matches (user already fixed it) | ||
| id: check_fixed | ||
| if: steps.regen.outputs.needs_fix == 'false' && steps.find_pr.outputs.exists == 'true' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| // User fixed licenses themselves, close our auto-fix PR | ||
| const prNumber = ${{ steps.find_pr.outputs.pr_number }}; | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| body: `## ✅ Closing - licenses already fixed\n\nThe base PR #${context.payload.pull_request.number} now has up-to-date license files. This auto-fix PR is no longer needed.` | ||
| }); | ||
| await github.rest.pulls.update({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: prNumber, | ||
| state: 'closed' | ||
| }); | ||
| core.info(`Closed PR #${prNumber} as licenses are now fixed`); | ||
| - name: Close PR if hash changed (dependencies changed) | ||
| id: check_hash_changed | ||
| if: | | ||
| steps.regen.outputs.needs_fix == 'true' && | ||
| steps.find_pr.outputs.exists == 'true' && | ||
| steps.find_pr.outputs.old_hash != '' && | ||
| steps.find_pr.outputs.old_hash != steps.regen.outputs.license_hash | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const prNumber = ${{ steps.find_pr.outputs.pr_number }}; | ||
| const oldHash = '${{ steps.find_pr.outputs.old_hash }}'; | ||
| const newHash = '${{ steps.regen.outputs.license_hash }}'; | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| body: `## 🔄 Closing - dependencies changed\n\nThe base PR #${context.payload.pull_request.number} has different license requirements now.\n\n- Old hash: \`${oldHash}\`\n- New hash: \`${newHash}\`\n\nA new auto-fix PR will be created.` | ||
| }); | ||
| await github.rest.pulls.update({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: prNumber, | ||
| state: 'closed' | ||
| }); | ||
| core.setOutput('create_new', 'true'); | ||
| core.info(`Closed PR #${prNumber} due to hash change`); | ||
| - name: Create or update license fix PR | ||
| if: | | ||
| steps.regen.outputs.needs_fix == 'true' && | ||
| (steps.find_pr.outputs.exists == 'false' || steps.check_hash_changed.outputs.create_new == 'true') | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const basePR = context.payload.pull_request.number; | ||
| const baseBranch = context.payload.pull_request.head.ref; | ||
| const licenseHash = '${{ steps.regen.outputs.license_hash }}'; | ||
| const branchName = `auto-fix/licenses-for-pr-${basePR}`; | ||
| // Create new branch from base PR | ||
| const { data: baseRef } = await github.rest.git.getRef({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| ref: `heads/${baseBranch}` | ||
| }); | ||
| try { | ||
| await github.rest.git.createRef({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| ref: `refs/heads/${branchName}`, | ||
| sha: baseRef.object.sha | ||
| }); | ||
| } catch (error) { | ||
| // Branch might exist, update it | ||
| await github.rest.git.updateRef({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| ref: `heads/${branchName}`, | ||
| sha: baseRef.object.sha, | ||
| force: true | ||
| }); | ||
| } | ||
| // Checkout the new branch and commit license changes | ||
| await exec.exec('git', ['fetch', 'origin', branchName]); | ||
| await exec.exec('git', ['checkout', '-B', branchName, `origin/${branchName}`]); | ||
| await exec.exec('git', ['config', 'user.name', 'github-actions[bot]']); | ||
| await exec.exec('git', ['config', 'user.email', '41898282+github-actions[bot]@users.noreply.github.com']); | ||
| // Regenerate licenses on this branch | ||
| process.env.CI = 'true'; | ||
| const goRoot = (await exec.getExecOutput('go', ['env', 'GOROOT'])).stdout.trim(); | ||
| process.env.GOROOT = goRoot; | ||
| process.env.PATH = `${goRoot}/bin:${process.env.PATH}`; | ||
| await exec.exec('./script/licenses'); | ||
| await exec.exec('git', ['add', 'third-party', 'third-party-licenses.*.md']); | ||
| await exec.exec('git', ['commit', '-m', `chore: auto-fix license files for PR #${basePR}`]); | ||
| await exec.exec('git', ['push', 'origin', branchName, '--force']); | ||
| // Create PR | ||
| const { data: newPR } = await github.rest.pulls.create({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| title: `🤖 Auto-fix licenses for PR #${basePR}`, | ||
| head: branchName, | ||
| base: baseBranch, | ||
| body: `## Automated License Update | ||
| This PR automatically updates license files for PR #${basePR}. | ||
| ### What happened | ||
| Dependencies were added/updated in #${basePR}, which requires regenerating license documentation. | ||
| ### What to do | ||
| - **Option 1:** Merge this PR to add the license updates to #${basePR} | ||
| - **Option 2:** Manually run \`./script/licenses\` in #${basePR} and push (this PR will auto-close) | ||
| This PR will automatically close if: | ||
| - License files in #${basePR} are updated manually | ||
| - Dependencies in #${basePR} change (a new PR will be created) | ||
| <!-- auto-fix-for-pr:${basePR} --> | ||
| <!-- license-hash:${licenseHash} -->` | ||
| }); | ||
| core.info(`Created auto-fix PR #${newPR.number}`); | ||