Skip to content
Open
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
23 changes: 12 additions & 11 deletions .github/workflows/automatic-updates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,27 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Run automation script
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
id: updt
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
result-encoding: string
script: |
const { default: script } = await import(`${process.env.GITHUB_WORKSPACE}/build-automation.mjs`);
return script(github);
node-version-file: .node-version
cache: npm
- name: Install dependencies
run: npm ci

- name: Run automation script
run: npm run build

- name: Create update PR
id: cpr
if: steps.updt.outputs.result != ''
if: env.NODE_PR_TITLE != ''
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.GH_API_TOKEN }}
author: 'Node.js GitHub Bot <nodejs-github-bot@users.noreply.github.com>'
branch: update-branch
base: main
commit-message: 'feat: Node.js ${{ steps.updt.outputs.result }}'
title: 'feat: Node.js ${{ steps.updt.outputs.result }}'
commit-message: '${{ env.NODE_PR_TITLE }}'
title: '${{ env.NODE_PR_TITLE }}'
delete-branch: true
team-reviewers: |
nodejs/docker
158 changes: 62 additions & 96 deletions build-automation.mjs
Original file line number Diff line number Diff line change
@@ -1,107 +1,73 @@
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' },
import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { env } from 'node:process';
import { exportVariable } from '@actions/core';

import shell from 'shelljs';

const updatedVersions = [];

try {
// get the folders with a digit, assuming they're the Node.js major versions
const supportedVersions = readdirSync('./').filter((file) => {
return file.match(/\d/);
});

console.log(`Found major versions in repo: ${supportedVersions}`);

console.log('Grabbing Index.json files');
const availableVersions = await fetch(
'https://nodejs.org/download/release/index.json',
);
const officialIndexJson = await availableVersions.json();

for (let supportedVersion of supportedVersions) {
console.log(`Checking for updates for ${supportedVersion}`);
const folders = readdirSync(join('.', supportedVersion));
let latestVersion = officialIndexJson.find((indexVersion) =>
indexVersion.version.startsWith(`v${supportedVersion}`),
);

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',
const lastFolder = folders.at(-1);
const dockerFile = readFileSync(
join('.', supportedVersion, lastFolder, 'Dockerfile'),
'utf-8',
);

// 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" }
const localVersion =
'v' +
dockerFile.match(/NODE_VERSION=(?<version>\d*\.\d*\.\d)/).groups[
'version'
];
console.log(`\tRead version ${localVersion} from ${lastFolder}`);

let filteredNewerVersions = {};

for (let availableVersion of availableVersionsJson) {
const [availableMajor, availableMinor, availablePatch] =
availableVersion.version.split('v')[1].split('.');
if (latestSupportedVersions[availableMajor] == null) {
continue;
}
// eslint-disable-next-line no-unused-vars
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}`,
};
}
if (latestVersion.version !== localVersion) {
console.warn(
`\tFound new version ${latestVersion.version}, released on ${latestVersion.date}!`,
);
let updateStatement = `bash update.sh ${supportedVersion}`;
console.log(`\tRunning '${updateStatement}'.`);
shell.exec(updateStatement);
updatedVersions.push(latestVersion.version);
} else {
console.log(`\tEverything up to date for ${latestVersion.version}!
\tReleased: ${latestVersion.date}
\tSecurity release: ${latestVersion.security}`);
}

return {
shouldUpdate:
Object.keys(filteredNewerVersions).length > 0 &&
JSON.stringify(filteredNewerVersions) !==
JSON.stringify(latestSupportedVersions),
versions: filteredNewerVersions,
};
} 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, run update.sh
const { shouldUpdate, versions } = await checkIfThereAreNewVersions(github);

if (!shouldUpdate) {
console.log('No new versions found. No update required.');
process.exit(0);
if (updatedVersions.length !== 0) {
env.NODE_PR_TITLE = `feat: Node.js ${updatedVersions.join(', ')}`;
// Let the GitHub Action library set the GITHUB_ENV file rather than manually handling it
exportVariable('NODE_PR_TITLE', env.NODE_PR_TITLE);
}
} catch (error) {
console.error(error);
process.exit(1);
} finally {
if (env.NODE_PR_TITLE) {
console.log(`PR will be created with title '${env.NODE_PR_TITLE}'`);
} else {
let updatedVersions = [];
for (const [version, newVersion] of Object.entries(versions)) {
const { stdout } = await exec(`./update.sh ${version}`);
console.log(stdout);
updatedVersions.push(newVersion.fullVersion);
}

if (updatedVersions.length === 0) {
console.log('No versions with musl builds were updated.');
process.exit(0);
}

const { stdout } = await exec(`git diff`);
console.log(stdout);

return updatedVersions.join(', ');
console.log('No Pull Request will be created.');
}
}
Loading
Loading