Skip to content

Commit

Permalink
Add param support for payload configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
joshbrucker committed Apr 3, 2024
1 parent 3bfd6ed commit 3704890
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 25 deletions.
32 changes: 20 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ resources:
github_token: ((github-token))
```
- `github_api`: *Required.* The Github API URL for your repo.
- `github_token`: *Required.* [A Github token with the `admin:repo_hook` scope.](https://github.com/settings/tokens/new?scopes=admin:repo_hook) Additionally, the token's account must [be an administrator of your repo](https://help.github.com/en/articles/managing-an-individuals-access-to-an-organization-repository) to manage the repo's webhooks.
- `github_api`: *Required.* The Github API URL for your repo.
- `github_token`: *Required.* [A Github token with the `admin:repo_hook` scope.](https://github.com/settings/tokens/new?scopes=admin:repo_hook) Additionally, the token's account must [be an administrator of your repo](https://help.github.com/en/articles/managing-an-individuals-access-to-an-organization-repository) to manage the repo's webhooks.

Behavior
--------
Expand All @@ -54,18 +54,26 @@ Create or delete a webhook using the configured parameters.
pipeline_instance_vars: {
your_instance_var_name: value
}
payload_base_url: your-payload-base-url
payload_content_type: json
payload_secret: your-payload-secret
```

