1name: PR Target Labeler
2
3# Decides where a PR is destined and reflects it with labels:
4# (no label) -> master only (default)
5# backport/v1 -> merge to master AND backport to release/v1 ("both")
6# target/v1 -> the PR already targets release/v1 directly (v1 only)
7#
8# Maintainers steer routing with comment commands on the PR:
9# /backport v1 add the backport/v1 label
10# /no-backport v1 remove it
11# The actual cherry-pick is performed by backport.yml once the PR is merged.
12
13on:
14 pull_request_target:
15 types: [opened, edited, reopened, synchronize]
16 issue_comment:
17 types: [created]
18
19permissions:
20 contents: read
21 pull-requests: write
22 issues: write
23
24jobs:
25 # Auto-label based on the PR's base branch and an explicit "backport" hint
26 # in the title/body. Never removes backport/v1 (a maintainer may have set it).
27 auto:
28 if: github.event_name == 'pull_request_target'
29 runs-on: ubuntu-latest
30 steps:
31 - uses: actions/github-script@v9
32 with:
33 github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
34 script: |
35 const pr = context.payload.pull_request;
36 const { owner, repo } = context.repo;
37 const issue_number = pr.number;
38 const base = pr.base.ref;
39 const have = new Set(pr.labels.map(l => l.name));
40 const add = [];
41
42 if (base === 'release/v1') {
43 if (!have.has('target/v1')) add.push('target/v1');
44 } else {
45 const text = `${pr.title}\n${pr.body || ''}`;
46 if (/\bback[- ]?port\b/i.test(text) && !have.has('backport/v1')) {
47 add.push('backport/v1');
48 }
49 }
50
51 if (add.length) {
52 await github.rest.issues.addLabels({ owner, repo, issue_number, labels: add });
53 console.log(`added: ${add.join(', ')}`);
54 }
55
56 # Comment commands. Restricted to users with write access to the repo.
57 command:
58 if: >
59 github.event_name == 'issue_comment'
60 && github.event.issue.pull_request
61 && (startsWith(github.event.comment.body, '/backport')
62 || startsWith(github.event.comment.body, '/no-backport'))
63 runs-on: ubuntu-latest
64 steps:
65 - uses: actions/github-script@v9
66 with:
67 github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
68 script: |
69 const { owner, repo } = context.repo;
70 const issue_number = context.issue.number;
71 const body = context.payload.comment.body.trim();
72 const assoc = context.payload.comment.author_association;
73 const commenter = context.payload.comment.user.login;
74
75 if (!['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc)) {
76 await github.rest.issues.createComment({
77 owner, repo, issue_number,
78 body: `Sorry @${commenter}, only maintainers can change backport routing.`,
79 });
80 return;
81 }
82
83 // Only the v1 target is supported for now.
84 if (!/\bv1\b/.test(body)) {
85 await github.rest.issues.createComment({
86 owner, repo, issue_number,
87 body: `Usage: \`/backport v1\` or \`/no-backport v1\`.`,
88 });
89 return;
90 }
91
92 const remove = body.startsWith('/no-backport');
93 if (remove) {
94 try {
95 await github.rest.issues.removeLabel({ owner, repo, issue_number, name: 'backport/v1' });
96 } catch (e) {
97 if (e.status !== 404) throw e;
98 }
99 } else {
100 await github.rest.issues.addLabels({ owner, repo, issue_number, labels: ['backport/v1'] });
101 }
102
103 await github.rest.reactions.createForIssueComment({
104 owner, repo, comment_id: context.payload.comment.id, content: 'rocket',
105 });