Skip to content

Commit a3b8623

Browse files
committed
ci(update-deps): switch to create-pull-request action to fix api limitation
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent cbca310 commit a3b8623

1 file changed

Lines changed: 49 additions & 169 deletions

File tree

.github/workflows/.update-deps.yml

Lines changed: 49 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,26 @@ jobs:
3636
private-key: ${{ secrets.DOCKER_GITHUB_BUILDER_WRITE_PRIVATE_KEY }}
3737
owner: docker
3838
repositories: github-builder
39+
-
40+
name: Checkout
41+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
42+
with:
43+
token: ${{ steps.write-app.outputs.token }}
44+
fetch-depth: 0
45+
persist-credentials: false
3946
-
4047
name: Update dependency
48+
id: update
4149
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
4250
env:
4351
INPUT_DEP: ${{ matrix.dep }}
4452
with:
4553
github-token: ${{ steps.write-app.outputs.token }}
4654
script: |
4755
const dep = core.getInput('dep');
48-
56+
const fs = require('fs');
57+
const path = require('path');
58+
4959
const dependencyConfigs = {
5060
buildx: {
5161
key: 'BUILDX_VERSION',
@@ -99,7 +109,7 @@ jobs:
99109
},
100110
sbom: {
101111
key: 'SBOM_IMAGE',
102-
name: 'SBOM image',
112+
name: 'BuildKit Syft Scanner image',
103113
branch: 'deps/sbom-image',
104114
files: [
105115
'.github/workflows/build.yml',
@@ -147,7 +157,7 @@ jobs:
147157
},
148158
toolkit: {
149159
key: 'DOCKER_ACTIONS_TOOLKIT_MODULE',
150-
name: 'docker/actions-toolkit module',
160+
name: 'actions-toolkit module',
151161
branch: 'deps/docker-actions-toolkit-module',
152162
files: [
153163
'.github/workflows/build.yml',
@@ -215,20 +225,6 @@ jobs:
215225
return Buffer.from(data.content, data.encoding).toString('utf8');
216226
}
217227
218-
async function getTextFile(github, owner, repo, path, ref) {
219-
const response = await github.rest.repos.getContent({
220-
owner,
221-
repo,
222-
path,
223-
ref
224-
});
225-
return {
226-
path,
227-
sha: response.data.sha,
228-
content: decodeContent(response.data)
229-
};
230-
}
231-
232228
function readEnvValue(content, key) {
233229
const pattern = new RegExp(`^ ${escapeRegExp(key)}: "([^"]*)"$`, 'm');
234230
const match = content.match(pattern);
@@ -266,74 +262,25 @@ jobs:
266262
return `${quoted.slice(0, -1).join(', ')}, and ${quoted.at(-1)}`;
267263
}
268264
269-
async function findOpenPullRequest(github, context, branch, base) {
270-
const pulls = await github.rest.pulls.list({
271-
...context.repo,
272-
state: 'open',
273-
head: `${context.repo.owner}:${branch}`,
274-
base,
275-
per_page: 100
276-
});
277-
return pulls.data[0] ?? null;
278-
}
279-
280265
const config = dependencyConfigs[dep];
281266
if (!config) {
282267
core.setFailed(`Unknown dependency ${dep}`);
283268
return;
284269
}
285270
286-
const repo = await github.rest.repos.get(context.repo);
287-
const defaultBranch = repo.data.default_branch;
288-
const branchRefName = `heads/${config.branch}`;
289-
const openPullRequest = await findOpenPullRequest(github, context, config.branch, defaultBranch);
290-
291271
const target = await config.resolve({github});
292272
core.info(`Resolved ${config.key} to ${target.value} from ${config.sourceUrl}`);
293273
294-
const baseFiles = await Promise.all(config.files.map((path) => getTextFile(github, context.repo.owner, context.repo.repo, path, defaultBranch)));
295-
const baseValues = unique(baseFiles.map((file) => readEnvValue(file.content, config.key)));
296-
const baseIsUpToDate = baseValues.every((value) => value === target.value);
297-
298-
if (baseIsUpToDate) {
299-
core.info(`${config.key} is already up to date on ${defaultBranch}`);
300-
if (openPullRequest) {
301-
await github.rest.pulls.update({
302-
...context.repo,
303-
pull_number: openPullRequest.number,
304-
state: 'closed'
305-
});
306-
core.notice(`Closed stale pull request #${openPullRequest.number}`);
307-
}
308-
return;
309-
}
310-
311-
let branchExists = false;
312-
try {
313-
await github.rest.git.getRef({
314-
...context.repo,
315-
ref: branchRefName
316-
});
317-
branchExists = true;
318-
} catch (error) {
319-
if (error.status !== 404) {
320-
throw error;
321-
}
322-
}
323-
324-
const defaultRef = await github.rest.git.getRef({
325-
...context.repo,
326-
ref: `heads/${defaultBranch}`
274+
const workingFiles = config.files.map((filePath) => {
275+
const absolutePath = path.join(process.env.GITHUB_WORKSPACE, filePath);
276+
const content = fs.readFileSync(absolutePath, 'utf8');
277+
return {
278+
path: filePath,
279+
absolutePath,
280+
content
281+
};
327282
});
328-
const parentCommitSha = defaultRef.data.object.sha;
329-
330-
// Always rebuild updater branches from the latest default branch head
331-
// so stale dependency PRs do not accumulate merge conflicts.
332-
const workingRef = defaultBranch;
333-
const workingFiles = await Promise.all(
334-
config.files.map((path) => getTextFile(github, context.repo.owner, context.repo.repo, path, workingRef))
335-
);
336-
283+
const baseValues = unique(workingFiles.map((file) => readEnvValue(file.content, config.key)));
337284
const changes = [];
338285
for (const file of workingFiles) {
339286
const replacement = replaceEnvValue(file.content, config.key, target.value);
@@ -344,107 +291,40 @@ jobs:
344291
path: file.path,
345292
before: replacement.before,
346293
after: target.value,
347-
content: replacement.content
294+
content: replacement.content,
295+
absolutePath: file.absolutePath
348296
});
349297
}
350298
351299
if (changes.length > 0) {
352-
const parentCommit = await github.rest.git.getCommit({
353-
...context.repo,
354-
commit_sha: parentCommitSha
355-
});
356-
357-
const tree = [];
358300
for (const change of changes) {
359-
const blob = await github.rest.git.createBlob({
360-
...context.repo,
361-
content: change.content,
362-
encoding: 'utf-8'
363-
});
364-
tree.push({
365-
path: change.path,
366-
mode: '100644',
367-
type: 'blob',
368-
sha: blob.data.sha
369-
});
370-
}
371-
372-
const newTree = await github.rest.git.createTree({
373-
...context.repo,
374-
base_tree: parentCommit.data.tree.sha,
375-
tree
376-
});
377-
378-
const commit = await github.rest.git.createCommit({
379-
...context.repo,
380-
message: `chore(deps): bump ${config.key} to ${target.to}`,
381-
tree: newTree.data.sha,
382-
parents: [parentCommitSha]
383-
});
384-
385-
if (branchExists) {
386-
await github.rest.git.updateRef({
387-
...context.repo,
388-
ref: branchRefName,
389-
sha: commit.data.sha,
390-
force: true
391-
});
392-
} else {
393-
await github.rest.git.createRef({
394-
...context.repo,
395-
ref: `refs/${branchRefName}`,
396-
sha: commit.data.sha
397-
});
398-
branchExists = true;
301+
fs.writeFileSync(change.absolutePath, change.content, 'utf8');
399302
}
400303
} else {
401-
core.info(`No file changes needed on branch ${config.branch}`);
304+
core.info(`No workspace changes needed for ${config.key}`);
402305
}
403306
404-
const comparison = await github.rest.repos.compareCommits({
405-
...context.repo,
406-
base: defaultBranch,
407-
head: config.branch
408-
});
409-
410-
if (comparison.data.ahead_by === 0) {
411-
core.info(`Branch ${config.branch} does not differ from ${defaultBranch}`);
412-
if (openPullRequest) {
413-
await github.rest.pulls.update({
414-
...context.repo,
415-
pull_number: openPullRequest.number,
416-
state: 'closed'
417-
});
418-
core.notice(`Closed stale pull request #${openPullRequest.number}`);
419-
}
420-
return;
421-
}
422-
423-
const title = `chore(deps): bump ${config.name} to ${target.to}`;
424307
const beforeValue = formatList(baseValues);
425-
const body = [
426-
`This updates ${config.key} from ${beforeValue} to \`${target.value}\`.`,
427-
'',
428-
`The source of truth for this update is ${config.sourceUrl}.`
429-
].join('\n');
430-
431-
if (openPullRequest) {
432-
await github.rest.pulls.update({
433-
...context.repo,
434-
pull_number: openPullRequest.number,
435-
title,
436-
body
437-
});
438-
core.notice(`Updated pull request #${openPullRequest.number}`);
439-
return;
440-
}
441-
442-
const pullRequest = await github.rest.pulls.create({
443-
...context.repo,
444-
title,
445-
body,
446-
head: config.branch,
447-
base: defaultBranch
448-
});
449-
450-
core.notice(`Created pull request #${pullRequest.data.number}`);
308+
const commitMessage = `chore(deps): update ${config.name} to ${target.to}`;
309+
310+
core.setOutput('branch', config.branch);
311+
core.setOutput('commit-message', commitMessage);
312+
core.setOutput('key', config.key);
313+
core.setOutput('before-value', beforeValue);
314+
core.setOutput('target-value', target.value);
315+
core.setOutput('source-url', config.sourceUrl);
316+
-
317+
name: Create pull request
318+
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
319+
with:
320+
base: main
321+
branch: ${{ steps.update.outputs.branch }}
322+
token: ${{ steps.write-app.outputs.token }}
323+
commit-message: ${{ steps.update.outputs.commit-message }}
324+
title: ${{ steps.update.outputs.commit-message }}
325+
signoff: true
326+
delete-branch: true
327+
body: |
328+
This updates ${{ steps.update.outputs.key }} from ${{ steps.update.outputs.before-value }} to `${{ steps.update.outputs.target-value }}`.
329+
330+
The source of truth for this update is ${{ steps.update.outputs.source-url }}.

0 commit comments

Comments
 (0)