From 312c174db1c3052ef879a24e99b0e8f085f5fead Mon Sep 17 00:00:00 2001 From: Yaraslau Kurmyza Date: Mon, 29 Apr 2024 12:35:14 +0200 Subject: [PATCH] feat(github): Ignore missing task groups on auto-cancel --- changelog/issue-6761.md | 7 ++++ services/github/src/handlers/index.js | 13 ++++++-- services/github/test/handler_test.js | 47 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 changelog/issue-6761.md diff --git a/changelog/issue-6761.md b/changelog/issue-6761.md new file mode 100644 index 00000000000..cd065dddf42 --- /dev/null +++ b/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. diff --git a/services/github/src/handlers/index.js b/services/github/src/handlers/index.js index 6350e2cec13..f8a601a830f 100644 --- a/services/github/src/handlers/index.js +++ b/services/github/src/handlers/index.js @@ -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, ))); diff --git a/services/github/test/handler_test.js b/services/github/test/handler_test.js index baf529080f3..aa919090b91 100644 --- a/services/github/test/handler_test.js +++ b/services/github/test/handler_test.js @@ -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 () {