284 lines
13 KiB
Markdown
284 lines
13 KiB
Markdown
# GovOPlaN Release Console
|
|
|
|
The release console is a local operator tool for planning and executing
|
|
GovOPlaN releases. It belongs to the `govoplan` meta repository because it works
|
|
across all local checkouts, release scripts, module manifests, migration audits,
|
|
catalog files, Git state, and signing keys.
|
|
|
|
The current implementation has a read-only dashboard plus guarded local
|
|
candidate/publish actions:
|
|
|
|
- inspect repositories from `repositories.json`
|
|
- show dirty, ahead, behind, missing, no-HEAD, and tag state
|
|
- show local package catalog and keyring state
|
|
- optionally run release/dev migration audits
|
|
- propose next actions without executing them
|
|
- compare local catalog/keyring JSON with the published channel and public
|
|
keyring when online checks are enabled
|
|
- configure target versions per release unit in the web UI
|
|
- select the repositories that should advance through checkboxes
|
|
- generate dry-run selective release plans for independently versioned packages
|
|
- create annotated source release tags for selected clean, version-aligned
|
|
repositories and publish each branch/tag pair atomically
|
|
- generate signed catalog candidates for the selected release units
|
|
- preview/apply/push reviewed catalog candidates behind explicit confirmations
|
|
|
|
Start it from the meta repository:
|
|
|
|
```sh
|
|
./.venv/bin/python tools/release/release-console.py
|
|
```
|
|
|
|
The server binds to `127.0.0.1` by default and prints a URL containing a local
|
|
API token. Open that URL in a browser on the same machine.
|
|
|
|
The web UI starts with a repository table. Each repository can be checked
|
|
independently and assigned its own target version. Repositories without version
|
|
metadata remain visible so they can be planned as initial releases. `Build Plan`
|
|
shows the dry-run commands for the selected rows, and `Generate Candidate`
|
|
creates a signed catalog candidate that advances only selected repositories that
|
|
already have a catalog entry.
|
|
|
|
`Build Plan` also returns structured release-gate findings for each selected
|
|
repository. The plan names the recommended next action and gives an explicit
|
|
remediation for source-version, lockfile, Core WebUI composition, Git state, and
|
|
worktree findings. A target version that has not yet been applied consistently
|
|
to the selected source tree is therefore explained before the source-tag
|
|
preflight rather than appearing only as an error after the operator tries to
|
|
tag. `source_preflight_ready` means that the plan-visible source gates pass; the
|
|
non-mutating `Preview Tag + Publish` remains mandatory for remote, manifest, and
|
|
immutable-tag checks.
|
|
|
|
Dashboard collection is also fail closed. Unreadable Core version metadata or a
|
|
malformed module contract is returned as a bounded `collection_errors` entry
|
|
with a remediation, marks the dashboard blocked, and becomes a structured
|
|
blocker in both full and selective release plans. The console does not silently
|
|
omit a contract or turn these source errors into an HTTP 500.
|
|
|
|
The release-control area above the repository table is read-only and is meant
|
|
to become the central release cockpit. It shows:
|
|
|
|
- local and published channel health
|
|
- catalog/keyring drift
|
|
- signature and trusted-key status
|
|
- published module versions and refs
|
|
- local checkout version drift against the catalog
|
|
- catalog-declared interface compatibility
|
|
|
|
The target-version control can generate the next major, minor, or subversion
|
|
from the current base version. Manual target input accepts explicit versions
|
|
such as `0.2.0` or `0.2.0-alpha1`, but requires the first three version numbers
|
|
to move forward.
|
|
|
|
Plain repository pushes are separate from catalog publication. `Preview Push`
|
|
shows the selected repository push commands. `Push Selected` requires `PUSH` in
|
|
the repository push confirmation field.
|
|
|
|
The source release panel closes the former gap between a release plan and a
|
|
catalog candidate. `Preview Tag + Publish` is non-mutating. `Create Tags`
|
|
requires `TAG`; `Publish Tags` requires `PUBLISH` and atomically pushes the
|
|
selected branch and annotated tag. The gate requires an aligned target version,
|
|
a clean named branch with a HEAD, and a checkout that is not behind. Existing
|
|
local or remote tags must resolve to the selected HEAD and are never moved.
|
|
The local and remote annotated tag objects must also be identical, not merely
|
|
point at the same commit. Before any source tag is created, the console loads
|
|
the cross-repository module registry. This release gate also rejects every
|
|
user-facing workflow documentation topic that has no scope condition, or has
|
|
an alternative condition without `required_scopes` or `any_scopes`.
|
|
|
|
The catalog workflow panel can also operate on the same selected rows:
|
|
|
|
- `Generate` creates a signed candidate below `runtime/release-candidates/`.
|
|
- `Preview` validates a candidate and shows what would be copied into the
|
|
website repository.
|
|
- `Apply + Website Tag` requires `APPLY` in the confirmation field.
|
|
- `Push Website Release` requires `PUSH` in the confirmation field.
|
|
|
|
Source release tags belong to Core or module repositories. Website catalog
|
|
publication creates a separate catalog tag in the website repository; the UI
|
|
names these independently to avoid confusing the two immutable references.
|
|
|
|
Candidate signing is fail-closed: every Core and module source ref in the
|
|
complete post-update catalog must already have the requested annotated tag both
|
|
locally and on the configured source remote. Both tags must be the same
|
|
annotation object with version-aligned tagged package metadata. Selected tags
|
|
must additionally resolve to the selected clean, version-aligned HEAD, and the
|
|
signed `selected_units` record captures the peeled commit and tag-object
|
|
identifiers. Create and publish the source tags before using `Generate`.
|
|
|
|
Catalog publication repeats that check for selected units and also verifies
|
|
every Core and module source ref in the complete candidate, including entries
|
|
preserved from the previous catalog. Historical refs need not be at the current
|
|
worktree HEAD, but their local and remote annotated tags must match and their
|
|
tagged installable package and module-manifest metadata must declare the catalog
|
|
version. New selected releases additionally pass the stricter current-source
|
|
alignment gate, including public runtime version declarations. A candidate
|
|
cannot be applied or published while any referenced source tag is absent or
|
|
inconsistent; the preview and API response list each repository and missing or
|
|
invalid ref so the operator can repair the exact source releases first.
|
|
|
|
Read-only provenance checks derive a same-host HTTPS Git URL from conventional
|
|
SSH remotes when possible, with a non-interactive check of the configured remote
|
|
as fallback. Source tag creation and atomic publication always use the explicit
|
|
configured Git remote.
|
|
|
|
The default signing key is
|
|
`$HOME/.config/govoplan/release-keys/release-key-1.pem` when no signing key is
|
|
entered in the UI.
|
|
|
|
Generate a selective release plan from the terminal:
|
|
|
|
```sh
|
|
./.venv/bin/python tools/release/release-plan.py \
|
|
--repo govoplan-files \
|
|
--target-version 0.1.9 \
|
|
--channel stable \
|
|
--online
|
|
```
|
|
|
|
`--online` compares the local catalog/keyring with the published channel and
|
|
published keyring. Use `--remote-tags` only when the plan also needs to check
|
|
Git remotes for tag existence; that can be slower across the full repository
|
|
set.
|
|
|
|
Build a signed selective catalog candidate:
|
|
|
|
```sh
|
|
KEY_DIR="$HOME/.config/govoplan/release-keys"
|
|
|
|
./.venv/bin/python tools/release/release-catalog.py selective \
|
|
--repo-version govoplan-files=0.1.9 \
|
|
--channel stable \
|
|
--catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem"
|
|
```
|
|
|
|
This writes candidate catalog/keyring files below `runtime/release-candidates/`,
|
|
generates the browsable module directory below `modules/`, validates the signed
|
|
candidate with the module installer validator, and reports whether the candidate
|
|
catalog/keyring match the currently published channel. It does not publish to
|
|
the website repository.
|
|
|
|
Regenerate the browsable module directory from an existing catalog/keyring:
|
|
|
|
```sh
|
|
./.venv/bin/python tools/release/release-catalog.py module-directory \
|
|
--catalog ../addideas-govoplan-website/public/catalogs/v1/channels/stable.json \
|
|
--keyring ../addideas-govoplan-website/public/catalogs/v1/keyring.json \
|
|
--output-dir runtime/module-directory-preview \
|
|
--channel stable
|
|
```
|
|
|
|
Preview publication of a reviewed candidate:
|
|
|
|
```sh
|
|
./.venv/bin/python tools/release/release-catalog.py publish-candidate \
|
|
--candidate-dir runtime/release-candidates/stable-YYYYMMDD-HHMMSS \
|
|
--channel stable
|
|
```
|
|
|
|
Apply the reviewed candidate into the website repository without pushing:
|
|
|
|
```sh
|
|
./.venv/bin/python tools/release/release-catalog.py publish-candidate \
|
|
--candidate-dir runtime/release-candidates/stable-YYYYMMDD-HHMMSS \
|
|
--channel stable \
|
|
--apply \
|
|
--commit \
|
|
--tag
|
|
```
|
|
|
|
Push is a separate explicit flag:
|
|
|
|
```sh
|
|
./.venv/bin/python tools/release/release-catalog.py publish-candidate \
|
|
--candidate-dir runtime/release-candidates/stable-YYYYMMDD-HHMMSS \
|
|
--channel stable \
|
|
--apply \
|
|
--commit \
|
|
--tag \
|
|
--push
|
|
```
|
|
|
|
Published channels are expected below the public catalog base URL:
|
|
|
|
- `https://govoplan.add-ideas.de/catalogs/v1/channels/stable.json`
|
|
- `https://govoplan.add-ideas.de/catalogs/v1/keyring.json`
|
|
|
|
The console treats channels as release artifacts. A package can advance without
|
|
forcing every repository to the same tag, but channel publication must preserve
|
|
the unchanged package versions, validate interface compatibility, sign the
|
|
updated catalog, and keep the published keyring healthy.
|
|
|
|
When a selected module exposes a WebUI package, its requested version must also
|
|
match Core's `webui/package.release.json` input and the resolved
|
|
`package-lock.release.json` entry. The source-tag preflight, selective plan, and
|
|
catalog-candidate writer all enforce this composition boundary. Pins for modules
|
|
that are not part of the selective release remain unchanged.
|
|
|
|
Release integration also enforces repository and composition version alignment
|
|
and generates a CycloneDX SBOM from the resolved Python environment and the
|
|
release WebUI lockfile. Catalog publication should attach that immutable SBOM
|
|
and its digest to the corresponding Core/composition release.
|
|
|
|
Addresses and Notifications have current WebUI source contributions but are
|
|
not part of the pinned v0.1.8 WebUI release composition because their v0.1.8
|
|
tags predate those packages. They re-enter the release composition only through
|
|
new, immutable module tags whose backend, manifest, frontend, and lock metadata
|
|
pass the alignment gate.
|
|
|
|
Candidate publication verifies signatures against the already published
|
|
keyring, not against keys supplied only by the candidate. A changed keyring
|
|
must have its canonical SHA-256 embedded in the signed catalog. The public
|
|
module-directory files are regenerated from that verified catalog and keyring
|
|
at publication time; candidate-supplied directory files are never copied as
|
|
authoritative provenance.
|
|
|
|
## Published Module Directory
|
|
|
|
The target release repository is an online, browsable module directory. The
|
|
catalog remains the machine-readable channel entry point, but the published
|
|
space should also expose a tree that operators and installations can inspect:
|
|
|
|
- `/catalogs/v1/channels/<channel>.json` describes the active channel state.
|
|
- `/catalogs/v1/keyring.json` publishes trusted release signing keys.
|
|
- `/catalogs/v1/modules/<module>/<version>/manifest.json` describes one
|
|
published module version, including repository refs, package refs, contracts,
|
|
compatibility windows, signatures, and available artifacts.
|
|
- `/catalogs/v1/modules/<module>/index.json` lists available versions for
|
|
one module.
|
|
- `/catalogs/v1/modules/index.json` lists all published modules.
|
|
|
|
Gitea tags/releases remain the source release anchors. The public GovOPlaN
|
|
catalog directory becomes the installation-facing release repository that points
|
|
to those anchors and carries structured compatibility information.
|
|
|
|
Selective catalog candidates now include this directory tree. Publishing a
|
|
candidate copies the channel catalog, keyring, and `modules/` tree into the
|
|
website repository together.
|
|
|
|
Selective catalog generation can add a module that is not yet represented in
|
|
the source channel. Initial entries are synthesized from the selected
|
|
repository's `[project]` metadata, `govoplan.modules` entry point, and runtime
|
|
`ModuleManifest`; there is no separate hand-maintained initial-entry list. The
|
|
release gate requires the entry point to resolve inside the selected checkout,
|
|
exact package/manifest/frontend version agreement, verified source-tag
|
|
provenance, a non-conflicting module id, and complete required dependency and
|
|
interface closure in the resulting candidate. Classification beyond the
|
|
manifest-derived `official` tag remains an explicit later catalog curation
|
|
step rather than an inferred business/service label.
|
|
|
|
## Direction
|
|
|
|
The console should grow in slices:
|
|
|
|
1. Read-only dashboard and next-action suggestions.
|
|
2. Release plan builder that writes explicit JSON plans.
|
|
3. Dry-run executor that shows exact commands and expected file changes.
|
|
4. Apply executor for commit, tag, push, artifact build, signing, and catalog
|
|
publication.
|
|
5. Compatibility planner for manifest contracts and version ranges.
|
|
6. Install/test workflow that validates a release from tags or catalog entries.
|
|
|
|
All mutation must stay explicit: plan first, dry run second, apply only after a
|
|
clear confirmation.
|