Skip to content

Commit

Permalink
Merge pull request #6989 from taskcluster/feat/6984-ignore-missing-ta…
Browse files Browse the repository at this point in the history
…skgroups-on-cancel

Ignore missing task groups on auto-cancel
  • Loading branch information
matt-boris committed Apr 29, 2024
2 parents a84ce33 + 312c174 commit 781ee40
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 2 deletions.
7 changes: 7 additions & 0 deletions changelog/issue-6761.md
@@ -0,0 +1,7 @@
audience: developers
level: patch
reference: issue 6984
---

Github auto-cancel gracefully ignores missing task groups and doesn't log errors in github comments.
This can happen when decision task failed on previous runs.
13 changes: 11 additions & 2 deletions services/github/src/handlers/index.js
Expand Up @@ -308,8 +308,17 @@ class Handlers {
const limitedQueueClient = this.queueClient.use({ authorizedScopes: scopes });

debug(`Found running task groups: ${taskGroupIds.join(', ')}. Sealing and cancelling`);
await Promise.all(taskGroupIds.map(taskGroupId => limitedQueueClient.sealTaskGroup(taskGroupId)));
await Promise.all(taskGroupIds.map(taskGroupId => limitedQueueClient.cancelTaskGroup(taskGroupId)));
try {
await Promise.all(taskGroupIds.map(taskGroupId => limitedQueueClient.sealTaskGroup(taskGroupId)));
await Promise.all(taskGroupIds.map(taskGroupId => limitedQueueClient.cancelTaskGroup(taskGroupId)));
} catch (queueErr) {
if (queueErr.errorCode !== 'ResourceNotFound' || queueErr.statusCode !== 404) {
throw queueErr;
}
// we can ignore task groups that were not yet created on queue side, and simply mark as cancelled in the db
this.monitor.reportError(`Task group not found in queue: ${queueErr.message} while canceling`);
}

await Promise.all(taskGroupIds.map(taskGroupId => this.context.db.fns.set_github_build_state(
taskGroupId, GITHUB_BUILD_STATES.CANCELLED,
)));
Expand Down
47 changes: 47 additions & 0 deletions services/github/test/handler_test.js
Expand Up @@ -340,7 +340,54 @@ helper.secrets.mockSuite(testing.suiteName(), [], function (mock, skipping) {
({ Type, Severity, Fields }) => Type === 'monitor.error' && Severity === LEVELS.err && Fields.message.includes('sealTaskGroup error: missing scopes'),
));
monitor.manager.reset();
});

test('non-existent task groups queue.sealTask/cancelTaskGroup group are ignored', async function () {
const err = new Error('ResourceNotFound');
err.errorCode = 'ResourceNotFound';
err.statusCode = 404;
handlers.queueClient = new taskcluster.Queue({
rootUrl: 'https://tc.example.com',
fake: {
sealTaskGroup: async (taskGroupId) => {
err.method = 'sealTaskGroup';
throw err;
},
cancelTaskGroup: async (taskGroupId) => {
err.method = 'cancelTaskGroup';
throw err;
},
},
});

await addBuild({ state: 'pending', taskGroupId: 'aa', pullNumber: 1, eventType: 'pull_request.opened' });
await addBuild({ state: 'pending', taskGroupId: 'bb', pullNumber: 1, eventType: 'pull_request.synchronize' });

const instGithub = github.inst(5828);

await handlers.realCancelPreviousTaskGroups({
instGithub,
debug: sinon.stub(),
newBuild: {
sha: COMMIT_SHA, organization: 'TaskclusterRobot', repository: 'hooks-testing',
pull_number: 1, event_type: 'pull_request.synchronize',
},
});
assert(instGithub.issues.createComment.notCalled);

const monitor = await helper.load('monitor');
assert(monitor.manager.messages.some(
({ Type, Severity, Fields }) => Type === 'monitor.error' && Severity === LEVELS.err && Fields.message.includes('Task group not found in queue'),
));
monitor.manager.reset();

// builds should still be cancelled in db
const [[buildA], [buildB]] = await Promise.all([
helper.db.fns.get_github_build_pr('aa'),
helper.db.fns.get_github_build_pr('bb'),
]);
assert.equal(buildA.state, 'cancelled');
assert.equal(buildB.state, 'cancelled');
});

test('calls queue.sealTaskGroup/cancelTaskGroup for pulNumber excluding new task group id', async function () {
Expand Down

0 comments on commit 781ee40

Please sign in to comment.