Skip to content

Commit 6ae1091

Browse files
Merge branch 'main' into dependabot/docker/node-24-alpine
2 parents 26fd3c3 + 3e8d224 commit 6ae1091

4 files changed

Lines changed: 127 additions & 0 deletions

File tree

src/autoupdater.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ export class AutoUpdater {
450450
const retryCount = this.config.retryCount();
451451
const retrySleep = this.config.retrySleep();
452452
const mergeConflictAction = this.config.mergeConflictAction();
453+
const mergeConflictLabel = this.config.mergeConflictLabel();
453454

454455
let retries = 0;
455456

@@ -489,6 +490,37 @@ export class AutoUpdater {
489490
// Ignore conflicts if configured to do so.
490491
ghCore.info('Merge conflict detected, skipping update.');
491492
return false;
493+
} else if (mergeConflictAction === 'label') {
494+
ghCore.info(
495+
'Merge conflict detected, labelling with label: ' +
496+
mergeConflictLabel,
497+
);
498+
// Fetch current labels on the PR
499+
const { data: prData } = await this.octokit.rest.pulls.get({
500+
owner: mergeOpts.owner as string,
501+
repo: mergeOpts.repo as string,
502+
pull_number: prNumber,
503+
});
504+
const currentLabels = prData.labels
505+
.map((l: any) => l.name)
506+
.filter(Boolean);
507+
if (!currentLabels.includes(mergeConflictLabel)) {
508+
const newLabels = [...currentLabels, mergeConflictLabel];
509+
await this.octokit.rest.issues.update({
510+
owner: mergeOpts.owner as string,
511+
repo: mergeOpts.repo as string,
512+
issue_number: prNumber,
513+
labels: newLabels,
514+
});
515+
ghCore.info(
516+
`Added merge conflict label '${mergeConflictLabel}' to PR #${prNumber}.`,
517+
);
518+
} else {
519+
ghCore.info(
520+
`Merge conflict label '${mergeConflictLabel}' already present on PR #${prNumber}.`,
521+
);
522+
}
523+
return false;
492524
} else {
493525
// Else, throw an error so we don't continue retrying.
494526
ghCore.error('Merge conflict error trying to update branch');

src/config-loader.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export class ConfigLoader {
6161
return this.getValue('MERGE_CONFLICT_ACTION', false, 'fail');
6262
}
6363

64+
mergeConflictLabel(): string {
65+
return this.getValue('MERGE_CONFLICT_LABEL', false, 'merge-conflict');
66+
}
67+
6468
githubRef(): string {
6569
return this.getValue('GITHUB_REF', true, '');
6670
}

test/autoupdate.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
WorkflowDispatchEvent,
1717
WorkflowRunEvent,
1818
} from '@octokit/webhooks-types/schema';
19+
import * as core from '@actions/core';
1920

2021
type PullRequestResponse =
2122
Endpoints['GET /repos/{owner}/{repo}/pulls/{pull_number}']['response'];
@@ -1323,4 +1324,87 @@ describe('test `merge`', () => {
13231324
expect(scope.isDone()).toBe(true);
13241325
}
13251326
});
1327+
1328+
test('merge conflict label is configured and merge conflict label is already present', async () => {
1329+
(config.retryCount as jest.Mock).mockReturnValue(0);
1330+
(config.mergeConflictAction as jest.Mock).mockReturnValue('label');
1331+
(config.mergeConflictLabel as jest.Mock).mockReturnValue('merge-conflict');
1332+
const updater = new AutoUpdater(config, emptyEvent);
1333+
1334+
// Mock the PR labels to already include the merge conflict label
1335+
const prNumber = 1;
1336+
const existingLabels = [
1337+
{ id: 1, name: 'bug' },
1338+
{ id: 2, name: 'merge-conflict' },
1339+
];
1340+
1341+
// nock for merge attempt (409 merge conflict)
1342+
const mergeScope = nock('https://api.github.com:443')
1343+
.post(`/repos/${owner}/${repo}/merges`, {
1344+
commit_message: mergeOpts.commit_message,
1345+
base: mergeOpts.base,
1346+
head: mergeOpts.head,
1347+
})
1348+
.reply(409, { message: 'Merge conflict' });
1349+
1350+
const getScope = nock('https://api.github.com:443')
1351+
.get(`/repos/${owner}/${repo}/pulls/${prNumber}`)
1352+
.reply(200, { labels: existingLabels });
1353+
1354+
const updateScope = nock('https://api.github.com:443')
1355+
.patch(`/repos/${owner}/${repo}/issues/${prNumber}`)
1356+
.reply(200, {});
1357+
1358+
const setOutput = jest.fn();
1359+
const infoSpy = jest.spyOn(core, 'info');
1360+
1361+
await updater.merge(owner, prNumber, mergeOpts, setOutput);
1362+
1363+
expect(mergeScope.isDone()).toBe(true);
1364+
expect(getScope.isDone()).toBe(true);
1365+
expect(updateScope.isDone()).toBe(false);
1366+
expect(infoSpy).toHaveBeenCalledWith(
1367+
expect.stringContaining('already present'),
1368+
);
1369+
});
1370+
1371+
test('merge conflict label is configured and merge conflict label is not present', async () => {
1372+
(config.retryCount as jest.Mock).mockReturnValue(0);
1373+
(config.mergeConflictAction as jest.Mock).mockReturnValue('label');
1374+
(config.mergeConflictLabel as jest.Mock).mockReturnValue('merge-conflict');
1375+
const updater = new AutoUpdater(config, emptyEvent);
1376+
1377+
// Mock the PR labels to already include the merge conflict label
1378+
const prNumber = 1;
1379+
const existingLabels = [{ id: 1, name: 'bug' }];
1380+
1381+
// nock for merge attempt (409 merge conflict)
1382+
const mergeScope = nock('https://api.github.com:443')
1383+
.post(`/repos/${owner}/${repo}/merges`, {
1384+
commit_message: mergeOpts.commit_message,
1385+
base: mergeOpts.base,
1386+
head: mergeOpts.head,
1387+
})
1388+
.reply(409, { message: 'Merge conflict' });
1389+
1390+
const getScope = nock('https://api.github.com:443')
1391+
.get(`/repos/${owner}/${repo}/pulls/${prNumber}`)
1392+
.reply(200, { labels: existingLabels });
1393+
1394+
const updateScope = nock('https://api.github.com:443')
1395+
.patch(`/repos/${owner}/${repo}/issues/${prNumber}`)
1396+
.reply(200, {});
1397+
1398+
const setOutput = jest.fn();
1399+
const infoSpy = jest.spyOn(core, 'info');
1400+
1401+
await updater.merge(owner, prNumber, mergeOpts, setOutput);
1402+
1403+
expect(mergeScope.isDone()).toBe(true);
1404+
expect(getScope.isDone()).toBe(true);
1405+
expect(updateScope.isDone()).toBe(false);
1406+
expect(infoSpy).toHaveBeenCalledWith(
1407+
expect.stringContaining('Added merge conflict label'),
1408+
);
1409+
});
13261410
});

test/config-loader.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ const tests = [
7171
default: 'fail',
7272
type: 'string',
7373
},
74+
{
75+
name: 'mergeConflictLabel',
76+
envVar: 'MERGE_CONFLICT_LABEL',
77+
required: false,
78+
default: 'merge-conflict',
79+
type: 'string',
80+
},
7481
{
7582
name: 'githubRef',
7683
envVar: 'GITHUB_REF',

0 commit comments

Comments
 (0)