-
Notifications
You must be signed in to change notification settings - Fork 2k
Automating docker-node part of the official Node Docker images release process #1646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
80 commits
Select commit
Hold shift + click to select a range
d04fe8f
GitHub action and script to retrieve versions
Pehesi97 93e42d6
Check if there are any new versions
Pehesi97 47809f1
exit if there is no new version
Pehesi97 613a705
check for security releases
Pehesi97 44086cd
remove trailing spaces
Pehesi97 a6da360
fix comparison login
Pehesi97 d063f38
musl version and security release logic
Pehesi97 578e4e0
comment ranUpdates logic
Pehesi97 8c80519
replace map by for..of
Pehesi97 926b1a6
for..of newVersions Object.keys
Pehesi97 4f6c62e
revert logic changes
Pehesi97 a28cc65
testing the automation in github actions
Pehesi97 92c29cd
replace source with .
Pehesi97 c5333a7
set -ue
Pehesi97 029d93c
use bash as shell
Pehesi97 56bd0cb
stop using set -ue
Pehesi97 e823a9d
debug
Pehesi97 d27ea05
debug
Pehesi97 7693e81
debug
Pehesi97 d362256
more debug
Pehesi97 ebd3737
not running actions on the official repo for now
Pehesi97 81293c6
test PR creation
Pehesi97 dd4234a
using main as the base branch for the newly created PR
Pehesi97 86601f7
fallback value for base branch
Pehesi97 35aa688
using single quotes for fallback value
Pehesi97 df65183
github ref name
Pehesi97 5185650
ref_name typo
Pehesi97 67137ce
using pull request head ref for testing the action
Pehesi97 8753805
fix typo
Pehesi97 ad1eabd
testing check suite pass
Pehesi97 1cc6a5b
prevent cron from running for now
Pehesi97 1b5da14
Update .github/workflows/automatic-updates.yml
Pehesi97 b912711
apply changes asked by SimenB
Pehesi97 56503a3
Merge branch 'gh-action-automate' of github.com:Pehesi97/docker-node …
Pehesi97 8e0e021
trigger pr synchronize
Pehesi97 f21ad78
removes mapSeries
Pehesi97 18c71d0
for..of with actually iterable object
Pehesi97 c18b65b
using main branch as base to the generated PR
Pehesi97 dafff87
head_branch option
Pehesi97 c0953d9
check_suite event without arguments
Pehesi97 759a0f4
testing auto-merge
Pehesi97 2240470
triggering action
Pehesi97 ee8b9e9
add a simple sleep
Pehesi97 b2eec25
wait 1 sec
Pehesi97 1d8bfcd
wait 2 seconds
Pehesi97 dc117df
wait 10 seconds
Pehesi97 e35cab7
create update PR
Pehesi97 06e3eea
changing base branch
Pehesi97 1550ccb
testing auto-merge in test-branch-main
Pehesi97 41358c8
checkout again once the PR is created
Pehesi97 a3a2835
await setTimeout
Pehesi97 e6566a7
fix arguments
Pehesi97 3f2a7b9
debug
Pehesi97 212e6c5
debug
Pehesi97 94d1081
ignoring update branch
Pehesi97 eedf0cb
debug schedule
Pehesi97 88d3e3b
finish
Pehesi97 01b63ba
remove PR for updates section from CONTRIBUTING.md
Pehesi97 ff6c3da
remove unused file
Pehesi97 d2dacf7
Update .github/workflows/automatic-updates.yml
cc73894
Update .github/workflows/automatic-updates.yml
0d254b1
requested changes
Pehesi97 6767207
requested changes pt 2
Pehesi97 ae95adf
requested changes pt 3
Pehesi97 4ec8a7f
Update check-pr-status.mjs
cbeb27b
Update build-automation.mjs
b6a6b36
Update build-automation.mjs
2d8fefa
Update build-automation.mjs
dcb738b
Update build-automation.mjs
c5df443
requested changes pt 4
Pehesi97 bc31eb8
chore: move continue statement
SimenB 9b6d362
oops
SimenB 9e8edb9
Update .github/workflows/automatic-updates.yml
a470faa
auto approve PR when checks pass
Pehesi97 7b48bda
juliangruber's auto-approve action
f17b561
Update .github/workflows/automatic-updates.yml
82f03ea
Update .github/workflows/automatic-updates.yml
89773e7
Update .github/workflows/automatic-updates.yml
31e167f
Update .github/workflows/automatic-updates.yml
efc5719
tweaks
SimenB File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
name: Automatically update Docker image versions | ||
|
||
on: | ||
schedule: | ||
- cron: "*/15 * * * *" | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
if: github.repository_owner == 'nodejs' | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Run automation script | ||
uses: actions/github-script@v6 | ||
id: updt | ||
with: | ||
script: | | ||
const { default: script } = await import(`${process.env.GITHUB_WORKSPACE}/build-automation.mjs`); | ||
await script(github); | ||
|
||
- name: Create update PR | ||
id: cpr | ||
uses: peter-evans/create-pull-request@v3 | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
branch: update-branch | ||
base: main | ||
commit-message: "Update to ${{ steps.updt.outputs.updated-versions }}" | ||
title: "Update to ${{ steps.updt.outputs.updated-versions }}" | ||
delete-branch: true | ||
team-reviewers: | | ||
@nodejs/docker | ||
|
||
- name: Check CI status periodically | ||
uses: actions/github-script@v6 | ||
with: | ||
script: | | ||
const { default: script } = await import(`${process.env.GITHUB_WORKSPACE}/check-pr-status.mjs`); | ||
await script(github, '${{ github.repository }}', ${{ steps.cpr.outputs.pull-request-number }}); | ||
|
||
- name: Auto-approve the PR | ||
uses: juliangruber/approve-pull-request-action@v1 | ||
with: | ||
# Cannot use `GITHUB_TOKEN` as it's not allowed to approve own PR | ||
github-token: ${{ secrets.GH_API_TOKEN }} | ||
number: ${{ steps.cpr.outputs.pull-request-number }} | ||
|
||
- name: Merge PR | ||
uses: juliangruber/merge-pull-request-action@v1 | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
number: ${{ steps.cpr.outputs.pull-request-number }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { promisify } from "util"; | ||
|
||
import child_process from "child_process"; | ||
|
||
const exec = promisify(child_process.exec); | ||
|
||
// a function that queries the Node.js release website for new versions, | ||
// compare the available ones with the ones we use in this repo | ||
// and returns whether we should update or not | ||
const checkIfThereAreNewVersions = async (github) => { | ||
try { | ||
const { stdout: versionsOutput } = await exec(". ./functions.sh && get_versions", { shell: "bash" }); | ||
|
||
const supportedVersions = versionsOutput.trim().split(" "); | ||
|
||
let latestSupportedVersions = {}; | ||
|
||
for (let supportedVersion of supportedVersions) { | ||
const { stdout } = await exec(`ls ${supportedVersion}`); | ||
|
||
const { stdout: fullVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${stdout.trim().split("\n")[0]}`, { shell: "bash" }); | ||
|
||
console.log(fullVersionOutput); | ||
|
||
latestSupportedVersions[supportedVersion] = { fullVersion: fullVersionOutput.trim() }; | ||
} | ||
|
||
const { data: availableVersionsJson } = await github.request('https://nodejs.org/download/release/index.json'); | ||
|
||
// filter only more recent versions of availableVersionsJson for each major version in latestSupportedVersions' keys | ||
// e.g. if latestSupportedVersions = { "12": "12.22.10", "14": "14.19.0", "16": "16.14.0", "17": "17.5.0" } | ||
// and availableVersions = ["Node.js 12.22.10", "Node.js 12.24.0", "Node.js 14.19.0", "Node.js 14.22.0", "Node.js 16.14.0", "Node.js 16.16.0", "Node.js 17.5.0", "Node.js 17.8.0"] | ||
// return { "12": "12.24.0", "14": "14.22.0", "16": "16.16.0", "17": "17.8.0" } | ||
|
||
let filteredNewerVersions = {}; | ||
|
||
for (let availableVersion of availableVersionsJson) { | ||
const [availableMajor, availableMinor, availablePatch] = availableVersion.version.split("v")[1].split("."); | ||
if (latestSupportedVersions[availableMajor] == null) { | ||
continue; | ||
} | ||
const [_latestMajor, latestMinor, latestPatch] = latestSupportedVersions[availableMajor].fullVersion.split("."); | ||
if (latestSupportedVersions[availableMajor] && (Number(availableMinor) > Number(latestMinor) || (availableMinor === latestMinor && Number(availablePatch) > Number(latestPatch)))) { | ||
filteredNewerVersions[availableMajor] = { fullVersion: `${availableMajor}.${availableMinor}.${availablePatch}` }; | ||
} | ||
} | ||
|
||
return { | ||
shouldUpdate: Object.keys(filteredNewerVersions).length > 0 && JSON.stringify(filteredNewerVersions) !== JSON.stringify(latestSupportedVersions), | ||
versions: filteredNewerVersions, | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
// a function that queries the Node.js unofficial release website for new musl versions and security releases, | ||
// and returns relevant information | ||
const checkForMuslVersionsAndSecurityReleases = async (github, versions) => { | ||
try { | ||
const { data: unofficialBuildsIndexText } = await github.request('https://unofficial-builds.nodejs.org/download/release/index.json'); | ||
|
||
for (let version of Object.keys(versions)) { | ||
const { data: unofficialBuildsWebsiteText } = await github.request(`https://unofficial-builds.nodejs.org/download/release/v${versions[version].fullVersion}`); | ||
|
||
versions[version].muslBuildExists = unofficialBuildsWebsiteText.includes("musl"); | ||
versions[version].isSecurityRelease = unofficialBuildsIndexText.find(indexVersion => indexVersion.version === `v${versions[version].fullVersion}`)?.security; | ||
} | ||
return versions; | ||
} catch (error) { | ||
console.error(error); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
export default async function(github) { | ||
// if there are no new versions, exit gracefully | ||
// if there are new versions, | ||
// check for musl builds | ||
// then run update.sh | ||
const { shouldUpdate, versions } = await checkIfThereAreNewVersions(github); | ||
|
||
if (!shouldUpdate) { | ||
console.log("No new versions found. No update required."); | ||
process.exit(0); | ||
} else { | ||
const newVersions = await checkForMuslVersionsAndSecurityReleases(github, versions); | ||
let updatedVersions = []; | ||
for (let version of Object.keys(newVersions)) { | ||
if (newVersions[version].muslBuildExists) { | ||
const { stdout } = await exec(`./update.sh ${newVersions[version].isSecurityRelease ? "-s " : ""}${version}`); | ||
console.log(stdout); | ||
updatedVersions.push(newVersions[version].fullVersion); | ||
} else { | ||
console.log(`There's no musl build for version ${newVersions[version].fullVersion} yet.`); | ||
process.exit(0); | ||
} | ||
} | ||
console.log(`::set-output name=updated-versions::${updatedVersions.join(',')}`); | ||
const { stdout } = (await exec(`git diff`)); | ||
console.log(stdout); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// fetch /repos/{owner}/{repo}/pulls/{pull_number} | ||
// and check its mergeable_state | ||
// if "clean", exit with status code 0 | ||
// else exit with error | ||
import { setTimeout } from 'timers/promises'; | ||
|
||
const tries = 10; | ||
const retryDelay = 30000; | ||
|
||
export default async function(github, repository, pull_number) { | ||
const [owner, repo] = repository.split('/'); | ||
await setTimeout(retryDelay); | ||
|
||
for (let t = 0; t < tries; t++) { | ||
try { | ||
const { data } = await github.rest.pulls.get({owner, repo, pull_number}) | ||
|
||
console.log(data); | ||
if (data.mergeable_state === 'clean') { | ||
process.exit(0); | ||
} | ||
await setTimeout(retryDelay); | ||
} catch (error) { | ||
console.error(error); | ||
process.exit(1); | ||
} | ||
} | ||
process.exit(1); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.