Skip to content

Commit 306ab9d

Browse files
committed
chore: address some review feedback
1 parent 985bed5 commit 306ab9d

File tree

2 files changed

+102
-50
lines changed

2 files changed

+102
-50
lines changed

src/build-images-handler.ts

Lines changed: 85 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,26 @@ const files = [
1515
'.devcontainer/docker-compose.yml',
1616
];
1717

18-
export async function getPreviousTargetOid(payload: RegistryPackagePublishedEvent) {
18+
export async function shouldUpdateFiles(octokit: Octokit, oid: string) {
19+
const { data: file } = await octokit.rest.repos.getContent({
20+
...REPOS.electron,
21+
path: files[0],
22+
});
23+
24+
if (!('content' in file)) {
25+
throw new Error(`Incorrectly received array when fetching content for ${files[0]}`);
26+
}
27+
28+
const fileContent = Buffer.from(file.content, 'base64').toString('utf-8');
29+
const match = fileContent.match(oid);
30+
if (match?.[0] === oid) {
31+
return false;
32+
}
33+
34+
return true;
35+
}
36+
37+
export async function getPreviousOid(payload: RegistryPackagePublishedEvent) {
1938
const { registry_package, organization } = payload;
2039
const { target_oid, name } = registry_package.package_version;
2140

@@ -42,15 +61,14 @@ export async function getPreviousTargetOid(payload: RegistryPackagePublishedEven
4261

4362
export async function updateFilesWithNewOid(
4463
octokit: Octokit,
45-
filePaths: string[],
46-
previousTargetOid: string,
64+
previousOid: string,
4765
targetOid: string,
4866
branchName: string,
4967
) {
5068
const d = debug(`roller/github:updateFilesWithNewOid`);
5169
let updatedAny = false;
5270

53-
for (const filePath of filePaths) {
71+
for (const filePath of files) {
5472
try {
5573
const { data: file } = await octokit.rest.repos.getContent({
5674
...REPOS.electron,
@@ -62,20 +80,14 @@ export async function updateFilesWithNewOid(
6280
}
6381

6482
const fileContent = Buffer.from(file.content, 'base64').toString('utf-8');
65-
const match = fileContent.match(previousTargetOid);
83+
const match = fileContent.match(previousOid);
6684
if (!match) {
6785
d(`No match found for ${filePath}`);
6886
continue;
6987
}
7088

71-
const currentSha = match[0];
72-
if (currentSha === targetOid) {
73-
d(`No update needed for ${filePath}`);
74-
continue;
75-
}
76-
77-
d(`Updating ${filePath} from ${currentSha} to ${targetOid}`);
78-
const newContent = fileContent.replace(currentSha, targetOid);
89+
d(`Updating ${filePath} from ${match[0]} to ${targetOid}`);
90+
const newContent = fileContent.replace(match[0], targetOid);
7991
await octokit.rest.repos.createOrUpdateFileContents({
8092
...REPOS.electron,
8193
path: filePath,
@@ -125,46 +137,75 @@ export async function handleBuildImagesCheck(payload: RegistryPackagePublishedEv
125137
const d = debug(`roller/github:handleBuildImagesCheck`);
126138
const octokit = await getOctokit();
127139

128-
const { target_oid } = payload.registry_package.package_version;
129-
const previousTargetOid = await getPreviousTargetOid(payload);
130-
console.log('Previous target OID:', previousTargetOid);
140+
const { target_oid: targetOid } = payload.registry_package.package_version;
141+
const previousOid = await getPreviousOid(payload);
131142

132-
if (!previousTargetOid) {
143+
if (!previousOid) {
133144
d('No previous target OID found, cannot proceed with updates');
134145
return;
135146
}
136147

137148
const branchName = `roller/build-images/${MAIN_BRANCH}`;
138-
const { ref, sha } = await prepareGitBranch(octokit, branchName, MAIN_BRANCH);
139-
140-
d(`Preparing to update files with new OID: ${target_oid}`);
141-
const updatedFiles = await updateFilesWithNewOid(
142-
octokit,
143-
files,
144-
previousTargetOid,
145-
target_oid,
146-
branchName,
147-
);
148-
149-
if (!updatedFiles) {
150-
d('No files were updated, skipping PR creation');
151-
return;
152-
}
153149

154-
d(`Creating ref=${ref} at sha=${sha}`);
155-
await octokit.rest.git.createRef({ ...REPOS.electron, ref, sha });
156-
157-
d(`Raising a PR for ${branchName} to ${MAIN_BRANCH}`);
158-
const pr = await octokit.rest.pulls.create({
150+
// Look for a pre-existing PR that targets this branch to see if we can update that.
151+
const { data: prs } = await octokit.rest.pulls.list({
159152
...REPOS.electron,
160-
base: MAIN_BRANCH,
161153
head: `${REPOS.electron.owner}:${branchName}`,
162-
title: `build: update build-images to ${target_oid.slice(0, 7)}`,
163-
body: `This PR updates the build-images references from ${previousTargetOid.slice(
164-
0,
165-
7,
166-
)} to ${target_oid.slice(0, 7)}.`,
154+
state: 'open',
167155
});
168156

169-
d(`New PR: ${pr.data.html_url}`);
157+
if (prs.length > 0) {
158+
const pr = prs[0];
159+
const oid = targetOid.slice(0, 7);
160+
161+
d(`Found existing PR: #${pr.number} opened by ${pr.user.login} - updating`);
162+
163+
d(`Preparing to update files with new OID: ${targetOid}`);
164+
const updatedFiles = await updateFilesWithNewOid(octokit, previousOid, targetOid, branchName);
165+
166+
if (!updatedFiles) {
167+
d('No files were updated, skipping PR update');
168+
return;
169+
}
170+
171+
await octokit.rest.pulls.update({
172+
...REPOS.electron,
173+
pull_number: pr.number,
174+
title: `chore: bump build image tag to ${oid}`,
175+
body: `This PR updates the build-images references from ${previousOid.slice(
176+
0,
177+
7,
178+
)} to ${oid}.`,
179+
});
180+
return;
181+
} else {
182+
d(`No existing PR found for ${branchName} - creating a new one`);
183+
const { ref, sha } = await prepareGitBranch(octokit, branchName, MAIN_BRANCH);
184+
185+
const shouldUpdate = await shouldUpdateFiles(octokit, targetOid);
186+
if (!shouldUpdate) {
187+
d('Build images are up to date - skipping PR creation');
188+
return;
189+
}
190+
191+
d(`Creating ref=${ref} at sha=${sha}`);
192+
await octokit.rest.git.createRef({ ...REPOS.electron, ref, sha });
193+
194+
d(`Preparing to update files with new OID: ${targetOid}`);
195+
await updateFilesWithNewOid(octokit, previousOid, targetOid, branchName);
196+
197+
d(`Raising a PR for ${branchName} to ${MAIN_BRANCH}`);
198+
const pr = await octokit.rest.pulls.create({
199+
...REPOS.electron,
200+
base: MAIN_BRANCH,
201+
head: `${REPOS.electron.owner}:${branchName}`,
202+
title: `build: update build-images to ${targetOid.slice(0, 7)}`,
203+
body: `This PR updates the build-images references from ${previousOid.slice(
204+
0,
205+
7,
206+
)} to ${targetOid.slice(0, 7)}.`,
207+
});
208+
209+
d(`New PR: ${pr.data.html_url}`);
210+
}
170211
}

tests/build-images.test.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getOctokit } from '../src/utils/octokit';
55

66
import { Probot, ProbotOctokit } from 'probot';
77
import { MAIN_BRANCH } from '../src/constants';
8+
import { randomBytes } from 'node:crypto';
89
const nock = require('nock');
910

1011
const GH_API = 'https://api.github.com';
@@ -99,6 +100,9 @@ describe('build-images', () => {
99100
},
100101
pulls: {
101102
create: vi.fn(),
103+
list: vi.fn().mockResolvedValue({
104+
data: [],
105+
}),
102106
},
103107
},
104108
};
@@ -143,7 +147,7 @@ describe('build-images', () => {
143147
const payload = JSON.parse(JSON.stringify(payloadJson));
144148
payload.registry_package.package_version.target_oid = 'newtargetoid123';
145149

146-
const previousTargetOid = await buildImagesHandler.getPreviousTargetOid(payload);
150+
const previousTargetOid = await buildImagesHandler.getPreviousOid(payload);
147151
expect(previousTargetOid).toBe('424eedbf277ad9749ffa9219068aa72ed4a5e373');
148152
});
149153

@@ -222,14 +226,13 @@ describe('build-images', () => {
222226

223227
const result = await buildImagesHandler.updateFilesWithNewOid(
224228
mockOctokit,
225-
['.github/workflows/linux-publish.yml'],
226229
'oldsha123',
227230
'newsha456',
228231
branchName,
229232
);
230233

231234
expect(result).toBe(true);
232-
expect(mockOctokit.rest.repos.getContent).toHaveBeenCalledTimes(1);
235+
expect(mockOctokit.rest.repos.getContent).toHaveBeenCalledTimes(7);
233236
expect(mockOctokit.rest.repos.createOrUpdateFileContents).toHaveBeenCalledTimes(1);
234237
expect(mockOctokit.rest.repos.createOrUpdateFileContents).toHaveBeenCalledWith(
235238
expect.objectContaining({
@@ -251,7 +254,6 @@ describe('build-images', () => {
251254

252255
const result = await buildImagesHandler.updateFilesWithNewOid(
253256
mockOctokit,
254-
['.github/workflows/linux-publish.yml'],
255257
'oldsha123',
256258
'newsha456',
257259
branchName,
@@ -269,6 +271,8 @@ describe('build-images', () => {
269271
data: { html_url: 'https://github.com/electron/electron/pull/123' },
270272
});
271273

274+
mockOctokit.rest.pulls.list.mockResolvedValue({ data: [] });
275+
272276
mockOctokit.rest.repos.getContent.mockImplementation(() => {
273277
return {
274278
data: {
@@ -305,7 +309,14 @@ describe('build-images', () => {
305309
});
306310

307311
it('skips PR creation when no files need updating', async () => {
308-
vi.spyOn(buildImagesHandler, 'getPreviousTargetOid').mockResolvedValue('oldsha123');
312+
const newSha = randomBytes(20).toString('hex');
313+
314+
mockOctokit.rest.pulls.list.mockResolvedValue({ data: [] });
315+
mockOctokit.rest.repos.getContent.mockResolvedValue({
316+
data: { content: Buffer.from(newSha).toString('base64') },
317+
});
318+
319+
vi.spyOn(buildImagesHandler, 'getPreviousOid').mockResolvedValue('oldsha123');
309320

310321
vi.spyOn(buildImagesHandler, 'prepareGitBranch').mockResolvedValue({
311322
ref: `refs/heads/${branchName}`,
@@ -317,7 +328,7 @@ describe('build-images', () => {
317328
vi.spyOn(buildImagesHandler, 'updateFilesWithNewOid').mockResolvedValue(false);
318329

319330
const payload = JSON.parse(JSON.stringify(payloadJson));
320-
payload.registry_package.package_version.target_oid = 'newsha456';
331+
payload.registry_package.package_version.target_oid = newSha;
321332

322333
await buildImagesHandler.handleBuildImagesCheck(payload);
323334

0 commit comments

Comments
 (0)