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
4 changes: 2 additions & 2 deletions .github/workflows/official-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
- '**/Dockerfile'
- '**/docker-entrypoint.sh'
- 'versions.json'
- 'stackbrew.js'
- 'stackbrew.mjs'

jobs:
pr:
Expand All @@ -36,7 +36,7 @@ jobs:
- name: Generate Stackbrew for diff
run: |
cd docker-node
./stackbrew.js > ../official-images/library/node
./stackbrew.mjs ../official-images/library/node

- name: Create PR in official-images
id: create-pr
Expand Down
2 changes: 1 addition & 1 deletion genMatrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const getAffectedDockerfiles = (filesAdded, filesModified, filesRenamed) => {
};

const getFullNodeVersionFromDockerfile = (file) =>
fs.readFileSync(file, 'utf8').match(/^ENV NODE_VERSION=(\d*\.*\d*\.\d*)/m)[1];
fs.readFileSync(file, 'utf8').match(/^ENV NODE_VERSION=(\S*)/m)[1];

const getDockerfileMatrixEntry = (file) => {
const [variant] = path.dirname(file).split(path.sep).slice(-1);
Expand Down
172 changes: 0 additions & 172 deletions stackbrew.js

This file was deleted.

184 changes: 184 additions & 0 deletions stackbrew.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#!/usr/bin/env node

import { readFileSync, writeFileSync } from 'node:fs';
import { basename, resolve } from 'node:path';
import { execSync } from 'node:child_process';

// Grab last git commit
function getCommitHasForPath(path) {
return execSync(`git log -1 --format=%H HEAD -- ${path}`).toString().trim();
}

// Grab nodejs/Release values as the authoritative start/maintenance/end dates
const releaseTimes = await fetch(
'https://raw.githubusercontent.com/nodejs/Release/refs/heads/main/schedule.json',
);
const releaseJson = await releaseTimes.json();

// Grab the nodejs.org index.json as the authoritative Codename values, since that can lag the Release repo JSON
const availableVersions = await fetch(
'https://nodejs.org/download/release/index.json',
);
const officialIndexJson = await availableVersions.json();

const stackbrewPath = basename(import.meta.filename);

// Header
let stackbrew = `# this file is generated via https://github.com/nodejs/docker-node/blob/${getCommitHasForPath(stackbrewPath)}/${stackbrewPath}

Maintainers: The Node.js Docker Team <https://github.com/nodejs/docker-node> (@nodejs)
GitRepo: https://github.com/nodejs/docker-node.git
GitFetch: refs/heads/main\n`;

const config = JSON.parse(readFileSync('versions.json'));

const localVersions = Object.keys(config).reverse();

let midnight = new Date();
midnight.setHours(0, 0, 0, 0);
const now = midnight.getTime();
let foundLTS = false;
let foundCurrent = false;

for (const majorVersion of localVersions) {
let releaseRepoInfo = releaseJson[`v${majorVersion}`];
let nodejsOrgReleaseInfo = officialIndexJson.find((indexVersion) =>
indexVersion.version.startsWith(`v${majorVersion}`),
);
let currentStart = new Date(`${releaseRepoInfo.start}T00:00:00.00`).getTime();
// First Alpha build is the only active one, and when the "start" of the release hasn't cut over
let isAlpha = nodejsOrgReleaseInfo.version.includes('alpha');
// The Current/Latest release is the first non-Alpha major that has hit it's "start" date
let isCurrent = foundCurrent
? false
: !isAlpha && (isNaN(currentStart) || now >= currentStart);
foundCurrent |= isCurrent;
let codename = nodejsOrgReleaseInfo.lts
? nodejsOrgReleaseInfo.lts.toLowerCase()
: '';
// The LTS tag is only set on the most recent LTS release
let isLTS = foundLTS ? false : codename !== '';
foundLTS |= isLTS;
let defaultAlpine = config[majorVersion]['alpine-default'];
let defaultDebian = config[majorVersion]['debian-default'];
let defaultSlim = `${config[majorVersion]['debian-default']}-slim`;
let variants = config[majorVersion].variants;
for (const variant in variants) {
let tags;

if (isAlpha) {
// Only push explicit variants during the Alpha phase
tags = [`${nodejsOrgReleaseInfo.version.substring(1)}-${variant}`];

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note sure if some of the other combos of floating variants should also be added like:

  • alpha for the default Debian
  • alpha-slim for the default Debian-slim
  • alpha-alpine for whatever is the default Alpine during the Alpha
    Could skip the various alpha-trixie, etc though

} else {
let fullVersion = nodejsOrgReleaseInfo.version.match(
/v(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/,
);
tags = [
`${fullVersion.groups.major}.${fullVersion.groups.minor}.${fullVersion.groups.patch}-${variant}`,
`${fullVersion.groups.major}.${fullVersion.groups.minor}-${variant}`,
`${fullVersion.groups.major}-${variant}`,
];

if (codename) {
tags.push(`${codename}-${variant}`);
}

if (variant === defaultAlpine) {
tags.push(
`${fullVersion.groups.major}.${fullVersion.groups.minor}.${fullVersion.groups.patch}-alpine`,
);
tags.push(
`${fullVersion.groups.major}.${fullVersion.groups.minor}-alpine`,
);
tags.push(`${fullVersion.groups.major}-alpine`);

if (codename) {
tags.push(`${codename}-alpine`);
}

if (isCurrent) {
tags.push('alpine');
tags.push('current-alpine');
}

if (isLTS) {
tags.push(`lts-alpine`);
}
} else if (variant === defaultDebian) {
tags.push(
`${fullVersion.groups.major}.${fullVersion.groups.minor}.${fullVersion.groups.patch}`,
);
tags.push(`${fullVersion.groups.major}.${fullVersion.groups.minor}`);
tags.push(`${fullVersion.groups.major}`);

if (codename) {
tags.push(`${codename}`);
}

if (isCurrent) {
tags.push(variant);
tags.push('latest');
tags.push('current');
}

if (isLTS) {
tags.push('lts');
if (codename) {
tags.push(`lts-${codename}`);
}
}
} else if (variant === defaultSlim) {
tags.push(
`${fullVersion.groups.major}.${fullVersion.groups.minor}.${fullVersion.groups.patch}-slim`,
);
tags.push(
`${fullVersion.groups.major}.${fullVersion.groups.minor}-slim`,
);
tags.push(`${fullVersion.groups.major}-slim`);

if (codename) {
tags.push(`${codename}-slim`);
}

if (isCurrent) {
tags.push('slim');
tags.push('current-slim');
}

if (isLTS) {
tags.push(`lts-slim`);
}
}

if (isCurrent) {
tags.push(`${variant}`);
tags.push(`current-${variant}`);
}

if (isLTS) {
tags.push(`lts-${variant}`);
}
}

stackbrew += `
Tags: ${tags
.filter((x, i, a) => a.indexOf(x) == i)
.sort()
.join(', ')}
Architectures: ${config[majorVersion].variants[variant].join(', ')}
GitCommit: ${getCommitHasForPath(`${majorVersion}/${variant}`)}
Directory: ${`${majorVersion}/${variant}`}\n`;
}
}

try {
const outputFile = process.argv[2];

if (outputFile) {
writeFileSync(resolve(outputFile), stackbrew);
} else {
console.log(stackbrew);
}
} catch (ex) {
console.error("Couldn't handle output", ex);
}
Loading
Loading