Skip to content

Commit

Permalink
feat(webhook): Support multiple arrays of tags is matchers. (github-a…
Browse files Browse the repository at this point in the history
…ws-runners#2736)

* feat(multi-runner): Support multiple arrays of tags in matchers

* Run ci for webhook

* fix terraform type

* fix formatting

* fix terraform type

* fix terraform type

* fix: some fixes.

* fix: readme.

* fix example workflow labes

* add test for multiple label match

* add test for multiple label match

Co-authored-by: navdeepg2021 <navdeepg2021@gmail.com>
  • Loading branch information
npalm and navdeepg2021 committed Dec 28, 2022
1 parent 12a403d commit d17f441
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 40 deletions.
2 changes: 1 addition & 1 deletion examples/multi-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This module shows how to create GitHub action runners with multiple runner configuration together in one deployment. This example has the configurations for the following runner types with the relevant labels supported by them as matchers:

- Linux ARM64 `["self-hosted", "linux", "arm64", "amazon"]`
- Linux Ubuntu `["self-hosted", "linux", "x64", "ubuntu"]`
- Linux Ubuntu `["self-hosted", "linux", "x64", "ubuntu-latest"]` or `["self-hosted", "linux", "x64", "ubuntu-2204"]``
- Linux X64 `["self-hosted", "linux", "x64", "amazon"]`
- Windows X64 `["self-hosted", "windows", "x64", "servercore-2022"]`

Expand Down
12 changes: 6 additions & 6 deletions examples/multi-runner/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module "multi-runner" {
multi_runner_config = {
"linux-arm64" = {
matcherConfig : {
labelMatchers = ["self-hosted", "linux", "arm64", "amazon"]
labelMatchers = [["self-hosted", "linux", "arm64", "amazon"]]
exactMatch = true
}
fifo = true
Expand All @@ -33,7 +33,7 @@ module "multi-runner" {
},
"linux-ubuntu" = {
matcherConfig : {
labelMatchers = ["self-hosted", "linux", "x64", "ubuntu"]
labelMatchers = [["self-hosted", "linux", "x64", "ubuntu-latest"], ["self-hosted", "linux", "x64", "ubuntu-2204"]]
exactMatch = true
}
fifo = true
Expand All @@ -45,12 +45,12 @@ module "multi-runner" {
runner_config = {
runner_os = "linux"
runner_architecture = "x64"
runner_extra_labels = "ubuntu"
runner_extra_labels = "ubuntu-latest,ubuntu-2204"
runner_run_as = "ubuntu"
enable_ssm_on_runners = true
instance_types = ["m5ad.large", "m5a.large"]
runners_maximum_count = 1
scale_down_schedule_expression = "cron(* * * * ? *)"
runner_run_as = "ubuntu"
userdata_template = "./templates/user-data.sh"
ami_owners = ["099720109477"] # Canonical's Amazon account ID

Expand Down Expand Up @@ -93,7 +93,7 @@ module "multi-runner" {
},
"windows-x64" = {
matcherConfig : {
labelMatchers = ["self-hosted", "windows", "x64", "servercore-2022"]
labelMatchers = [["self-hosted", "windows", "x64", "servercore-2022"]]
exactMatch = true
}
fifo = true
Expand All @@ -114,7 +114,7 @@ module "multi-runner" {
},
"linux-x64" = {
matcherConfig : {
labelMatchers = ["self-hosted", "linux", "x64", "amazon"]
labelMatchers = [["self-hosted", "linux", "x64", "amazon"]]
exactMatch = false
}
fifo = true
Expand Down
6 changes: 3 additions & 3 deletions modules/multi-runner/README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions modules/multi-runner/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ variable "multi_runner_config" {
})

matcherConfig = object({
labelMatchers = list(string)
labelMatchers = list(list(string))
exactMatch = optional(bool, false)
})
fifo = optional(bool, false)
Expand Down Expand Up @@ -165,7 +165,7 @@ variable "multi_runner_config" {
pool_config: "The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for week days to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1."
}
matcherConfig: {
labelMatchers: "The list of labels supported by the runner configuration."
labelMatchers: "The list of list of labels supported by the runner configuration. `[[self-hosted, linux, x64, example]]`"
exactMatch: "If set to true all labels in the workflow job must match the GitHub labels (os, architecture and `self-hosted`). When false if __any__ workflow label matches it will trigger the webhook."
}
fifo: "Enable a FIFO queue to remain the order of events received by the webhook. Suggest to set to true for repo level runners."
Expand Down
3 changes: 2 additions & 1 deletion modules/webhook/lambdas/webhook/src/sqs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ export interface ActionRequestMessage {
}

export interface MatcherConfig {
labelMatchers: string[];
labelMatchers: string[][];
exactMatch: bool;
}

export interface QueueConfig {
matcherConfig: MatcherConfig;
id: string;
Expand Down
69 changes: 53 additions & 16 deletions modules/webhook/lambdas/webhook/src/webhook/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted', 'test'],
labelMatchers: [['self-hosted', 'test']],
exactMatch: true,
},
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted', 'test1'],
labelMatchers: [['self-hosted', 'test1']],
exactMatch: true,
},
},
Expand All @@ -180,14 +180,14 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['linux', 'TEST', 'self-hosted'],
labelMatchers: [['linux', 'TEST', 'self-hosted']],
exactMatch: true,
},
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted', 'test1'],
labelMatchers: [['self-hosted', 'test1']],
exactMatch: true,
},
},
Expand All @@ -212,14 +212,14 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted', 'test', 'test2'],
labelMatchers: [['self-hosted', 'test', 'test2']],
exactMatch: true,
},
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted', 'test1'],
labelMatchers: [['self-hosted', 'test1']],
exactMatch: true,
},
},
Expand All @@ -244,14 +244,14 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted', 'x64', 'linux', 'test'],
labelMatchers: [['self-hosted', 'x64', 'linux', 'test']],
exactMatch: true,
},
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted', 'x64', 'linux', 'test1'],
labelMatchers: [['self-hosted', 'x64', 'linux', 'test1']],
exactMatch: true,
},
},
Expand All @@ -276,14 +276,14 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted', 'test', 'test2'],
labelMatchers: [['self-hosted', 'test', 'test2']],
exactMatch: true,
},
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted', 'x64'],
labelMatchers: [['self-hosted', 'x64']],
exactMatch: false,
},
},
Expand All @@ -308,14 +308,14 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted', 'x64', 'linux', 'test'],
labelMatchers: [['self-hosted', 'x64', 'linux', 'test']],
exactMatch: false,
},
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted', 'x64', 'linux', 'test1'],
labelMatchers: [['self-hosted', 'x64', 'linux', 'test1']],
exactMatch: false,
},
},
Expand All @@ -339,15 +339,15 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted'],
labelMatchers: [['self-hosted']],
exactMatch: false,
},
id: 'ubuntu-queue-id',
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted'],
labelMatchers: [['self-hosted']],
exactMatch: false,
},
id: 'default-queue-id',
Expand Down Expand Up @@ -380,15 +380,15 @@ describe('handler', () => {
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: ['self-hosted'],
labelMatchers: [['self-hosted']],
exactMatch: false,
},
id: 'ubuntu-queue-id',
},
{
...queuesConfig[1],
matcherConfig: {
labelMatchers: ['self-hosted'],
labelMatchers: [['self-hosted']],
exactMatch: false,
},
id: 'default-queue-id',
Expand Down Expand Up @@ -418,6 +418,43 @@ describe('handler', () => {
});
});

it('Check webhook will accept jobs when matchers accepts multiple labels.', async () => {
process.env.RUNNER_CONFIG = JSON.stringify([
{
...queuesConfig[0],
matcherConfig: {
labelMatchers: [
['self-hosted', 'arm64', 'linux', 'ubuntu-latest'],
['self-hosted', 'arm64', 'linux', 'ubuntu-2204'],
],
exactMatch: false,
},
id: 'ubuntu-queue-id',
},
]);
const event = JSON.stringify({
...workflowjob_event,
workflow_job: {
...workflowjob_event.workflow_job,
labels: ['self-hosted', 'linux', 'arm64', 'ubuntu-latest'],
},
});
const resp = await handle(
{ 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' },
event,
);
expect(resp.statusCode).toBe(201);
expect(sendActionRequest).toBeCalledWith({
id: workflowjob_event.workflow_job.id,
repositoryName: workflowjob_event.repository.name,
repositoryOwner: workflowjob_event.repository.owner.login,
eventType: 'workflow_job',
installationId: 0,
queueId: 'ubuntu-queue-id',
queueFifo: false,
});
});

describe('Test for check_run is ignored.', () => {
it('handles check_run events', async () => {
const event = JSON.stringify(checkrun_event);
Expand Down
16 changes: 10 additions & 6 deletions modules/webhook/lambdas/webhook/src/webhook/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,22 @@ function isRepoNotAllowed(repoFullName: string, repositoryWhiteList: string[]):
return repositoryWhiteList.length > 0 && !repositoryWhiteList.includes(repoFullName);
}

function canRunJob(workflowJobLabels: string[], runnerLabels: string[], workflowLabelCheckAll: boolean): boolean {
runnerLabels = runnerLabels.map((element) => {
return element.toLowerCase();
function canRunJob(
workflowJobLabels: string[],
runnerLabelsMatchers: string[][],
workflowLabelCheckAll: boolean,
): boolean {
runnerLabelsMatchers = runnerLabelsMatchers.map((runnerLabel) => {
return runnerLabel.map((label) => label.toLowerCase());
});
const match = workflowLabelCheckAll
? workflowJobLabels.every((l) => runnerLabels.includes(l.toLowerCase()))
: workflowJobLabels.some((l) => runnerLabels.includes(l.toLowerCase()));
? workflowJobLabels.every((wl) => runnerLabelsMatchers.some((rl) => rl.includes(wl.toLowerCase())))
: workflowJobLabels.some((wl) => runnerLabelsMatchers.some((rl) => rl.includes(wl.toLowerCase())));

logger.debug(
`Received workflow job event with labels: '${JSON.stringify(workflowJobLabels)}'. The event does ${
match ? '' : 'NOT '
}match the runner labels: '${Array.from(runnerLabels).join(',')}'`,
}match the runner labels: '${Array.from(runnerLabelsMatchers).join(',')}'`,
LogFields.print(),
);
return match;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"arn": "queueARN",
"fifo": false,
"matcherConfig": {
"labelMatchers": [
"labelMatchers": [[
"self-hosted",
"linux",
"x64",
"ubuntu"
],
]],
"exactMatch": true
}
},
Expand All @@ -18,12 +18,12 @@
"arn": "queueARN",
"fifo": false,
"matcherConfig": {
"labelMatchers": [
"labelMatchers": [[
"self-hosted",
"linux",
"x64",
"latest"
],
]],
"exactMatch": false
}
}
Expand Down
2 changes: 1 addition & 1 deletion modules/webhook/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ variable "runner_config" {
id = string
fifo = bool
matcherConfig = object({
labelMatchers = list(string)
labelMatchers = list(list(string))
exactMatch = bool
})
}))
Expand Down

0 comments on commit d17f441

Please sign in to comment.