- `org`: *Required.* Your github organization.
- `repo`: *Required.* Your github repository.
- `resource_name`: *Required.* Name of the resource to be associated with your webhook.
- `webhook_token`: *Required.* Arbitrary string to identify your webhook. Must match the `webhook_token` property of the resource your webhook points to.
- `operation`: *Required.*
- `create` to create a new webhook. Updates existing webhook if your configuration differs from remote.
- `delete` to delete an existing webhook. Outputs current timestamp on non-existing webhooks.
- `events`: *Optional*. An array of [events](https://developer.github.com/webhooks/#events) which will trigger your webhook. Default: `push`
- `pipeline`: *Optional.* Defaults to the name of the pipeline executing the task
- `pipeline_instance_vars`: *Optional.* Instance vars to append to the webhook url. These help Concourse identify which [instance pipeline](https://concourse-ci.org/resources.html#schema.resource.webhook_token) it should invoke
- `org`: *Required.* Your github organization.
- `repo`: *Required.* Your github repository.
- `resource_name`: *Required.* Name of the resource to be associated with your webhook.
- `webhook_token`: *Required.* Arbitrary string to identify your webhook. Must match the `webhook_token` property of the resource your webhook points to.
- `operation`: *Required.*
- `create` to create a new webhook. Updates existing webhook if your configuration differs from remote.
- `delete` to delete an existing webhook. Outputs current timestamp on non-existing webhooks.
- `events`: *Optional*. An array of [events](https://developer.github.com/webhooks/#events) which will trigger your webhook. Default: `push`
- `pipeline`: *Optional.* Defaults to the name of the pipeline executing the task
- `pipeline_instance_vars`: *Optional.* Instance vars to append to the webhook url. These help Concourse identify which [instance pipeline](https://concourse-ci.org/resources.html#schema.resource.webhook_token) it should invoke
- `payload_base_url`: *Optional.* The base URL to send the webhook payload to. Defaults to the external Concourse URL of the pipeline executing the task.
- `payload_content_type`: *Optional.* Default: `json`
- `json` to serialize payloads to JSON.
- `form` to serialize payloads to x-www-form-urlencoded.
- `payload_secret`: *Optional.* Secret that is used as the key to generate [delivery signature headers](https://docs.github.com/en/webhooks/webhook-events-and-payloads#delivery-headers), if the destination requires it for delivery validation.

## Example
Include the github-webhook-resource in your pipeline.yml file
Expand Down
8 changes: 6 additions & 2 deletions bin/out.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ stdin.on('end', function () {

function buildUrl(source, params) {
const instanceVars = buildInstanceVariables(params);
return encodeURI(`${env.ATC_EXTERNAL_URL}/api/v1/teams/${env.BUILD_TEAM_NAME}/pipelines/${params.pipeline ? params.pipeline : env.BUILD_PIPELINE_NAME}/resources/${params.resource_name}/check/webhook?webhook_token=${params.webhook_token}${instanceVars}`);
const payloadBaseUrl = params.payload_base_url ? params.payload_base_url : env.ATC_EXTERNAL_URL;
const pipeline = params.pipeline ? params.pipeline : env.BUILD_PIPELINE_NAME;

return encodeURI(`${payloadBaseUrl}/api/v1/teams/${env.BUILD_TEAM_NAME}/pipelines/${pipeline}/resources/${params.resource_name}/check/webhook?webhook_token=${params.webhook_token}${instanceVars}`);
}

function buildInstanceVariables(params) {
Expand Down Expand Up @@ -84,7 +87,8 @@ async function processWebhook(source, params) {

const config = {
'url': url,
'content-type': 'json'
'content_type': params.payload_content_type ? params.payload_content_type : 'json',
'secret': params.payload_secret
};

const body = {
Expand Down
9 changes: 5 additions & 4 deletions bin/out.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('out', () => {
});

describe('buildUrl', () => {
it('defaults to using the current pipeline name', () => {
it('defaults to using the concourse env vars', () => {
process.env.ATC_EXTERNAL_URL = 'https://example.com';
process.env.BUILD_PIPELINE_NAME = 'pipeline';
process.env.BUILD_TEAM_NAME = 'team';
Expand All @@ -55,17 +55,18 @@ describe('out', () => {
expect(instanceVar).toEqual("https://example.com/api/v1/teams/team/pipelines/pipeline/resources/resource/check/webhook?webhook_token=token")
});

it('prefers the pipeline name from params', () => {
it('prefers the concourse vars from params', () => {
process.env.ATC_EXTERNAL_URL = 'https://example.com';
process.env.BUILD_PIPELINE_NAME = 'pipeline';
process.env.BUILD_TEAM_NAME = 'team';
const params = {
pipeline: 'another-pipeline',
pipeline: 'param-pipeline',
payload_base_url: 'https://param-example.com',
resource_name: 'resource',
webhook_token: 'token'
}
const instanceVar = out.buildUrl(null, params);
expect(instanceVar).toEqual("https://example.com/api/v1/teams/team/pipelines/another-pipeline/resources/resource/check/webhook?webhook_token=token")
expect(instanceVar).toEqual("https://param-example.com/api/v1/teams/team/pipelines/param-pipeline/resources/resource/check/webhook?webhook_token=token")
});
});
});
16 changes: 14 additions & 2 deletions bin/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require('ajv-errors')(ajv);
require('ajv-keywords')(ajv, 'transform');

const validOperations = ['create', 'delete'];
const validContentTypes = ['form', 'json'];

const envSchema = {
type: 'object',
Expand Down Expand Up @@ -47,13 +48,24 @@ const configSchema = {
enum: validOperations,
errorMessage: { enum: 'must be either create or delete' }
},
pipeline: {
pipeline: {
type: 'string',
transform: ['trim', 'toLowerCase']
},
pipeline_instance_vars: {
pipeline_instance_vars: {
type: 'object',
},
payload_base_url: {
type: 'string',
transform: ['trim', 'toLowerCase']
},
payload_content_type: {
type: 'string',
transform: ['trim', 'toEnumCase'],
enum: validContentTypes,
errorMessage: { enum: 'must be either form or json' }
},
payload_secret: { type: 'string' }
},
required: ['org', 'repo', 'resource_name', 'webhook_token', 'operation']
},
Expand Down
31 changes: 26 additions & 5 deletions bin/validate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ describe('validate.input', () => {
'params.webhook_token',
'params.operation',
'params.pipeline',
'params.payload_base_url',
'params.payload_content_type',
'params.payload_secret'
];

constrainedFields.forEach(field => {
Expand All @@ -131,7 +134,11 @@ describe('validate.input', () => {
repo: '',
resource_name: '',
webhook_token: '',
operation: 'create'
operation: 'create',
pipeline: '',
payload_base_url: '',
payload_content_type: 'json',
payload_secret: ''
}
};

Expand All @@ -158,14 +165,18 @@ describe('validate.input', () => {
operation: 'CrEaTe',
events: ['pUsH'],
pipeline: 'mYPipeline',
pipeline_instance_vars: {}
pipeline_instance_vars: {},
payload_base_url: 'hTTps://ExampLe.com',
payload_content_type: 'JsOn'
}
};

expect(() => validate.config(config)).not.toThrow();
expect(config.params.operation).toBe('create');
expect(config.params.events).toEqual(['push']);
expect(config.params.pipeline).toBe('mypipeline');
expect(config.params.payload_base_url).toBe('https://example.com');
expect(config.params.payload_content_type).toBe('json');
});

it('trims whitespace', () => {
Expand All @@ -182,14 +193,18 @@ describe('validate.input', () => {
operation: ' create ',
events: [' push '],
pipeline: ' mypipeline ',
pipeline_instance_vars: {}
pipeline_instance_vars: {},
payload_base_url: ' https://example.com ',
payload_content_type: ' json '
}
};

expect(() => validate.config(config)).not.toThrow();
expect(config.params.operation).toBe('create');
expect(config.params.events).toEqual(['push']);
expect(config.params.pipeline).toBe('mypipeline');
expect(config.params.payload_base_url).toBe('https://example.com');
expect(config.params.payload_content_type).toBe('json');
});

it('checks fields with array constraint', () => {
Expand All @@ -211,7 +226,10 @@ describe('validate.input', () => {
operation: 'create',
events: [],
pipeline: '',
pipeline_instance_vars: {}
pipeline_instance_vars: {},
payload_base_url: '',
payload_content_type: 'json',
payload_secret: ''
}
};

Expand Down Expand Up @@ -243,7 +261,10 @@ describe('validate.input', () => {
operation: 'create',
events: [],
pipeline: '',
pipeline_instance_vars: {}
pipeline_instance_vars: {},
payload_base_url: '',
payload_content_type: 'json',
payload_secret: ''
}
};

Expand Down

0 comments on commit 3704890

Please sign in to comment.