Compare commits

..
4 Commits
Author SHA1 Message Date
Kevin Veen-Birkenbach f6228988e1 Release version 1.15.2
CI / security-codeql (push) Has been cancelled
CI / test-unit (push) Has been cancelled
CI / test-integration (push) Has been cancelled
CI / test-env-virtual (push) Has been cancelled
CI / test-env-nix (push) Has been cancelled
CI / test-e2e (push) Has been cancelled
CI / test-virgin-user (push) Has been cancelled
CI / test-virgin-root (push) Has been cancelled
CI / lint-shell (push) Has been cancelled
CI / lint-python (push) Has been cancelled
CI / lint-docker (push) Has been cancelled
Mark stable commit / mark-stable (push) Canceled after 0s
2026-05-28 11:06:43 +02:00
Kevin Veen-Birkenbach 5c7171acd9 fix(config): add alias: infinito for infinito-nexus/core
`pkgmgr install infinito` (and `pkgmgr path infinito`, `pkgmgr version
infinito`, etc.) failed with:

    Identifier 'infinito' did not match any repository in config.

The infinito-nexus/core entry in defaults.yaml had no alias, so the
resolver could only match it via the full id `github.com/infinito-nexus/core`
or the bare repository name `core`. Downstream consumers (the
infinito-nexus-core Dockerfile, roles/sys-cli, roles/web-app-navigator,
and the test-install-pkgmgr CI job) all invoke the short identifier
`infinito` and broke once kpmx 1.15.x was rolled out via the floating
`pkgmgr-<distro>:stable` images.

Registering `alias: infinito` on the entry restores the short identifier
without renaming the repository or touching the consumer side.
2026-05-28 11:05:47 +02:00
Kevin Veen-Birkenbach 06cc5b6725 Release version 1.15.1
Mark stable commit / mark-stable (push) Canceled after 0s
2026-05-28 08:18:23 +02:00
Kevin Veen-BirkenbachandClaude Opus 4.7 ece575cc73 fix(release/changelog): insert new entry under H1 instead of above it
update_changelog used to blindly prepend the new ## [version] entry to
the entire file body. When CHANGELOG.md leads with a # Changelog H1
the result was:

  ## [new] - YYYY-MM-DD
  ...
  # Changelog
  ## [old] - ...

which trips markdownlint MD041 (first-line-h1) and MD012
(no-multiple-blanks), and reads as if the document were two stacked
changelogs.

The new _insert_after_h1 helper:

* Synthesises # Changelog when the file is empty.
* Inserts the entry between the existing H1 (plus any intro prose)
  and the first existing ## release entry.
