Skip to content

Commit

Permalink
feat(3209): Skip execution of virtual job and mark it as SUCCESS
Browse files Browse the repository at this point in the history
  • Loading branch information
sagar1312 committed Oct 3, 2024
1 parent 09b0fb0 commit 90b2cf7
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 29 deletions.
96 changes: 67 additions & 29 deletions plugins/queue/scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ const TEMPORAL_TOKEN_TIMEOUT = 12 * 60; // 12 hours in minutes
const TEMPORAL_UNZIP_TOKEN_TIMEOUT = 2 * 60; // 2 hours in minutes
const BLOCKED_BY_SAME_JOB_WAIT_TIME = 5;

/**
* Checks whether the job associated with the build is virtual or not
* @method isVirtualJob
* @param {Object} annotations Job Annotations
* @return {Boolean}
*/
function isVirtualJob(annotations) {
return annotations && annotations['screwdriver.cd/virtualJob'];
}

/**
* Posts a new build event to the API
* @method postBuildEvent
Expand Down Expand Up @@ -300,7 +310,8 @@ async function start(executor, config) {
apiUri,
pipeline,
isPR,
prParentJobId
prParentJobId,
annotations
} = config;
const forceStart = /\[(force start)\]/.test(causeMessage);

Expand Down Expand Up @@ -411,48 +422,75 @@ async function start(executor, config) {
throw value.error;
}

const token = executor.tokenGen(Object.assign(tokenConfig, { scope: ['temporal'] }), TEMPORAL_TOKEN_TIMEOUT);

// set the start time in the queue
Object.assign(config, { token });
// Store the config in redis
await executor.redisBreaker.runCommand('hset', executor.buildConfigTable, buildId, JSON.stringify(config));

const blockedBySameJob = reach(config, 'annotations>screwdriver.cd/blockedBySameJob', {
separator: '>',
default: true
});
const blockedBySameJobWaitTime = reach(config, 'annotations>screwdriver.cd/blockedBySameJobWaitTime', {
separator: '>',
default: BLOCKED_BY_SAME_JOB_WAIT_TIME
});
if (isVirtualJob(annotations)) {
// Bypass execution of the build if the job is virtual
const payload = {
status: 'SUCCESS',
statusMessage: 'Skipping execution of the virtual job'
};

// Note: arguments to enqueue are [queue name, job name, array of args]
enq = await executor.queueBreaker.runCommand('enqueue', executor.buildQueue, 'start', [
{
buildId,
jobId,
blockedBy: blockedBy.toString(),
blockedBySameJob,
blockedBySameJobWaitTime
}
]);
if (buildStats) {
await helper
.updateBuild(
{
buildId,
token: buildToken,
apiUri,
payload: { stats: build.stats, status: 'QUEUED' }
payload
},
helper.requestRetryStrategy
)
.catch(err => {
logger.error(`Failed to update build status for build ${buildId}: ${err}`);
logger.error(`virtualBuilds: failed to update build status for build ${buildId}: ${err}`);

throw err;
});
} else {
const token = executor.tokenGen(
Object.assign(tokenConfig, { scope: ['temporal'] }),
TEMPORAL_TOKEN_TIMEOUT
);

// set the start time in the queue
Object.assign(config, { token });
// Store the config in redis
await executor.redisBreaker.runCommand('hset', executor.buildConfigTable, buildId, JSON.stringify(config));

const blockedBySameJob = reach(config, 'annotations>screwdriver.cd/blockedBySameJob', {
separator: '>',
default: true
});
const blockedBySameJobWaitTime = reach(config, 'annotations>screwdriver.cd/blockedBySameJobWaitTime', {
separator: '>',
default: BLOCKED_BY_SAME_JOB_WAIT_TIME
});

// Note: arguments to enqueue are [queue name, job name, array of args]
enq = await executor.queueBreaker.runCommand('enqueue', executor.buildQueue, 'start', [
{
buildId,
jobId,
blockedBy: blockedBy.toString(),
blockedBySameJob,
blockedBySameJobWaitTime
}
]);
if (buildStats) {
await helper
.updateBuild(
{
buildId,
token: buildToken,
apiUri,
payload: { stats: build.stats, status: 'QUEUED' }
},
helper.requestRetryStrategy
)
.catch(err => {
logger.error(`Failed to update build status for build ${buildId}: ${err}`);

throw err;
});
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions test/plugins/queue/scheduler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,36 @@ describe('scheduler test', () => {
assert.calledWith(queueMock.enqueue, 'builds', 'start', [partialTestDefaultConfig]);
});
});

it('skip execution of the build and update the status to SUCCESS for virtual job', () => {
const dateNow = Date.now();
const sandbox = sinon.createSandbox({
useFakeTimers: false
});

sandbox.useFakeTimers(dateNow);
buildMock.stats = {};
testConfig.build = buildMock;
testConfig.annotations['screwdriver.cd/virtualJob'] = true;

return scheduler.start(executor, testConfig).then(() => {
assert.calledTwice(queueMock.connect);
assert.notCalled(redisMock.hset);
assert.notCalled(queueMock.enqueue);
assert.calledOnce(executor.tokenGen);
assert.calledWith(
helperMock.updateBuild,
{
buildId,
token: 'buildToken',
apiUri: 'http://api.com',
payload: { status: 'SUCCESS', statusMessage: 'Skipping execution of the virtual job' }
},
helperMock.requestRetryStrategy
);
sandbox.restore();
});
});
});

describe('startFrozen', () => {
Expand Down

0 comments on commit 90b2cf7

Please sign in to comment.