diff --git a/lib/pipeline.js b/lib/pipeline.js index 8540119d..c4f7735a 100644 --- a/lib/pipeline.js +++ b/lib/pipeline.js @@ -152,7 +152,7 @@ class PipelineModel extends BaseModel { /** * Attach Screwdriver webhook to the pipeline's repository - * @param webhookUrl The webhook to be added + * @param {String} webhookUrl The webhook to be added * @method addWebhook * @return {Promise} */ @@ -193,6 +193,41 @@ class PipelineModel extends BaseModel { /* eslint-enable no-understore-dangle */ } + /** + * Sync PR by looking up the PR's screwdriver.yaml + * Update the permutations to be correct + * @param {Integer} prNum PR Number + * @method syncPR + * @return {Promise} + */ + syncPR(prNum) { + // Lazy load factory dependency to prevent circular dependency issues + // https://nodejs.org/api/modules.html#modules_cycles + /* eslint-disable global-require */ + const JobFactory = require('./jobFactory'); + /* eslint-enable global-require */ + + const jobFactory = JobFactory.getInstance(); + + return this.admin + .then(user => user.unsealToken()) + .then(token => this.scm.getPrInfo({ + scmUri: this.scmUri, + token, + prNum + })) + .then(prInfo => Promise.all([ + this.getConfiguration(prInfo.ref), + jobFactory.get({ pipelineId: this.id, name: `PR-${prNum}` }) + ])) + .then(([parsedConfig, job]) => { + job.permutations = parsedConfig.jobs.main; + + return job.update(); + }) + .then(() => this); + } + /** * Sync the pipeline by looking up screwdriver.yaml * Create, update, or disable jobs if necessary. diff --git a/package.json b/package.json index f9f2d77a..e20496f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "screwdriver-models", - "version": "21.2.0", + "version": "22.0.0", "description": "Screwdriver models", "main": "index.js", "scripts": { diff --git a/test/lib/pipeline.test.js b/test/lib/pipeline.test.js index 4c02dc1f..1145c7f0 100644 --- a/test/lib/pipeline.test.js +++ b/test/lib/pipeline.test.js @@ -98,7 +98,8 @@ describe('Pipeline Model', () => { }; jobFactoryMock = { create: sinon.stub(), - list: sinon.stub() + list: sinon.stub(), + get: sinon.stub() }; eventFactoryMock = { list: sinon.stub() @@ -115,7 +116,8 @@ describe('Pipeline Model', () => { addWebhook: sinon.stub(), getFile: sinon.stub(), decorateUrl: sinon.stub(), - getOpenedPRs: sinon.stub() + getOpenedPRs: sinon.stub(), + getPrInfo: sinon.stub() }; parserMock = sinon.stub(); @@ -372,6 +374,62 @@ describe('Pipeline Model', () => { }); }); + describe('syncPR', () => { + let prJob; + + beforeEach(() => { + datastore.update.resolves(null); + scmMock.getFile.resolves('superyamlcontent'); + scmMock.getPrInfo.resolves({ ref: 'pulls/1/merge' }); + parserMock.withArgs('superyamlcontent', templateFactoryMock).resolves(PARSED_YAML); + userFactoryMock.get.withArgs({ username: 'batman' }).resolves({ + unsealToken: sinon.stub().resolves('foo') + }); + prJob = { + update: sinon.stub().resolves(null), + isPR: sinon.stub().returns(true), + name: 'PR-1', + state: 'ENABLED', + archived: false + }; + }); + + it('update PR config', () => { + jobFactoryMock.get.resolves(prJob); + + return pipeline.syncPR(1).then(() => { + assert.calledWith(scmMock.getFile, { + path: 'screwdriver.yaml', + ref: 'pulls/1/merge', + scmUri: 'github.com:12345:master', + token: 'foo' + }); + assert.called(prJob.update); + assert.deepEqual(prJob.permutations, PARSED_YAML.jobs.main); + }); + }); + + it('returns error if fails to get configuration', () => { + const error = new Error('fails to get config'); + + scmMock.getFile.rejects(error); + + return pipeline.syncPR(1).catch((err) => { + assert.deepEqual(err, error); + }); + }); + + it('returns error if fails to get PR job', () => { + const error = new Error('fails to get job'); + + jobFactoryMock.get.rejects(error); + + return pipeline.syncPR(1).catch((err) => { + assert.deepEqual(err, error); + }); + }); + }); + describe('syncPRs', () => { let prJob;