* For legacy headerless files (file starts with ##) prepends the
  synthesised H1 + entry, so the resulting document is also
  MD041-clean.

Tests cover the three layouts (empty, H1+existing-entries,
legacy-headerless). All 61 release-unit tests stay green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 08:17:35 +02:00
9 changed files with 111 additions and 16 deletions

No files matched your search

+10
View File
@@ -1,3 +1,13 @@
# Changelog
## [1.15.2] - 2026-05-28
* Restore `infinito` as an alias for the infinito-nexus/core repository so `pkgmgr install infinito` (and friends) resolves again.
## [1.15.1] - 2026-05-28
* Insert pkgmgr release changelog entry under the H1 instead of above it. Fixes the markdownlint MD041 (first-line-h1) and MD012 (no-multiple-blanks) regressions that previously trashed every CHANGELOG.md after a release.
## [1.15.0] - 2026-05-28
* Add pkgmgr archive subcommand: promote fully-checked NNN-topic.md spec files into the directorys README Archive section and delete the source files. Lookup pattern, README path, and template handling are configurable. Extracted from infinito-nexus-core so every kpmx-managed repo gets the same archival flow.
+1 -1
View File
@@ -32,7 +32,7 @@
rec {
pkgmgr = pyPkgs.buildPythonApplication {
pname = "package-manager";
version = "1.15.0";
version = "1.15.2";
# Use the git repo as source
src = ./.;
+1 -1
View File
@@ -1,7 +1,7 @@
# Maintainer: Kevin Veen-Birkenbach <info@veen.world>
pkgname=package-manager
pkgver=1.15.0
pkgver=1.15.2
pkgrel=1
pkgdesc="Local-flake wrapper for Kevin's package-manager (Nix-based)."
arch=('any')
+12
View File
@@ -1,3 +1,15 @@
package-manager (1.15.2-1) unstable; urgency=medium
* Restore `infinito` as an alias for the infinito-nexus/core repository so `pkgmgr install infinito` (and friends) resolves again.
-- Kevin Veen-Birkenbach <kevin@veen.world> Thu, 28 May 2026 11:06:43 +0200
package-manager (1.15.1-1) unstable; urgency=medium
* Insert pkgmgr release changelog entry under the H1 instead of above it. Fixes the markdownlint MD041 (first-line-h1) and MD012 (no-multiple-blanks) regressions that previously trashed every CHANGELOG.md after a release.
-- Kevin Veen-Birkenbach <kevin@veen.world> Thu, 28 May 2026 08:18:23 +0200
package-manager (1.15.0-1) unstable; urgency=medium
* Add pkgmgr archive subcommand: promote fully-checked NNN-topic.md spec files into the directorys README Archive section and delete the source files. Lookup pattern, README path, and template handling are configurable. Extracted from infinito-nexus-core so every kpmx-managed repo gets the same archival flow.
+7 -1
View File
@@ -1,5 +1,5 @@
Name: package-manager
Version: 1.15.0
Version: 1.15.2
Release: 1%{?dist}
Summary: Wrapper that runs Kevin's package-manager via Nix flake
@@ -74,6 +74,12 @@ echo ">>> package-manager removed. Nix itself was not removed."
/usr/lib/package-manager/
%changelog
* Thu May 28 2026 Kevin Veen-Birkenbach <kevin@veen.world> - 1.15.2-1
- Restore `infinito` as an alias for the infinito-nexus/core repository so `pkgmgr install infinito` (and friends) resolves again.
* Thu May 28 2026 Kevin Veen-Birkenbach <kevin@veen.world> - 1.15.1-1
- Insert pkgmgr release changelog entry under the H1 instead of above it. Fixes the markdownlint MD041 (first-line-h1) and MD012 (no-multiple-blanks) regressions that previously trashed every CHANGELOG.md after a release.
* Thu May 28 2026 Kevin Veen-Birkenbach <kevin@veen.world> - 1.15.0-1
- Add pkgmgr archive subcommand: promote fully-checked NNN-topic.md spec files into the directorys README Archive section and delete the source files. Lookup pattern, README path, and template handling are configurable. Extracted from infinito-nexus-core so every kpmx-managed repo gets the same archival flow.
+1 -1
View File
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "kpmx"
version = "1.15.0"
version = "1.15.2"
description = "Kevin's package-manager tool (pkgmgr)"
readme = "README.md"
requires-python = ">=3.9"
@@ -1,11 +1,50 @@
from __future__ import annotations
import os
import re
from datetime import date
from typing import Optional
from .editor import _open_editor_for_changelog
H1_RE = re.compile(r"^#\s+\S", re.MULTILINE)
H2_RE = re.compile(r"^##\s+\S", re.MULTILINE)
def _insert_after_h1(existing: str, entry: str) -> str:
"""Place *entry* after the H1 (and any intro prose), above the first H2.
If the file has no H1 we synthesise ``# Changelog`` so the resulting
document is markdown-lint-clean (MD041 first-line-h1).
If the file has no H2 yet we append *entry* after the H1 block.
Existing behaviour for legacy headerless files (file starts with
``## ``) is preserved: *entry* is prepended unchanged.
"""
if not existing.strip():
return f"# Changelog\n\n{entry}"
if not H1_RE.search(existing):
# Legacy layout: file starts with `## [version]` and has no H1.
# Synthesise the H1 so the merged file is lint-clean.
return f"# Changelog\n\n{entry}{existing.lstrip()}"
# File has an H1. Find the first H2 (existing release section).
h2_match = H2_RE.search(existing)
if h2_match is None:
# H1 + optional intro but no release entries yet — append entry
# after a single blank line.
suffix = (
""
if existing.endswith("\n\n")
else ("\n" if existing.endswith("\n") else "\n\n")
)
return f"{existing}{suffix}{entry}"
# Insert new entry just before the first H2.
head = existing[: h2_match.start()].rstrip("\n") + "\n\n"
tail = existing[h2_match.start() :]
return f"{head}{entry}{tail}"
def update_changelog(
changelog_path: str,
@@ -13,9 +52,11 @@ def update_changelog(
message: Optional[str] = None,
preview: bool = False,
) -> str:
"""
Prepend a new release section to CHANGELOG.md with the new version,
current date, and a message.
"""Insert a new release entry into CHANGELOG.md.
The entry is placed after the documents H1 heading (creating one if
missing) and above any existing release entries, so the result stays
markdown-lint-clean (MD041 first-line-h1, MD012 no-multiple-blanks).
"""
today = date.today().isoformat()
@@ -32,8 +73,7 @@ def update_changelog(
else:
message = editor_message
header = f"## [{new_version}] - {today}\n"
header += f"\n* {message}\n\n"
entry = f"## [{new_version}] - {today}\n\n* {message}\n\n"
if os.path.exists(changelog_path):
try:
@@ -45,14 +85,14 @@ def update_changelog(
else:
changelog = ""
new_changelog = header + "\n" + changelog if changelog else header
new_changelog = _insert_after_h1(changelog, entry)
print("\n================ CHANGELOG ENTRY ================")
print(header.rstrip())
print(entry.rstrip())
print("=================================================\n")
if preview:
print(f"[PREVIEW] Would prepend new entry for {new_version} to CHANGELOG.md")
print(f"[PREVIEW] Would insert new entry for {new_version} into CHANGELOG.md")
return message
with open(changelog_path, "w", encoding="utf-8") as f:
+1
View File
@@ -265,6 +265,7 @@ repositories:
- 44D8F11FD62F878E
- B5690EEEBB952194
- account: infinito-nexus
alias: infinito
provider: github.com
description: Infinito.nexus streamlines Linux-based system setups and Docker image administration, perfect for servers and PCs. It offers extensive solutions for system initialization, admin tools, backups, monitoring, updates, driver management, security, and VPNs.
homepage: https://infinito.nexus
@@ -256,7 +256,7 @@ class TestUpdateSpecVersion(unittest.TestCase):
class TestUpdateChangelog(unittest.TestCase):
def test_update_changelog_creates_file_if_missing(self) -> None:
def test_update_changelog_creates_file_with_h1_if_missing(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, "CHANGELOG.md")
self.assertFalse(os.path.exists(path))
@@ -267,10 +267,35 @@ class TestUpdateChangelog(unittest.TestCase):
with open(path, "r", encoding="utf-8") as f:
content = f.read()
self.assertIn("## [1.2.3]", content)
# New file must lead with an H1 so markdownlint MD041 is happy.
self.assertTrue(content.startswith("# Changelog\n\n## [1.2.3]"))
self.assertIn("First release", content)
def test_update_changelog_prepends_entry_to_existing_content(self) -> None:
def test_update_changelog_inserts_below_existing_h1(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, "CHANGELOG.md")
existing = "# Changelog\n\n## [0.1.0] - 2024-01-01\n\n* Initial content\n"
with open(path, "w", encoding="utf-8") as f:
f.write(existing)
update_changelog(path, "1.0.0", message="Second release", preview=False)
with open(path, "r", encoding="utf-8") as f:
content = f.read()
# H1 still on top, new entry above the existing one.
self.assertTrue(content.startswith("# Changelog\n\n## [1.0.0]"))
# Exactly one H1.
self.assertEqual(
content.count("\n# Changelog\n") + content.startswith("# Changelog\n"), 1
)
# Old entry still present, after the new one.
self.assertLess(
content.index("## [1.0.0]"),
content.index("## [0.1.0]"),
)
def test_update_changelog_legacy_headerless_gets_h1_synthesized(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, "CHANGELOG.md")
with open(path, "w", encoding="utf-8") as f:
@@ -281,7 +306,8 @@ class TestUpdateChangelog(unittest.TestCase):
with open(path, "r", encoding="utf-8") as f:
content = f.read()
self.assertTrue(content.startswith("## [1.0.0]"))
# An H1 is added so MD041 is satisfied even for legacy files.
self.assertTrue(content.startswith("# Changelog\n\n## [1.0.0]"))
self.assertIn("## [0.1.0] - 2024-01-01", content)
def test_update_changelog_preview_does_not_write(self) -> None: