Skip to content

Commit

Permalink
Merge pull request #13 from upsidr/add-more-documentation
Browse files Browse the repository at this point in the history
Adjust wording and add image
  • Loading branch information
rytswd authored Sep 16, 2021
2 parents b8b9267 + 929be2f commit 67f3c3a
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 18 deletions.
63 changes: 56 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,75 @@

Merge Gatekeeper provides extra control for Pull Request management.

## 🌄 What does Merge Gatekeeper provide, and Why?
## 🌄 What Does Merge Gatekeeper Provide, and Why?

<!-- == imptr: background / begin from: ./docs/details.md#[background] == -->

Pull Request plays a significant part in day-to-day development, and making sure all the merges are controled is essential for building robust system. GitHub provides some control over CI, reviews, etc., but there are some limitations with handling special cases.
Pull Request plays a significant part in day-to-day development, and it is essential to ensure all merges are well controlled and managed to build robust system. GitHub provides controls over CI, reviews, etc., but there are some limitations around handling specific use cases. Merge Gatekeeper helps overcome those by adding extra controls, such as monorepo friendly branch protection.

At UPSIDER, we have a few internal repositories set up with a monorepo structure, where there are many types of code in the single repository. This comes with its own pros and cons, but with GitHub Action and merge control, there is no way to specify "Ensure Go build and test pass _if and only if_ Go code is updated", or "Ensure E2E tests are run and successful _if and only if_ frontend code is updated". Because of this limitation, we would either need to run all the CI jobs for all the code for any Pull Requests, or do not set any limitation based on the CI status. <sup>(\*1)</sup>
At UPSIDER, we have a few internal repositories set up with a monorepo structure, with many types of code in a single repository. This comes with its own pros and cons, but one difficulty is how we end up with various CI jobs, which only run for changes that touch relevant files. With GitHub's branch protection, there is no way to specify "Ensure Go build and test pass _if and only if_ Go code is updated", or "Ensure E2E tests are run and successful _if and only if_ frontend code is updated". This is due to the GitHub branch protection design to specify a list of jobs to pass, which is only driven by the target branch name, regardless of change details. Because of this limitation, we would either need to run all the CI jobs for any Pull Requests, or do not set any limitation based on the CI status. <sup><sub><sup>(\*1)</sup></sub></sup>

Merge Gatekeeper was created to provide more control over merges.
**Merge Gatekeeper** was created to provide more control for merges. By placing Merge Gatekeeper to run for all PRs, it can check all other CI jobs that get kicked off, and ensure all the jobs are completed successfully. If there is any job that has failed, Merge Gatekeeper will fail as well. This allows merge protection based on Merge Gatekeeper, which can effectively ensure any CI failure will block merge. All you need is the Merge Gatekeeper as one of the PR based GitHub Action, and set the branch protection rule as shown below.

---
![Branch protection example](/assets/images/branch-protection-example.png)

We are looking to add a few more features, such as extra signoff from non-coder, label based check, etc.

NOTE <sup>(\*1)</sup>: There are some other hacks, such as using an empty job with the same name to override the status, but those solutions do not provide the flexible control we are after.
<sup><sub>NOTE:
<sup>(\*1)</sup> There are some other hacks, such as using an empty job with the same name to override the status, but those solutions do not provide the flexible control we are after.</sub></sup>

<!-- == imptr: background / end == -->

You can find [more details here](/docs/details.md).

## 🚀 How Can I Use Merge Gatekeeper?

<!-- == imptr: example-usage / begin from: ./docs/action-usage.md#[simple-usage] == -->

The easiest approach is to copy the standard definition, and save it under `.github/workspaces` directory. There is no further modification required unless you have some specific requirements.

#### With `curl`

```bash
curl -sSL https://raw.githubusercontent.com/upsidr/merge-gatekeeper/main/example/merge-gatekeeper.yml \
> .github/workflows/merge-gatekeeper.yml
```

#### Directly copy YAML

The below is the copy of [`/example/merge-gatekeeper.yml`](/example/merge-gatekeeper.yml).

<!-- TODO: replace below using Importer once Importer supports code block wrapping
== imptr: basic-yaml / begin from: ./example/definitions.yaml#[standard-setup] == -->

