mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 10:06:15 -08:00
ci(nightly): set the electron-builder publish channel for nightly builds (#1611)
This commit is contained in:
1 parent
d3dee05a84
commit
9a3aa63490
6 files changed
+123
-14
No files matched your search
@@ -493,7 +493,9 @@ jobs:
|
||||
# offer it, and it must be in package.json before the frontend
|
||||
# and backend builds and electron-builder read it. The value
|
||||
# comes from the nightly-version job so every job of this run
|
||||
# builds the same version.
|
||||
# builds the same version. The script also sets the electron-
|
||||
# builder publish channel to "nightly", which names the updater
|
||||
# metadata nightly-mac.yml / nightly.yml / nightly-linux.yml.
|
||||
if: needs.nightly-version.outputs.version != ''
|
||||
# Windows runners default to PowerShell, where "${NIGHTLY_VERSION}"
|
||||
# expands to nothing and the script rejects the empty version.
|
||||
|
||||
@@ -1715,7 +1715,7 @@ The factory pattern ensures a single codebase works in both environments without
|
||||
CI injects the git commit into `apps/web/src/environments/build-commit.ts` via `tools/build/inject-build-commit.mjs` (same placeholder pattern as the TMDB key inject); `Settings > About` then shows `"<version> (<short-sha>)"`. The semver version itself stays untouched on PR and tag builds — a `-sha` suffix would flip electron-updater into prerelease mode and leak into installer/artifact version fields. Local/dev builds keep the placeholder empty and show the plain version.
|
||||
|
||||
**Nightly Builds And Update Channel**:
|
||||
Master pushes are the nightly channel. The leading `nightly-version` job computes one `<patch>-nightly.<commit date>.<run number>` version per run (`tools/release/nightly-version.mjs`; the patch is bumped only when `v<package.json version>` already exists on origin, so the release-cut window stays below the imminent release), every build job writes it into `package.json` (`--apply --version`), and the `create-release` job publishes the artifacts as a prerelease of `4gray/iptvnator-nightly` (secret `NIGHTLY_RELEASE_TOKEN`; missing token only warns) instead of the rolling `test-master` draft, keeping the newest 20. electron-builder names the updater metadata after the prerelease tag (`nightly-mac.yml` / `nightly.yml` / `nightly-linux.yml`), so upload globs and the macOS merge accept both names. `Settings.updateChannel` (Settings → About, Electron only, default `stable`) is mirrored into the main-process config (`APP_UPDATE_CHANNEL`, `app-update-channel.ts`) for the startup check; `AppUpdateService` applies the channel to electron-updater before every check (`app-update-feed.ts`: feed repository, `allowPrerelease`, channel name, and `allowDowngrade` forced back to `false` — assigning a channel silently enables downgrades) and reads release notes from the repository the requested version belongs to (`app-update-release-catalog.ts`). Switching back to stable is forward-only: the nightly stays until a newer stable release exists, because a downgrade could hit a database schema a nightly migration already applied. Contract: `docs/architecture/release-pipeline.md` ("Nightly channel").
|
||||
Master pushes are the nightly channel. The leading `nightly-version` job computes one `<patch>-nightly.<commit date>.<run number>` version per run (`tools/release/nightly-version.mjs`; the patch is bumped only when `v<package.json version>` already exists on origin, so the release-cut window stays below the imminent release), every build job writes it into `package.json` and sets `publish[0].channel: nightly` in `electron-builder.json` (`--apply --version`; electron-builder does not derive the channel from the prerelease tag for the GitHub provider), and the `create-release` job publishes the artifacts as a prerelease of `4gray/iptvnator-nightly` (secret `NIGHTLY_RELEASE_TOKEN`; missing token only warns) instead of the rolling `test-master` draft, keeping the newest 20. the explicit publish channel names the updater metadata `nightly-mac.yml` / `nightly.yml` / `nightly-linux.yml`, and upload globs plus the macOS merge accept both names. `Settings.updateChannel` (Settings → About, Electron only, default `stable`) is mirrored into the main-process config (`APP_UPDATE_CHANNEL`, `app-update-channel.ts`) for the startup check; `AppUpdateService` applies the channel to electron-updater before every check (`app-update-feed.ts`: feed repository, `allowPrerelease`, channel name, and `allowDowngrade` forced back to `false` — assigning a channel silently enables downgrades) and reads release notes from the repository the requested version belongs to (`app-update-release-catalog.ts`). Switching back to stable is forward-only: the nightly stays until a newer stable release exists, because a downgrade could hit a database schema a nightly migration already applied. Contract: `docs/architecture/release-pipeline.md` ("Nightly channel").
|
||||
|
||||
### Testing Strategy
|
||||
|
||||
|
||||
@@ -299,9 +299,13 @@ frontend and backend builds and before electron-builder reads it
|
||||
is offered it; smaller than `0.23.1` and `0.24.0`, so the next stable
|
||||
release is offered to nightly users on either channel.
|
||||
- The run number only grows, so nightlies order correctly within a day.
|
||||
- electron-builder derives the updater channel files from the prerelease
|
||||
tag: `nightly-mac.yml`, `nightly.yml`, `nightly-linux.yml`. The artifact
|
||||
upload globs and the macOS metadata merge accept both names.
|
||||
- The same `--apply` sets `publish[0].channel: nightly` in
|
||||
`electron-builder.json`, which 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 produced `latest-*.yml` and the publish step refused
|
||||
it). The artifact upload globs and the macOS metadata merge accept both
|
||||
names.
|
||||
- The root `package.json` is an Nx `sharedGlobals` input, so the rewritten
|
||||
version reaches the `web` and `electron-backend` bundles (which embed it)
|
||||
instead of a cache hit built from the released version.
|
||||
|
||||
@@ -24,9 +24,10 @@ export const DEFAULT_APP_UPDATE_CHANNEL: AppUpdateChannel = 'stable';
|
||||
|
||||
/**
|
||||
* Prerelease identifier every nightly version carries
|
||||
* (`0.23.1-nightly.20260915.1234`). electron-builder derives the updater
|
||||
* channel file (`nightly-mac.yml`, `nightly.yml`, `nightly-linux.yml`) from
|
||||
* it, and electron-updater matches release tags on the same identifier.
|
||||
* (`0.23.1-nightly.20260915.1234`). The nightly build sets the same name as
|
||||
* electron-builder's publish channel, which names the updater metadata
|
||||
* (`nightly-mac.yml`, `nightly.yml`, `nightly-linux.yml`), and
|
||||
* electron-updater matches release tags on the same identifier.
|
||||
*/
|
||||
export const NIGHTLY_PRERELEASE_TAG = 'nightly';
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user