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
21 changes: 10 additions & 11 deletions src/build-images-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import debug from 'debug';
import { Octokit } from '@octokit/rest';
import type { Context } from 'probot';

import { getContent } from './utils/github-utils.js';
import { getOctokit } from './utils/octokit.js';
import { MAIN_BRANCH, REPOS } from './constants.js';

Expand All @@ -17,17 +18,16 @@ const files = [
];

export async function shouldUpdateFiles(octokit: Octokit, oid: string) {
const { data: file } = await octokit.rest.repos.getContent({
const file = await getContent(octokit, {
...REPOS.electron,
path: files[0],
});

if (!('content' in file)) {
throw new Error(`Incorrectly received array when fetching content for ${files[0]}`);
if (file === null) {
throw new Error(`Could not fetch content for ${files[0]}`);
}

const fileContent = Buffer.from(file.content, 'base64').toString('utf-8');
const match = fileContent.match(oid);
const match = file.content.match(oid);
if (match?.[0] === oid) {
return false;
}
Expand Down Expand Up @@ -72,24 +72,23 @@ export async function updateFilesWithNewOid(

for (const filePath of files) {
try {
const { data: file } = await octokit.rest.repos.getContent({
const file = await getContent(octokit, {
...REPOS.electron,
path: filePath,
});

if (!('content' in file)) {
throw new Error(`Incorrectly received array when fetching content for ${filePath}`);
if (file === null) {
throw new Error(`Could not fetch content for ${filePath}`);
}

const fileContent = Buffer.from(file.content, 'base64').toString('utf-8');
const match = fileContent.match(previousOid);
const match = file.content.match(previousOid);
if (!match) {
d(`No match found for ${filePath}`);
continue;
}

d(`Updating ${filePath} from ${match[0]} to ${targetOid}`);
const newContent = fileContent.replace(match[0], targetOid);
const newContent = file.content.replace(match[0], targetOid);
await octokit.rest.repos.createOrUpdateFileContents({
...REPOS.electron,
path: filePath,
Expand Down
19 changes: 9 additions & 10 deletions src/chromium-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { MAIN_BRANCH, REPOS, ROLL_TARGETS } from './constants.js';
import { compareChromiumVersions } from './utils/compare-chromium-versions.js';
import { getChromiumReleases, Release } from './utils/get-chromium-tags.js';
import { getSupportedBranches } from './utils/get-supported-branches.js';
import { getContent } from './utils/github-utils.js';
import { getOctokit } from './utils/octokit.js';
import { roll } from './utils/roll.js';
import { ReposGetBranchResponseItem, ReposListBranchesResponseItem } from './types.js';
Expand All @@ -15,19 +16,18 @@ async function rollReleaseBranch(github: Octokit, branch: BranchItem) {
const d = debug(`roller/chromium:rollReleaseBranch('${branch.name}')`);

d(`Fetching DEPS for ${branch.name}`);
const { data: depsData } = await github.repos.getContent({
const deps = await getContent(github, {
...REPOS.electron,
path: 'DEPS',
ref: branch.commit.sha,
});

if (!('content' in depsData)) {
throw new Error(`Incorrectly received array when fetching DEPS content for ${branch.name}`);
if (deps === null) {
throw new Error(`Could not fetch DEPS content for ${branch.name}`);
}

const deps = Buffer.from(depsData.content, 'base64').toString('utf8');
const versionRegex = new RegExp(`${ROLL_TARGETS.chromium.depsKey}':\n +'(.+?)',`, 'm');
const [, chromiumVersion] = versionRegex.exec(deps);
const [, chromiumVersion] = versionRegex.exec(deps.content);

const chromiumMajorVersion = Number(chromiumVersion.split('.')[0]);

Expand Down Expand Up @@ -75,20 +75,19 @@ async function rollMainBranch(github: Octokit) {
}

d(`Fetching DEPS for ${MAIN_BRANCH}`);
const { data: depsData } = await github.repos.getContent({
const deps = await getContent(github, {
owner: REPOS.electron.owner,
repo: REPOS.electron.repo,
path: 'DEPS',
ref: MAIN_BRANCH,
});

if (!('content' in depsData)) {
throw new Error(`Incorrectly received array when fetching DEPS content for ${MAIN_BRANCH}`);
if (deps === null) {
throw new Error(`Could not fetch DEPS content for ${MAIN_BRANCH}`);
}

const deps = Buffer.from(depsData.content, 'base64').toString('utf8');
const versionRegex = new RegExp(`${ROLL_TARGETS.chromium.depsKey}':\n +'(.+?)',`, 'm');
const [, currentVersion] = versionRegex.exec(deps);
const [, currentVersion] = versionRegex.exec(deps.content);

// We should be able to parse major version as a number.
const chromiumMajorVersion = Number(currentVersion.split('.')[0]);
Expand Down
11 changes: 5 additions & 6 deletions src/node-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import debug from 'debug';
import * as semver from 'semver';

import { MAIN_BRANCH, REPOS, ROLL_TARGETS } from './constants.js';
import { getContent } from './utils/github-utils.js';
import { getOctokit } from './utils/octokit.js';
import { roll } from './utils/roll.js';
import { ReposListBranchesResponseItem } from './types.js';
Expand Down Expand Up @@ -76,23 +77,21 @@ async function rollBranch(branch: string, isMain: boolean): Promise<void> {
});

d(`Fetching DEPS for branch ${targetBranch.name} in electron/electron`);
const { data: depsData } = await github.repos.getContent({
const deps = await getContent(github, {
owner: REPOS.electron.owner,
repo: REPOS.electron.repo,
path: 'DEPS',
ref: branch,
});

if (!('content' in depsData)) {
d(`Error - incorrectly got array when fetching DEPS content for ${branch}`);
if (deps === null) {
d(`Error - could not fetch DEPS content for ${branch}`);
throw new Error(`Upgrade check failed - see logs for more details`);
}

const deps = Buffer.from(depsData.content, 'base64').toString('utf8');

// find node version from DEPS
const versionRegex = new RegExp(`${ROLL_TARGETS.node.depsKey}':\n +'(.+?)',`, 'm');
const [, depsNodeVersion] = versionRegex.exec(deps);
const [, depsNodeVersion] = versionRegex.exec(deps.content);
const majorVersion = semver.major(semver.clean(depsNodeVersion));

d(`Computing latest upstream version for Node ${majorVersion}`);
Expand Down
7 changes: 4 additions & 3 deletions src/utils/arc-image.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Octokit } from '@octokit/rest';
import { MAIN_BRANCH, REPOS } from '../constants.js';
import { getContent } from './github-utils.js';
import { getOctokit } from './octokit.js';

const WINDOWS_RUNNER_REGEX = /ARG RUNNER_VERSION=([\d.]+)/;
Expand All @@ -9,13 +10,13 @@ const LINUX_IMAGE_REGEX =
/if eq .cpuArch "amd64".*\n.*image: ghcr.io\/actions\/actions-runner:([0-9]+\.[0-9]+\.[0-9]+@sha256:[a-f0-9]{64}).*\n.*{{- else }}.*\n.*image: ghcr.io\/actions\/actions-runner:([0-9]+\.[0-9]+\.[0-9]+@sha256:[a-f0-9]{64})/;

export async function getFileContent(octokit: Octokit, filePath: string, ref = MAIN_BRANCH) {
const { data } = await octokit.repos.getContent({
const data = await getContent(octokit, {
...REPOS.electronInfra,
path: filePath,
ref,
});
if ('content' in data) {
return { raw: Buffer.from(data.content, 'base64').toString('utf8'), sha: data.sha };
if (data !== null) {
return { raw: data.content, sha: data.sha };
}
throw 'wat';
}
Expand Down
42 changes: 39 additions & 3 deletions src/utils/chromium-gitiles.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
const CHROMIUM_GITILES_BASE = 'https://chromium.googlesource.com/chromium/src';
export const CHROMIUM_GITILES_BASE = 'https://chromium.googlesource.com/chromium/src';

export interface ChromiumCommit {
commit: string;
tree: string;
parents: string[];
author: {
name: string;
email: string;
time: string;
};
committer: {
name: string;
email: string;
time: string;
};
message: string;
}

/**
* Parse a Gitiles JSON response, stripping the )]}' security prefix.
*/
function parseGitilesJSON(text: string) {
return JSON.parse(text.slice(text.indexOf('{')));
}

/**
* Get the current HEAD SHA from Chromium main branch
*/
export async function getChromiumHeadSha(): Promise<string> {
const response = await fetch(`${CHROMIUM_GITILES_BASE}/+/refs/heads/main?format=JSON`);
const text = await response.text();
// Gitiles returns JSON with )]}' prefix for security
const data = JSON.parse(text.slice(text.indexOf('{')));
const data = parseGitilesJSON(text);
return data.commit;
}

Expand Down Expand Up @@ -42,3 +65,16 @@ export async function didChromiumFilesChange(

return false;
}

export async function getChromiumCommits(
fromRef: string,
toRef: string,
): Promise<{ log: ChromiumCommit[]; next?: string }> {
const url = `${CHROMIUM_GITILES_BASE}/+log/${fromRef}..${toRef}?format=JSON`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch Chromium commits: ${response.status}`);
}
const text = await response.text();
return parseGitilesJSON(text);
}
31 changes: 0 additions & 31 deletions src/utils/get-chromium-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,3 @@ export async function getChromiumReleases({
const releases = (await response.json()) as Release[];
return releases.sort((a, b) => a.time - b.time).map((r) => r.version);
}

export interface ChromiumCommit {
commit: string;
tree: string;
parents: string[];
author: {
name: string;
email: string;
time: string;
};
committer: {
name: string;
email: string;
time: string;
};
message: string;
}

export async function getChromiumCommits(
fromRef: string,
toRef: string,
): Promise<{ log: ChromiumCommit[]; next?: string }> {
const url = `https://chromium.googlesource.com/chromium/src/+log/${fromRef}..${toRef}?format=JSON`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch Chromium commits: ${response.status}`);
}
const text = await response.text();
// Gitiles prefixes JSON responses with )]}' for security, so strip it
return JSON.parse(text.slice(text.indexOf('{')));
}
13 changes: 13 additions & 0 deletions src/utils/github-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Octokit as GitHub } from '@octokit/rest';

export async function getContent(
github: GitHub,
options: Parameters<typeof github.repos.getContent>[0],
): Promise<{ content: string; sha: string } | null> {
const { data } = await github.repos.getContent(options);

if (!('content' in data)) return null;

const content = Buffer.from(data.content, 'base64').toString('utf8');
return { content, sha: data.sha };
}
5 changes: 2 additions & 3 deletions src/utils/pr-text.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ROLL_TARGETS, RollTarget } from '../constants.js';
import { CHROMIUM_GITILES_BASE } from './chromium-gitiles.js';

interface PRTextDetails {
previousVersion: string;
Expand All @@ -23,9 +24,7 @@ function getChromiumPRText(details: PRTextDetails) {
const isMain = !newVersion.includes('.');
const shortVersion = isMain ? newVersion.substr(11) : newVersion;
const shortPreviousVersion = isMain ? previousVersion.substr(11) : previousVersion;
const diffLink =
`https://chromium.googlesource.com/chromium/src/+log/` +
`${previousVersion}..${newVersion}?n=10000&pretty=fuller`;
const diffLink = `${CHROMIUM_GITILES_BASE}/+log/${previousVersion}..${newVersion}?n=10000&pretty=fuller`;
return {
title: `chore: bump ${ROLL_TARGETS.chromium.name} to ${shortVersion} (${branchName})`,
body: `Updating Chromium to ${shortVersion}${isMain ? ' (main)' : ''}.
Expand Down
12 changes: 6 additions & 6 deletions src/utils/roll-build-images.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import debug from 'debug';

import { MAIN_BRANCH, REPOS } from '../constants.js';
import { CHROMIUM_GITILES_BASE } from './chromium-gitiles.js';
import { getContent } from './github-utils.js';
import { getOctokit } from './octokit.js';
import { PullsListResponseItem } from '../types.js';
import { Octokit } from '@octokit/rest';
Expand All @@ -10,13 +12,13 @@ export async function getFileContentFromBuildImages(
filePath: string,
ref = MAIN_BRANCH,
) {
const { data } = await octokit.repos.getContent({
const data = await getContent(octokit, {
...REPOS.buildImages,
path: filePath,
ref,
});
if ('content' in data) {
return { raw: Buffer.from(data.content, 'base64').toString('utf8'), sha: data.sha };
if (data !== null) {
return { raw: data.content, sha: data.sha };
}
throw new Error(`Failed to get content for ${filePath}`);
}
Expand Down Expand Up @@ -47,9 +49,7 @@ export async function rollBuildImages(

const { owner, repo } = REPOS.buildImages;

const diffLink =
`https://chromium.googlesource.com/chromium/src/+log/` +
`${previousSha}..${newSha}?n=10000&pretty=fuller`;
const diffLink = `${CHROMIUM_GITILES_BASE}/+log/${previousSha}..${newSha}?n=10000&pretty=fuller`;

// Look for a pre-existing PR that targets this branch to see if we can update that.
let existingPrsForBranch: PullsListResponseItem[] = [];
Expand Down
12 changes: 6 additions & 6 deletions src/utils/update-deps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { REPOS } from '../constants.js';
import { getContent } from './github-utils.js';
import { getOctokit } from './octokit.js';

export interface UpdateDepsParams {
Expand All @@ -11,27 +12,26 @@ export interface UpdateDepsParams {
export async function updateDepsFile({ depName, depKey, branch, targetVersion }: UpdateDepsParams) {
const github = await getOctokit();

const { data } = await github.repos.getContent({
const deps = await getContent(github, {
...REPOS.electron,
path: 'DEPS',
ref: branch,
});

if (!('content' in data)) return;
if (deps === null) return;

const content = Buffer.from(data.content, 'base64').toString('utf8');
const previousRegex = new RegExp(`${depKey}':\n +'(.+?)',`, 'm');
const [, previousDEPSVersion] = previousRegex.exec(content);
const [, previousDEPSVersion] = previousRegex.exec(deps.content);

if (targetVersion !== previousDEPSVersion) {
const regexToReplace = new RegExp(`(${depKey}':\n +').+?',`, 'gm');
const newContent = content.replace(regexToReplace, `$1${targetVersion}',`);
const newContent = deps.content.replace(regexToReplace, `$1${targetVersion}',`);
await github.repos.createOrUpdateFileContents({
...REPOS.electron,
path: 'DEPS',
content: Buffer.from(newContent).toString('base64'),
message: `chore: bump ${depName} in DEPS to ${targetVersion}`,
sha: data.sha,
sha: deps.sha,
branch,
});
}
Expand Down
Loading