mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
chore(release): begin 0.25 development and publish 0.24 article (#1674)
This commit is contained in:
1 parent
512e9787a8
commit
0e4e1d2169
13 files changed
+102
-56
No files matched your search
@@ -73,11 +73,12 @@ the complete 27-asset set documented in `docs/architecture/release-pipeline.md`.
|
||||
It is read-only, and fails on an already-published release. Still review the
|
||||
authored text and generated commits by eye.
|
||||
|
||||
After verification, manually publish the GitHub release. That publication
|
||||
automatically verifies its Snap assets and uploads them to `edge`.
|
||||
Installed-Snap smoke and candidate/stable promotion remain manual. Keep the
|
||||
blog draft during artifact verification; publish it in a follow-up commit and
|
||||
verify the website deployment.
|
||||
Manually publish the release; this verifies and uploads Snaps
|
||||
to `edge`. Installed-Snap smoke and candidate/stable promotion stay manual.
|
||||
After public-asset verification, publish the draft blog and update
|
||||
`apps/website/released-version.json` to the published version together.
|
||||
Follow the release pipeline's offline-download checks and verify deployment;
|
||||
never use the development/nightly version for this pin.
|
||||
|
||||
## Failure Safety
|
||||
|
||||
|
||||
@@ -73,11 +73,12 @@ the complete 27-asset set documented in `docs/architecture/release-pipeline.md`.
|
||||
It is read-only, and fails on an already-published release. Still review the
|
||||
authored text and generated commits by eye.
|
||||
|
||||
After verification, manually publish the GitHub release. That publication
|
||||
automatically verifies its Snap assets and uploads them to `edge`.
|
||||
Installed-Snap smoke and candidate/stable promotion remain manual. Keep the
|
||||
blog draft during artifact verification; publish it in a follow-up commit and
|
||||
verify the website deployment.
|
||||
Manually publish the release; this verifies and uploads Snaps
|
||||
to `edge`. Installed-Snap smoke and candidate/stable promotion stay manual.
|
||||
After public-asset verification, publish the draft blog and update
|
||||
`apps/website/released-version.json` to the published version together.
|
||||
Follow the release pipeline's offline-download checks and verify deployment;
|
||||
never use the development/nightly version for this pin.
|
||||
|
||||
## Failure Safety
|
||||
|
||||
|
||||
+6
-2
@@ -11,7 +11,7 @@ this marker — see `.changes/README.md`.
|
||||
|
||||
<!-- next-release -->
|
||||
|
||||
# [0.24.0](https://github.com/4gray/iptvnator/compare/v0.23.0...v0.24.0) (2026-09-21)
|
||||
# [0.24.0](https://github.com/4gray/iptvnator/compare/v0.23.0...v0.24.0) (2026-09-24)
|
||||
|
||||
|
||||

|
||||
@@ -40,7 +40,11 @@ Before updating, back up your playlists and important data. Desktop startup appl
|
||||
|
||||
## Thanks
|
||||
|
||||
Thank you to [@Bpl5966](https://github.com/Bpl5966) for MPV reconnects and extra options ([#1515](https://github.com/4gray/iptvnator/pull/1515)), [@mark-jardine](https://github.com/mark-jardine) for the EPG time offset ([#1489](https://github.com/4gray/iptvnator/pull/1489)), and [@larsemig](https://github.com/larsemig) for stream information ([#1578](https://github.com/4gray/iptvnator/pull/1578)). A warm thank-you to everyone who reported issues, tested builds, helped in the [Telegram community](https://t.me/iptvnator), or supported development. 💙
|
||||
Thank you to [@Bpl5966](https://github.com/Bpl5966) for MPV reconnects and extra options ([#1515](https://github.com/4gray/iptvnator/pull/1515)), [@mark-jardine](https://github.com/mark-jardine) for the EPG time offset ([#1489](https://github.com/4gray/iptvnator/pull/1489)), and [@larsemig](https://github.com/larsemig) for stream information ([#1578](https://github.com/4gray/iptvnator/pull/1578)).
|
||||
|
||||
Thank you also to [@thejdubb02](https://github.com/thejdubb02) for the original zoom-persistence, Turkish-search and Xtream EPG-refresh fixes ([#1613](https://github.com/4gray/iptvnator/pull/1613), [#1612](https://github.com/4gray/iptvnator/pull/1612), [#1610](https://github.com/4gray/iptvnator/pull/1610)). This work was incorporated and extended in [#1617](https://github.com/4gray/iptvnator/pull/1617), [#1640](https://github.com/4gray/iptvnator/pull/1640) and [#1647](https://github.com/4gray/iptvnator/pull/1647), with his co-authorship preserved.
|
||||
|
||||
A warm thank-you to everyone who reported issues, tested builds, helped in the [Telegram community](https://t.me/iptvnator), or supported development. 💙
|
||||
|
||||
If IPTVnator is useful to you, you can help keep it moving through [GitHub Sponsors](https://github.com/sponsors/4gray) or [Ko-fi](https://ko-fi.com/4gray).
|
||||
|
||||
|
||||
@@ -26,10 +26,7 @@
|
||||
<link rel="icon" type="image/x-icon" href="assets/icons/favicon.ico" />
|
||||
<script src="assets/app-config.js" defer></script>
|
||||
<style>
|
||||
/* Inline splash — paints immediately while the JS bundle and the
|
||||
styles.css (~300KB) are still downloading and Angular is
|
||||
bootstrapping. Removed from the DOM by main.ts after
|
||||
bootstrapApplication() resolves. No assets, zero extra HTTP. */
|
||||
/* Asset-free splash while bundles load; main.ts removes it after bootstrap. */
|
||||
#initial-splash {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
|
||||
@@ -74,11 +74,12 @@ resolves it at build time:
|
||||
options whose file is missing are dropped, sizes and the publish date come
|
||||
from the API. `deploy-website.yml` passes `GITHUB_TOKEN` to the build so
|
||||
the call is authenticated.
|
||||
2. Fallback: the root `package.json` version with the asset naming pattern
|
||||
from `electron-builder.json`. This is deterministic but cannot prove the
|
||||
files exist yet (a version bump lands on `master` before the release is
|
||||
published), so a warning is printed. Set `WEBSITE_SKIP_RELEASE_FETCH=1` to
|
||||
force it for offline or reproducible builds.
|
||||
2. Fallback: the published version pinned in `released-version.json` with
|
||||
the asset naming pattern from `electron-builder.json`. Advance this pin
|
||||
only after that GitHub release is public and its assets are verified, in
|
||||
the follow-up commit that publishes the article. It must stay independent
|
||||
of the root `package.json` development/nightly version. Set
|
||||
`WEBSITE_SKIP_RELEASE_FETCH=1` to force it for offline or reproducible builds.
|
||||
|
||||
Both paths produce the same page structure. Adding an artifact means adding a
|
||||
`DownloadOption` (matcher + fallback name) in `downloads.ts`; the pages and the
|
||||
@@ -88,7 +89,9 @@ resolved version.
|
||||
`pnpm nx test website` builds the site and runs
|
||||
`tools/testing/website-download-pages.test.mjs`, which checks titles,
|
||||
canonicals, direct asset links, JSON-LD, cross-links and sitemap entries
|
||||
without depending on a specific version.
|
||||
without depending on a specific version. Resolver regression tests use the real
|
||||
Astro build constants and cover offline builds, rate limits and timeouts,
|
||||
ensuring each platform keeps links to the pinned published release.
|
||||
|
||||
Two of the suites drive the built site in a real browser:
|
||||
`tools/testing/website-screenshot-showcase.test.mjs` (the home page channel
|
||||
|
||||
@@ -4,16 +4,9 @@ import { defineConfig } from 'astro/config';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
import mdx from '@astrojs/mdx';
|
||||
|
||||
/**
|
||||
* Repository version for the download pages' offline fallback
|
||||
* (`src/lib/downloads.ts`). Read from the workspace root through the file
|
||||
* system and injected as a build-time constant: importing the root
|
||||
* `package.json` from inside the project trips the Nx module-boundaries rule
|
||||
* ("external resources cannot be imported using a relative path"), and a
|
||||
* value fixed at build time is what the fallback needs anyway.
|
||||
*/
|
||||
/** Published version for offline downloads; independent of the nightly base. */
|
||||
const { version } = JSON.parse(
|
||||
readFileSync(new URL('../../package.json', import.meta.url), 'utf8'),
|
||||
readFileSync(new URL('./released-version.json', import.meta.url), 'utf8'),
|
||||
);
|
||||
|
||||
// Tailwind (v3) is applied via apps/website/postcss.config.mjs — the
|
||||
@@ -26,7 +19,7 @@ export default defineConfig({
|
||||
integrations: [sitemap(), mdx()],
|
||||
vite: {
|
||||
define: {
|
||||
__IPTVNATOR_VERSION__: JSON.stringify(version),
|
||||
__IPTVNATOR_RELEASED_VERSION__: JSON.stringify(version),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "0.24.0"
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
title: v0.24 - Release Notes
|
||||
description: A rebuilt programme guide, channels and episodes within reach in fullscreen, and live stream information — plus more dependable sources, playback and upgrades.
|
||||
featured: true
|
||||
pubDate: 2026-09-21
|
||||
pubDate: 2026-09-24
|
||||
author: 4gray
|
||||
heroImage: /iptvnator/blog/v0-24/announce.png
|
||||
tags:
|
||||
- release
|
||||
draft: true
|
||||
draft: false
|
||||
---
|
||||
|
||||
import BlogImageSlider from '../../components/blog/BlogImageSlider.astro';
|
||||
@@ -24,7 +24,7 @@ There is plenty around those three changes: local XMLTV files, catch-up download
|
||||
|
||||
<ReleaseMeta
|
||||
version="v0.24.0"
|
||||
releaseDate="September 21, 2026"
|
||||
releaseDate="September 24, 2026"
|
||||
channels={['Desktop', 'PWA']}
|
||||
/>
|
||||
|
||||
@@ -106,7 +106,7 @@ The player overlay now shows stream information: resolution, playback and source
|
||||
- **AppManager discovery.** AppImages include the repository metadata AppManager needs to find and download complete updates. ([#1559](https://github.com/4gray/iptvnator/pull/1559))
|
||||
- **Review inactive sources together.** Desktop users can select sources to remove, retain individual entries and see the result for each deletion. ([#1596](https://github.com/4gray/iptvnator/pull/1596))
|
||||
- **Check source availability.** Desktop playlist lists show background availability checks for Stalker portals and M3U links alongside Xtream accounts. ([#1592](https://github.com/4gray/iptvnator/pull/1592))
|
||||
- **Try the nightly channel.** Settings → About offers builds from master. Stable remains the default; returning from nightly waits for a newer stable release. ([#1608](https://github.com/4gray/iptvnator/pull/1608))
|
||||
- **Try the nightly channel.** Settings → About offers builds from master, also available in the [nightly repository](https://github.com/4gray/iptvnator-nightly/releases). Stable remains the default; returning from nightly waits for a newer stable release. ([#1608](https://github.com/4gray/iptvnator/pull/1608))
|
||||
|
||||
## Other changes
|
||||
|
||||
@@ -235,7 +235,11 @@ Please back up your playlists and important data before updating. Desktop startu
|
||||
|
||||
## Thanks
|
||||
|
||||
Thank you to [@Bpl5966](https://github.com/Bpl5966) for embedded MPV reconnects and extra options ([#1515](https://github.com/4gray/iptvnator/pull/1515)), [@mark-jardine](https://github.com/mark-jardine) for the EPG time offset ([#1489](https://github.com/4gray/iptvnator/pull/1489)), and [@larsemig](https://github.com/larsemig) for stream information ([#1578](https://github.com/4gray/iptvnator/pull/1578)). Welcome to Bpl5966 and mark-jardine, whose first contributions are included in this release.
|
||||
Thank you to [@Bpl5966](https://github.com/Bpl5966) for embedded MPV reconnects and extra options ([#1515](https://github.com/4gray/iptvnator/pull/1515)), [@mark-jardine](https://github.com/mark-jardine) for the EPG time offset ([#1489](https://github.com/4gray/iptvnator/pull/1489)), and [@larsemig](https://github.com/larsemig) for stream information ([#1578](https://github.com/4gray/iptvnator/pull/1578)).
|
||||
|
||||
Thank you also to [@thejdubb02](https://github.com/thejdubb02) for the original zoom-persistence, Turkish-search and Xtream EPG-refresh fixes ([#1613](https://github.com/4gray/iptvnator/pull/1613), [#1612](https://github.com/4gray/iptvnator/pull/1612), [#1610](https://github.com/4gray/iptvnator/pull/1610)). This work was incorporated and extended in [#1617](https://github.com/4gray/iptvnator/pull/1617), [#1640](https://github.com/4gray/iptvnator/pull/1640) and [#1647](https://github.com/4gray/iptvnator/pull/1647), with his co-authorship preserved.
|
||||
|
||||
Welcome to Bpl5966, mark-jardine and thejdubb02, whose first contributions are included in this release.
|
||||
|
||||
A warm thank-you to everyone who reported issues, tested builds and helped others in the [Telegram community](https://t.me/iptvnator), and to the sponsors and donors who make time for this project possible. 💙 If IPTVnator is useful to you, you can support its development through [GitHub Sponsors](https://github.com/sponsors/4gray) or [Ko-fi](https://ko-fi.com/4gray).
|
||||
|
||||
|
||||
Vendored
+2
-6
@@ -1,8 +1,4 @@
|
||||
/// <reference types="astro/client" />
|
||||
|
||||
/**
|
||||
* Repository version from the workspace root `package.json`, injected at
|
||||
* build time by `astro.config.mjs` through Vite `define`. Used by the download
|
||||
* pages' offline fallback (`src/lib/downloads.ts`).
|
||||
*/
|
||||
declare const __IPTVNATOR_VERSION__: string;
|
||||
/** Published release from released-version.json, injected by astro.config.mjs. */
|
||||
declare const __IPTVNATOR_RELEASED_VERSION__: string;
|
||||
@@ -7,13 +7,13 @@ import type { DownloadPlatform } from './platforms';
|
||||
* *published* release so that every direct link points at an asset that
|
||||
* exists, and so file sizes and the publish date can be shown. When the API
|
||||
* is unreachable (offline build, rate limit, `WEBSITE_SKIP_RELEASE_FETCH=1`)
|
||||
* the pages fall back to the repository version from the root `package.json`
|
||||
* — injected as `__IPTVNATOR_VERSION__` by `astro.config.mjs`, since a
|
||||
* relative import of the root manifest violates the Nx module boundaries —
|
||||
* and the known asset naming pattern from `electron-builder.json`.
|
||||
* the pages fall back to the published version in `released-version.json`,
|
||||
* injected as `__IPTVNATOR_RELEASED_VERSION__` by `astro.config.mjs`, and the
|
||||
* known asset naming pattern from `electron-builder.json`. The development
|
||||
* version in the root package manifest must never select download assets.
|
||||
*/
|
||||
|
||||
const FALLBACK_VERSION = __IPTVNATOR_VERSION__;
|
||||
const FALLBACK_VERSION = __IPTVNATOR_RELEASED_VERSION__;
|
||||
|
||||
export const GITHUB_REPO = '4gray/iptvnator';
|
||||
export const REPO_URL = `https://github.com/${GITHUB_REPO}`;
|
||||
@@ -38,8 +38,8 @@ export interface ResolvedRelease {
|
||||
url: string;
|
||||
publishedAt: Date | null;
|
||||
assets: ReleaseAsset[];
|
||||
/** Where the data came from; the fallback cannot promise that the files exist yet. */
|
||||
source: 'github-api' | 'package-json';
|
||||
/** Whether the API or the pinned published version supplied the release. */
|
||||
source: 'github-api' | 'published-version';
|
||||
}
|
||||
|
||||
export interface DownloadOption {
|
||||
@@ -321,10 +321,10 @@ function fallbackRelease(): ResolvedRelease {
|
||||
url: `${RELEASES_URL}/tag/${tag}`,
|
||||
publishedAt: null,
|
||||
assets,
|
||||
source: 'package-json',
|
||||
source: 'published-version',
|
||||
};
|
||||
}
|
||||
|
||||
function warnFallback(reason: string): void {
|
||||
console.warn(`[website] Latest release lookup failed (${reason}); using package.json version ${FALLBACK_VERSION}.`);
|
||||
console.warn(`[website] Latest release lookup failed (${reason}); using pinned published version ${FALLBACK_VERSION}.`);
|
||||
}
|
||||
@@ -436,8 +436,13 @@ Publishing the GitHub release is manual. That publication automatically
|
||||
verifies its Snap assets and uploads them to `edge`; installed-Snap smoke and
|
||||
candidate/stable promotion remain manual (see
|
||||
`tools/packaging/validate-snap-release-boundary.mjs`). Keep the blog post a
|
||||
draft during artifact verification, then publish it in a follow-up commit and
|
||||
verify the website deployment.
|
||||
draft during artifact verification. After the release is public and its assets
|
||||
are verified, publish the blog and advance
|
||||
`apps/website/released-version.json` to that published version in the same
|
||||
follow-up commit. Run `WEBSITE_SKIP_RELEASE_FETCH=1 pnpm nx test website --skip-nx-cache`,
|
||||
compare the generated download links with the public release assets, and
|
||||
verify the website deployment. The fallback pin must never follow the
|
||||
development/nightly version in the root `package.json`.
|
||||
|
||||
If a Store upload fails after publication, run `publish-snap.yaml` from
|
||||
`master` with its `tag` input set to the existing public stable tag, for example
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iptvnator",
|
||||
"version": "0.24.0",
|
||||
"version": "0.25.0",
|
||||
"engines": {
|
||||
"node": "^22.22.3 || ^24.15.0"
|
||||
},
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import vm from 'node:vm';
|
||||
import ts from 'typescript';
|
||||
import astroConfig from '../../apps/website/astro.config.mjs';
|
||||
|
||||
/**
|
||||
* Structural checks for the per-OS download pages in the built website.
|
||||
* The build resolves the latest release from the GitHub API and falls back to
|
||||
* package.json, so assertions accept any semver version but insist on direct
|
||||
* the pinned published version, so assertions accept any semver but insist on direct
|
||||
* asset links, canonical URLs, structured data and internal linking.
|
||||
*/
|
||||
|
||||
const distRoot = new URL('../../dist/apps/website/', import.meta.url);
|
||||
const { version: publishedVersion } = JSON.parse(await readFile(new URL('../../apps/website/released-version.json', import.meta.url), 'utf8'));
|
||||
const SITE = 'https://4gray.github.io/iptvnator';
|
||||
|
||||
const readDist = (relativePath) => readFile(new URL(relativePath, distRoot), 'utf8');
|
||||
@@ -152,3 +156,38 @@ test('sitemap lists the download pages', async () => {
|
||||
assert.match(sitemap, new RegExp(`<loc>${SITE}/${path}</loc>`));
|
||||
}
|
||||
});
|
||||
|
||||
// Use the real Astro defines so a development-version bump cannot silently
|
||||
// change the offline download URLs. The API is the only mocked boundary.
|
||||
for (const failure of ['offline', 'rate-limit', 'timeout']) {
|
||||
test(`release lookup ${failure}: downloads stay on the published release`, async () => {
|
||||
const source = await readFile(new URL('../../apps/website/src/lib/downloads.ts', import.meta.url), 'utf8');
|
||||
const code = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText;
|
||||
const exports = {};
|
||||
let fetchCalls = 0;
|
||||
const warnings = [];
|
||||
vm.runInNewContext(code, {
|
||||
exports,
|
||||
...Object.fromEntries(Object.entries(astroConfig.vite.define).map(([name, value]) => [name, JSON.parse(value)])),
|
||||
process: { env: { WEBSITE_SKIP_RELEASE_FETCH: failure === 'offline' ? '1' : '0' } },
|
||||
AbortSignal,
|
||||
console: { warn(message) { warnings.push(message); } },
|
||||
fetch: async () => {
|
||||
fetchCalls++;
|
||||
if (failure === 'timeout') throw new Error('The operation timed out');
|
||||
return { ok: false, status: 403 };
|
||||
},
|
||||
});
|
||||
const release = await exports.getLatestRelease();
|
||||
assert.equal(release.version, publishedVersion, 'The published release is independent of the upcoming development version');
|
||||
assert.equal(fetchCalls, failure === 'offline' ? 0 : 1);
|
||||
assert.equal(warnings.length, failure === 'offline' ? 0 : 1);
|
||||
for (const platform of ['windows', 'macos', 'linux']) {
|
||||
const downloads = exports.resolveDownloads(release, platform);
|
||||
assert.ok(downloads.length > 0);
|
||||
for (const download of downloads) {
|
||||
assert.ok(download.url.includes(`/releases/download/v${publishedVersion}/iptvnator-${publishedVersion}-`), download.url);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user