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

Support pipeline name as param #43

Merged
merged 3 commits into from
Nov 30, 2022
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ Create or delete a webhook using the configured parameters.
webhook_token: your-token
operation: create
events: [push, pull_request]
pipeline: pipeline-name
pipeline_instance_vars: {
your_instance_var_name: value
}
```

- `org`: *Required.* Your github organization.
Expand All @@ -60,6 +64,8 @@ Create or delete a webhook using the configured parameters.
- `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

## Example
Include the github-webhook-resource in your pipeline.yml file
Expand Down
17 changes: 13 additions & 4 deletions bin/out.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ stdin.on('end', function () {
});

function buildUrl(source, params) {
const instanceVars = buildInstanceVariables();
return encodeURI(`${env.ATC_EXTERNAL_URL}/api/v1/teams/${env.BUILD_TEAM_NAME}/pipelines/${env.BUILD_PIPELINE_NAME}/resources/${params.resource_name}/check/webhook?webhook_token=${params.webhook_token}${instanceVars}`);
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}`);
}

function buildInstanceVariables() {
function buildInstanceVariables(params) {
let vars = "";
if (env.BUILD_PIPELINE_INSTANCE_VARS) {
try {
Expand All @@ -62,6 +62,15 @@ function buildInstanceVariables() {
throw new Error(exception);
}
}
if ("pipeline_instance_vars" in params && params.pipeline_instance_vars) {
try {
for (const [key, value] of Object.entries(params.pipeline_instance_vars)) {
vars += `&vars.${key}="${value}"`;
}
} catch(exception) {
throw new Error(exception);
}
}
return vars;
}

Expand Down Expand Up @@ -200,4 +209,4 @@ function log(message) {
console.error(message);
}

module.exports = { buildInstanceVariables };
module.exports = { buildInstanceVariables, buildUrl };
73 changes: 53 additions & 20 deletions bin/out.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const out = require('./out');

describe('buildInstanceVaribles', () => {
describe('out', () => {

const OLD_ENV = process.env;

Expand All @@ -13,26 +13,59 @@ describe('buildInstanceVaribles', () => {
process.env = OLD_ENV;
});

it('with unset variables, returns empty string', () => {
delete process.env.BUILD_PIPELINE_INSTANCE_VARS;
const instanceVar = out.buildInstanceVariables();
expect(instanceVar).toEqual('')
});

it('with empty variables, returns empty string', () => {
process.env.BUILD_PIPELINE_INSTANCE_VARS = "{}";
const instanceVar = out.buildInstanceVariables();
expect(instanceVar).toEqual('')
});

it('with bad json, it throws an exception', () => {
process.env.BUILD_PIPELINE_INSTANCE_VARS = "{695988";
expect(() => out.buildInstanceVariables()).toThrow();
describe('buildInstanceVaribles', () => {
it('with unset variables, returns empty string', () => {
delete process.env.BUILD_PIPELINE_INSTANCE_VARS;
const params = {};
const instanceVar = out.buildInstanceVariables(params);
expect(instanceVar).toEqual('')
});

it('with empty variables, returns empty string', () => {
process.env.BUILD_PIPELINE_INSTANCE_VARS = "{}";
const params = {pipeline_instance_vars: {}};
const instanceVar = out.buildInstanceVariables(params);
expect(instanceVar).toEqual('')
});

it('with bad json, it throws an exception', () => {
process.env.BUILD_PIPELINE_INSTANCE_VARS = "{695988";
const params = {};
expect(() => out.buildInstanceVariables(params)).toThrow();
});

it('with valid instance variables, it builds variable string to append to url', () => {
process.env.BUILD_PIPELINE_INSTANCE_VARS = '{"name":"John", "age":30, "car":"Toyota"}';
const params = {pipeline_instance_vars: {"license": "full"}};
const instanceVar = out.buildInstanceVariables(params);
expect(instanceVar).toEqual(`&vars.name="John"&vars.age="30"&vars.car="Toyota"&vars.license="full"`)
});
});

it('with valid instance variables, it builds variable string to append to url', () => {
process.env.BUILD_PIPELINE_INSTANCE_VARS = '{"name":"John", "age":30, "car":"Toyota"}';
const instanceVar = out.buildInstanceVariables();
expect(instanceVar).toEqual(`&vars.name="John"&vars.age="30"&vars.car="Toyota"`)
describe('buildUrl', () => {
it('defaults to using the current pipeline name', () => {
process.env.ATC_EXTERNAL_URL = 'https://example.com';
process.env.BUILD_PIPELINE_NAME = 'pipeline';
process.env.BUILD_TEAM_NAME = 'team';
const params = {
resource_name: 'resource',
webhook_token: 'token'
}
const instanceVar = out.buildUrl(null, params);
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', () => {
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',
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")
});
});
});
9 changes: 8 additions & 1 deletion bin/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ const configSchema = {
transform: ['trim', 'toEnumCase'],
enum: validOperations,
errorMessage: { enum: 'must be either create or delete' }
}
},
pipeline: {
type: 'string',
transform: ['trim', 'toLowerCase']
},
pipeline_instance_vars: {
type: 'object',
},
},
required: ['org', 'repo', 'resource_name', 'webhook_token', 'operation']
},
Expand Down
49 changes: 45 additions & 4 deletions bin/validate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe('validate.input', () => {
'params.resource_name',
'params.webhook_token',
'params.operation',
'params.pipeline',
];

constrainedFields.forEach(field => {
Expand Down Expand Up @@ -155,13 +156,16 @@ describe('validate.input', () => {
resource_name: '',
webhook_token: '',
operation: 'CrEaTe',
events: ['pUsH']
events: ['pUsH'],
pipeline: 'mYPipeline',
pipeline_instance_vars: {}
}
};

expect(() => validate.config(config)).not.toThrow();
expect(config.params.operation).toBe('create');
expect(config.params.events).toEqual(['push']);
expect(config.params.pipeline).toBe('mypipeline');
});

it('trims whitespace', () => {
Expand All @@ -176,18 +180,21 @@ describe('validate.input', () => {
resource_name: '',
webhook_token: '',
operation: ' create ',
events: [' push ']
events: [' push '],
pipeline: ' mypipeline ',
pipeline_instance_vars: {}
}
};

expect(() => validate.config(config)).not.toThrow();
expect(config.params.operation).toBe('create');
expect(config.params.events).toEqual(['push']);
expect(config.params.pipeline).toBe('mypipeline');
});

it('checks fields with array constraint', () => {
const constrainedFields = [
'params.events'
'params.events',
];

constrainedFields.forEach(field => {
Expand All @@ -202,7 +209,41 @@ describe('validate.input', () => {
resource_name: '',
webhook_token: '',
operation: 'create',
events: []
events: [],
pipeline: '',
pipeline_instance_vars: {}
}
};

expect(() => validate.config(config)).not.toThrow();

const fieldTree = field.split('.');
config[fieldTree[0]][fieldTree[1]] = null;

expect(() => validate.config(config)).toThrow();
});
});

it('checks fields with object constraint', () => {
const constrainedFields = [
'params.pipeline_instance_vars'
];

constrainedFields.forEach(field => {
const config = {
source: {
github_api: '',
github_token: ''
},
params: {
org: '',
repo: '',
resource_name: '',
webhook_token: '',
operation: 'create',
events: [],
pipeline: '',
pipeline_instance_vars: {}
}
};

Expand Down