Skip to content

Commit

Permalink
Send complete event (#29)
Browse files Browse the repository at this point in the history
* Send complete event

* put original event in data

* Update README.md

Co-authored-by: Sebass van Boxel <hello@svboxel.com>

* Update payload name for the origin event

* fix readme

Co-authored-by: Sebass van Boxel <hello@svboxel.com>
  • Loading branch information
thspinto and SvanBoxel authored Feb 19, 2021
1 parent a2be6d2 commit e748722
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 43 deletions.
58 changes: 31 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,34 @@ You can install the app by [clicking here](https://github.com/apps/organization-

<img width="400" alt="Screenshot 2020-12-18 at 17 12 00" src="https://user-images.githubusercontent.com/24505883/102635920-4247eb80-4154-11eb-9ec2-0cb8bc58196c.png">

If you don't want to install it on all repositories, then make sure to at least include the `.github` repository of your organization.
If you don't want to install it on all repositories, then make sure to at least include the `.github` repository of your organization.

<img width="400" alt="Screenshot 2020-12-18 at 17 14 27" src="https://user-images.githubusercontent.com/24505883/102636098-81763c80-4154-11eb-80f5-50e21b33020f.png">

After you install the app, you can create a centrally defined workflow. There are a couple of things to keep in mind when you do this:
After you install the app, you can create a centrally defined workflow. There are a couple of things to keep in mind when you do this:

### Listening to the right event
This app dispatches workflow runs with the `repository_dispatch` event and the `org-workflow-bot` type. Create a new workflow in the `.github/workflows` directory of your organization's `.github` repository with the yml definition below:

```yml
name: compliance-check
name: compliance-check

on:
repository_dispatch:
types: [org-workflow-bot] # <-- requirement to trigger central workflows
types: [org-workflow-bot] # <-- requirement to trigger central workflows
```
> 💡 Don't want to store your organization workflows in the `.github` repository? You can define a custom repository in the [configuration file](#app-configuration).
### Registering the run
To let this app keep track of Action runs and expose this information back to the original commit in the source repository it needs to register the workflow run. Like in the example below, start the workflow by registering the run. After this you can add your steps and jobs like you would in a typical Actions workflow.

```yml
name: compliance-check
name: compliance-check
on:
repository_dispatch:
types: [org-workflow-bot]
types: [org-workflow-bot]
jobs:
register-and-lint:
runs-on: ubuntu-latest
Expand All @@ -50,16 +50,16 @@ jobs:
name: ${{ github.workflow }} # Default: name of workflow. This name is shown with the check, but can be changed.
# ... the checks and jobs that need to happen in your workflow.
```
```
Make sure to not change the `id`, `callback_url`, `sha`, and `run_id`. The `name` argument is shown next to the check on the original commit and can be changed. (default is the name of the workflow)

<img width="500" alt="Screenshot 2020-12-22 at 10 05 34" src="https://user-images.githubusercontent.com/24505883/102870418-479b8380-443d-11eb-9fe7-ea78a20a09fb.png">
<img width="500" alt="Screenshot 2020-12-22 at 10 05 34" src="https://user-images.githubusercontent.com/24505883/102870418-479b8380-443d-11eb-9fe7-ea78a20a09fb.png">

_(☝ source repository)_

You have the possibilty to show the user specific documentation or enforce specific checks, see [Action inputs](#action-inputs) for more information about this.
You have the possibilty to show the user specific documentation or enforce specific checks, see [Action inputs](#action-inputs) for more information about this.

> 👀 Optional: If you don't register the run, the workflow is triggered without providing information to the user that pushed the commit like in the image above. You can still manually provide this information using one of the [Check Actions](https://github.com/marketplace?type=actions&query=checks) that is available in the GitHub Marketplace.
> 👀 Optional: If you don't register the run, the workflow is triggered without providing information to the user that pushed the commit like in the image above. You can still manually provide this information using one of the [Check Actions](https://github.com/marketplace?type=actions&query=checks) that is available in the GitHub Marketplace.

### Checking out code
Because the [GITHUB_SECRET](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow#about-the-github_token-secret) is scoped to the repository it is running in, you need to leverage the GitHub App to get access to the repository that triggered the workflow. You can use the repository, ref, and token that is supplied in the dispatch payload by the app for this:
Expand All @@ -71,13 +71,13 @@ Because the [GITHUB_SECRET](https://docs.github.com/en/free-pro-team@latest/acti
repository: ${{ github.event.client_payload.repository.full_name }}
ref: ${{ github.event.client_payload.sha }}
token: ${{ github.event.client_payload.token }}
- name: Markdown Lint
- name: Markdown Lint
```

> ❗ The token in the dispatch payload is redacted in the workflow logs and cannot be used by users that only have read access to the `.github` repository. Any user who has _push access to the main branch of the `.github` repository_ can however use this token in a workflow and execute commands that are within the scope of this application. (See [App permissions](#app-permission))

### 🚀 Ready to go
You're ready to go! Two examples of centralized workflow can be found [here](./examples), an example organization that uses this app [here](https://github.com/saturn-inc), and [this video](https://drive.google.com/file/d/1Ums09BTHwS2h2TrH9dLsw5z98wFvJxDa/view?usp=sharing) explains from start to end how to set it up yourself.
You're ready to go! Two examples of centralized workflow can be found [here](./examples), an example organization that uses this app [here](https://github.com/saturn-inc), and [this video](https://drive.google.com/file/d/1Ums09BTHwS2h2TrH9dLsw5z98wFvJxDa/view?usp=sharing) explains from start to end how to set it up yourself.

### App permissions
This app needs the following permissions:
Expand All @@ -90,20 +90,20 @@ This app needs the following permissions:
## How it works
When installed in an organization, the app's logic is triggered by any `push` event. When this happens, the app collects all relevant information and [dispatches](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#repository_dispatch) this to the `.github` repository of your organization. Here, all central workflow files configured with the `repository_dispatch` event and `org-workflow-bot` type are triggered.

To map commits, checks, and workflow run, and to make sure workflows can rerun without any problem, some data persistence is needed. Because of this you need to register the run at the start of a workflow. When the workflow finishes the app retrieves what source repository and commit triggered the central workflow, and exposes the workflow results back to the original commit. This data (source repository, check id, sha, and run id) is automatically removed after 90 days.
To map commits, checks, and workflow run, and to make sure workflows can rerun without any problem, some data persistence is needed. Because of this you need to register the run at the start of a workflow. When the workflow finishes the app retrieves what source repository and commit triggered the central workflow, and exposes the workflow results back to the original commit. This data (source repository, check id, sha, and run id) is automatically removed after 90 days.

## App configuration
Optionally you can define a custom configuration in the `.github` repository by creating a `organization-workflows-settings.yml` file. This configuration should be defined as a YAML file and - for now - has a single configuration setting.

`workflows_repository`: The repository where your organization workflows are defined. (default: `.github`)
`include_workflows_repository`: Whether to run these checks for the central workflows_repository. (default: `false`)
`workflows_repository`: The repository where your organization workflows are defined. (default: `.github`)
`include_workflows_repository`: Whether to run these checks for the central workflows_repository. (default: `false`)
`exclude.repositories`: Repositories that are excluded and should not trigger organization workflows. Accepts wildcards. (default: `[]`)

```yml
workflows_repository: our-organization-workflows
include_workflows_repository: false
exclude:
repositories:
exclude:
repositories:
- do_not_run_check_for_this_repo
- 'playground-*'
- test_repository
Expand All @@ -112,15 +112,15 @@ exclude:
## Action inputs
The following inputs should be provided for every organization workflow.

- **id (required)**: ID of run (provided by GitHub app via `github.event.client_payload.id`)
- **run_id (required)**: ID of workflow run (provided via GitHub syntax `github.run_id`)
- **name (required)**: Name of check (Use `github.workflow` to use the name of the workflow)
- **callback_url (required)**: Callback url for register call (provided by GitHub app via `github.event.client_payload.callback_url`)
- **sha (required)**: Sha of original commit (provided by GitHub app via `github.event.client_payload.sha`)
- **enforce (optional)**: Enforce [required status check](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/enabling-required-status-checks). _Default: false_
- **id (required)**: ID of run (provided by GitHub app via `github.event.client_payload.id`)
- **run_id (required)**: ID of workflow run (provided via GitHub syntax `github.run_id`)
- **name (required)**: Name of check (Use `github.workflow` to use the name of the workflow)
- **callback_url (required)**: Callback url for register call (provided by GitHub app via `github.event.client_payload.callback_url`)
- **sha (required)**: Sha of original commit (provided by GitHub app via `github.event.client_payload.sha`)
- **enforce (optional)**: Enforce [required status check](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/enabling-required-status-checks). _Default: false_
- **enforce_admin (optional)** Enforce [required status check](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/enabling-required-status-checks) for admins. _Default: false_
- **documentation (optional)**: Link to documentation of this check. This is shown with the status check on the original commit. (eg `.github/workflows/compliance-info.md`) _Default: null_

```yml
- uses: SvanBoxel/organization-workflow@main
with:
Expand All @@ -134,9 +134,14 @@ The following inputs should be provided for every organization workflow.
documentation: "README.md"
```

## Original event information

The complete event generated in the repository that triggered the workflow is available at `${{ github.event.client_payload.event.<event_field_path> }}`.
Checkout [Github's docs](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#push) to see the information available in the event.

## Development
### Codespaces
A [Codespaces environment](https://github.com/features/codespaces) is defined so you can get started right away. Open this repository in the codespace and run `npm run dev` to start the app in development mode. It will prompt you to follow a couple of instruction to configure your GitHub app and set your .env values.
A [Codespaces environment](https://github.com/features/codespaces) is defined so you can get started right away. Open this repository in the codespace and run `npm run dev` to start the app in development mode. It will prompt you to follow a couple of instruction to configure your GitHub app and set your .env values.

<img width="679" alt="Screenshot 2020-12-22 at 13 29 01" src="https://user-images.githubusercontent.com/24505883/102888754-ae2e9a80-4459-11eb-92cf-5789f945e4d8.png">

Expand Down Expand Up @@ -181,4 +186,3 @@ For more, check out the [Contributing Guide](CONTRIBUTING.md).
## License
[ISC](LICENSE) © 2020 Sebass van Boxel <hello@svboxel.com>
13 changes: 7 additions & 6 deletions src/handlers/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ async function handlePush(context: Context): Promise<void> {

const sha = context.payload.after
const webhook = await context.octokit.apps.getWebhookConfigForApp()
const token = await context.octokit.apps.createInstallationAccessToken({
const token = await context.octokit.apps.createInstallationAccessToken({
installation_id: context?.payload?.installation?.id || 0,
repository_ids: [context.payload.repository.id]
repository_ids: [context.payload.repository.id]
})

const data = {
Expand All @@ -48,13 +48,13 @@ async function handlePush(context: Context): Promise<void> {
full_name: context.payload.repository.full_name
}
}

const run = new Run({
...data,
checks: [],
config: pick(config, config_keys)
});

const { _id } = await run.save()

await context.octokit.repos.createDispatchEvent({
Expand All @@ -63,10 +63,11 @@ async function handlePush(context: Context): Promise<void> {
event_type: repository_dispatch_type,
client_payload: {
id: _id.toString(),
token: token.data.token,
...data,
token: token.data.token
event: context.payload
}
})
}

export default handlePush;
export default handlePush;
21 changes: 11 additions & 10 deletions test/handlers/push.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,21 +113,22 @@ describe('push handler', () => {
test('should call octokit createDispatchEvent correct data', async () => {
await handlePush(context);
expect(context.octokit.repos.createDispatchEvent).toBeCalledWith({
owner: context.payload.repository.owner.login,
owner: context.payload.repository.owner.login,
repo: ".github",
event_type: "org-workflow-bot",
client_payload: {
sha: context.payload.after,
sha: context.payload.after,
id: id,
token: token,
callback_url: `${callback_url}/org-workflows/register`,
id: id,
repository: {
full_name: context.payload.repository.full_name,
name: context.payload.repository.name,
owner: context.payload.repository.owner.login,
}
callback_url: `${callback_url}/org-workflows/register`,
repository: {
full_name: context.payload.repository.full_name,
name: context.payload.repository.name,
owner: context.payload.repository.owner.login,
},
event: event.payload
}
})
})
})
});
});

0 comments on commit e748722

Please sign in to comment.