ci(nightly): set the electron-builder publish channel for nightly builds (#1611)

This commit is contained in:
4gray authored and GitHub committed 2026-09-16 07:50:50 +02:00
1 parent d3dee05a84
commit 9a3aa63490
6 files changed
+123 -14

No files matched your search

+52 -6
View File
@@ -16,8 +16,12 @@
* - The date is the commit's UTC date and the last identifier is the
* workflow run number, which only ever grows, so nightlies order
* correctly across days and within one day.
* - electron-builder derives the updater channel file names from the
* prerelease tag (`nightly-mac.yml`, `nightly.yml`, `nightly-linux.yml`).
* - `--apply` also sets `publish[0].channel` to `nightly` in
* `electron-builder.json`, which is what names the updater metadata
* `nightly-mac.yml` / `nightly.yml` / `nightly-linux.yml`. electron-builder
* does NOT derive that name from the prerelease tag for the GitHub
* provider: the first nightly run shipped `latest-*.yml` files and the
* publish step refused them.
*
* A release cut commits the new version to master before (or together
* with) its tag. While `v<package.json version>` does not exist yet, that
@@ -36,6 +40,7 @@
* Usage:
* node tools/release/nightly-version.mjs # print
* node tools/release/nightly-version.mjs --apply --version X # write X
* into package.json + electron-builder.json
*
* Inputs default to the repository `package.json`, the HEAD commit date,
* `GITHUB_RUN_NUMBER`, and a `git ls-remote` probe for the base tag;
@@ -108,6 +113,26 @@ export function parseBooleanFlag(value, flag) {
throw new Error(`${flag} must be "true" or "false", got "${value}".`);
}
/**
* Points electron-builder's updater metadata at the nightly channel. Written
* as 4-space JSON like `configure-linux-frame-copy-build.mjs`, which has
* already rewritten the file the same way on Linux by the time this runs.
*/
export function applyNightlyPublishChannel(electronBuilderJsonText) {
const config = JSON.parse(electronBuilderJsonText);
const publish = Array.isArray(config.publish) ? config.publish : null;
if (!publish || publish.length === 0 || publish[0]?.provider !== 'github') {
throw new Error(
'electron-builder.json must declare a github publish provider first.'
);
}
publish[0] = { ...publish[0], channel: NIGHTLY_TAG };
return `${JSON.stringify(config, null, 4)}\n`;
}
/** Replaces the `version` line in `package.json` text, formatting intact. */
export function applyNightlyVersion(packageJsonText, version) {
if (!PACKAGE_VERSION_LINE.test(packageJsonText)) {
@@ -239,11 +264,32 @@ function main(argv) {
}
if (options.apply) {
writeFileSync(
packageJsonPath,
applyNightlyVersion(packageJsonText, version)
// Resolve both replacements before touching either file, so a bad
// electron-builder.json cannot leave package.json half-applied.
const electronBuilderJsonPath = new URL(
'../../electron-builder.json',
import.meta.url
);
let nextPackageJson;
let nextElectronBuilderJson;
try {
nextPackageJson = applyNightlyVersion(packageJsonText, version);
nextElectronBuilderJson = applyNightlyPublishChannel(
readFileSync(electronBuilderJsonPath, 'utf8')
);
} catch (error) {
console.error(
error instanceof Error ? error.message : String(error)
);
return 1;
}
writeFileSync(packageJsonPath, nextPackageJson);
writeFileSync(electronBuilderJsonPath, nextElectronBuilderJson);
console.error(
`Applied nightly version ${version} to package.json and the nightly publish channel to electron-builder.json.`
);
console.error(`Applied nightly version ${version} to package.json.`);
}
console.log(version);
+56
View File
@@ -1,6 +1,8 @@
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { describe, it } from 'node:test';
import {
applyNightlyPublishChannel,
applyNightlyVersion,
buildNightlyVersion,
isNightlyVersion,
@@ -164,6 +166,60 @@ describe('applyNightlyVersion', () => {
});
});
describe('applyNightlyPublishChannel', () => {
it('sets the github publish channel and keeps the rest of the config', () => {
const source = JSON.stringify(
{
appId: 'x',
publish: [{ provider: 'github', owner: '4gray', repo: 'iptvnator' }],
mac: { target: ['dmg'] },
},
null,
4
);
const result = applyNightlyPublishChannel(source);
assert.deepEqual(JSON.parse(result), {
appId: 'x',
publish: [
{
provider: 'github',
owner: '4gray',
repo: 'iptvnator',
channel: 'nightly',
},
],
mac: { target: ['dmg'] },
});
assert.ok(result.endsWith('}\n'));
assert.match(result, /^\{\n {4}"appId"/);
});
it('applies to the repository config as committed', () => {
const committed = readFileSync(
new URL('../../electron-builder.json', import.meta.url),
'utf8'
);
assert.equal(
JSON.parse(applyNightlyPublishChannel(committed)).publish[0].channel,
'nightly'
);
});
it('refuses a config without a github publish provider', () => {
assert.throws(
() => applyNightlyPublishChannel('{"publish":[{"provider":"generic"}]}'),
/github publish provider/
);
assert.throws(
() => applyNightlyPublishChannel('{}'),
/github publish provider/
);
});
});
describe('explicit version input', () => {
it('accepts only the shape the script itself produces', () => {
assert.equal(isNightlyVersion('0.23.1-nightly.20260915.1234'), true);