Add registry-backed module package releases
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
# Package Registry Releases
|
||||
|
||||
GovOPlaN publishes reusable module artifacts through Gitea's native PyPI and
|
||||
npm registries. These packages improve developer installation, release
|
||||
resolution, cacheability, and artifact inspection. They do not replace the
|
||||
signed runtime distribution: the signed manifest and digest-pinned OCI images
|
||||
remain the production deployment authority.
|
||||
|
||||
## Publication boundary
|
||||
|
||||
Every repository with a `pyproject.toml` contains
|
||||
`.gitea/workflows/module-package-release.yml`. The meta repository owns the
|
||||
canonical template and installs it with:
|
||||
|
||||
```bash
|
||||
python tools/repo/sync-module-package-workflows.py --write
|
||||
python tools/repo/sync-module-package-workflows.py --check
|
||||
```
|
||||
|
||||
The workflow runs for `v*` tags and may be dispatched manually for an existing
|
||||
tag. Before building, it verifies that:
|
||||
|
||||
- the selected tag is covered by repository tag protection;
|
||||
- the tagged commit is contained in `main`;
|
||||
- the tag, Python project version, and optional WebUI package version agree;
|
||||
- package names remain in the `govoplan-*` and `@govoplan/*-webui` namespaces.
|
||||
|
||||
It builds one wheel and, where applicable, one npm tarball. The workflow records
|
||||
the source tag, source commit, filename, size, and SHA-256 in
|
||||
`package-artifacts.json` before publishing. Gitea rejects a second upload of the
|
||||
same package version, so correction requires a new version rather than artifact
|
||||
replacement.
|
||||
|
||||
Published WebUI packages contain registry-compatible dependencies only. The
|
||||
workflow converts an internal dependency pinned to a protected `vX.Y.Z` Git tag
|
||||
into the exact `X.Y.Z` registry version and rejects unresolved `file:` or Git
|
||||
dependencies. Repository development metadata may therefore keep local or Git
|
||||
references without leaking them into the published package contract.
|
||||
|
||||
## One-time Gitea setup
|
||||
|
||||
Protect `v*` tags in every package repository and the meta repository. Allow
|
||||
only the `Owners` team to create or delete those tags.
|
||||
|
||||
```bash
|
||||
set -a
|
||||
. ~/.config/gitea/gitea.env
|
||||
set +a
|
||||
python tools/gitea/gitea-configure-package-releases.py --apply
|
||||
```
|
||||
|
||||
Create a dedicated personal access token with only `write:package` scope and
|
||||
store these organization-level Actions secrets on `GovOPlaN`:
|
||||
|
||||
- `GOVOPLAN_PACKAGE_USERNAME`: account owning the package token;
|
||||
- `GOVOPLAN_PACKAGE_TOKEN`: dedicated package-write token.
|
||||
|
||||
Do not use an administrator or general release token. Gitea 1.24 does not grant
|
||||
package publication to the automatic Actions job token. Organization secrets
|
||||
allow the same least-privilege credential to serve every module workflow.
|
||||
|
||||
## Exact release consumption
|
||||
|
||||
`tools/release/generate-release-package-set.py` translates the reviewed Git
|
||||
source refs in `requirements-release.txt` into an exact registry package set.
|
||||
It resolves each version tag to its commit and verifies the package metadata in
|
||||
that tag.
|
||||
|
||||
`tools/release/resolve-package-artifacts.py` then downloads exactly those wheel
|
||||
and WebUI versions from Gitea. It reads the identity embedded in every wheel and
|
||||
npm tarball, rejects missing, duplicate, unexpected, or oversized artifacts,
|
||||
and writes `package-artifacts.lock.json` with SHA-256 values and npm integrity
|
||||
values. Credentials are accepted only through environment variables and are
|
||||
never written to the lock. Python resolution ignores ambient pip configuration
|
||||
and extra indexes for GovOPlaN roots, preventing an internal package name from
|
||||
being selected from an undeclared registry.
|
||||
|
||||
The runtime distribution workflow uses the verified wheelhouse directly and
|
||||
installs module WebUI tarballs only after matching them to the lock. It publishes
|
||||
the package set, package lock, and hash-locked requirements as release assets.
|
||||
The package-lock SHA-256 is part of the signed distribution manifest. Runtime
|
||||
finalization also requires the lock's package versions and hashes to match the
|
||||
wheel composition embedded in the images. OCI assembly remains network-free
|
||||
after package and third-party dependency resolution.
|
||||
|
||||
The source refs remain in the module catalog for source provenance and release
|
||||
planning. Production installation consumes the signed runtime images rather
|
||||
than invoking `pip`, `npm`, or Git on the target host.
|
||||
|
||||
## Developer meta-package
|
||||
|
||||
`packages/govoplan-meta` builds the optional `govoplan` package. Its default
|
||||
dependencies mirror the reviewed runtime roots; `govoplan[full]` adds all
|
||||
currently packageable workspace modules. Regenerate it after changing release
|
||||
requirements or package versions:
|
||||
|
||||
```bash
|
||||
python tools/release/generate-developer-meta-package.py
|
||||
python tools/release/generate-developer-meta-package.py --check
|
||||
```
|
||||
|
||||
`push-release-tag.sh` performs this synchronization before release commits and
|
||||
tags. The meta-package is for editable/developer setup and composition tests. It
|
||||
does not enable modules, apply migrations, provision services, or establish
|
||||
backup and recovery evidence.
|
||||
|
||||
Generic Packages are intentionally not used. Add that transport only when a
|
||||
consumer needs an artifact format unsupported by PyPI, npm, Gitea Releases, or
|
||||
the OCI registry.
|
||||
@@ -76,6 +76,13 @@ one place. If a deployment profile later needs pinned SHAs for every repository,
|
||||
generate that lock as a release artifact instead of making day-to-day
|
||||
development depend on submodule updates.
|
||||
|
||||
Module release tags also publish wheels and WebUI tarballs to the organization
|
||||
PyPI/npm registries. The meta release resolves exact versions into a hash-bound
|
||||
package lock before producing the signed OCI runtime. See
|
||||
`docs/PACKAGE_REGISTRY_RELEASES.md`. Git tags remain source provenance; package
|
||||
registries are reusable artifact transport; the signed runtime manifest and
|
||||
digest-pinned images remain production authority.
|
||||
|
||||
## Docker Placement
|
||||
|
||||
Whole-product Docker and production-like deployment composition belongs in
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"expires_at",
|
||||
"revoked",
|
||||
"deployer",
|
||||
"package_lock",
|
||||
"images",
|
||||
"dependencies",
|
||||
"composition",
|
||||
@@ -27,6 +28,7 @@
|
||||
"expires_at": { "type": "string", "format": "date-time" },
|
||||
"revoked": { "const": false },
|
||||
"deployer": { "$ref": "#/$defs/artifact" },
|
||||
"package_lock": { "$ref": "#/$defs/artifact" },
|
||||
"images": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
Reference in New Issue
Block a user