Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ export const REPO_OWNER = 'electron';

export const MAIN_BRANCH = 'main';

export const CHROMIUM_UPGRADE_WORKFLOW = {
owner: 'electron',
repo: 'agent-workflows',
workflow_id: 'chromium-upgrade.yml',
ref: 'main',
};

export const ROLL_TARGETS = {
node: {
name: 'node',
Expand Down
21 changes: 21 additions & 0 deletions src/utils/roll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as semver from 'semver';

import {
BACKPORT_CHECK_SKIP,
CHROMIUM_UPGRADE_WORKFLOW,
MAIN_BRANCH,
NO_BACKPORT,
REPOS,
Expand Down Expand Up @@ -54,6 +55,16 @@ async function updateLabels(
await addLabels(octokit, { prNumber, labels });
}

async function triggerChromiumUpgradeWorkflow(octokit: Octokit) {
const d = debug('roller/chromium:triggerChromiumUpgradeWorkflow()');
try {
await octokit.actions.createWorkflowDispatch(CHROMIUM_UPGRADE_WORKFLOW);
d(`Dispatched ${CHROMIUM_UPGRADE_WORKFLOW.workflow_id}`);
} catch (e) {
d(`Failed to dispatch ${CHROMIUM_UPGRADE_WORKFLOW.workflow_id}: ${e.message}`);
}
}

export async function roll({
rollTarget,
electronBranch,
Expand All @@ -66,6 +77,8 @@ export async function roll({
`roll triggered for electron branch=${electronBranch.name} ${rollTarget.depsKey}=${targetVersion}`,
);

let didRoll = false;

// Look for a pre-existing PR that targets this branch to see if we can update that.
const existingPrsForBranch = (await github.paginate('GET /repos/:owner/:repo/pulls', {
base: electronBranch.name,
Expand Down Expand Up @@ -131,6 +144,8 @@ export async function roll({
previousVersion: prVersionText[1],
prNumber: pr.number,
});

didRoll = true;
}
} else {
d(`No existing PR found - raising a new PR`);
Expand Down Expand Up @@ -185,5 +200,11 @@ export async function roll({
});

d(`New PR: ${newPr.data.html_url}`);

didRoll = true;
}

if (didRoll && rollTarget === ROLL_TARGETS.chromium && electronBranch.name === MAIN_BRANCH) {
await triggerChromiumUpgradeWorkflow(github);
}
}
93 changes: 92 additions & 1 deletion tests/utils/roll.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';

import { roll } from '../../src/utils/roll.js';
import { getOctokit } from '../../src/utils/octokit.js';
import { ROLL_TARGETS, REPOS } from '../../src/constants.js';
import {
CHROMIUM_UPGRADE_WORKFLOW,
MAIN_BRANCH,
REPOS,
ROLL_TARGETS,
} from '../../src/constants.js';
import { updateDepsFile } from '../../src/utils/update-deps.js';

vi.mock('../../src/utils/octokit.js');
Expand Down Expand Up @@ -44,6 +49,9 @@ describe('roll()', () => {
addLabels: vi.fn(),
listLabelsOnIssue: vi.fn().mockReturnValue({ data: [] }),
},
actions: {
createWorkflowDispatch: vi.fn(),
},
};
vi.mocked(getOctokit).mockReturnValue(mockOctokit);
vi.mocked(updateDepsFile).mockResolvedValue({
Expand Down Expand Up @@ -177,6 +185,89 @@ describe('roll()', () => {
);
});

describe('chromium-upgrade workflow dispatch', () => {
const mainBranch = { ...branch, name: MAIN_BRANCH };

it('dispatches when creating a new chromium PR on main', async () => {
mockOctokit.paginate.mockReturnValue([]);

await roll({
rollTarget: ROLL_TARGETS.chromium,
electronBranch: mainBranch,
targetVersion: '120.0.0.0',
});

expect(mockOctokit.actions.createWorkflowDispatch).toHaveBeenCalledTimes(1);
expect(mockOctokit.actions.createWorkflowDispatch).toHaveBeenCalledWith(
CHROMIUM_UPGRADE_WORKFLOW,
);
});

it('dispatches when updating an existing chromium PR on main', async () => {
mockOctokit.paginate.mockReturnValue([
{
user: { login: 'electron-roller[bot]' },
title: `chore: bump ${ROLL_TARGETS.chromium.name} to bar`,
number: 1,
head: { ref: 'asd' },
body: 'Original-Version: 119.0.0.0',
labels: [],
created_at: new Date().toISOString(),
},
]);

await roll({
rollTarget: ROLL_TARGETS.chromium,
electronBranch: mainBranch,
targetVersion: '120.0.0.0',
});

expect(mockOctokit.actions.createWorkflowDispatch).toHaveBeenCalledTimes(1);
expect(mockOctokit.actions.createWorkflowDispatch).toHaveBeenCalledWith(
CHROMIUM_UPGRADE_WORKFLOW,
);
});

it('does not dispatch for node rolls on main', async () => {
mockOctokit.paginate.mockReturnValue([]);

await roll({
rollTarget: ROLL_TARGETS.node,
electronBranch: mainBranch,
targetVersion: 'v10.0.0',
});

expect(mockOctokit.actions.createWorkflowDispatch).not.toHaveBeenCalled();
});

it('does not dispatch for chromium rolls on a release branch', async () => {
mockOctokit.paginate.mockReturnValue([]);

await roll({
rollTarget: ROLL_TARGETS.chromium,
electronBranch: branch,
targetVersion: '120.0.0.0',
});

expect(mockOctokit.actions.createWorkflowDispatch).not.toHaveBeenCalled();
});

it('does not throw when dispatch itself fails', async () => {
mockOctokit.paginate.mockReturnValue([]);
mockOctokit.actions.createWorkflowDispatch.mockRejectedValueOnce(new Error('boom'));

await expect(
roll({
rollTarget: ROLL_TARGETS.chromium,
electronBranch: mainBranch,
targetVersion: '120.0.0.0',
}),
).resolves.toBeUndefined();

expect(mockOctokit.pulls.create).toHaveBeenCalled();
});
});

it('skips PR if existing one has been paused', async () => {
mockOctokit.paginate.mockReturnValue([
{
Expand Down