Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add param support for payload configurations #50

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading