feat(standards): drop the site CI variant + require changelog reconciliation before release

- Remove the push-triggered build-and-deploy-site pipeline and every "site"
  reference; Type B is now a single tag-triggered service pipeline
  (service-docker.yaml).
- Inventory now covers packages + the auth-server service only (repos.json
  11 -> 9; docs/mcp are no longer part of the standard).
- Versioning standard: reconcile [Unreleased] against the last tag before
  promoting, and always show proposed entries to the user for approval.
- Update registry.py compliance/release text and list_repos types, build.py
  component descriptions, and rebuild the MCP bundle + lib/wiki HTML.
This commit is contained in:
2026-10-17 00:41:52 +05:30
parent e33a6d6704
commit 104bf3eb1e
28 changed files with 234 additions and 353 deletions

View File

@@ -769,7 +769,7 @@ chosen by what the repository produces:</p>
<td><strong>B — Docker deployment</strong></td>
<td><code>templates/drone/service-docker.yaml</code></td>
<td>An image pushed to the registry and run as a container</td>
<td><code>auth-server</code>, <code>docs</code>, <code>mcp</code></td>
<td><code>auth-server</code></td>
</tr>
</tbody>
</table>
@@ -808,30 +808,25 @@ with <code>from_secret</code> — never commit credentials.</p>
</ul>
<hr />
<h2 id="type-b-docker-deployment-service-dockeryaml">Type B — Docker deployment (<code>service-docker.yaml</code>)</h2>
<p>For services and sites that ship a container image. The file contains <strong>two
pipelines</strong>, each mirroring a repo family:</p>
<ol>
<li><strong><code>build-and-deploy-service</code></strong> — triggered on <code>tag</code> (a long-running
API/worker service, e.g. <code>auth-server</code>):</li>
<p>For a service that ships a container image — a long-running API/worker, e.g.
<code>auth-server</code>. The file contains <strong>one pipeline</strong>, <code>build-and-deploy-service</code>,
triggered on <code>tag</code>:</p>
<ul>
<li><code>fetch-tags</code> — resolve the latest tag into <code>LATEST_TAG.txt</code>; fail if there
are no tags.</li>
are no tags.</li>
<li><code>check-version</code> — <strong>guard</strong>: fail unless <code>$DRONE_TAG</code> equals the repo-root
<code>VERSION</code> file (see <a href="../11_versioning_and_changelog/">11 – Versioning &amp; Changelog</a>).</li>
<code>VERSION</code> file (see <a href="../11_versioning_and_changelog/">11 – Versioning &amp; Changelog</a>).</li>
<li><code>check-remote-image</code> — if <code>aetos/&lt;app&gt;:&lt;tag&gt;</code> already exists locally, exit
<code>78</code> and skip the build.</li>
<code>78</code> and skip the build.</li>
<li><code>quality-gate</code> — install from <code>requirements.txt</code> and run
<code>black</code> / <code>ruff</code> / <code>mypy</code> / <code>pytest</code>.</li>
<code>black</code> / <code>ruff</code> / <code>mypy</code> / <code>pytest</code>.</li>
<li><code>build-image</code> — <code>docker build</code> with the private-index build args, tagged
<code>aetos/&lt;app&gt;:&lt;tag&gt;</code> and <code>:latest</code>.</li>
<code>aetos/&lt;app&gt;:&lt;tag&gt;</code> and <code>:latest</code>.</li>
<li><code>push-image</code> — login, re-tag with <code>$REGISTRY_HOST</code>, push both tags.</li>
<li><code>stop-old</code> — <code>docker rm -f &lt;app&gt;</code>.</li>
<li><code>run-container</code> — <code>docker run -d --name &lt;app&gt; -p &lt;host&gt;:&lt;container&gt;
--restart always</code> with the service's <code>-e</code> environment.</li>
<li><strong><code>build-and-deploy-site</code></strong> — triggered on <code>push</code> (a static/HTTP site, e.g.
<code>docs</code>, <code>mcp</code>): <code>build-image</code> → <code>push-image</code> → <code>stop-old</code> → <code>run-container</code>,
with no tag resolution, no quality gate, and no version guard (it ships
<code>:latest</code> only).</li>
</ol>
--restart always</code> with the service's <code>-e</code> environment.</li>
</ul>
<p>Secrets: <code>PIP_REPO_URL</code>, <code>PIP_USERNAME</code>, <code>PIP_PASSWORD</code> (service build args),
<code>REGISTRY_HOST</code>, <code>REGISTRY_USER</code>, <code>REGISTRY_PASS</code>, plus the service runtime env
(for example <code>MONGO_*</code>, <code>JWT_SECRET</code>).</p>
@@ -861,11 +856,6 @@ pipelines</strong>, each mirroring a repo family:</p>
<td><code>9003:8000</code></td>
</tr>
<tr>
<td><code>&lt;site&gt;</code></td>
<td>site image / container name</td>
<td><code>docs</code></td>
</tr>
<tr>
<td><code>&lt;ENV_VAR&gt;</code></td>
<td>runtime environment variable</td>
<td><code>MONGO_HOST</code></td>
@@ -883,8 +873,7 @@ pipelines</strong>, each mirroring a repo family:</p>
version to equal the tag; a service needs a root <code>VERSION</code> file that equals
the tag. See <a href="../11_versioning_and_changelog/">11 – Versioning &amp; Changelog</a>.</li>
<li>Do not rename the pipelines; tooling and runbooks key off
<code>build-and-publish-pypi</code>, <code>build-and-deploy-service</code>, and
<code>build-and-deploy-site</code>.</li>
<code>build-and-publish-pypi</code> and <code>build-and-deploy-service</code>.</li>
</ul>
<hr />
<h2 id="related">Related</h2>

View File

@@ -556,6 +556,21 @@
</span>
</a>
<nav class="md-nav" aria-label="The changelog">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#reconcile-before-releasing" class="md-nav__link">
<span class="md-ellipsis">
Reconcile before releasing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@@ -771,6 +786,21 @@
</span>
</a>
<nav class="md-nav" aria-label="The changelog">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#reconcile-before-releasing" class="md-nav__link">
<span class="md-ellipsis">
Reconcile before releasing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@@ -842,7 +872,7 @@
<h1 id="versioning-changelog">Versioning &amp; Changelog</h1>
<h2 id="summary">Summary</h2>
<p>Every Aetos artifact — library, service, or site — is versioned with
<p>Every Aetos artifact — library or service — is versioned with
<a href="https://semver.org/spec/v2.0.0.html">Semantic Versioning</a> and documents its
releases in a <a href="https://keepachangelog.com/en/1.1.0/">Keep a Changelog</a> file.
The <strong>version file is the source of truth</strong>, the <strong>git tag must equal it</strong>, and
@@ -867,7 +897,7 @@ and tag contract is exactly what those two CI shapes consume.</p>
<td><code>check-version</code> also reads it to skip duplicates</td>
</tr>
<tr>
<td>Service / site (Docker)</td>
<td>Service (Docker)</td>
<td><code>VERSION</code> file at the repo root</td>
<td>one line, <code>x.y.z</code>; the service <strong>reads</strong> it (build-arg) — never hardcode the version</td>
</tr>
@@ -934,16 +964,35 @@ one open <code>[Unreleased]</code> section with the change categories that apply
<li>Categories: <strong>Added</strong>, <strong>Changed</strong>, <strong>Deprecated</strong>, <strong>Removed</strong>, <strong>Fixed</strong>,
<strong>Security</strong>. Omit empty categories.</li>
<li>Security fixes get their own entry even if the change is otherwise a bug fix.</li>
<li>Keep <code>[Unreleased]</code> current: add an entry in the same change that introduces
the behaviour, not later.</li>
<li>The <code>[Unreleased]</code> heading is never renamed; copy its content into the new
version heading and clear it.</li>
</ul>
<h3 id="reconcile-before-releasing">Reconcile before releasing</h3>
<p><code>[Unreleased]</code> is a <strong>draft, not the source of truth</strong>. It is only trustworthy
when it was maintained alongside each change; a long-running branch or a change
that skipped the changelog leaves it stale, so it can silently under-report a
release. Verify it against the change before you promote:</p>
<ol>
<li>List what actually changed since the last release:
<code>git log &lt;last-tag&gt;..HEAD</code> and <code>git diff --stat &lt;last-tag&gt;..HEAD</code>.</li>
<li>Compare that against <code>[Unreleased]</code>; add an entry for every user-facing change
that is missing.</li>
<li><strong>Always show the proposed additions to the user and wait for approval</strong>
before promoting. If an entry is ambiguous, ask rather than guess.</li>
</ol>
<p>Only then promote. Never cut a release with a known gap between the diff and the
changelog.</p>
<hr />
<h2 id="tagging-strategy-mr-based">Tagging strategy (MR-based)</h2>
<p>The release version is known while the change is still a merge request, so the
bump travels with the change and only the tag is added afterwards:</p>
<ol>
<li><strong>In the MR</strong> — set the intended release version: <code>version</code> in
<code>pyproject.toml</code> (or the <code>VERSION</code> file) to <code>x.y.z</code>, and promote the
<li><strong>In the MR</strong> — reconcile <code>[Unreleased]</code> against the change (see
<a href="#reconcile-before-releasing">Reconcile before releasing</a>) and get the user's
approval for any additions. Then set the intended release version: <code>version</code>
in <code>pyproject.toml</code> (or the <code>VERSION</code> file) to <code>x.y.z</code>, and promote the
changelog (below). Changelog entries and link references name the
<strong>version/tag</strong>, never a commit id.</li>
<li><strong>Merge or squash</strong> the MR into <code>main</code>.</li>
@@ -970,8 +1019,11 @@ After the user confirms the MR is merged/squashed and says to proceed:</p>
<h2 id="release-checklist">Release checklist</h2>
<ol>
<li>Confirm the quality gate is green and <code>main</code> is up to date.</li>
<li>In the MR: move every <code>[Unreleased]</code> entry under the new version heading with
the target date (<code>## [x.y.z] - YYYY-MM-DD</code>); restore an empty <code>[Unreleased]</code>
<li>In the MR: reconcile <code>[Unreleased]</code> against the change being released —
<code>git log &lt;last-tag&gt;..HEAD</code> and <code>git diff --stat &lt;last-tag&gt;..HEAD</code> — add any
missing user-facing entries, and get the user's approval for the additions.
Then move every <code>[Unreleased]</code> entry under the new version heading with the
target date (<code>## [x.y.z] - YYYY-MM-DD</code>) and restore an empty <code>[Unreleased]</code>
on top.</li>
<li>In the MR: add the two compare-link references at the bottom of the
changelog, naming the version/tag (never a commit id).</li>

View File

@@ -557,9 +557,9 @@
</li>
<li class="md-nav__item">
<a href="#services-sites-type-b" class="md-nav__link">
<a href="#services-type-b" class="md-nav__link">
<span class="md-ellipsis">
Services &amp; sites (Type B)
Services (Type B)
</span>
</a>
@@ -711,9 +711,9 @@
</li>
<li class="md-nav__item">
<a href="#services-sites-type-b" class="md-nav__link">
<a href="#services-type-b" class="md-nav__link">
<span class="md-ellipsis">
Services &amp; sites (Type B)
Services (Type B)
</span>
</a>
@@ -837,14 +837,13 @@ Paths are relative to the <code>aetos/</code> workspace root.</p>
</tbody>
</table>
<hr />
<h2 id="services-sites-type-b">Services &amp; sites (Type B)</h2>
<h2 id="services-type-b">Services (Type B)</h2>
<p>A container image pushed to the registry and run on the Docker host. Version
source is the <code>VERSION</code> file; Drone file is <code>service-docker.yaml</code>.</p>
<table>
<thead>
<tr>
<th>Repo</th>
<th>Type</th>
<th>Path</th>
<th>Trigger</th>
<th>Docs</th>
@@ -853,29 +852,13 @@ source is the <code>VERSION</code> file; Drone file is <code>service-docker.yaml
<tbody>
<tr>
<td><code>auth-server</code></td>
<td>service</td>
<td><code>auth-server</code></td>
<td>tag</td>
<td>api, lib, wiki</td>
</tr>
<tr>
<td><code>docs</code></td>
<td>site</td>
<td><code>docs</code></td>
<td>push</td>
<td>—</td>
</tr>
<tr>
<td><code>mcp</code></td>
<td>site</td>
<td><code>mcp</code></td>
<td>push</td>
<td>—</td>
</tr>
</tbody>
</table>
<p>The <strong>service</strong> variant is tag-triggered and enforces <code>tag == VERSION</code>. The
<strong>site</strong> variant is push-triggered, ships <code>:latest</code>, and has no tag guard.</p>
<p>Tag-triggered and enforces <code>tag == VERSION</code>.</p>
<hr />
<h2 id="required-files-per-repo">Required files per repo</h2>
<table>
@@ -895,7 +878,7 @@ source is the <code>VERSION</code> file; Drone file is <code>service-docker.yaml
<td><code>python-lib.yaml</code></td>
</tr>
<tr>
<td>service / site</td>
<td>service</td>
<td><code>VERSION</code></td>
<td><code>CHANGELOG.md</code></td>
<td><code>service-docker.yaml</code></td>

File diff suppressed because one or more lines are too long

Binary file not shown.