|
| 1 | +# Commit Queue |
| 2 | + |
| 3 | +> Stability: 1 - Experimental |
| 4 | +
|
| 5 | +*tl;dr: You can land Pull Requests by adding the `commit-queue` label to it.* |
| 6 | + |
| 7 | +Commit Queue is an experimental feature for the project which simplifies the |
| 8 | +landing process by automating it via GitHub Actions. With it, Collaborators are |
| 9 | +able to land Pull Requests by adding the `commit-queue` label to a PR. All |
| 10 | +checks will run via node-core-utils, and if the Pull Request is ready to land, |
| 11 | +the Action will rebase it and push to master. |
| 12 | + |
| 13 | +This document gives an overview on how the Commit Queue works, as well as |
| 14 | +implementation details, reasoning for design choices, and current limitations. |
| 15 | + |
| 16 | +## Overview |
| 17 | + |
| 18 | +From a high-level, the Commit Queue works as follow: |
| 19 | + |
| 20 | +1. Collaborators will add `commit-queue` label to Pull Reuqests ready to land |
| 21 | +2. Every five minutes the queue will do the following for each Pull Request |
| 22 | + with the label: |
| 23 | + 1. Check if the PR also has a `request-ci` label (if it has, skip this PR |
| 24 | + since it's pending a CI run) |
| 25 | + 2. Check if the last Jenkins CI is finished running (if it is not, skip this |
| 26 | + PR) |
| 27 | + 3. Remove the `commit-queue` label |
| 28 | + 4. Run `git node land <pr>` |
| 29 | + 5. If it fails: |
| 30 | + 1. Abort `git node land` session |
| 31 | + 2. Add `commit-queue-failed` label to the PR |
| 32 | + 3. Leave a comment on the PR with the output from `git node land` |
| 33 | + 4. Skip next steps, go to next PR in the queue |
| 34 | + 6. If it succeeds: |
| 35 | + 1. Push the changes to nodejs/node |
| 36 | + 2. Leave a comment on the PR with `Landed in ...` |
| 37 | + 3. Close the PR |
| 38 | + 4. Go to next PR in the queue |
| 39 | + |
| 40 | +## Current Limitations |
| 41 | + |
| 42 | +The Commit Queue feature is still in early stages, and as such it might not |
| 43 | +work for more complex Pull Requests. These are the currently known limitations |
| 44 | +of the commit queue: |
| 45 | + |
| 46 | +1. The Pull Request must have only one commit |
| 47 | +2. A CI must've ran and succeeded since the last change on the PR |
| 48 | +3. A Collaborator must have approved the PR since the last change |
| 49 | +4. Only Jenkins CI is checked (Actions, V8 CI and CITGM are ignored) |
| 50 | + |
| 51 | +## Implementation |
| 52 | + |
| 53 | +The [action](/.github/workflows/commit_queue.yml) will run on scheduler |
| 54 | +events every five minutes. Five minutes is the smallest number accepted by |
| 55 | +the scheduler. The scheduler is not guaranteed to run every five minutes, it |
| 56 | +might take longer between runs. |
| 57 | + |
| 58 | +Using the scheduler is preferrable over using pull_request_target for two |
| 59 | +reasons: |
| 60 | + |
| 61 | +1. if two Commit Queue Actions execution overlap, there's a high-risk that |
| 62 | + the last one to finish will fail because the local branch will be out of |
| 63 | + sync with the remote after the first Action pushes. `issue_comment` event |
| 64 | + has the same limitation. |
| 65 | +2. `pull_request_target` will only run if the Action exists on the base commit |
| 66 | + of a pull request, and it will run the Action version present on that |
| 67 | + commit, meaning we wouldn't be able to use it for already opened PRs |
| 68 | + without rebasing them first. |
| 69 | + |
| 70 | +`node-core-utils` is configured with a personal token and |
| 71 | +a Jenkins token from |
| 72 | +[@nodejs-github-bot](https://github.com/nodejs/github-bot). |
| 73 | +`octokit/graphql-action` is used to fetch all Pull Requests with the |
| 74 | +`commit-queue` label. The output is a JSON payload, so `jq` is used to turn |
| 75 | +that into a list of PR ids we can pass as arguments to |
| 76 | +[`commit-queue.sh`](./tools/actions/commit-queue.sh). |
| 77 | + |
| 78 | +> The personal token only needs permission for public repositories and to read |
| 79 | +> profiles, we can use the GITHUB_TOKEN for write operations. Jenkins token is |
| 80 | +> required to check CI status. |
| 81 | +
|
| 82 | +`commit-queue.sh` receives the following positional arguments: |
| 83 | + |
| 84 | +1. The repository owner |
| 85 | +2. The repository name |
| 86 | +3. The Action GITHUB_TOKEN |
| 87 | +4. Every positional argument starting at this one will be a Pull Reuqest ID of |
| 88 | + a Pull Request with commit-queue set. |
| 89 | + |
| 90 | +The script will iterate over the pull requests. `ncu-ci` is used to check if |
| 91 | +the last CI is still pending, and calls to the GitHub API are used to check if |
| 92 | +the PR is waiting for CI to start (`request-ci` label). The PR is skipped if CI |
| 93 | +is pending. No other CI validation is done here since `git node land` will fail |
| 94 | +if the last CI failed. |
| 95 | + |
| 96 | +The script removes the `commit-queue` label. It then runs `git node land`, |
| 97 | +forwarding stdout and stderr to a file. If any errors happens, |
| 98 | +`git node land --abort` is run, and then a `commit-queue-failed` label is added |
| 99 | +to the PR, as well as a comment with the output of `git node land`. |
| 100 | + |
| 101 | +If no errors happen during `git node land`, the script will use the |
| 102 | +`GITHUB_TOKEN` to push the changes to `master`, and then will leave a |
| 103 | +`Landed in ...` comment in the PR, and then will close it. Iteration continues |
| 104 | +until all PRs have done the steps above. |
| 105 | + |
| 106 | +## Reverting Broken Commits |
| 107 | + |
| 108 | +Reverting broken commits is done manually by Collaborators, just like when |
| 109 | +commits are landed manually via `git node land`. An easy way to revert is a |
| 110 | +good feature for the project, but is not explicitly required for the Commit |
| 111 | +Queue to work because the Action lands PRs just like collaborators do today. If |
| 112 | +once we start using the Commit Queue we notice that the number of required |
| 113 | +reverts increases drastically, we can pause the queue until a Revert Queue is |
| 114 | +implemented, but until then we can enable the Commit Queue and then work on a |
| 115 | +Revert Queue as a follow up. |
0 commit comments