vpnhide/docs/changelog.md
okhsunrog ad2590a453 refactor(scripts): unreleased section + rename scripts
Rework the changelog and release flow to remove the aspirational
top-level version that made it unclear whether new entries were
landing in an already-released section.

Schema change: `changelog.json` now has an explicit `unreleased`
object instead of hoisting the upcoming version to the top level. The
old `{version, sections, history}` layout becomes
`{unreleased, history}`, with the previously-released version moved
into `history[0]`.

New entries always go into `unreleased` via `changelog.py`. Releasing
is a single atomic operation (`release.py X.Y.Z`) that promotes
`unreleased` into `history[0]` with the target version number,
propagates the version to every source file, and regenerates the
markdown artifacts.

Script renames:
- `_changelog.py` → `changelog_lib.py` (no more underscore-prefixed
  module that's imported by two siblings)
- `changelog-add.py` → `changelog.py`
- `update-version.py` → `release.py` (does more than just version
  propagation — the name now reflects the full release action)

CHANGELOG.md rendering follows Keep a Changelog: a `## [Unreleased]`
block appears on top only when there are unreleased entries; the
update-json/changelog.md shown in Magisk/KSU popups still skips
Unreleased (only released versions make sense there).

Docs (docs/changelog.md, docs/releasing.md, CONTRIBUTING.md, CLAUDE.md)
updated with the new commands and the clarified model.

CLAUDE.md additionally gains a "read these before doing any work"
section that lists the contributor docs — so future sessions load the
workflow rules into context instead of skipping them as optional.
2026-04-17 14:34:47 +03:00

2 KiB

Changelog

Source of truth

lsposed/app/src/main/assets/changelog.json — bilingual (en/ru), full history.

Schema:

{
  "unreleased": {
    "sections": [
      { "type": "fixed", "items": [{"en": "...", "ru": "..."}] }
    ]
  },
  "history": [
    { "version": "0.6.1", "sections": [...] },
    { "version": "0.6.0", "sections": [...] }
  ]
}

unreleased collects entries during development. history[0] is the most recent released version. The top-level structure is flat — there is no aspirational "upcoming version" field; the name is fixed only when release.py is run.

Generated files (do NOT edit by hand)

Two markdown files are regenerated from the JSON by scripts/changelog_lib.py:

  • CHANGELOG.md at repo root — full history, Keep a Changelog format. Renders ## [Unreleased] on top when that section has entries, then each history entry as ## vX.Y.Z. CI extracts a single ## vX.Y.Z block for the GitHub release body, so don't edit release notes by hand either.
  • update-json/changelog.md — last 5 released versions only (no Unreleased block). Shown by Magisk/KSU in the update popup inside the manager app.

Adding an entry

From a PR branch:

./scripts/changelog.py <type> "<EN text>" "<RU text>"

Types: added, changed, fixed, removed, deprecated, security.

The entry lands in unreleased.sections. Both markdown files are regenerated automatically. Commit lsposed/app/src/main/assets/changelog.json, CHANGELOG.md, and update-json/changelog.md alongside your code change.

When to add an entry

Add one for user-visible changes:

  • new features / behaviour changes
  • bug fixes that affect released versions
  • security fixes
  • breaking changes (also bump major/minor as appropriate)

Skip for: internal refactors with no behaviour change, documentation-only changes, CI/build tweaks, test additions.

Cutting a release

See releasing.md. The release script promotes unreleased into history[0] atomically with the version bump — there is no separate "rotate" step.