Bump github.com/spf13/cobra from 1.10.1 to 1.10.2 #154
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: pr-validation | |
| on: | |
| pull_request: | |
| types: [opened, edited, synchronize, reopened, ready_for_review, assigned, unassigned, labeled, unlabeled] | |
| workflow_dispatch: | |
| jobs: | |
| require-assignment-and-linked-issue: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check PR has assignee | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const pr = context.payload.pull_request; | |
| const author = pr.user && pr.user.login ? pr.user.login : ''; | |
| // Load maintainers from optional .github/MAINTAINERS (usernames, one per line, optionally prefixed with @) | |
| async function loadMaintainers() { | |
| const set = new Set(); | |
| try { | |
| const repo = await github.rest.repos.get({ owner: context.repo.owner, repo: context.repo.repo }); | |
| const defaultBranch = repo.data.default_branch; | |
| const { data } = await github.rest.repos.getContent({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| path: '.github/MAINTAINERS', | |
| ref: defaultBranch, | |
| }); | |
| const content = Buffer.from(data.content, 'base64').toString('utf8'); | |
| for (const raw of content.split(/\r?\n/)) { | |
| const l = raw.trim(); | |
| if (!l || l.startsWith('#')) continue; | |
| set.add(l.replace(/^@/, '')); | |
| } | |
| } catch (e) { | |
| // Fallback: treat repo owner as maintainer if file is missing or unreadable | |
| set.add(context.repo.owner); | |
| } | |
| if (set.size === 0) { | |
| set.add(context.repo.owner); | |
| } | |
| return set; | |
| } | |
| const maintainers = await loadMaintainers(); | |
| const isMaintainerAuthor = maintainers.has(author); | |
| const hasAssignee = pr.assignees && pr.assignees.length > 0; | |
| if (!hasAssignee && isMaintainerAuthor) { | |
| core.notice(`No assignee set, but PR author @${author} is a maintainer; passing assignment check.`); | |
| } else if (!hasAssignee) { | |
| core.setFailed('PR must have at least one assignee (or be opened by a maintainer).'); | |
| } | |
| - name: Require linked issue (mention or closing keywords) | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const pr = context.payload.pull_request; | |
| const body = (pr.body || '') + '\n' + (pr.title || ''); | |
| const closeRegex = /(close[sd]?|fixe[sd]?|resolve[sd]?)\s+#(\d+)/ig; | |
| const mentionRegex = /#(\d+)/g; | |
| const numbers = new Set(); | |
| let m; | |
| while ((m = closeRegex.exec(body)) !== null) { | |
| numbers.add(parseInt(m[2], 10)); | |
| } | |
| while ((m = mentionRegex.exec(body)) !== null) { | |
| numbers.add(parseInt(m[1], 10)); | |
| } | |
| if (numbers.size === 0) { | |
| core.setFailed('PR must link an issue (e.g., add "#123" in the title/body or use closing keywords).'); | |
| } | |
| core.exportVariable('LINKED_ISSUES', Array.from(numbers).join(',')); | |
| - name: Check linked issues are assigned | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const env = process.env; | |
| const nums = (env.LINKED_ISSUES || '').split(',').filter(Boolean).map(n => parseInt(n, 10)); | |
| const numbers = new Set(nums); | |
| let checked = 0; | |
| for (const number of numbers) { | |
| try { | |
| const { data: issue } = await github.rest.issues.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: number, | |
| }); | |
| checked++; | |
| if (!issue.assignees || issue.assignees.length === 0) { | |
| core.setFailed(`Linked issue #${number} has no assignee.`); | |
| } | |
| } catch (e) { | |
| core.warning(`Could not fetch issue #${number}: ${e.message}`); | |
| // ignore 404 or private/missing issues | |
| } | |
| } | |
| if (checked === 0) { | |
| core.warning('No accessible linked issues could be verified. Ensure at least one valid issue is referenced in the PR body/title.'); | |
| } |