mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
docs(release): backfill curated 0.23.0 release notes, fix the notes CLI -- trap (#1263)
Backfills the 0.23.0 release notes the .changes/ pipeline missed: it landed after most of the release was already merged, leaving 4 notes for 79 commits. Adds 22 curated notes (26 total: 14 features, 11 fixes, 1 perf). Curated rather than exhaustive — the GitHub release body renders these above GitHub's own list of every merged PR, so related PRs are folded into one note per user-facing story: shared player controls (8 PRs), embedded MPV frame-copy (4), manual EPG mapping (3), plus five more pairs. Tooling-only scopes get no note. No screenshot slugs: none of the five manifest shots depicts a 0.23 headline feature, and the capture run asserts TMDB enrichment stays disabled. Two tooling fixes found while writing them: - parseArgs now ignores a bare `--`. npm needs it to forward arguments past the script name; pnpm hands it to the script verbatim, so `pnpm run release:notes:github -- --version 0.24.0` died on the very separator typed to make forwarding work. Unknown flags and missing values still fail as before. Covered by new subprocess CLI tests wired into the release-tools target. - .changes/README.md claimed every non-consume mode was a safe dry run; --format changelog and --format blog write their target file. No app or lib code, no version bump, no --consume, no CHANGELOG.md or website changes — those stay owned by release-cut.
This commit is contained in:
1 parent
75c45c9e91
commit
02b966895d
26 files changed
+340
-3
No files matched your search
+13
-2
@@ -69,9 +69,20 @@ node tools/release/build-release-notes.mjs --consume
|
||||
```
|
||||
|
||||
The release version comes from the root `package.json` — bump it first, then
|
||||
generate. `--version 0.24.0` overrides it for a dry run before the bump.
|
||||
generate. `--version 0.24.0` overrides it to preview a release before the bump:
|
||||
|
||||
Only `--consume` deletes anything; every other mode is a safe dry run.
|
||||
```bash
|
||||
pnpm run release:notes:github --version 0.24.0
|
||||
```
|
||||
|
||||
A bare `--` separator is accepted and ignored, so the npm habit of
|
||||
`pnpm run release:notes:github -- --version 0.24.0` works too: pnpm forwards
|
||||
that separator to the script rather than consuming it the way npm does.
|
||||
|
||||
`--validate` and `--format github` only read and print. `--format changelog`
|
||||
and `--format blog` write their target file (rerunning `changelog` for the same
|
||||
version replaces that section rather than duplicating it). Only `--consume`
|
||||
deletes anything.
|
||||
|
||||
The release sequence is: bump the version → `release:notes:changelog` →
|
||||
`release:notes:blog` → `--consume` → commit → tag → push. The tag build then
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: backup
|
||||
issues: [1017]
|
||||
---
|
||||
|
||||
Backups carry hidden Xtream categories correctly. An export used to lose which
|
||||
categories you had hidden, and restoring such a backup then hid every category
|
||||
of that kind.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: downloads
|
||||
---
|
||||
|
||||
Downloads can be paused and picked up later. A paused transfer keeps what it
|
||||
already fetched and continues from that point instead of starting over, and
|
||||
downloads cut short by a crash or a closed app come back as paused rather than
|
||||
lost.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: embedded-mpv
|
||||
---
|
||||
|
||||
Experimental Embedded MPV can draw video inside the app window instead of into a
|
||||
separate layer pinned on top of it, so menus, dialogs and the player controls
|
||||
stop being swallowed by the picture. Available on macOS (Apple Silicon), Windows
|
||||
and Linux x64; switching it on needs a restart.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: epg
|
||||
---
|
||||
|
||||
Channels whose guide never matched can be mapped by hand: right-click a channel
|
||||
in any list and pick "Map EPG channel" to attach it to a channel from your
|
||||
uploaded XMLTV guide. The mapping is remembered and used everywhere the guide is
|
||||
read — M3U playlists, Xtream and Stalker portals alike.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: favorites
|
||||
issues: [1137]
|
||||
---
|
||||
|
||||
Favorites stop losing changes. The custom drag-and-drop order of an Xtream
|
||||
playlist's own favorites is saved again, and two favorites or history entries
|
||||
added at almost the same moment no longer quietly overwrite each other.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
type: feature
|
||||
area: i18n
|
||||
issues: [1192]
|
||||
---
|
||||
|
||||
IPTVnator speaks Hungarian, its 19th language — contributed by @htibcsike.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
type: feature
|
||||
area: m3u
|
||||
issues: [86, 614, 656, 733, 752]
|
||||
---
|
||||
|
||||
MPEG-DASH channels play in the built-in player, ClearKey-encrypted ones
|
||||
included — the keys are read from the playlist's #KODIPROP lines, whether they
|
||||
sit above or below the channel entry. Streams locked with Widevine or PlayReady
|
||||
still cannot be played, but they now say so instead of failing silently.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: m3u
|
||||
issues: [1189]
|
||||
---
|
||||
|
||||
Playlists with very long stream URLs — Pluto TV style lists that carry a session
|
||||
token in every link — import in full again instead of collapsing into a single
|
||||
channel.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: playback
|
||||
---
|
||||
|
||||
An optional new set of player controls that looks and behaves the same in the
|
||||
HTML5, Video.js and ArtPlayer players, with picture-in-picture and, in
|
||||
fullscreen, the name of what you are watching. Enable it in Settings → Playback;
|
||||
left off, each of the three keeps its own controls exactly as before.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: playback
|
||||
---
|
||||
|
||||
The inline player on movie and series pages fills the whole content area like a
|
||||
theater: the video sits centered in black instead of leaving a strip of app
|
||||
background beside it. In the built-in web players, an optional ambient mode
|
||||
fills that space with a blurred, dimmed copy of the poster.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: playback
|
||||
---
|
||||
|
||||
A series playing inline on a wide window shows an "Up Next" rail beside the
|
||||
video: the rest of the season and the start of the next one, the current episode
|
||||
highlighted, watch progress on every card. Click one to jump straight to it.
|
||||
Built-in web players only; switch the rail off in Settings → Playback.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
type: fix
|
||||
area: playlists
|
||||
issues: [931]
|
||||
---
|
||||
|
||||
One unreachable playlist no longer holds up the rest. Refreshes give up after 30
|
||||
seconds and run a few at a time, so your other playlists still update, and the
|
||||
message on startup names how many actually failed instead of always claiming
|
||||
success.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: search
|
||||
issues: [1161]
|
||||
---
|
||||
|
||||
Searching for names that carry punctuation inside them — "A&E", "X-Men",
|
||||
"L'Equipe" — finds them anywhere in a title, including channels the provider
|
||||
prefixes, like "US: A&E".
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: settings
|
||||
---
|
||||
|
||||
A new setting drops the country prefix from live channel names, turning
|
||||
"UK - BBC One" into "BBC One" in lists, the guide and the player. Movie and
|
||||
series titles are left alone, and names that only look like a prefix — "Sky -
|
||||
Sports F1" — stay intact.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: perf
|
||||
area: stalker
|
||||
---
|
||||
|
||||
Detail pages for anything that is not a series — a movie, a live channel, a VOD
|
||||
item that only looks like a series — no longer fire an episode-list request
|
||||
before they can show anything, so they open faster on every route in, from
|
||||
browsing and search to Favorites, Recent and the dashboard.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: stalker
|
||||
---
|
||||
|
||||
Series opened from Favorites, Recent or the dashboard show their current
|
||||
episodes. One saved back when a single episode existed used to keep showing that
|
||||
one episode forever; the list is refreshed from the portal in the background
|
||||
instead.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: stalker
|
||||
---
|
||||
|
||||
The Live TV section loads its full channel list up front: search covers every
|
||||
channel instead of only the page you are on, genres show how many channels they
|
||||
hold, and Live TV opens on a grid of all channels. Guide data for the visible
|
||||
rows loads in bulk, so it shows up without playing a channel first.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: tmdb
|
||||
---
|
||||
|
||||
Series pages show whether a show has ended or is still returning, so you know
|
||||
before committing to it. Directors and creators became clickable avatar chips
|
||||
like the cast — they open the person's page, where directing credits now sit
|
||||
alongside acting ones.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: tmdb
|
||||
---
|
||||
|
||||
Titles that providers dress up with language or quality tags — "|ALB| Fallout",
|
||||
"4K-DE - The Pitt (2025)", "Breaking Bad-eng" — now match against TMDB, so they
|
||||
get artwork, plot and cast like the rest of the catalog. Shows split into one
|
||||
entry per season also pull the season that entry really contains.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: xtream
|
||||
issues: [1138]
|
||||
---
|
||||
|
||||
Catch-up is available from Favorites and Recent, not just Live TV, so an
|
||||
archived programme is reachable wherever the channel is. The programme currently
|
||||
on air can also be restarted from the beginning.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: fix
|
||||
area: xtream
|
||||
---
|
||||
|
||||
Portals sitting behind Cloudflare or a similar firewall connect again. Those
|
||||
setups answered the app with a challenge page instead of data, so "Test
|
||||
connection" failed on portals that worked fine in every other player; requests
|
||||
now identify themselves the way an ordinary IPTV player does.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: feature
|
||||
area: xtream
|
||||
---
|
||||
|
||||
Continue Watching resumes a series where you left it: opening one from the
|
||||
dashboard starts the exact episode at its saved position, and the series page
|
||||
offers "Play episode N" instead of always starting at the first one. Episodes
|
||||
launched in MPV or VLC count towards this too.
|
||||
@@ -90,6 +90,13 @@ function parseArgs(argv) {
|
||||
case '--force':
|
||||
options.force = true;
|
||||
break;
|
||||
// npm needs `--` to forward arguments past the script name; pnpm
|
||||
// hands it to the script verbatim. Ignore it so the habitual
|
||||
// `pnpm run release:notes:github -- --version 0.24.0` works
|
||||
// instead of dying on its own separator. There are no positional
|
||||
// arguments for it to delimit.
|
||||
case '--':
|
||||
break;
|
||||
default:
|
||||
throw new Error(`unknown argument: ${arg}`);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* CLI-level tests for build-release-notes.mjs.
|
||||
*
|
||||
* The script parses its arguments and runs on import, so these drive the real
|
||||
* entry point in a subprocess rather than importing parseArgs directly.
|
||||
*/
|
||||
|
||||
import assert from 'node:assert/strict';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { after, describe, it } from 'node:test';
|
||||
|
||||
const workspaceRoot = path.resolve(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
'../..'
|
||||
);
|
||||
const CLI = path.join(workspaceRoot, 'tools/release/build-release-notes.mjs');
|
||||
const tempDirs = [];
|
||||
|
||||
/** A notes directory holding one valid note, so runs have something to render. */
|
||||
function makeNotesDir() {
|
||||
const directory = mkdtempSync(path.join(tmpdir(), 'release-cli-'));
|
||||
tempDirs.push(directory);
|
||||
|
||||
writeFileSync(
|
||||
path.join(directory, 'playback-example.md'),
|
||||
'---\ntype: feature\narea: playback\n---\n\nAn example note.\n',
|
||||
'utf8'
|
||||
);
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {{ status: number, stdout: string, stderr: string }}
|
||||
*/
|
||||
function runCli(args) {
|
||||
try {
|
||||
const stdout = execFileSync(process.execPath, [CLI, ...args], {
|
||||
cwd: workspaceRoot,
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
|
||||
return { status: 0, stdout, stderr: '' };
|
||||
} catch (error) {
|
||||
return {
|
||||
status: error.status ?? 1,
|
||||
stdout: error.stdout ?? '',
|
||||
stderr: error.stderr ?? '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
after(() => {
|
||||
for (const directory of tempDirs) {
|
||||
rmSync(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe('build-release-notes CLI arguments', () => {
|
||||
it('validates a notes directory', () => {
|
||||
const result = runCli(['--validate', '--dir', makeNotesDir()]);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.match(result.stdout, /1 release note\(s\) valid\./);
|
||||
});
|
||||
|
||||
it('ignores a bare `--` separator', () => {
|
||||
// pnpm forwards `--` to the script instead of consuming it, so the
|
||||
// npm-style `pnpm run release:notes:validate -- --dir x` reaches us
|
||||
// with the separator still attached.
|
||||
const result = runCli(['--validate', '--', '--dir', makeNotesDir()]);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.match(result.stdout, /1 release note\(s\) valid\./);
|
||||
});
|
||||
|
||||
it('ignores a leading `--` separator', () => {
|
||||
const result = runCli(['--', '--validate', '--dir', makeNotesDir()]);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.match(result.stdout, /1 release note\(s\) valid\./);
|
||||
});
|
||||
|
||||
it('renders the github body with a version passed after `--`', () => {
|
||||
const result = runCli([
|
||||
'--format',
|
||||
'github',
|
||||
'--',
|
||||
'--version',
|
||||
'0.24.0',
|
||||
'--dir',
|
||||
makeNotesDir(),
|
||||
]);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.match(result.stdout, /## Features/);
|
||||
assert.match(result.stdout, /\*\*playback\*\* — An example note\./);
|
||||
});
|
||||
|
||||
it('still rejects a genuinely unknown argument', () => {
|
||||
const result = runCli(['--validate', '--nope']);
|
||||
|
||||
assert.equal(result.status, 1);
|
||||
assert.match(result.stderr, /unknown argument: --nope/);
|
||||
});
|
||||
|
||||
it('still rejects a flag whose value is missing', () => {
|
||||
const result = runCli(['--format']);
|
||||
|
||||
assert.equal(result.status, 1);
|
||||
assert.match(result.stderr, /--format requires a value/);
|
||||
});
|
||||
});
|
||||
@@ -12,14 +12,16 @@
|
||||
"{workspaceRoot}/tools/release/release-notes-render.mjs",
|
||||
"{workspaceRoot}/tools/release/extract-changelog-section.mjs",
|
||||
"{workspaceRoot}/tools/release/check-release-note-gate.mjs",
|
||||
"{workspaceRoot}/tools/release/build-release-notes.mjs",
|
||||
"{workspaceRoot}/tools/release/screenshot-guards.mjs",
|
||||
"{workspaceRoot}/tools/release/screenshots.manifest.json",
|
||||
"{workspaceRoot}/tools/release/release-notes.test.mjs",
|
||||
"{workspaceRoot}/tools/release/release-note-gate.test.mjs",
|
||||
"{workspaceRoot}/tools/release/build-release-notes.test.mjs",
|
||||
"{workspaceRoot}/tools/release/screenshot-guards.test.mjs"
|
||||
],
|
||||
"options": {
|
||||
"command": "node --test tools/release/release-notes.test.mjs tools/release/release-note-gate.test.mjs tools/release/screenshot-guards.test.mjs",
|
||||
"command": "node --test tools/release/release-notes.test.mjs tools/release/release-note-gate.test.mjs tools/release/build-release-notes.test.mjs tools/release/screenshot-guards.test.mjs",
|
||||
"cwd": "{workspaceRoot}"
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user