-
-
Notifications
You must be signed in to change notification settings - Fork 1
103 lines (94 loc) · 4.53 KB
/
Copy pathcommit-queue.yml
File metadata and controls
103 lines (94 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# Landing a pull request when it is labelled `commit-queue`.
#
# `pull_request_target` runs in the context of the base branch and can reach
# secrets, which `pull_request` cannot do for a fork. That is only safe while
# nothing from the pull request reaches this runner, and nothing does: the
# checkout is this repository at the base branch, and the commit messages
# being read come from the API rather than from a fetch.
#
# Never add a build, an install or a test step here, and never check out the
# branch under review. Those belong in the checks this workflow waits for,
# which run without a token that can write anything.
#
# Actions are pinned by commit, never by tag.
name: Commit Queue
on:
pull_request_target:
types: [labeled]
permissions:
contents: read
# Two labels applied in quick succession should not race each other into the
# same merge.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: false
jobs:
land:
name: Land
if: github.event.label.name == 'commit-queue'
runs-on: ubuntu-latest
steps:
- name: Mint a token for the app
id: token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.LAND_APP_ID }}
private-key: ${{ secrets.LAND_APP_PRIVATE_KEY }}
# No `ref:`. For this event the default is already the base branch, and
# naming it explicitly, even as `base.ref`, is indistinguishable to a
# reader -- and to a scanner -- from naming the branch under review.
# Nothing from that branch is fetched at all: its commit messages are
# asked of the API, so a stranger's code never reaches this runner.
- name: Check out this repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Nothing here pushes, and a token left in .git/config is one more
# thing that could be picked up by something that should not have it.
persist-credentials: false
- name: Set up Node.js runtime
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: 'package.json'
- name: Land it
id: land
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
# Whoever applied the label, whose right to push is checked before
# anything is merged. Applying a label needs only triage.
LAND_ACTOR: ${{ github.event.sender.login }}
NUMBER: ${{ github.event.pull_request.number }}
run: node build/tasks/land-pull-request.mts "${NUMBER}"
# The label is a request, not a state: once the queue has answered it,
# one way or the other, it has been spent. Leaving it on a landed pull
# request would say the queue still had something to do.
#
# `unlabeled` is not among the events above, so taking it off cannot
# start another run. Failing to take it off is not worth failing a run
# that has already merged, hence the `|| true`.
# Both of these go through the REST API rather than `gh pr edit` and
# `gh pr comment`, which reach for GraphQL and so want organization
# permissions neither task needs. The app happens to satisfy them today;
# tightening its permissions, or installing it somewhere with fewer,
# would break these silently behind the `|| true`. The endpoints below
# need only the pull request permission the app already has, and the
# label one names a single label rather than trusting a flag to be
# subtractive.
- name: Take the label back off
if: always() && steps.token.outcome == 'success'
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
NUMBER: ${{ github.event.pull_request.number }}
run: |
gh api --silent -X DELETE \
"repos/${GITHUB_REPOSITORY}/issues/${NUMBER}/labels/commit-queue" \
|| true
- name: Say why it did not land
if: failure() && steps.token.outcome == 'success'
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
NUMBER: ${{ github.event.pull_request.number }}
RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
gh api --silent -X POST \
"repos/${GITHUB_REPOSITORY}/issues/${NUMBER}/comments" \
-f "body=The commit queue did not land this. See ${RUN} — the label has been taken back off, so re-applying it is a deliberate second try."