```yaml
---
name: Merge Gatekeeper

You can find [more details here](/docs/details.md).
on:
pull_request:
branches:
- main
- master

jobs:
merge-gatekeeper:
runs-on: ubuntu-latest
steps:
- name: Run Merge Gatekeeper
uses: upsidr/merge-gatekeeper@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
<!-- == imptr: example-usage / end == -->
You can find [more details here](/docs/action-usage.md).
## 🧪 Action Inputs
There are some customisation available for Merge Gatekeeper.
<!-- == imptr: inputs / begin from: ./docs/action-usage.md#[inputs] == -->
| Name | Description | Required |
Expand All @@ -35,3 +82,5 @@ You can find [more details here](/docs/details.md).
| `ref` | Git ref to check out. This falls back to the HEAD for given PR, but can be set to any ref. | |

<!-- == imptr: inputs / end == -->

You can find [more details here](/docs/action-usage.md).
Binary file added assets/images/branch-protection-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 20 additions & 3 deletions docs/action-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,23 @@

### Copy Standard YAML

If you are after the other job status check provided by Merge Gatekeeper, you will simply need to copy the following YAML.
<!-- == export: simple-usage / begin == -->

The easiest approach is to copy the standard definition, and save it under `.github/workspaces` directory. There is no further modification required unless you have some specific requirements.

#### With `curl`

```bash
curl -sSL https://raw.githubusercontent.com/upsidr/merge-gatekeeper/main/example/merge-gatekeeper.yml \
> .github/workflows/merge-gatekeeper.yml
```

#### Directly copy YAML

The below is the copy of [`/example/merge-gatekeeper.yml`](/example/merge-gatekeeper.yml).

<!-- TODO: replace below using Importer once Importer supports code block wrapping
== imptr: basic-yaml / begin from: ./example/definitions.yaml#[standard-setup] == -->

```yaml
---
Expand All @@ -33,15 +49,14 @@ on:
jobs:
merge-gatekeeper:
runs-on: ubuntu-latest
name: Merge Gatekeeper
steps:
- name: Run Merge Gatekeeper
uses: upsidr/merge-gatekeeper@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
You can find the exact file at [`/example/merge-gatekeeper.yml`](/example/merge-gatekeeper.yml).
<!-- == export: simple-usage / end == -->
### Using Importer
Expand All @@ -55,3 +70,5 @@ Create a YAML file with just a single Importer Marker:
```

With that, you can simply run `importer update FILENAME` to get the latest spec. You can also update the file used to specific branch or version.

###
29 changes: 21 additions & 8 deletions docs/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@

<!-- == export: background / begin == -->

Pull Request plays a significant part in day-to-day development, and making sure all the merges are controled is essential for building robust system. GitHub provides some control over CI, reviews, etc., but there are some limitations with handling special cases.
Pull Request plays a significant part in day-to-day development, and it is essential to ensure all merges are well controlled and managed to build robust system. GitHub provides controls over CI, reviews, etc., but there are some limitations around handling specific use cases. Merge Gatekeeper helps overcome those by adding extra controls, such as monorepo friendly branch protection.

At UPSIDER, we have a few internal repositories set up with a monorepo structure, where there are many types of code in the single repository. This comes with its own pros and cons, but with GitHub Action and merge control, there is no way to specify "Ensure Go build and test pass _if and only if_ Go code is updated", or "Ensure E2E tests are run and successful _if and only if_ frontend code is updated". Because of this limitation, we would either need to run all the CI jobs for all the code for any Pull Requests, or do not set any limitation based on the CI status. <sup>(\*1)</sup>
At UPSIDER, we have a few internal repositories set up with a monorepo structure, with many types of code in a single repository. This comes with its own pros and cons, but one difficulty is how we end up with various CI jobs, which only run for changes that touch relevant files. With GitHub's branch protection, there is no way to specify "Ensure Go build and test pass _if and only if_ Go code is updated", or "Ensure E2E tests are run and successful _if and only if_ frontend code is updated". This is due to the GitHub branch protection design to specify a list of jobs to pass, which is only driven by the target branch name, regardless of change details. Because of this limitation, we would either need to run all the CI jobs for any Pull Requests, or do not set any limitation based on the CI status. <sup><sub><sup>(\*1)</sup></sub></sup>

Merge Gatekeeper was created to provide more control over merges.
**Merge Gatekeeper** was created to provide more control for merges. By placing Merge Gatekeeper to run for all PRs, it can check all other CI jobs that get kicked off, and ensure all the jobs are completed successfully. If there is any job that has failed, Merge Gatekeeper will fail as well. This allows merge protection based on Merge Gatekeeper, which can effectively ensure any CI failure will block merge. All you need is the Merge Gatekeeper as one of the PR based GitHub Action, and set the branch protection rule as shown below.

---
![Branch protection example](/assets/images/branch-protection-example.png)

NOTE <sup>(\*1)</sup>: There are some other hacks, such as using an empty job with the same name to override the status, but those solutions do not provide the flexible control we are after.
We are looking to add a few more features, such as extra signoff from non-coder, label based check, etc.

<sup><sub>NOTE:
<sup>(\*1)</sup> There are some other hacks, such as using an empty job with the same name to override the status, but those solutions do not provide the flexible control we are after.</sub></sup>

<!-- == export: background / end == -->

## Support
## Features

<!-- == export: support / begin == -->
<!-- == export: features / begin == -->

Merge Gatekeeper provides additional control that may be useful for large and complex repositories.

Expand All @@ -33,4 +36,14 @@ We are currently considering additional validation controls such as:
- extra approval by comment
- label validation

<!-- == export: support / end == -->
<!-- == export: features / end == -->

## How does Merge Gatekeeper work?

<!-- == implementation-details: support / begin == -->

Merge Gatekeeper periodically validates the PR status by hitting GitHub API. The GitHub token is thus required for Merge Gatekeeper to operate, and it's often enough to have `${{ secrets.GITHUB_TOKEN }}` to be provided. The API call to list PR jobs will reveal how many jobs need to run for the given PR, check each job status, and finally return the validation status - success based on completing all the jobs, or timeout error. It is important for Merge Gatekeeper to know the Job name of itself, so that when API call returns Merge Gatekeeper as a part of the PR jobs, it would ignore its status (otherwise it will never succeed).

<!-- TODO: Add more about other validation types when we add support -->

<!-- == implementation-details: support / end == -->
22 changes: 22 additions & 0 deletions example/definitions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,25 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
# == export: standard-setup / end ==

# == export: custom-job-name / begin ==
---
name: Merge Gatekeeper

on:
pull_request:
branches:
- main
- master

jobs:
merge-gatekeeper-custom:
runs-on: ubuntu-latest
name: Custom Name for Merge Gatekeeper
steps:
- name: Run Merge Gatekeeper
uses: upsidr/merge-gatekeeper@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
self: Custom Name for Merge Gatekeeper # This must match with the Job name provided above.
# == export: custom-job-name / end ==

0 comments on commit 67f3c3a

Please sign in to comment.