Compare commits
4 Commits
a754366901
...
e33a6d6704
| Author | SHA1 | Date | |
|---|---|---|---|
| e33a6d6704 | |||
| 5971f26c08 | |||
| df03f41771 | |||
| 8cc9631fe7 |
141
build.py
141
build.py
@@ -99,13 +99,26 @@ def _read_title(path: Path) -> str:
|
||||
return _module_name(path.stem).replace("_", " ").title()
|
||||
|
||||
|
||||
def _wiki_module_name(rel: Path) -> str:
|
||||
"""Map a wiki page path to a namespaced module name.
|
||||
|
||||
``04_development/02_releasing.md`` -> ``wiki_development_releasing``; the
|
||||
``wiki_`` prefix keeps wiki pages from colliding with lib modules (both have
|
||||
an ``index``).
|
||||
"""
|
||||
parts = [NUM_PREFIX.sub("", part) or part for part in rel.with_suffix("").parts]
|
||||
return "wiki_" + "_".join(parts)
|
||||
|
||||
|
||||
def build_bundle(folder: Path, dry_run: bool = False) -> None:
|
||||
"""Regenerate ``<name>/mcp`` from ``folder/src/lib`` markdown.
|
||||
"""Regenerate ``<name>/mcp`` from ``folder/src/lib`` and ``folder/src/wiki``.
|
||||
|
||||
The bundle mirrors the lib site (in the same way doc-forge's MCP output
|
||||
mirrors its lib documentation). Writes ``index.json``, ``nav.json`` and
|
||||
``modules/*.json`` in the doc-forge MCP bundle shape. Hand-authored extras
|
||||
(e.g. ``libraries.json``) are left untouched.
|
||||
(e.g. ``libraries.json``) are left untouched. Wiki pages (``src/wiki/**``)
|
||||
are also bundled, under a ``wiki_`` namespaced module name, so the runbooks
|
||||
are reachable from the MCP.
|
||||
|
||||
Args:
|
||||
folder (Path): The hub folder owning a ``src/lib``.
|
||||
@@ -149,6 +162,17 @@ def build_bundle(folder: Path, dry_run: bool = False) -> None:
|
||||
"title": _read_title(path),
|
||||
})
|
||||
|
||||
wiki = folder / "src" / "wiki"
|
||||
if wiki.is_dir():
|
||||
for path in sorted(wiki.rglob("*.md")):
|
||||
module = _wiki_module_name(path.relative_to(wiki))
|
||||
write_module(module, path.read_text(encoding="utf-8"))
|
||||
nav.append({
|
||||
"module": module,
|
||||
"resource": f"docs://modules/{module}",
|
||||
"title": _read_title(path),
|
||||
})
|
||||
|
||||
(out_dir / "nav.json").write_text(
|
||||
json.dumps(nav, indent=2, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
@@ -239,6 +263,8 @@ _TEMPLATE_COMPONENTS: list[dict[str, str]] = [
|
||||
"description": "OpenAPI contract skeleton."},
|
||||
{"kind": "pyproject", "path": "pyproject.toml", "placeholder": "",
|
||||
"description": "Packaging + dependency pins."},
|
||||
{"kind": "changelog", "path": "CHANGELOG.md", "placeholder": "",
|
||||
"description": "Keep a Changelog file with an [Unreleased] section (versioning standard)."},
|
||||
{"kind": "dockerfile", "path": "Dockerfile", "placeholder": "",
|
||||
"description": "API + worker image with private-index wiring."},
|
||||
{"kind": "dockerignore", "path": ".dockerignore", "placeholder": "",
|
||||
@@ -412,6 +438,115 @@ def build_drone_templates(folder: Path, dry_run: bool = False) -> None:
|
||||
f"({len(manifest['components'])} components)")
|
||||
|
||||
|
||||
# ── Release standard bundle ───────────────────────────────────────────────────
|
||||
|
||||
# The release artefacts shipped in ``src/templates/release``. One canonical
|
||||
# changelog (Keep a Changelog + SemVer) and the service version file. See
|
||||
# standards "11_versioning_and_changelog".
|
||||
_RELEASE_COMPONENTS: list[dict[str, str]] = [
|
||||
{"kind": "changelog", "path": "CHANGELOG.md", "placeholder": "",
|
||||
"description": "Keep a Changelog skeleton: one [Unreleased] section + compare links."},
|
||||
{"kind": "version-file", "path": "VERSION", "placeholder": "",
|
||||
"description": "Single-line SemVer source of truth for services and sites."},
|
||||
]
|
||||
|
||||
|
||||
def build_release_manifest(template_root: Path) -> dict[str, object]:
|
||||
"""Describe every artefact in the vendored release standard.
|
||||
|
||||
Args:
|
||||
template_root (Path): The vendored ``templates/release`` directory.
|
||||
|
||||
Returns:
|
||||
dict[str, object]: Manifest with the component entries and the
|
||||
tag == version invariant.
|
||||
"""
|
||||
components: list[dict[str, str]] = []
|
||||
for entry in _RELEASE_COMPONENTS:
|
||||
rel = entry["path"]
|
||||
if not (template_root / rel).exists():
|
||||
raise SystemExit(f"[ERR] release template missing: {rel}")
|
||||
components.append({
|
||||
"kind": entry["kind"],
|
||||
"path": rel,
|
||||
"placeholder": entry["placeholder"],
|
||||
"description": entry["description"],
|
||||
})
|
||||
return {
|
||||
"project": "standards",
|
||||
"template": "templates/release",
|
||||
"invariant": "git tag == version file (enforced by the Drone guard)",
|
||||
"components": components,
|
||||
}
|
||||
|
||||
|
||||
def build_release_templates(folder: Path, dry_run: bool = False) -> None:
|
||||
"""Vendor ``folder/src/templates/release`` into ``<name>/mcp/templates/release``.
|
||||
|
||||
Ships the canonical ``CHANGELOG.md`` and ``VERSION`` in the MCP bundle so an
|
||||
agent can drop them into a repo, and emits ``release.json`` describing them.
|
||||
|
||||
Args:
|
||||
folder (Path): The hub folder owning ``src/templates/release``.
|
||||
dry_run (bool): Print the plan without executing.
|
||||
"""
|
||||
name = folder.name
|
||||
src = folder / "src" / "templates" / "release"
|
||||
if not src.is_dir():
|
||||
return
|
||||
out_dir = folder / "mcp" / "templates" / "release"
|
||||
if dry_run:
|
||||
print(f"[REL] {name} {src.relative_to(ROOT)}/** -> {out_dir.relative_to(ROOT)}/**")
|
||||
return
|
||||
|
||||
if out_dir.exists():
|
||||
shutil.rmtree(out_dir)
|
||||
out_dir.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copytree(
|
||||
src, out_dir,
|
||||
ignore=shutil.ignore_patterns("__pycache__", "*.pyc", ".git"),
|
||||
)
|
||||
manifest = build_release_manifest(out_dir)
|
||||
(folder / "mcp" / "release.json").write_text(
|
||||
json.dumps(manifest, indent=2, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
print(f"[REL] {name} release templates vendored to {out_dir.relative_to(ROOT)}/ "
|
||||
f"({len(manifest['components'])} components)")
|
||||
|
||||
|
||||
# ── Repository inventory bundle ───────────────────────────────────────────────
|
||||
|
||||
|
||||
def build_repos(folder: Path, dry_run: bool = False) -> None:
|
||||
"""Publish ``folder/src/repos.json`` as ``<name>/mcp/repos.json``.
|
||||
|
||||
The repository inventory (name, type, version source, Drone shape) is a
|
||||
single hand-authored JSON file, surfaced to agents through the
|
||||
``registry://repos`` resource and the ``list_repos`` tool. See standards
|
||||
"15_repository_inventory".
|
||||
|
||||
Args:
|
||||
folder (Path): The hub folder owning ``src/repos.json``.
|
||||
dry_run (bool): Print the plan without executing.
|
||||
"""
|
||||
name = folder.name
|
||||
src = folder / "src" / "repos.json"
|
||||
if not src.is_file():
|
||||
return
|
||||
out = folder / "mcp" / "repos.json"
|
||||
if dry_run:
|
||||
print(f"[REP] {name} {src.relative_to(ROOT)} -> {out.relative_to(ROOT)}")
|
||||
return
|
||||
|
||||
data = json.loads(src.read_text(encoding="utf-8"))
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
out.write_text(
|
||||
json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
print(f"[REP] {name} repo inventory written to {out.relative_to(ROOT)} "
|
||||
f"({len(data.get('repos', []))} repos)")
|
||||
|
||||
|
||||
# ── CLI ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -432,6 +567,8 @@ def main() -> None:
|
||||
build_bundle(folder, dry_run=args.dry_run)
|
||||
build_templates(folder, dry_run=args.dry_run)
|
||||
build_drone_templates(folder, dry_run=args.dry_run)
|
||||
build_release_templates(folder, dry_run=args.dry_run)
|
||||
build_repos(folder, dry_run=args.dry_run)
|
||||
build_html(folder, dry_run=args.dry_run)
|
||||
|
||||
|
||||
|
||||
179
registry.py
179
registry.py
@@ -11,6 +11,8 @@ Resources:
|
||||
registry://libraries (the structured catalog)
|
||||
registry://components (the template component index)
|
||||
registry://drone (the CI template index)
|
||||
registry://release (the release template index)
|
||||
registry://repos (the repository inventory)
|
||||
|
||||
Tools:
|
||||
ping (from the base server)
|
||||
@@ -20,12 +22,17 @@ Tools:
|
||||
get_app_template (the whole app skeleton as a path -> content map)
|
||||
list_drone_templates (the two CI shapes: PyPI package / Docker deployment)
|
||||
get_drone_template (kind -> exact .drone.yml template)
|
||||
list_release_templates (the changelog + version-file artefacts)
|
||||
get_release_template (kind -> exact release template file)
|
||||
list_repos (the covered repositories: type, path, version source)
|
||||
|
||||
Prompts:
|
||||
intake (the questions to gather before building)
|
||||
build (the two axes -> deterministic build prompt)
|
||||
start_app (combined entry: intake, then build)
|
||||
trial (self-contained trial build into a scratch dir)
|
||||
compliance (remediate repos against the CI + versioning standard)
|
||||
release (agent-assisted tagging after the release MR is merged)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -91,6 +98,46 @@ def _build_text(app_name: str, resources: str, pipelines: str, auth: str) -> str
|
||||
)
|
||||
|
||||
|
||||
_COMPLIANCE_TEXT = (
|
||||
"# Compliance — align repositories with the CI + versioning standard\n\n"
|
||||
"Read `docs://modules/drone_pipelines` and `docs://modules/versioning_and_changelog`,\n"
|
||||
"then enumerate the working set with `registry://repos` (or `list_repos()`).\n\n"
|
||||
"For each repository, bring it to the standard for its `type`:\n\n"
|
||||
"- **package** — `version` in `pyproject.toml`; root `CHANGELOG.md`; Drone file\n"
|
||||
" from `get_drone_template(\"drone-pypi\")` (`python-lib.yaml`, tag-triggered).\n"
|
||||
"- **service / site** — root `VERSION`; root `CHANGELOG.md`; Drone file from\n"
|
||||
" `get_drone_template(\"drone-service\")` (`service-docker.yaml`; tag-triggered\n"
|
||||
" service variant, push-triggered site variant). The service must read its\n"
|
||||
" version from `VERSION` (e.g. a build arg) — never hardcode it.\n\n"
|
||||
"Steps:\n"
|
||||
"1. Inspect each repo (`git -C <path> tag`, version file, `CHANGELOG.md`,\n"
|
||||
" `.drone.yml`) and list the gaps — never assume.\n"
|
||||
"2. Add missing files from `get_release_template(\"changelog\"/\"version-file\")`.\n"
|
||||
"3. Replace `.drone.yml` with the guarded template for the repo's type.\n"
|
||||
"4. Align the version file with the intended tag.\n"
|
||||
"5. Commit per repo (one focused commit); **do not push or tag** without the\n"
|
||||
" user's explicit go-ahead.\n"
|
||||
)
|
||||
|
||||
_RELEASE_TEXT = (
|
||||
"# Release — tag the merged commit\n\n"
|
||||
"The version bump and changelog promotion live **in the release merge\n"
|
||||
"request**; the tag is created on the commit that results from merging it.\n"
|
||||
"See `docs://modules/versioning_and_changelog`.\n\n"
|
||||
"Do this only after the user confirms the MR is merged/squashed and tells you\n"
|
||||
"to proceed — never tag before the merge.\n\n"
|
||||
"1. Wait for that explicit go-ahead.\n"
|
||||
"2. Find the commit that introduced the version bump `x.y.z`:\n"
|
||||
" - package: `git log -S 'version = \"x.y.z\"' -n 1 --format='%H %s' -- pyproject.toml`\n"
|
||||
" - service / site: `git log -S 'x.y.z' -n 1 --format='%H %s' -- VERSION`\n"
|
||||
"3. Verify that commit's version file equals `x.y.z` (the Drone guard enforces\n"
|
||||
" `tag == version`).\n"
|
||||
"4. Tag **only** that commit, lightweight and bare: `git tag x.y.z <sha>`.\n"
|
||||
"5. **Do not push.** Ask the user to run `git push origin x.y.z`, then Drone\n"
|
||||
" builds the release.\n"
|
||||
)
|
||||
|
||||
|
||||
class StandardsMCPServer(MCPServer):
|
||||
"""MCP server for the `standards` bundle with discovery/scaffolding tools.
|
||||
|
||||
@@ -136,6 +183,39 @@ class StandardsMCPServer(MCPServer):
|
||||
return {"error": "not_found", "path": str(path), "components": []}
|
||||
return json.loads(path.read_bytes())
|
||||
|
||||
def _release(self) -> dict[str, Any]:
|
||||
"""Load the release (versioning + changelog) template manifest."""
|
||||
path = Path(self.mcp_root) / "release.json"
|
||||
if not path.exists():
|
||||
return {"error": "not_found", "path": str(path), "components": []}
|
||||
return json.loads(path.read_bytes())
|
||||
|
||||
def _repos(self) -> dict[str, Any]:
|
||||
"""Load the repository inventory."""
|
||||
path = Path(self.mcp_root) / "repos.json"
|
||||
if not path.exists():
|
||||
return {"error": "not_found", "path": str(path), "repos": []}
|
||||
return json.loads(path.read_bytes())
|
||||
|
||||
def _find_release_component(self, kind: str) -> dict[str, Any] | None:
|
||||
for entry in self._release().get("components", []):
|
||||
if entry.get("kind") == kind:
|
||||
return entry
|
||||
return None
|
||||
|
||||
def _read_release_component(self, entry: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Read a vendored release standard file."""
|
||||
rel = entry["path"]
|
||||
path = Path(self.mcp_root) / "templates" / "release" / rel
|
||||
if not path.exists():
|
||||
return {"error": "not_found", "path": str(path)}
|
||||
return {
|
||||
"kind": entry["kind"],
|
||||
"path": rel,
|
||||
"placeholder": entry.get("placeholder"),
|
||||
"content": path.read_text(encoding="utf-8"),
|
||||
}
|
||||
|
||||
def _find_drone_component(self, kind: str) -> dict[str, Any] | None:
|
||||
for entry in self._drone().get("components", []):
|
||||
if entry.get("kind") == kind:
|
||||
@@ -228,6 +308,20 @@ class StandardsMCPServer(MCPServer):
|
||||
def drone() -> dict[str, Any]:
|
||||
return self._drone()
|
||||
|
||||
@self.app.resource("registry://release")
|
||||
def release_templates() -> dict[str, Any]:
|
||||
return self._release()
|
||||
|
||||
@self.app.resource("registry://repos")
|
||||
def repos() -> dict[str, Any]:
|
||||
"""Return the repository inventory.
|
||||
|
||||
Use this to enumerate the repositories covered by the CI and
|
||||
versioning standards, each with its type, path, version source, and
|
||||
Drone shape. Paths are relative to the aetos/ workspace root.
|
||||
"""
|
||||
return self._repos()
|
||||
|
||||
@self.app.resource("docs://spec")
|
||||
def spec() -> dict[str, Any]:
|
||||
"""Return the pinned auth-server OpenAPI contract.
|
||||
@@ -380,6 +474,66 @@ class StandardsMCPServer(MCPServer):
|
||||
}
|
||||
return self._read_drone_component(entry)
|
||||
|
||||
@self.app.tool()
|
||||
def list_release_templates() -> list[dict[str, Any]]:
|
||||
"""List the release/versioning template artefacts.
|
||||
|
||||
These are the files every repo carries for releases: a Keep a
|
||||
Changelog ``CHANGELOG.md`` and, for services, a root ``VERSION``
|
||||
file. See standards "11_versioning_and_changelog".
|
||||
|
||||
Returns:
|
||||
list[dict[str, Any]]:
|
||||
Entries with ``kind``, ``path``, ``placeholder`` and
|
||||
``description``. Fetch one with :func:`get_release_template`.
|
||||
"""
|
||||
return self._release().get("components", [])
|
||||
|
||||
@self.app.tool()
|
||||
def get_release_template(kind: str) -> dict[str, Any]:
|
||||
"""Return the exact release standard file for a component kind.
|
||||
|
||||
Use this to drop the canonical changelog / version file into a repo
|
||||
instead of inventing one. See :func:`list_release_templates` for
|
||||
valid kinds ("changelog", "version-file").
|
||||
|
||||
Args:
|
||||
kind (str): Component kind, e.g. "changelog" or "version-file".
|
||||
|
||||
Returns:
|
||||
dict[str, Any]: ``{kind, path, placeholder, content}`` or an
|
||||
error entry when the kind is unknown.
|
||||
"""
|
||||
entry = self._find_release_component(kind)
|
||||
if entry is None:
|
||||
return {
|
||||
"error": "unknown_kind",
|
||||
"kind": kind,
|
||||
"available": [c["kind"] for c in self._release().get("components", [])],
|
||||
}
|
||||
return self._read_release_component(entry)
|
||||
|
||||
@self.app.tool()
|
||||
def list_repos(type: str | None = None) -> list[dict[str, Any]]:
|
||||
"""List the repositories covered by the CI and versioning standards.
|
||||
|
||||
Each entry has: ``name``, ``type`` ("package" | "service" | "site"),
|
||||
``path`` (relative to the aetos/ workspace root), ``version_source``
|
||||
("pyproject.toml" | "VERSION"), ``drone`` (the template file),
|
||||
``trigger`` ("tag" | "push"), ``docs`` kinds, and ``mcp``.
|
||||
|
||||
Args:
|
||||
type (str | None): Optional filter, e.g. "package" or "site".
|
||||
|
||||
Returns:
|
||||
list[dict[str, Any]]: Matching repository entries.
|
||||
"""
|
||||
repos = self._repos().get("repos", [])
|
||||
if type:
|
||||
needle = type.strip().lower()
|
||||
return [r for r in repos if str(r.get("type", "")).lower() == needle]
|
||||
return repos
|
||||
|
||||
@self.app.prompt()
|
||||
def intake() -> str:
|
||||
"""Return the questions to gather before building an app.
|
||||
@@ -472,3 +626,28 @@ class StandardsMCPServer(MCPServer):
|
||||
"back so the standard can be amended.\n\n"
|
||||
f"Delete `{target}` once you are satisfied.\n"
|
||||
)
|
||||
|
||||
@self.app.prompt()
|
||||
def compliance() -> str:
|
||||
"""Return the procedure to align repositories with the standard.
|
||||
|
||||
Use this to audit and remediate the repos listed in
|
||||
`registry://repos` against the Drone and versioning standards.
|
||||
|
||||
Returns:
|
||||
str: The compliance/remediation prompt.
|
||||
"""
|
||||
return _COMPLIANCE_TEXT
|
||||
|
||||
@self.app.prompt()
|
||||
def release() -> str:
|
||||
"""Return the agent-assisted tagging procedure.
|
||||
|
||||
Use after the user confirms the release MR is merged/squashed: find
|
||||
the commit that bumped the version file, tag only that commit, and
|
||||
ask the user to push the tag.
|
||||
|
||||
Returns:
|
||||
str: The release/tagging prompt.
|
||||
"""
|
||||
return _RELEASE_TEXT
|
||||
|
||||
@@ -549,6 +549,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -540,6 +540,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -531,6 +531,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -558,6 +558,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -567,6 +567,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -558,6 +558,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -531,6 +531,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -540,6 +540,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<link rel="prev" href="../08_human_in_loop/">
|
||||
|
||||
|
||||
<link rel="next" href="../12_genericity_matrix/">
|
||||
<link rel="next" href="../10_drone_pipelines/">
|
||||
|
||||
|
||||
<link rel="icon" href="../assets/images/favicon.png">
|
||||
@@ -558,6 +558,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
957
standards/lib/10_drone_pipelines/index.html
Normal file
957
standards/lib/10_drone_pipelines/index.html
Normal file
@@ -0,0 +1,957 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<meta name="description" content="The rules and library registry of the standardized application blueprint.">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="prev" href="../09_infra_adaptors/">
|
||||
|
||||
|
||||
<link rel="next" href="../11_versioning_and_changelog/">
|
||||
|
||||
|
||||
<link rel="icon" href="../assets/images/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
|
||||
|
||||
|
||||
|
||||
<title>Drone Pipelines - Aetos Standards — Reference</title>
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/main.84d31ad4.min.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan">
|
||||
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#drone-pipelines" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="md-header md-header--shadow" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href=".." title="Aetos Standards — Reference" class="md-header__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Aetos Standards — Reference
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
||||
</label>
|
||||
<div class="md-search" data-md-component="search" role="dialog">
|
||||
<label class="md-search__overlay" for="__search"></label>
|
||||
<div class="md-search__inner" role="search">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
||||
<label class="md-search__icon md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
|
||||
</label>
|
||||
<nav class="md-search__options" aria-label="Search">
|
||||
|
||||
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
|
||||
</a>
|
||||
|
||||
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
||||
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Initializing search
|
||||
</div>
|
||||
<ol class="md-search-result__list" role="presentation"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href=".." title="Aetos Standards — Reference" class="md-nav__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
||||
|
||||
</a>
|
||||
Aetos Standards — Reference
|
||||
</label>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href=".." class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Home
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../01_build_recipe/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Build Recipe
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../02_layering_rules/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Layering Rules
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../03_composition_root/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Composition Root
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../04_spec_first_routing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Spec-First Routing
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../05_crud_template/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
CRUD Template
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../06_pipeline_scaffold/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Pipeline Scaffold
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../07_worker_and_progress/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Worker & Progress
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../08_human_in_loop/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Human-in-the-Loop
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../09_infra_adaptors/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Infra Adapters
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
|
||||
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
<a href="./" class="md-nav__link md-nav__link--active">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#summary" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Summary
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#type-a-pypi-package-python-libyaml" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Type A — PyPI package (python-lib.yaml)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#type-b-docker-deployment-service-dockeryaml" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Type B — Docker deployment (service-docker.yaml)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#what-not-to-do" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
What not to do
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#related" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Related
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Genericity Matrix
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../14_auth_integration/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Auth Integration
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../13_library_registry/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Library Registry
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#summary" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Summary
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#type-a-pypi-package-python-libyaml" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Type A — PyPI package (python-lib.yaml)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#type-b-docker-deployment-service-dockeryaml" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Type B — Docker deployment (service-docker.yaml)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#what-not-to-do" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
What not to do
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#related" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Related
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1 id="drone-pipelines">Drone Pipelines</h1>
|
||||
<h2 id="summary">Summary</h2>
|
||||
<p>Every Aetos repository ships a Drone CI definition at <code>.drone.yml</code>. There is
|
||||
exactly <strong>one standard per repository</strong>, and there are <strong>two types of file</strong>,
|
||||
chosen by what the repository produces:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>File</th>
|
||||
<th>Produces</th>
|
||||
<th>Repos</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>A — PyPI package</strong></td>
|
||||
<td><code>templates/drone/python-lib.yaml</code></td>
|
||||
<td>A wheel + sdist on the private index</td>
|
||||
<td><code>dagpipe</code>, <code>doc-forge</code>, <code>hexa</code>, <code>mail-intake</code>, <code>mongo-ops</code>, <code>omniread</code>, <code>openapi-first</code>, <code>py-jwt</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Both templates run on <code>platform: linux / arm64</code> with the workspace at
|
||||
<code>/drone/src</code>. Copy the matching template to <code><repo>/.drone.yml</code>; the Type A file
|
||||
needs no edits, the Type B file needs its placeholders filled in (below).</p>
|
||||
<blockquote>
|
||||
<p>Conventions: <code>.drone.yml</code> (not <code>.yaml</code>), one file per repo, secrets injected
|
||||
with <code>from_secret</code> — never commit credentials.</p>
|
||||
</blockquote>
|
||||
<hr />
|
||||
<h2 id="type-a-pypi-package-python-libyaml">Type A — PyPI package (<code>python-lib.yaml</code>)</h2>
|
||||
<p>For internal libraries. The file contains <strong>two pipelines</strong>:</p>
|
||||
<ol>
|
||||
<li><strong><code>build-and-publish-pypi</code></strong> — triggered on <code>tag</code>:</li>
|
||||
<li><code>check-version</code> — <strong>guard</strong>: fail unless <code>$DRONE_TAG</code> equals the version in
|
||||
<code>pyproject.toml</code>; then read <code>name</code> / <code>version</code> and query
|
||||
<code>$PIP_REPO_URL/simple/<package>/</code>; if that version already exists, exit
|
||||
<code>78</code> and skip the whole build (see <a href="../11_versioning_and_changelog/">11 – Versioning & Changelog</a>).</li>
|
||||
<li><code>quality-gate</code> — install the package with its <code>[dev]</code> extras from the
|
||||
private index, then <code>black --check</code>, <code>ruff check</code>, <code>mypy</code>, <code>pydoclint</code>,
|
||||
<code>pytest</code>.</li>
|
||||
<li><code>build-package</code> — <code>python -m build</code> into <code>dist/</code>.</li>
|
||||
<li><code>upload-to-private-pypi</code> — <code>twine upload</code> to <code>$PIP_REPO_URL</code>.</li>
|
||||
<li><strong><code>backfill-pypi-from-tags</code></strong> — triggered on <code>custom</code>:</li>
|
||||
<li><code>fetch-tags</code> — <code>git fetch --tags --force</code>.</li>
|
||||
<li><code>build-and-upload-missing</code> — walk every tag in version order, skip the ones
|
||||
already on the index, <code>git checkout</code> the rest, verify <code>tag == pyproject
|
||||
version</code> at that commit, build, and upload. This is the disaster-recovery /
|
||||
replay path.</li>
|
||||
</ol>
|
||||
<p>Secrets: <code>PIP_REPO_URL</code>, <code>PIP_USERNAME</code>, <code>PIP_PASSWORD</code>.</p>
|
||||
<ul>
|
||||
<li><strong>Ship as-is.</strong> Package name and version come from <code>pyproject.toml</code>, so the
|
||||
same file is reused verbatim across every library.</li>
|
||||
</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>
|
||||
<li><code>fetch-tags</code> — resolve the latest tag into <code>LATEST_TAG.txt</code>; fail if there
|
||||
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 & Changelog</a>).</li>
|
||||
<li><code>check-remote-image</code> — if <code>aetos/<app>:<tag></code> already exists locally, exit
|
||||
<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>
|
||||
<li><code>build-image</code> — <code>docker build</code> with the private-index build args, tagged
|
||||
<code>aetos/<app>:<tag></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 <app></code>.</li>
|
||||
<li><code>run-container</code> — <code>docker run -d --name <app> -p <host>:<container>
|
||||
--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>
|
||||
<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>
|
||||
<p>Placeholders to fill in per repo:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Placeholder</th>
|
||||
<th>Meaning</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code><app></code></td>
|
||||
<td>service image / container name</td>
|
||||
<td><code>auth-server</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>aetos/<app></code></td>
|
||||
<td>image repository on the registry</td>
|
||||
<td><code>aetos/auth-server</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><host-port></code> / <code><container-port></code></td>
|
||||
<td>published : in-image port</td>
|
||||
<td><code>9003:8000</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><site></code></td>
|
||||
<td>site image / container name</td>
|
||||
<td><code>docs</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><ENV_VAR></code></td>
|
||||
<td>runtime environment variable</td>
|
||||
<td><code>MONGO_HOST</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h2 id="what-not-to-do">What not to do</h2>
|
||||
<ul>
|
||||
<li>Do not hand-roll a third shape. A repo is either Type A or Type B, never both.</li>
|
||||
<li>Do not inline secrets; always use <code>from_secret</code>.</li>
|
||||
<li>Do not drop the <code>check-version</code> / <code>check-remote-image</code> skip — it guards the
|
||||
index and the running container against duplicate publishes.</li>
|
||||
<li>Do not drop the tag↔version guard. A package needs its <code>pyproject.toml</code>
|
||||
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 & 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>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="related">Related</h2>
|
||||
<ul>
|
||||
<li><a href="../01_build_recipe/">01 – Build Recipe</a> · <a href="../09_infra_adaptors/">09 – Infra Adapters</a> · <a href="../11_versioning_and_changelog/">11 – Versioning & Changelog</a> · <a href="../13_library_registry/">13 – Library Registry</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
||||
|
||||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
||||
</div>
|
||||
|
||||
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
|
||||
Back to top
|
||||
</button>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.sections", "navigation.expand", "navigation.top", "navigation.instant", "navigation.tracking", "navigation.indexes", "content.code.copy", "content.code.annotate", "content.tabs.link", "content.action.edit", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
||||
|
||||
|
||||
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1063
standards/lib/11_versioning_and_changelog/index.html
Normal file
1063
standards/lib/11_versioning_and_changelog/index.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
|
||||
|
||||
|
||||
<link rel="prev" href="../09_infra_adaptors/">
|
||||
<link rel="prev" href="../15_repository_inventory/">
|
||||
|
||||
|
||||
<link rel="next" href="../14_auth_integration/">
|
||||
@@ -442,6 +442,72 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -442,6 +442,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -444,6 +444,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
983
standards/lib/15_repository_inventory/index.html
Normal file
983
standards/lib/15_repository_inventory/index.html
Normal file
@@ -0,0 +1,983 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<meta name="description" content="The rules and library registry of the standardized application blueprint.">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="prev" href="../11_versioning_and_changelog/">
|
||||
|
||||
|
||||
<link rel="next" href="../12_genericity_matrix/">
|
||||
|
||||
|
||||
<link rel="icon" href="../assets/images/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
|
||||
|
||||
|
||||
|
||||
<title>Repository Inventory - Aetos Standards — Reference</title>
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/main.84d31ad4.min.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan">
|
||||
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#repository-inventory" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="md-header md-header--shadow" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href=".." title="Aetos Standards — Reference" class="md-header__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Aetos Standards — Reference
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
||||
</label>
|
||||
<div class="md-search" data-md-component="search" role="dialog">
|
||||
<label class="md-search__overlay" for="__search"></label>
|
||||
<div class="md-search__inner" role="search">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
||||
<label class="md-search__icon md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
|
||||
</label>
|
||||
<nav class="md-search__options" aria-label="Search">
|
||||
|
||||
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
|
||||
</a>
|
||||
|
||||
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
||||
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Initializing search
|
||||
</div>
|
||||
<ol class="md-search-result__list" role="presentation"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href=".." title="Aetos Standards — Reference" class="md-nav__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
||||
|
||||
</a>
|
||||
Aetos Standards — Reference
|
||||
</label>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href=".." class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Home
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../01_build_recipe/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Build Recipe
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../02_layering_rules/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Layering Rules
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../03_composition_root/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Composition Root
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../04_spec_first_routing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Spec-First Routing
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../05_crud_template/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
CRUD Template
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../06_pipeline_scaffold/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Pipeline Scaffold
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../07_worker_and_progress/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Worker & Progress
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../08_human_in_loop/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Human-in-the-Loop
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../09_infra_adaptors/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Infra Adapters
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
|
||||
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
<a href="./" class="md-nav__link md-nav__link--active">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#summary" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Summary
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#packages-type-a" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Packages (Type A)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#services-sites-type-b" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Services & sites (Type B)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#required-files-per-repo" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Required files per repo
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#reading-this-at-runtime" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Reading this at runtime
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#related" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Related
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Genericity Matrix
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../14_auth_integration/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Auth Integration
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../13_library_registry/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Library Registry
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#summary" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Summary
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#packages-type-a" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Packages (Type A)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#services-sites-type-b" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Services & sites (Type B)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#required-files-per-repo" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Required files per repo
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#reading-this-at-runtime" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Reading this at runtime
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#related" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Related
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1 id="repository-inventory">Repository Inventory</h1>
|
||||
<h2 id="summary">Summary</h2>
|
||||
<p>The canonical list of Aetos repositories covered by the CI and versioning
|
||||
standards, with the artifact each one produces, its version source, and its
|
||||
Drone shape. Every entry maps to the contract in
|
||||
<a href="../11_versioning_and_changelog/">11 – Versioning & Changelog</a> and the two CI
|
||||
files in <a href="../10_drone_pipelines/">10 – Drone Pipelines</a>.</p>
|
||||
<p>The same data is published machine-readably as the <code>registry://repos</code> MCP
|
||||
resource (and the <code>list_repos</code> tool), sourced from <code>standards/src/repos.json</code>.
|
||||
Paths are relative to the <code>aetos/</code> workspace root.</p>
|
||||
<hr />
|
||||
<h2 id="packages-type-a">Packages (Type A)</h2>
|
||||
<p>A wheel + sdist published to the private index. Version source is
|
||||
<code>pyproject.toml</code>; Drone file is <code>python-lib.yaml</code> (tag-triggered).</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Repo</th>
|
||||
<th>Path</th>
|
||||
<th>Docs</th>
|
||||
<th>MCP server</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>dagpipe</code></td>
|
||||
<td><code>dagpipe</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>dagpipe:8006</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>doc-forge</code></td>
|
||||
<td><code>doc-forge</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>docforge:8001</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>hexa</code></td>
|
||||
<td><code>hexa</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>hexa:8008</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>mail-intake</code></td>
|
||||
<td><code>mail-intake</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>mail_intake:8002</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>mongo-ops</code></td>
|
||||
<td><code>mongo-ops</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>mongo_ops:8007</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>omniread</code></td>
|
||||
<td><code>omniread</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>omniread:8003</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>openapi-first</code></td>
|
||||
<td><code>openapi-first</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>openapi_first:8004</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>py-jwt</code></td>
|
||||
<td><code>py-jwt</code></td>
|
||||
<td>lib, wiki</td>
|
||||
<td><code>jwtlib:8005</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h2 id="services-sites-type-b">Services & sites (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>
|
||||
</tr>
|
||||
</thead>
|
||||
<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>
|
||||
<hr />
|
||||
<h2 id="required-files-per-repo">Required files per repo</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Version source</th>
|
||||
<th>Changelog</th>
|
||||
<th>Drone</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>package</td>
|
||||
<td><code>pyproject.toml</code></td>
|
||||
<td><code>CHANGELOG.md</code></td>
|
||||
<td><code>python-lib.yaml</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>service / site</td>
|
||||
<td><code>VERSION</code></td>
|
||||
<td><code>CHANGELOG.md</code></td>
|
||||
<td><code>service-docker.yaml</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Every covered repository must be able to satisfy <code>tag == version</code>:
|
||||
the version file (never a commit id) is bumped in the release MR, the MR is
|
||||
merged, and the tag is created on the merged commit.</p>
|
||||
<hr />
|
||||
<h2 id="reading-this-at-runtime">Reading this at runtime</h2>
|
||||
<ul>
|
||||
<li>Resource: <code>registry://repos</code></li>
|
||||
<li>Tool: <code>list_repos()</code></li>
|
||||
<li>Humans: this page (mirror of <code>standards/src/repos.json</code>).</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="related">Related</h2>
|
||||
<ul>
|
||||
<li><a href="../10_drone_pipelines/">10 – Drone Pipelines</a> · <a href="../11_versioning_and_changelog/">11 – Versioning & Changelog</a> · <a href="../13_library_registry/">13 – Library Registry</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
||||
|
||||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
||||
</div>
|
||||
|
||||
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
|
||||
Back to top
|
||||
</button>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.sections", "navigation.expand", "navigation.top", "navigation.instant", "navigation.tracking", "navigation.indexes", "content.code.copy", "content.code.annotate", "content.tabs.link", "content.action.edit", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
||||
|
||||
|
||||
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -435,6 +435,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
|
||||
@@ -452,6 +452,72 @@
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="10_drone_pipelines/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Drone Pipelines
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="11_versioning_and_changelog/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Versioning & Changelog
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="15_repository_inventory/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Repository Inventory
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="12_genericity_matrix/" class="md-nav__link">
|
||||
|
||||
@@ -561,6 +627,11 @@ patterns, and the internal library catalog that agents consult while coding.</p>
|
||||
<li><strong>Worker & Progress</strong> — queued work, progress reporting, and visibility.</li>
|
||||
<li><strong>Human-in-the-Loop</strong> — guardrails and approvals inside automations.</li>
|
||||
<li><strong>Infra Adapters</strong> — how infrastructure connects without leaking into domain.</li>
|
||||
<li><strong>Drone Pipelines</strong> — the two CI shapes: a PyPI package or a Docker deployment.</li>
|
||||
<li><strong>Versioning & Changelog</strong> — SemVer, the tag↔version contract, and the release
|
||||
changelog.</li>
|
||||
<li><strong>Repository Inventory</strong> — every covered repo, its type, version source, and
|
||||
Drone shape.</li>
|
||||
<li><strong>Genericity Matrix</strong> — what is library-backed, template-provided, or authored.</li>
|
||||
<li><strong>Auth Integration</strong> — consuming the shared auth-server service (spec-driven,
|
||||
no auth code).</li>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -186,6 +186,12 @@
|
||||
"placeholder": "",
|
||||
"description": "Packaging + dependency pins."
|
||||
},
|
||||
{
|
||||
"kind": "changelog",
|
||||
"path": "CHANGELOG.md",
|
||||
"placeholder": "",
|
||||
"description": "Keep a Changelog file with an [Unreleased] section (versioning standard)."
|
||||
},
|
||||
{
|
||||
"kind": "dockerfile",
|
||||
"path": "Dockerfile",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"project": "standards",
|
||||
"type": "standards",
|
||||
"modules_count": 14,
|
||||
"modules_count": 22,
|
||||
"source": "hand-authored"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
"module": "index",
|
||||
"content": {
|
||||
"path": "index",
|
||||
"docstring": "# Standards Reference\n\nThe reference half of the Standards description: the enforceable rules,\npatterns, and the internal library catalog that agents consult while coding.\n\n- **Build Recipe** — the ordered, agentic checklist for a new app.\n- **Layering Rules** — the strict request → domain → repository layering and\n the rules that enforce it.\n- **Composition Root** — a single composition point wiring the whole app.\n- **Spec-First Routing** — the OpenAPI contract as the routing source of truth.\n- **CRUD Template** — the standardized generic resource endpoint scaffold.\n- **Pipeline Scaffold** — the deterministic pipeline skeleton for multi-stage\n jobs.\n- **Worker & Progress** — queued work, progress reporting, and visibility.\n- **Human-in-the-Loop** — guardrails and approvals inside automations.\n- **Infra Adapters** — how infrastructure connects without leaking into domain.\n- **Drone Pipelines** — the two CI shapes: a PyPI package or a Docker deployment.\n- **Genericity Matrix** — what is library-backed, template-provided, or authored.\n- **Auth Integration** — consuming the shared auth-server service (spec-driven,\n no auth code).\n- **Library Registry** — the catalog of internal libraries behind all of it.\n\nRead the **Wiki** for the philosophy and rationale; these pages are the\nreference that mirrors the `standards` MCP bundle.\n",
|
||||
"docstring": "# Standards Reference\n\nThe reference half of the Standards description: the enforceable rules,\npatterns, and the internal library catalog that agents consult while coding.\n\n- **Build Recipe** — the ordered, agentic checklist for a new app.\n- **Layering Rules** — the strict request → domain → repository layering and\n the rules that enforce it.\n- **Composition Root** — a single composition point wiring the whole app.\n- **Spec-First Routing** — the OpenAPI contract as the routing source of truth.\n- **CRUD Template** — the standardized generic resource endpoint scaffold.\n- **Pipeline Scaffold** — the deterministic pipeline skeleton for multi-stage\n jobs.\n- **Worker & Progress** — queued work, progress reporting, and visibility.\n- **Human-in-the-Loop** — guardrails and approvals inside automations.\n- **Infra Adapters** — how infrastructure connects without leaking into domain.\n- **Drone Pipelines** — the two CI shapes: a PyPI package or a Docker deployment.\n- **Versioning & Changelog** — SemVer, the tag↔version contract, and the release\n changelog.\n- **Repository Inventory** — every covered repo, its type, version source, and\n Drone shape.\n- **Genericity Matrix** — what is library-backed, template-provided, or authored.\n- **Auth Integration** — consuming the shared auth-server service (spec-driven,\n no auth code).\n- **Library Registry** — the catalog of internal libraries behind all of it.\n\nRead the **Wiki** for the philosophy and rationale; these pages are the\nreference that mirrors the `standards` MCP bundle.\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
8
standards/mcp/modules/repository_inventory.json
Normal file
8
standards/mcp/modules/repository_inventory.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"module": "repository_inventory",
|
||||
"content": {
|
||||
"path": "repository_inventory",
|
||||
"docstring": "# Repository Inventory\n\n## Summary\n\nThe canonical list of Aetos repositories covered by the CI and versioning\nstandards, with the artifact each one produces, its version source, and its\nDrone shape. Every entry maps to the contract in\n[11 – Versioning & Changelog](11_versioning_and_changelog.md) and the two CI\nfiles in [10 – Drone Pipelines](10_drone_pipelines.md).\n\nThe same data is published machine-readably as the `registry://repos` MCP\nresource (and the `list_repos` tool), sourced from `standards/src/repos.json`.\nPaths are relative to the `aetos/` workspace root.\n\n---\n\n## Packages (Type A)\n\nA wheel + sdist published to the private index. Version source is\n`pyproject.toml`; Drone file is `python-lib.yaml` (tag-triggered).\n\n| Repo | Path | Docs | MCP server |\n|------|------|------|------------|\n| `dagpipe` | `dagpipe` | lib, wiki | `dagpipe:8006` |\n| `doc-forge` | `doc-forge` | lib, wiki | `docforge:8001` |\n| `hexa` | `hexa` | lib, wiki | `hexa:8008` |\n| `mail-intake` | `mail-intake` | lib, wiki | `mail_intake:8002` |\n| `mongo-ops` | `mongo-ops` | lib, wiki | `mongo_ops:8007` |\n| `omniread` | `omniread` | lib, wiki | `omniread:8003` |\n| `openapi-first` | `openapi-first` | lib, wiki | `openapi_first:8004` |\n| `py-jwt` | `py-jwt` | lib, wiki | `jwtlib:8005` |\n\n---\n\n## Services & sites (Type B)\n\nA container image pushed to the registry and run on the Docker host. Version\nsource is the `VERSION` file; Drone file is `service-docker.yaml`.\n\n| Repo | Type | Path | Trigger | Docs |\n|------|------|------|---------|------|\n| `auth-server` | service | `auth-server` | tag | api, lib, wiki |\n| `docs` | site | `docs` | push | — |\n| `mcp` | site | `mcp` | push | — |\n\nThe **service** variant is tag-triggered and enforces `tag == VERSION`. The\n**site** variant is push-triggered, ships `:latest`, and has no tag guard.\n\n---\n\n## Required files per repo\n\n| Type | Version source | Changelog | Drone |\n|------|----------------|-----------|-------|\n| package | `pyproject.toml` | `CHANGELOG.md` | `python-lib.yaml` |\n| service / site | `VERSION` | `CHANGELOG.md` | `service-docker.yaml` |\n\nEvery covered repository must be able to satisfy `tag == version`:\nthe version file (never a commit id) is bumped in the release MR, the MR is\nmerged, and the tag is created on the merged commit.\n\n---\n\n## Reading this at runtime\n\n- Resource: `registry://repos`\n- Tool: `list_repos()`\n- Humans: this page (mirror of `standards/src/repos.json`).\n\n---\n\n## Related\n\n- [10 – Drone Pipelines](10_drone_pipelines.md) · [11 – Versioning & Changelog](11_versioning_and_changelog.md) · [13 – Library Registry](13_library_registry.md)\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
8
standards/mcp/modules/versioning_and_changelog.json
Normal file
8
standards/mcp/modules/versioning_and_changelog.json
Normal file
File diff suppressed because one or more lines are too long
8
standards/mcp/modules/wiki_components.json
Normal file
8
standards/mcp/modules/wiki_components.json
Normal file
File diff suppressed because one or more lines are too long
8
standards/mcp/modules/wiki_development_releasing.json
Normal file
8
standards/mcp/modules/wiki_development_releasing.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"module": "wiki_development_releasing",
|
||||
"content": {
|
||||
"path": "wiki_development_releasing",
|
||||
"docstring": "# Releasing & Versioning\n\nHow to cut a release of any Aetos repository. The rule lives in the reference\npage [Versioning & Changelog](../lib/11_versioning_and_changelog/); this is the\nrunbook you follow.\n\nEvery repository is one of two Drone shapes — a **PyPI package** or a **Docker\ndeployment** ([Drone Pipelines](../lib/10_drone_pipelines/)). Both release the\nsame way: the version bump and changelog promotion go **in the merge request**,\nand the tag is created on the merged commit.\n\n---\n\n## 🧾 Before you start\n\n- You have an open **merge request** holding the change, and `main` is green\n (the Drone quality gate passed on the last run).\n- You know whether this is a **breaking**, **feature**, or **fix** release.\n- The version file exists:\n - package → `version` in `pyproject.toml`\n - service / site → `VERSION` at the repo root\n\n---\n\n## 🚦 Pick the next version\n\nThe version file and the tag must be identical. For `0.y.z`, `0.y` is the major\nline (see the reference page); once at `1.0.0`, normal SemVer applies.\n\n| Change | `0.y.z` → | `1.0.0+` → |\n|--------|-----------|------------|\n| Breaking | `0.(y+1).0` | `(x+1).0.0` |\n| Feature | `0.y.(z+1)` | `x.(y+1).0` |\n| Fix | `0.y.(z+1)` | `x.y.(z+1)` |\n\n---\n\n## 🌿 Release in the MR\n\nThe version is known while the change is still a merge request, so the bump\nrides along with it. Do both edits **in the MR**:\n\n- **Promote the changelog** in `CHANGELOG.md`: move the `[Unreleased]` content\n under a new `## [x.y.z] - YYYY-MM-DD` heading, leave a fresh empty\n `[Unreleased]` on top, and add the compare links — naming the **version/tag**,\n never a commit id:\n\n ```markdown\n [Unreleased]: https://git.aetoskia.com/aetos/<repo>/compare/x.y.z...HEAD\n [x.y.z]: https://git.aetoskia.com/aetos/<repo>/compare/x.y.(z-1)...x.y.z\n ```\n\n- **Bump the version file** to the intended release version: `version = \"x.y.z\"`\n in `pyproject.toml` (packages) or the `VERSION` file (services/sites).\n\n---\n\n## 🏷️ Tag the merged commit\n\n1. **Merge or squash** the MR into `main`.\n2. **Create the tag** on the resulting commit: `git tag x.y.z` (lightweight).\n3. **Push the tag** (`git push origin x.y.z`) — Drone builds the release.\n\n### 🤖 Agent-assisted tagging\n\nThe agent does not author or merge the MR and never tags before the merge. After\nyou confirm the MR is merged/squashed and tell it to proceed, the agent:\n\n1. Waits for that explicit go-ahead.\n2. Finds the commit that introduced the bump:\n - package:\n `git log -S 'version = \"x.y.z\"' -n 1 --format='%H %s' -- pyproject.toml`\n - service / site:\n `git log -S 'x.y.z' -n 1 --format='%H %s' -- VERSION`\n3. Verifies that commit's version file equals `x.y.z`, then tags **only** that\n commit: `git tag x.y.z <sha>`.\n4. Does **not** push — it asks you to run `git push origin x.y.z`.\n\n---\n\n## 🤖 What Drone does\n\n- **Type A (package):** asserts `tag == pyproject version`, then skips if that\n version already exists on the index, runs the quality gate, builds, and\n uploads the wheel + sdist.\n- **Type B (service):** asserts `tag == VERSION`, resolves the tag, skips if the\n image already exists, runs the quality gate, builds, pushes, and restarts the\n container.\n- **Type B (site):** triggered on push, ships `:latest` and has no tag guard.\n\nIf the guard fails, nothing is published — fix the version file, amend the\ncommit, and move the tag **only** if it was never pushed.\n\n---\n\n## 🛟 Backfill / recovery\n\nIf an older tag never published (a past version-file mismatch, an index\noutage):\n\n- **Package:** run the `backfill-pypi-from-tags` pipeline (custom event). It\n checks out every tag, verifies `tag == pyproject version` at that commit,\n and uploads the ones missing from the index. Already-fixed history is never\n rewritten.\n- **Service:** rebuild the image for the missing tag with a fresh commit and a\n new patch version; do not move a published tag.\n\n---\n\n## 🔁 If a release is wrong\n\n- Never reuse or force-move a pushed tag.\n- Fix forward: bump to the next patch, promote the changelog, tag again.\n\n---\n\n## Related\n\n- [Testing & Quality Gates](01_testing.md) · [Versioning & Changelog](../lib/11_versioning_and_changelog/) · [Drone Pipelines](../lib/10_drone_pipelines/)\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
8
standards/mcp/modules/wiki_development_testing.json
Normal file
8
standards/mcp/modules/wiki_development_testing.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"module": "wiki_development_testing",
|
||||
"content": {
|
||||
"path": "wiki_development_testing",
|
||||
"docstring": "# Testing & Quality Gates\n\nTwo suites run under pytest with asyncio auto mode: **integration** (the HTTP\nedge against fakes) and **unit** (pure domain and pipeline logic). Finish a\nblueprint app only when every gate below passes.\n\n---\n\n## 🗂️ Layout\n\n```\ntests/\n integration/ # TestClient(app) + mocked resources\n unit/ # models, converters, pipeline stages/roots\n conftest.py # fixtures\n```\n\n---\n\n## 🚀 Integration tests\n\n- Build the app with `TestClient`.\n- Replace `app.state.db_resources` with fake repositories/services so no database\n is required.\n- Patch the auth introspection call (`httpx.AsyncClient.post`) to return a\n canned identity.\n- Assert status codes and bodies for list/get/create/update/delete, plus\n `400`, `404`, `204`, and the streaming endpoint's fallback.\n\n```python\nclient = TestClient(app)\napp.state.db_resources = {\"item_svc\": FakeItemService(), ...}\n\ndef test_create_item():\n r = client.post(\"/items\", json={\"name\": \"x\"})\n assert r.status_code == 200\n```\n\n---\n\n## 🧪 Unit tests\n\n- Domain models and converters: pure, no I/O.\n- Pipeline stages: feed a fixture state, assert the transformed state.\n- Assembled pipeline roots: **fixture parity** — replay a stored fixture input\n and compare against a golden output file.\n\n---\n\n## 🔐 Config-consistency tests\n\nFor rule-driven pipelines, add a test that cross-references rules against the\ndeclared pattern registry: every flag emitted must be defined; every defined\nflag must be reachable. This catches drift without running the pipeline.\n\n---\n\n## ✅ Quality gates\n\nA **definition of done** for any standard app:\n\n- `python -c \"import main\"` succeeds.\n- `pytest` passes.\n- The app serves the spec's operations; the worker drains its queue.\n- No domain module imports a web framework.\n- No infrastructure was reimplemented that a library already provides.\n\n---\n\n## 💡 Conventions\n\n- `asyncio_mode = \"auto\"`; no manual event loops.\n- Fixtures are checked into the repo (inputs + golden outputs).\n- Tests skip (not fail) when a required fixture is absent.\n- Do not mock the domain; mock only the infrastructure edge.\n\n---\n\n## Related\n\n- [02 – App Components](../02_components.md) · [03 – Start an App](../03_start_an_app.md) · [Overview](../01_overview.md)\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
8
standards/mcp/modules/wiki_index.json
Normal file
8
standards/mcp/modules/wiki_index.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"module": "wiki_index",
|
||||
"content": {
|
||||
"path": "wiki_index",
|
||||
"docstring": "# 🧩 Standards — the Aetos App Blueprint\n\nOne reusable architecture for every backend application in the Aetos ecosystem:\na spec-first HTTP edge, a framework-free domain core, a pluggable infrastructure\nlayer, and a single composition root.\n\nFill in **two axes only** and a new app is done: your **resource model**, and\n(if needed) your **pipeline family**. The blueprint itself never names a\nbusiness domain — expenses, health metrics, inventory, and analytics are all\nthe same shape underneath.\n\n> **Doc model:** this wiki is written for humans — how-to guides, the build\n> recipe, and quality gates. The enforceable rules (layering, composition root,\n> CRUD template, pipeline scaffold) and the library registry live in the\n> **reference** pages, mirrored by the machine-readable `standards` MCP bundle.\n> Query `find_library` before writing any infrastructure.\n\n---\n\n## 🚀 Key Features\n\n- 🧭 **Spec-first routing** — the OpenAPI document, not decorator routers, is\n the source of truth (operationId lookup)\n- 🏗️ **One-way layering** — `interfaces → domain → infra`, enforced\n- 🔌 **Single composition root** — every dependency is wired in exactly one place\n- 🧩 **Generic, not app-specific** — reusable rules versus two authoring axes\n- 📚 **Library-backed** — DB, DI, pipelines, ingestion, auth, and docs come from\n internal libraries, never hand-written\n- 🚦 **Explicit state machines** — durable job statuses, progress, and\n human-in-the-loop pauses\n\n---\n\n## 📁 Documentation Structure\n\n| Section | Description |\n|-----------------------------------------------------|--------------------------------------------------------|\n| [Overview](01_overview.md) | Philosophy, the one-way dependency rule, architecture |\n| [App Components](02_components.md) | The component model and how the pieces wire together |\n| [Start an App](03_start_an_app.md) | The entry point: gather the two axes, then build |\n| [Testing & Quality](04_development/01_testing.md) | Test layout and acceptance gates |\n\n**Reference** (separate site, mirrors the MCP bundle): the enforceable\nrules — [Build Recipe](../lib/01_build_recipe/), [Layering](../lib/02_layering_rules/), [Composition\nRoot](../lib/03_composition_root/), [Spec-First\nRouting](../lib/04_spec_first_routing/), [CRUD\nTemplate](../lib/05_crud_template/), [Pipeline\nScaffold](../lib/06_pipeline_scaffold/), [Worker &\nProgress](../lib/07_worker_and_progress/), [Human-in-the-Loop](../lib/08_human_in_loop/),\n[Infra Adapters](../lib/09_infra_adaptors/), [Genericity\nMatrix](../lib/12_genericity_matrix/), [Library\nRegistry](../lib/13_library_registry/).\n\n---\n\n## 🔗 Related Resources\n\n- **MCP bundle** — `standards` server on `:8009`: read `docs://index`,\n `docs://nav`, `docs://modules/{module}`; call `find_library(capability)`\n- **Library registry** — the catalog of internal libraries behind every app\n (`libraries.json`, served as `registry://libraries`)\n- **Template** — the runnable skeleton at `standards/src/templates/app/`\n- **Start a build** — invoke the `start_app` prompt on the `standards` server,\n or read the [Start an App](03_start_an_app.md) guide\n\n---\n\n© Aetoskia Internal — `standards`\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
8
standards/mcp/modules/wiki_overview.json
Normal file
8
standards/mcp/modules/wiki_overview.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"module": "wiki_overview",
|
||||
"content": {
|
||||
"path": "wiki_overview",
|
||||
"docstring": "# Overview\n\nThe blueprint is a **hexagonal (ports & adapters) application** with a\n**spec-first** web edge and a **single composition root**. It favors explicit\nwiring over implicit magic and existing internal libraries over hand-written\ninfrastructure. Start here to build the mental model; the enforceable details\nlive in the reference pages.\n\n---\n\n## 🏗️ Architecture\n\n```mermaid\nflowchart LR\n subgraph EDGE[\"interfaces/ — HTTP edge\"]\n OAS[\"openapi.yaml<br/>operationId contract\"]\n RT[\"<resource>/routes.py<br/>thin handlers\"]\n end\n\n subgraph CORE[\"domain/ — business core\"]\n MD[\"models\"]\n PT[\"ports (adapter binding seam)\"]\n SV[\"services\"]\n end\n\n subgraph INFRA[\"infra/ — adapters\"]\n RP[\"mongo repos (mongo-ops)\"]\n AD[\"cache · stores · llm · mail\"]\n DB[(\"MongoDB\")]\n end\n\n CR[\"init.py<br/>composition root\"]\n\n OAS --> RT\n RT --> SV\n SV --> PT\n SV --> RP\n PT -. depends on .- RP\n CR --- RT\n CR --- SV\n CR --- RP\n RP --> DB\n AD --- CR\n```\n\nThe rule holds at every edge: code in an outer ring may depend on a ring closer\nto the core, never the reverse. `domain/` never imports a web framework;\nonly its `ports/` seam reaches into `infra/` to bind adapters.\n\n> **Legend** — solid arrows are compile-time calls; dotted arrows are the\n> port/adapter binding, performed by the composition root at startup.\n\n---\n\n## 🔄 The one-way dependency rule\n\n| Ring | May import | Never imports |\n|-------------|------------------------------------|----------------------------------|\n| `interfaces/` | `domain`, framework glue (glue only) | business logic, `infra` directly |\n| `domain/` | its own models + its `ports/` seam (which binds `infra`/libraries) | web frameworks, `interfaces/` |\n| `infra/` | `domain` ports, drivers, libraries | — |\n| `init.py` | everything (the wiring point) | — |\n\n---\n\n## 🧭 Core principles\n\n1. **One-way dependencies.** `interfaces -> domain -> infra` is allowed; the\n reverse is forbidden.\n2. **Ports in the domain, adapters in infra.** A service depends on a port; the\n port's factory binds the concrete adapter, and the composition root calls\n those factories.\n3. **One composition root.** Nothing constructs its own dependencies. All\n wiring lives in one module (`init.py`) exposed as a flat resource registry.\n4. **Spec-first.** The HTTP contract is declared in `openapi.yaml`; route\n handlers are looked up by `operationId`. There are no decorator routers.\n5. **Reuse the libraries.** Orchestration, DI, Mongo repositories, ingestion,\n auth, and docs come from internal libraries — see the [Library\n Registry](../lib/13_library_registry/).\n6. **Explicit state machines.** Long-running work moves through explicit,\n durable statuses and can pause for human input.\n\n---\n\n## ⚙️ Runtime processes\n\nA standard app may run as up to three processes that share the same composition\nroot:\n\n| Process | Entry point | Responsibility |\n|---------|------------------------|-------------------------------------------|\n| API | `main.py` | serve HTTP; start/stop resources via lifespan |\n| Worker | `worker.py` | poll durable jobs, run pipelines, publish progress |\n| Scripts | `python -m scripts.<name>` | one-shot operator tasks |\n\n---\n\n## ➡️ Read Next\n\n- [02 – App Components](02_components.md) · [03 – Start an App](03_start_an_app.md)\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
8
standards/mcp/modules/wiki_start_an_app.json
Normal file
8
standards/mcp/modules/wiki_start_an_app.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"module": "wiki_start_an_app",
|
||||
"content": {
|
||||
"path": "wiki_start_an_app",
|
||||
"docstring": "# 🚀 Start an App\n\nThis is the entry point for building a new application from the blueprint. The\ngoal is one deterministic pass: you supply only the **two axes**, and the agent\ndoes the rest by reading the `standards` MCP, importing Tier A libraries, and\ncopying Tier B template components.\n\n> **Doc model:** this page is the human entry point. The deterministic,\n> machine-facing checklist lives in the reference page\n> [Build Recipe](../lib/01_build_recipe/), served as `docs://modules/build_recipe`.\n\n---\n\n## 🧾 What the agent needs from you\n\nGather these before starting — the `start_app` MCP prompt asks for them:\n\n1. **App name + one-line purpose.**\n2. **Axis 1 — resources.** Each resource, its fields, and relationships. Paste\n `openapi.yaml` if you already have it.\n3. **Axis 2 — pipelines.** Only if an input needs a multi-step transformation:\n the families and their input formats (or \"none\").\n4. **Auth needed now?** Default **no**. Auth is deferred (`py-jwt` primitives\n only), and an authless app is just a spec with no `security` keys — see\n [Spec-First Routing → Authless apps](../lib/04_spec_first_routing/#authless-apps).\n5. **Integrations.** Mongo, ingestion formats, email, LLM provider.\n\nIf you can state axes 1 and 2, the rest is mechanical.\n\n---\n\n## ▶️ How to start\n\nFrom an MCP client connected to the `standards` server:\n\n1. Invoke the **`intake`** prompt (or `start_app` with no arguments) to get the\n intake questions.\n2. Answer them, then invoke **`build`**\n (`build(app_name=..., resources=..., pipelines=..., auth=...)`), or use\n **`start_app`** to intake-and-build in one call.\n3. The prompt hands off to `docs://modules/build_recipe`; the agent scaffolds\n with `get_app_template()` and pulls exact files with\n `get_app_component(kind, resource=..., family=...)`, authoring only the\n app-specific parts.\n4. To validate the standard without touching a real app, invoke **`trial`**\n (`trial(app_name=..., build_path=...)`) to build into a scratch directory,\n prove it builds, and report findings.\n\nManual alternative — copy the skeleton and follow the reference recipe:\n\n```bash\ncp -r <docs>/standards/src/templates/app apps/<your-app>\n```\n\n---\n\n## 📚 Reference\n\n- [Build Recipe](../lib/01_build_recipe/) — the deterministic checklist\n- [Genericity Matrix](../lib/12_genericity_matrix/) — Tier A / B / C\n- [Library Registry](../lib/13_library_registry/) — the Tier A catalog\n- [App Components](02_components.md) — the component model\n\n---\n\n## Related\n\n- [01 – Overview](01_overview.md) · [02 – App Components](02_components.md) · [04 – Testing & Quality](04_development/01_testing.md)\n",
|
||||
"objects": {}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,11 @@
|
||||
"resource": "docs://modules/drone_pipelines",
|
||||
"title": "Drone Pipelines"
|
||||
},
|
||||
{
|
||||
"module": "versioning_and_changelog",
|
||||
"resource": "docs://modules/versioning_and_changelog",
|
||||
"title": "Versioning & Changelog"
|
||||
},
|
||||
{
|
||||
"module": "genericity_matrix",
|
||||
"resource": "docs://modules/genericity_matrix",
|
||||
@@ -64,9 +69,44 @@
|
||||
"resource": "docs://modules/auth_integration",
|
||||
"title": "Auth Integration"
|
||||
},
|
||||
{
|
||||
"module": "repository_inventory",
|
||||
"resource": "docs://modules/repository_inventory",
|
||||
"title": "Repository Inventory"
|
||||
},
|
||||
{
|
||||
"module": "index",
|
||||
"resource": "docs://modules/index",
|
||||
"title": "Standards Reference"
|
||||
},
|
||||
{
|
||||
"module": "wiki_overview",
|
||||
"resource": "docs://modules/wiki_overview",
|
||||
"title": "Overview"
|
||||
},
|
||||
{
|
||||
"module": "wiki_components",
|
||||
"resource": "docs://modules/wiki_components",
|
||||
"title": "App Components"
|
||||
},
|
||||
{
|
||||
"module": "wiki_start_an_app",
|
||||
"resource": "docs://modules/wiki_start_an_app",
|
||||
"title": "🚀 Start an App"
|
||||
},
|
||||
{
|
||||
"module": "wiki_development_testing",
|
||||
"resource": "docs://modules/wiki_development_testing",
|
||||
"title": "Testing & Quality Gates"
|
||||
},
|
||||
{
|
||||
"module": "wiki_development_releasing",
|
||||
"resource": "docs://modules/wiki_development_releasing",
|
||||
"title": "Releasing & Versioning"
|
||||
},
|
||||
{
|
||||
"module": "wiki_index",
|
||||
"resource": "docs://modules/wiki_index",
|
||||
"title": "🧩 Standards — the Aetos App Blueprint"
|
||||
}
|
||||
]
|
||||
19
standards/mcp/release.json
Normal file
19
standards/mcp/release.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"project": "standards",
|
||||
"template": "templates/release",
|
||||
"invariant": "git tag == version file (enforced by the Drone guard)",
|
||||
"components": [
|
||||
{
|
||||
"kind": "changelog",
|
||||
"path": "CHANGELOG.md",
|
||||
"placeholder": "",
|
||||
"description": "Keep a Changelog skeleton: one [Unreleased] section + compare links."
|
||||
},
|
||||
{
|
||||
"kind": "version-file",
|
||||
"path": "VERSION",
|
||||
"placeholder": "",
|
||||
"description": "Single-line SemVer source of truth for services and sites."
|
||||
}
|
||||
]
|
||||
}
|
||||
169
standards/mcp/repos.json
Normal file
169
standards/mcp/repos.json
Normal file
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"project": "standards",
|
||||
"note": "Machine-readable repository inventory. Mirrors standards/src/lib/15_repository_inventory.md. Read it with the registry://repos resource or the list_repos tool.",
|
||||
"path_convention": "relative to the aetos/ workspace root",
|
||||
"repos": [
|
||||
{
|
||||
"name": "dagpipe",
|
||||
"type": "package",
|
||||
"path": "dagpipe",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "dagpipe",
|
||||
"port": 8006
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "doc-forge",
|
||||
"type": "package",
|
||||
"path": "doc-forge",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "docforge",
|
||||
"port": 8001
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "hexa",
|
||||
"type": "package",
|
||||
"path": "hexa",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "hexa",
|
||||
"port": 8008
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mail-intake",
|
||||
"type": "package",
|
||||
"path": "mail-intake",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "mail_intake",
|
||||
"port": 8002
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mongo-ops",
|
||||
"type": "package",
|
||||
"path": "mongo-ops",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "mongo_ops",
|
||||
"port": 8007
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "omniread",
|
||||
"type": "package",
|
||||
"path": "omniread",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "omniread",
|
||||
"port": 8003
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "openapi-first",
|
||||
"type": "package",
|
||||
"path": "openapi-first",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "openapi_first",
|
||||
"port": 8004
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "py-jwt",
|
||||
"type": "package",
|
||||
"path": "py-jwt",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": {
|
||||
"server": "jwtlib",
|
||||
"port": 8005
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "auth-server",
|
||||
"type": "service",
|
||||
"path": "auth-server",
|
||||
"version_source": "VERSION",
|
||||
"drone": "service-docker.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": [
|
||||
"api",
|
||||
"lib",
|
||||
"wiki"
|
||||
],
|
||||
"mcp": null
|
||||
},
|
||||
{
|
||||
"name": "docs",
|
||||
"type": "site",
|
||||
"path": "docs",
|
||||
"version_source": "VERSION",
|
||||
"drone": "service-docker.yaml",
|
||||
"trigger": "push",
|
||||
"docs": [],
|
||||
"mcp": null
|
||||
},
|
||||
{
|
||||
"name": "mcp",
|
||||
"type": "site",
|
||||
"path": "mcp",
|
||||
"version_source": "VERSION",
|
||||
"drone": "service-docker.yaml",
|
||||
"trigger": "push",
|
||||
"docs": [],
|
||||
"mcp": null
|
||||
}
|
||||
]
|
||||
}
|
||||
22
standards/mcp/templates/app/CHANGELOG.md
Normal file
22
standards/mcp/templates/app/CHANGELOG.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project are documented here.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
## [0.1.0] - YYYY-MM-DD
|
||||
|
||||
### Added
|
||||
- Initial blueprint app scaffolded from the Aetos standard.
|
||||
|
||||
[Unreleased]: <repo-url>/compare/0.1.0...HEAD
|
||||
[0.1.0]: <repo-url>/releases/tag/0.1.0
|
||||
@@ -12,6 +12,10 @@
|
||||
# Secrets (Drone): PIP_REPO_URL, PIP_USERNAME, PIP_PASSWORD.
|
||||
# Copy to <repo>/.drone.yml unchanged; the package name and version are read
|
||||
# from pyproject.toml, so no per-repo edits are required.
|
||||
#
|
||||
# Version guard: the tag build fails unless the git tag equals the version in
|
||||
# pyproject.toml (see the versioning standard). This stops a tag from looking
|
||||
# like a release while silently publishing nothing.
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@@ -37,6 +41,11 @@ steps:
|
||||
commands:
|
||||
- PACKAGE_NAME=$(grep -E '^name\s*=' pyproject.toml | head -1 | cut -d'"' -f2)
|
||||
- VERSION=$(grep -E '^version\s*=' pyproject.toml | head -1 | cut -d'"' -f2)
|
||||
- |
|
||||
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
||||
echo "Tag '$DRONE_TAG' does not match pyproject version '$VERSION'; refusing to publish."
|
||||
exit 1
|
||||
fi
|
||||
- echo "Checking if $PACKAGE_NAME==$VERSION exists on $PIP_REPO_URL ..."
|
||||
- |
|
||||
if curl -fsSL -u "$PIP_USERNAME:$PIP_PASSWORD" "$PIP_REPO_URL/simple/$PACKAGE_NAME/" | grep -qE "${PACKAGE_NAME}-${VERSION}(-|\.tar\.gz|\.whl)"; then
|
||||
@@ -147,6 +156,12 @@ steps:
|
||||
|
||||
git checkout --force "$TAG"
|
||||
|
||||
TAG_VERSION=$(grep -E '^version\s*=' pyproject.toml | head -1 | cut -d'"' -f2)
|
||||
if [ "$TAG" != "$TAG_VERSION" ]; then
|
||||
echo "Tag $TAG != pyproject version $TAG_VERSION at that commit; skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Building $VERSION"
|
||||
rm -rf dist
|
||||
python -m build
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
# <host-port> published host port; <container-port> the in-image port.
|
||||
# <site> site image name for the site variant (e.g. docs, mcp).
|
||||
# <env-var> runtime environment variable consumed by the service.
|
||||
#
|
||||
# Version guard: the tag-triggered service variant fails unless the git tag
|
||||
# equals the repo-root VERSION file (see the versioning standard). The
|
||||
# push-triggered site variant ships :latest only and has no version to guard.
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@@ -64,6 +68,22 @@ steps:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: check-version
|
||||
image: alpine:3.20
|
||||
commands:
|
||||
- VERSION=$(cat VERSION 2>/dev/null | tr -d '\n')
|
||||
- echo "tag=$DRONE_TAG version=$VERSION"
|
||||
- |
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "VERSION file missing or empty; add it (see versioning standard)."
|
||||
exit 1
|
||||
fi
|
||||
- |
|
||||
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
||||
echo "Tag '$DRONE_TAG' does not match VERSION '$VERSION'; refusing to deploy."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: check-remote-image
|
||||
image: docker:24
|
||||
volumes:
|
||||
|
||||
37
standards/mcp/templates/release/CHANGELOG.md
Normal file
37
standards/mcp/templates/release/CHANGELOG.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project are documented here.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
|
||||
<!--
|
||||
In the release merge request, promote the entries above into a new heading and
|
||||
leave a fresh, empty [Unreleased] section. Name the version/tag, never a commit
|
||||
id:
|
||||
|
||||
## [0.1.0] - YYYY-MM-DD
|
||||
|
||||
### Added
|
||||
- Initial release.
|
||||
|
||||
Then update the compare links below. The tag is created on the merged commit —
|
||||
see the standard: Versioning & Changelog (registry://release).
|
||||
-->
|
||||
|
||||
[Unreleased]: <repo-url>/compare/0.1.0...HEAD
|
||||
[0.1.0]: <repo-url>/releases/tag/0.1.0
|
||||
1
standards/mcp/templates/release/VERSION
Normal file
1
standards/mcp/templates/release/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
0.0.0
|
||||
@@ -25,9 +25,10 @@ needs no edits, the Type B file needs its placeholders filled in (below).
|
||||
For internal libraries. The file contains **two pipelines**:
|
||||
|
||||
1. **`build-and-publish-pypi`** — triggered on `tag`:
|
||||
- `check-version` — read `name` / `version` from `pyproject.toml` and query
|
||||
- `check-version` — **guard**: fail unless `$DRONE_TAG` equals the version in
|
||||
`pyproject.toml`; then read `name` / `version` and query
|
||||
`$PIP_REPO_URL/simple/<package>/`; if that version already exists, exit
|
||||
`78` and skip the whole build.
|
||||
`78` and skip the whole build (see [11 – Versioning & Changelog](11_versioning_and_changelog.md)).
|
||||
- `quality-gate` — install the package with its `[dev]` extras from the
|
||||
private index, then `black --check`, `ruff check`, `mypy`, `pydoclint`,
|
||||
`pytest`.
|
||||
@@ -36,8 +37,9 @@ For internal libraries. The file contains **two pipelines**:
|
||||
2. **`backfill-pypi-from-tags`** — triggered on `custom`:
|
||||
- `fetch-tags` — `git fetch --tags --force`.
|
||||
- `build-and-upload-missing` — walk every tag in version order, skip the ones
|
||||
already on the index, `git checkout` the rest, build, and upload. This is
|
||||
the disaster-recovery / replay path.
|
||||
already on the index, `git checkout` the rest, verify `tag == pyproject
|
||||
version` at that commit, build, and upload. This is the disaster-recovery /
|
||||
replay path.
|
||||
|
||||
Secrets: `PIP_REPO_URL`, `PIP_USERNAME`, `PIP_PASSWORD`.
|
||||
|
||||
@@ -55,6 +57,8 @@ pipelines**, each mirroring a repo family:
|
||||
API/worker service, e.g. `auth-server`):
|
||||
- `fetch-tags` — resolve the latest tag into `LATEST_TAG.txt`; fail if there
|
||||
are no tags.
|
||||
- `check-version` — **guard**: fail unless `$DRONE_TAG` equals the repo-root
|
||||
`VERSION` file (see [11 – Versioning & Changelog](11_versioning_and_changelog.md)).
|
||||
- `check-remote-image` — if `aetos/<app>:<tag>` already exists locally, exit
|
||||
`78` and skip the build.
|
||||
- `quality-gate` — install from `requirements.txt` and run
|
||||
@@ -67,7 +71,8 @@ pipelines**, each mirroring a repo family:
|
||||
--restart always` with the service's `-e` environment.
|
||||
2. **`build-and-deploy-site`** — triggered on `push` (a static/HTTP site, e.g.
|
||||
`docs`, `mcp`): `build-image` → `push-image` → `stop-old` → `run-container`,
|
||||
with no tag resolution and no quality gate.
|
||||
with no tag resolution, no quality gate, and no version guard (it ships
|
||||
`:latest` only).
|
||||
|
||||
Secrets: `PIP_REPO_URL`, `PIP_USERNAME`, `PIP_PASSWORD` (service build args),
|
||||
`REGISTRY_HOST`, `REGISTRY_USER`, `REGISTRY_PASS`, plus the service runtime env
|
||||
@@ -91,6 +96,9 @@ Placeholders to fill in per repo:
|
||||
- Do not inline secrets; always use `from_secret`.
|
||||
- Do not drop the `check-version` / `check-remote-image` skip — it guards the
|
||||
index and the running container against duplicate publishes.
|
||||
- Do not drop the tag↔version guard. A package needs its `pyproject.toml`
|
||||
version to equal the tag; a service needs a root `VERSION` file that equals
|
||||
the tag. See [11 – Versioning & Changelog](11_versioning_and_changelog.md).
|
||||
- Do not rename the pipelines; tooling and runbooks key off
|
||||
`build-and-publish-pypi`, `build-and-deploy-service`, and
|
||||
`build-and-deploy-site`.
|
||||
@@ -99,4 +107,4 @@ Placeholders to fill in per repo:
|
||||
|
||||
## Related
|
||||
|
||||
- [01 – Build Recipe](01_build_recipe.md) · [09 – Infra Adapters](09_infra_adaptors.md) · [13 – Library Registry](13_library_registry.md)
|
||||
- [01 – Build Recipe](01_build_recipe.md) · [09 – Infra Adapters](09_infra_adaptors.md) · [11 – Versioning & Changelog](11_versioning_and_changelog.md) · [13 – Library Registry](13_library_registry.md)
|
||||
|
||||
157
standards/src/lib/11_versioning_and_changelog.md
Normal file
157
standards/src/lib/11_versioning_and_changelog.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# Versioning & Changelog
|
||||
|
||||
## Summary
|
||||
|
||||
Every Aetos artifact — library, service, or site — is versioned with
|
||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) and documents its
|
||||
releases in a [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) file.
|
||||
The **version file is the source of truth**, the **git tag must equal it**, and
|
||||
a Drone guard enforces that equality before anything is published. Releases are
|
||||
cut manually; a tag is what triggers the pipeline.
|
||||
|
||||
This page pairs with [10 – Drone Pipelines](10_drone_pipelines.md): the version
|
||||
and tag contract is exactly what those two CI shapes consume.
|
||||
|
||||
---
|
||||
|
||||
## The version contract
|
||||
|
||||
| Artifact | Source of truth | Notes |
|
||||
|----------|-----------------|-------|
|
||||
| Library (PyPI package) | `version` in `pyproject.toml` | `check-version` also reads it to skip duplicates |
|
||||
| Service / site (Docker) | `VERSION` file at the repo root | one line, `x.y.z`; the service **reads** it (build-arg) — never hardcode the version |
|
||||
|
||||
Rules:
|
||||
|
||||
1. **One version per repository.** No per-module versions.
|
||||
2. **Tag = version.** The git tag is bare SemVer (`0.0.6`), no `v` prefix, and
|
||||
it MUST match the version file byte-for-byte. The Drone guard fails the
|
||||
build otherwise — this is what stops a tag from silently publishing nothing.
|
||||
3. **A release is a tag, created after the change is merged.** The version bump
|
||||
and the changelog promotion travel inside the merge request (MR); the tag is
|
||||
added on the merged commit and pushed. See [Tagging strategy](#tagging-strategy-mr-based).
|
||||
4. **Never reuse a tag.** If a release is wrong, cut a new patch version.
|
||||
|
||||
### Pre-1.0 (0.y.z)
|
||||
|
||||
While a package is `0.y.z`, **`0.y` is treated as the major line**:
|
||||
|
||||
- breaking change → `0.(y+1).0`
|
||||
- new feature → `0.y.(z+1)`
|
||||
- bug fix → `0.y.(z+1)`
|
||||
|
||||
Once a package reaches `1.0.0`, normal SemVer applies. Do not ship `1.0.0`
|
||||
until the public API is considered stable.
|
||||
|
||||
---
|
||||
|
||||
## The changelog
|
||||
|
||||
`CHANGELOG.md` at the repo root, in Keep a Changelog form. It always has exactly
|
||||
one open `[Unreleased]` section with the change categories that apply:
|
||||
|
||||
```markdown
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
### Changed
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
### Security
|
||||
```
|
||||
|
||||
On release you **promote** it — never delete history:
|
||||
|
||||
```markdown
|
||||
## [0.0.6] - 2026-03-07
|
||||
|
||||
### Added
|
||||
- ...
|
||||
```
|
||||
|
||||
and add a link reference at the bottom:
|
||||
|
||||
```markdown
|
||||
[Unreleased]: https://git.aetoskia.com/aetos/<repo>/compare/0.0.6...HEAD
|
||||
[0.0.6]: https://git.aetoskia.com/aetos/<repo>/compare/0.0.5...0.0.6
|
||||
```
|
||||
|
||||
Conventions:
|
||||
|
||||
- Write entries for humans: one line each, imperative, referencing the user
|
||||
impact, not the commit hash.
|
||||
- Categories: **Added**, **Changed**, **Deprecated**, **Removed**, **Fixed**,
|
||||
**Security**. Omit empty categories.
|
||||
- Security fixes get their own entry even if the change is otherwise a bug fix.
|
||||
- The `[Unreleased]` heading is never renamed; copy its content into the new
|
||||
version heading and clear it.
|
||||
|
||||
---
|
||||
|
||||
## Tagging strategy (MR-based)
|
||||
|
||||
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:
|
||||
|
||||
1. **In the MR** — set the intended release version: `version` in
|
||||
`pyproject.toml` (or the `VERSION` file) to `x.y.z`, and promote the
|
||||
changelog (below). Changelog entries and link references name the
|
||||
**version/tag**, never a commit id.
|
||||
2. **Merge or squash** the MR into `main`.
|
||||
3. **Create the tag** `x.y.z` on the resulting commit (the merge/squash commit).
|
||||
4. **Push the tag** (`git push origin x.y.z`) — Drone builds the release.
|
||||
|
||||
Because the version bump is inside the tagged commit, the guard's
|
||||
`tag == version` check can only fail if the wrong commit was tagged.
|
||||
|
||||
### Agent-assisted tagging
|
||||
|
||||
The agent neither authors nor merges the MR, and never tags before the merge.
|
||||
After the user confirms the MR is merged/squashed and says to proceed:
|
||||
|
||||
1. **Wait** for that explicit go-ahead.
|
||||
2. Find the commit that introduced the version bump:
|
||||
- packages:
|
||||
`git log -S 'version = "x.y.z"' -n 1 --format='%H %s' -- pyproject.toml`
|
||||
- services:
|
||||
`git log -S 'x.y.z' -n 1 --format='%H %s' -- VERSION`
|
||||
3. Confirm that commit's version file equals `x.y.z`, then tag **only** that
|
||||
commit, lightweight and bare: `git tag x.y.z <sha>`.
|
||||
4. **Do not push.** Ask the user to push the tag: `git push origin x.y.z`.
|
||||
|
||||
---
|
||||
|
||||
## Release checklist
|
||||
|
||||
1. Confirm the quality gate is green and `main` is up to date.
|
||||
2. In the MR: move every `[Unreleased]` entry under the new version heading with
|
||||
the target date (`## [x.y.z] - YYYY-MM-DD`); restore an empty `[Unreleased]`
|
||||
on top.
|
||||
3. In the MR: add the two compare-link references at the bottom of the
|
||||
changelog, naming the version/tag (never a commit id).
|
||||
4. In the MR: set the version file — `pyproject.toml` (`version = "x.y.z"`) or
|
||||
`VERSION` — to the intended release version.
|
||||
5. Merge or squash the MR into `main`.
|
||||
6. Create the tag on the resulting commit: lightweight `git tag x.y.z`.
|
||||
7. Push the tag (`git push origin x.y.z`). Watch Drone: Type A publishes the
|
||||
wheel/sdist, Type B builds and deploys the image; both first assert
|
||||
`tag == version`.
|
||||
8. Do not reuse the tag if the run fails — fix and cut `x.y.(z+1)`.
|
||||
|
||||
---
|
||||
|
||||
## Why the guard matters
|
||||
|
||||
The version file and the tag are two facts that must agree; nothing in git
|
||||
enforces that by itself. A mismatch is not a theoretical risk — a package can be
|
||||
tagged `0.0.2` while its `pyproject.toml` still says `0.0.1`, and the publish
|
||||
step (which compares the **file** against the index) then skips the build
|
||||
entirely, so `0.0.2` never reaches the index while looking like a release. The
|
||||
Drone guard turns that silent no-op into a hard failure.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [10 – Drone Pipelines](10_drone_pipelines.md) · [15 – Repository Inventory](15_repository_inventory.md) · [01 – Build Recipe](01_build_recipe.md) · [13 – Library Registry](13_library_registry.md)
|
||||
74
standards/src/lib/15_repository_inventory.md
Normal file
74
standards/src/lib/15_repository_inventory.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Repository Inventory
|
||||
|
||||
## Summary
|
||||
|
||||
The canonical list of Aetos repositories covered by the CI and versioning
|
||||
standards, with the artifact each one produces, its version source, and its
|
||||
Drone shape. Every entry maps to the contract in
|
||||
[11 – Versioning & Changelog](11_versioning_and_changelog.md) and the two CI
|
||||
files in [10 – Drone Pipelines](10_drone_pipelines.md).
|
||||
|
||||
The same data is published machine-readably as the `registry://repos` MCP
|
||||
resource (and the `list_repos` tool), sourced from `standards/src/repos.json`.
|
||||
Paths are relative to the `aetos/` workspace root.
|
||||
|
||||
---
|
||||
|
||||
## Packages (Type A)
|
||||
|
||||
A wheel + sdist published to the private index. Version source is
|
||||
`pyproject.toml`; Drone file is `python-lib.yaml` (tag-triggered).
|
||||
|
||||
| Repo | Path | Docs | MCP server |
|
||||
|------|------|------|------------|
|
||||
| `dagpipe` | `dagpipe` | lib, wiki | `dagpipe:8006` |
|
||||
| `doc-forge` | `doc-forge` | lib, wiki | `docforge:8001` |
|
||||
| `hexa` | `hexa` | lib, wiki | `hexa:8008` |
|
||||
| `mail-intake` | `mail-intake` | lib, wiki | `mail_intake:8002` |
|
||||
| `mongo-ops` | `mongo-ops` | lib, wiki | `mongo_ops:8007` |
|
||||
| `omniread` | `omniread` | lib, wiki | `omniread:8003` |
|
||||
| `openapi-first` | `openapi-first` | lib, wiki | `openapi_first:8004` |
|
||||
| `py-jwt` | `py-jwt` | lib, wiki | `jwtlib:8005` |
|
||||
|
||||
---
|
||||
|
||||
## Services & sites (Type B)
|
||||
|
||||
A container image pushed to the registry and run on the Docker host. Version
|
||||
source is the `VERSION` file; Drone file is `service-docker.yaml`.
|
||||
|
||||
| Repo | Type | Path | Trigger | Docs |
|
||||
|------|------|------|---------|------|
|
||||
| `auth-server` | service | `auth-server` | tag | api, lib, wiki |
|
||||
| `docs` | site | `docs` | push | — |
|
||||
| `mcp` | site | `mcp` | push | — |
|
||||
|
||||
The **service** variant is tag-triggered and enforces `tag == VERSION`. The
|
||||
**site** variant is push-triggered, ships `:latest`, and has no tag guard.
|
||||
|
||||
---
|
||||
|
||||
## Required files per repo
|
||||
|
||||
| Type | Version source | Changelog | Drone |
|
||||
|------|----------------|-----------|-------|
|
||||
| package | `pyproject.toml` | `CHANGELOG.md` | `python-lib.yaml` |
|
||||
| service / site | `VERSION` | `CHANGELOG.md` | `service-docker.yaml` |
|
||||
|
||||
Every covered repository must be able to satisfy `tag == version`:
|
||||
the version file (never a commit id) is bumped in the release MR, the MR is
|
||||
merged, and the tag is created on the merged commit.
|
||||
|
||||
---
|
||||
|
||||
## Reading this at runtime
|
||||
|
||||
- Resource: `registry://repos`
|
||||
- Tool: `list_repos()`
|
||||
- Humans: this page (mirror of `standards/src/repos.json`).
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [10 – Drone Pipelines](10_drone_pipelines.md) · [11 – Versioning & Changelog](11_versioning_and_changelog.md) · [13 – Library Registry](13_library_registry.md)
|
||||
@@ -15,6 +15,10 @@ patterns, and the internal library catalog that agents consult while coding.
|
||||
- **Human-in-the-Loop** — guardrails and approvals inside automations.
|
||||
- **Infra Adapters** — how infrastructure connects without leaking into domain.
|
||||
- **Drone Pipelines** — the two CI shapes: a PyPI package or a Docker deployment.
|
||||
- **Versioning & Changelog** — SemVer, the tag↔version contract, and the release
|
||||
changelog.
|
||||
- **Repository Inventory** — every covered repo, its type, version source, and
|
||||
Drone shape.
|
||||
- **Genericity Matrix** — what is library-backed, template-provided, or authored.
|
||||
- **Auth Integration** — consuming the shared auth-server service (spec-driven,
|
||||
no auth code).
|
||||
|
||||
@@ -64,6 +64,8 @@ nav:
|
||||
- Human-in-the-Loop: 08_human_in_loop.md
|
||||
- Infra Adapters: 09_infra_adaptors.md
|
||||
- Drone Pipelines: 10_drone_pipelines.md
|
||||
- Versioning & Changelog: 11_versioning_and_changelog.md
|
||||
- Repository Inventory: 15_repository_inventory.md
|
||||
- Genericity Matrix: 12_genericity_matrix.md
|
||||
- Auth Integration: 14_auth_integration.md
|
||||
- Library Registry: 13_library_registry.md
|
||||
@@ -67,4 +67,5 @@ nav:
|
||||
- Overview: 01_overview.md
|
||||
- App Components: 02_components.md
|
||||
- Start an App: 03_start_an_app.md
|
||||
- Testing & Quality: 04_development/01_testing.md
|
||||
- Testing & Quality: 04_development/01_testing.md
|
||||
- Releasing & Versioning: 04_development/02_releasing.md
|
||||
117
standards/src/repos.json
Normal file
117
standards/src/repos.json
Normal file
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"project": "standards",
|
||||
"note": "Machine-readable repository inventory. Mirrors standards/src/lib/15_repository_inventory.md. Read it with the registry://repos resource or the list_repos tool.",
|
||||
"path_convention": "relative to the aetos/ workspace root",
|
||||
"repos": [
|
||||
{
|
||||
"name": "dagpipe",
|
||||
"type": "package",
|
||||
"path": "dagpipe",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "dagpipe", "port": 8006 }
|
||||
},
|
||||
{
|
||||
"name": "doc-forge",
|
||||
"type": "package",
|
||||
"path": "doc-forge",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "docforge", "port": 8001 }
|
||||
},
|
||||
{
|
||||
"name": "hexa",
|
||||
"type": "package",
|
||||
"path": "hexa",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "hexa", "port": 8008 }
|
||||
},
|
||||
{
|
||||
"name": "mail-intake",
|
||||
"type": "package",
|
||||
"path": "mail-intake",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "mail_intake", "port": 8002 }
|
||||
},
|
||||
{
|
||||
"name": "mongo-ops",
|
||||
"type": "package",
|
||||
"path": "mongo-ops",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "mongo_ops", "port": 8007 }
|
||||
},
|
||||
{
|
||||
"name": "omniread",
|
||||
"type": "package",
|
||||
"path": "omniread",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "omniread", "port": 8003 }
|
||||
},
|
||||
{
|
||||
"name": "openapi-first",
|
||||
"type": "package",
|
||||
"path": "openapi-first",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "openapi_first", "port": 8004 }
|
||||
},
|
||||
{
|
||||
"name": "py-jwt",
|
||||
"type": "package",
|
||||
"path": "py-jwt",
|
||||
"version_source": "pyproject.toml",
|
||||
"drone": "python-lib.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["lib", "wiki"],
|
||||
"mcp": { "server": "jwtlib", "port": 8005 }
|
||||
},
|
||||
{
|
||||
"name": "auth-server",
|
||||
"type": "service",
|
||||
"path": "auth-server",
|
||||
"version_source": "VERSION",
|
||||
"drone": "service-docker.yaml",
|
||||
"trigger": "tag",
|
||||
"docs": ["api", "lib", "wiki"],
|
||||
"mcp": null
|
||||
},
|
||||
{
|
||||
"name": "docs",
|
||||
"type": "site",
|
||||
"path": "docs",
|
||||
"version_source": "VERSION",
|
||||
"drone": "service-docker.yaml",
|
||||
"trigger": "push",
|
||||
"docs": [],
|
||||
"mcp": null
|
||||
},
|
||||
{
|
||||
"name": "mcp",
|
||||
"type": "site",
|
||||
"path": "mcp",
|
||||
"version_source": "VERSION",
|
||||
"drone": "service-docker.yaml",
|
||||
"trigger": "push",
|
||||
"docs": [],
|
||||
"mcp": null
|
||||
}
|
||||
]
|
||||
}
|
||||
22
standards/src/templates/app/CHANGELOG.md
Normal file
22
standards/src/templates/app/CHANGELOG.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project are documented here.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
## [0.1.0] - YYYY-MM-DD
|
||||
|
||||
### Added
|
||||
- Initial blueprint app scaffolded from the Aetos standard.
|
||||
|
||||
[Unreleased]: <repo-url>/compare/0.1.0...HEAD
|
||||
[0.1.0]: <repo-url>/releases/tag/0.1.0
|
||||
@@ -12,6 +12,10 @@
|
||||
# Secrets (Drone): PIP_REPO_URL, PIP_USERNAME, PIP_PASSWORD.
|
||||
# Copy to <repo>/.drone.yml unchanged; the package name and version are read
|
||||
# from pyproject.toml, so no per-repo edits are required.
|
||||
#
|
||||
# Version guard: the tag build fails unless the git tag equals the version in
|
||||
# pyproject.toml (see the versioning standard). This stops a tag from looking
|
||||
# like a release while silently publishing nothing.
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@@ -37,6 +41,11 @@ steps:
|
||||
commands:
|
||||
- PACKAGE_NAME=$(grep -E '^name\s*=' pyproject.toml | head -1 | cut -d'"' -f2)
|
||||
- VERSION=$(grep -E '^version\s*=' pyproject.toml | head -1 | cut -d'"' -f2)
|
||||
- |
|
||||
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
||||
echo "Tag '$DRONE_TAG' does not match pyproject version '$VERSION'; refusing to publish."
|
||||
exit 1
|
||||
fi
|
||||
- echo "Checking if $PACKAGE_NAME==$VERSION exists on $PIP_REPO_URL ..."
|
||||
- |
|
||||
if curl -fsSL -u "$PIP_USERNAME:$PIP_PASSWORD" "$PIP_REPO_URL/simple/$PACKAGE_NAME/" | grep -qE "${PACKAGE_NAME}-${VERSION}(-|\.tar\.gz|\.whl)"; then
|
||||
@@ -147,6 +156,12 @@ steps:
|
||||
|
||||
git checkout --force "$TAG"
|
||||
|
||||
TAG_VERSION=$(grep -E '^version\s*=' pyproject.toml | head -1 | cut -d'"' -f2)
|
||||
if [ "$TAG" != "$TAG_VERSION" ]; then
|
||||
echo "Tag $TAG != pyproject version $TAG_VERSION at that commit; skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Building $VERSION"
|
||||
rm -rf dist
|
||||
python -m build
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
# <host-port> published host port; <container-port> the in-image port.
|
||||
# <site> site image name for the site variant (e.g. docs, mcp).
|
||||
# <env-var> runtime environment variable consumed by the service.
|
||||
#
|
||||
# Version guard: the tag-triggered service variant fails unless the git tag
|
||||
# equals the repo-root VERSION file (see the versioning standard). The
|
||||
# push-triggered site variant ships :latest only and has no version to guard.
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@@ -64,6 +68,22 @@ steps:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: check-version
|
||||
image: alpine:3.20
|
||||
commands:
|
||||
- VERSION=$(cat VERSION 2>/dev/null | tr -d '\n')
|
||||
- echo "tag=$DRONE_TAG version=$VERSION"
|
||||
- |
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "VERSION file missing or empty; add it (see versioning standard)."
|
||||
exit 1
|
||||
fi
|
||||
- |
|
||||
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
||||
echo "Tag '$DRONE_TAG' does not match VERSION '$VERSION'; refusing to deploy."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: check-remote-image
|
||||
image: docker:24
|
||||
volumes:
|
||||
|
||||
37
standards/src/templates/release/CHANGELOG.md
Normal file
37
standards/src/templates/release/CHANGELOG.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project are documented here.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
|
||||
<!--
|
||||
In the release merge request, promote the entries above into a new heading and
|
||||
leave a fresh, empty [Unreleased] section. Name the version/tag, never a commit
|
||||
id:
|
||||
|
||||
## [0.1.0] - YYYY-MM-DD
|
||||
|
||||
### Added
|
||||
- Initial release.
|
||||
|
||||
Then update the compare links below. The tag is created on the merged commit —
|
||||
see the standard: Versioning & Changelog (registry://release).
|
||||
-->
|
||||
|
||||
[Unreleased]: <repo-url>/compare/0.1.0...HEAD
|
||||
[0.1.0]: <repo-url>/releases/tag/0.1.0
|
||||
1
standards/src/templates/release/VERSION
Normal file
1
standards/src/templates/release/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
0.0.0
|
||||
119
standards/src/wiki/04_development/02_releasing.md
Normal file
119
standards/src/wiki/04_development/02_releasing.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Releasing & Versioning
|
||||
|
||||
How to cut a release of any Aetos repository. The rule lives in the reference
|
||||
page [Versioning & Changelog](../lib/11_versioning_and_changelog/); this is the
|
||||
runbook you follow.
|
||||
|
||||
Every repository is one of two Drone shapes — a **PyPI package** or a **Docker
|
||||
deployment** ([Drone Pipelines](../lib/10_drone_pipelines/)). Both release the
|
||||
same way: the version bump and changelog promotion go **in the merge request**,
|
||||
and the tag is created on the merged commit.
|
||||
|
||||
---
|
||||
|
||||
## 🧾 Before you start
|
||||
|
||||
- You have an open **merge request** holding the change, and `main` is green
|
||||
(the Drone quality gate passed on the last run).
|
||||
- You know whether this is a **breaking**, **feature**, or **fix** release.
|
||||
- The version file exists:
|
||||
- package → `version` in `pyproject.toml`
|
||||
- service / site → `VERSION` at the repo root
|
||||
|
||||
---
|
||||
|
||||
## 🚦 Pick the next version
|
||||
|
||||
The version file and the tag must be identical. For `0.y.z`, `0.y` is the major
|
||||
line (see the reference page); once at `1.0.0`, normal SemVer applies.
|
||||
|
||||
| Change | `0.y.z` → | `1.0.0+` → |
|
||||
|--------|-----------|------------|
|
||||
| Breaking | `0.(y+1).0` | `(x+1).0.0` |
|
||||
| Feature | `0.y.(z+1)` | `x.(y+1).0` |
|
||||
| Fix | `0.y.(z+1)` | `x.y.(z+1)` |
|
||||
|
||||
---
|
||||
|
||||
## 🌿 Release in the MR
|
||||
|
||||
The version is known while the change is still a merge request, so the bump
|
||||
rides along with it. Do both edits **in the MR**:
|
||||
|
||||
- **Promote the changelog** in `CHANGELOG.md`: move the `[Unreleased]` content
|
||||
under a new `## [x.y.z] - YYYY-MM-DD` heading, leave a fresh empty
|
||||
`[Unreleased]` on top, and add the compare links — naming the **version/tag**,
|
||||
never a commit id:
|
||||
|
||||
```markdown
|
||||
[Unreleased]: https://git.aetoskia.com/aetos/<repo>/compare/x.y.z...HEAD
|
||||
[x.y.z]: https://git.aetoskia.com/aetos/<repo>/compare/x.y.(z-1)...x.y.z
|
||||
```
|
||||
|
||||
- **Bump the version file** to the intended release version: `version = "x.y.z"`
|
||||
in `pyproject.toml` (packages) or the `VERSION` file (services/sites).
|
||||
|
||||
---
|
||||
|
||||
## 🏷️ Tag the merged commit
|
||||
|
||||
1. **Merge or squash** the MR into `main`.
|
||||
2. **Create the tag** on the resulting commit: `git tag x.y.z` (lightweight).
|
||||
3. **Push the tag** (`git push origin x.y.z`) — Drone builds the release.
|
||||
|
||||
### 🤖 Agent-assisted tagging
|
||||
|
||||
The agent does not author or merge the MR and never tags before the merge. After
|
||||
you confirm the MR is merged/squashed and tell it to proceed, the agent:
|
||||
|
||||
1. Waits for that explicit go-ahead.
|
||||
2. Finds the commit that introduced the bump:
|
||||
- package:
|
||||
`git log -S 'version = "x.y.z"' -n 1 --format='%H %s' -- pyproject.toml`
|
||||
- service / site:
|
||||
`git log -S 'x.y.z' -n 1 --format='%H %s' -- VERSION`
|
||||
3. Verifies that commit's version file equals `x.y.z`, then tags **only** that
|
||||
commit: `git tag x.y.z <sha>`.
|
||||
4. Does **not** push — it asks you to run `git push origin x.y.z`.
|
||||
|
||||
---
|
||||
|
||||
## 🤖 What Drone does
|
||||
|
||||
- **Type A (package):** asserts `tag == pyproject version`, then skips if that
|
||||
version already exists on the index, runs the quality gate, builds, and
|
||||
uploads the wheel + sdist.
|
||||
- **Type B (service):** asserts `tag == VERSION`, resolves the tag, skips if the
|
||||
image already exists, runs the quality gate, builds, pushes, and restarts the
|
||||
container.
|
||||
- **Type B (site):** triggered on push, ships `:latest` and has no tag guard.
|
||||
|
||||
If the guard fails, nothing is published — fix the version file, amend the
|
||||
commit, and move the tag **only** if it was never pushed.
|
||||
|
||||
---
|
||||
|
||||
## 🛟 Backfill / recovery
|
||||
|
||||
If an older tag never published (a past version-file mismatch, an index
|
||||
outage):
|
||||
|
||||
- **Package:** run the `backfill-pypi-from-tags` pipeline (custom event). It
|
||||
checks out every tag, verifies `tag == pyproject version` at that commit,
|
||||
and uploads the ones missing from the index. Already-fixed history is never
|
||||
rewritten.
|
||||
- **Service:** rebuild the image for the missing tag with a fresh commit and a
|
||||
new patch version; do not move a published tag.
|
||||
|
||||
---
|
||||
|
||||
## 🔁 If a release is wrong
|
||||
|
||||
- Never reuse or force-move a pushed tag.
|
||||
- Fix forward: bump to the next patch, promote the changelog, tag again.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [Testing & Quality Gates](01_testing.md) · [Versioning & Changelog](../lib/11_versioning_and_changelog/) · [Drone Pipelines](../lib/10_drone_pipelines/)
|
||||
@@ -291,6 +291,25 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../04_development/02_releasing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -523,6 +542,28 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../04_development/02_releasing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -291,6 +291,25 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../04_development/02_releasing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -598,6 +617,28 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../04_development/02_releasing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -291,6 +291,25 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../04_development/02_releasing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -514,6 +533,28 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../04_development/02_releasing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
<link rel="prev" href="../../03_start_an_app/">
|
||||
|
||||
|
||||
<link rel="next" href="../02_releasing/">
|
||||
|
||||
|
||||
<link rel="icon" href="../../assets/images/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
|
||||
@@ -289,6 +291,25 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../02_releasing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -539,6 +560,28 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../02_releasing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
811
standards/wiki/04_development/02_releasing/index.html
Normal file
811
standards/wiki/04_development/02_releasing/index.html
Normal file
@@ -0,0 +1,811 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<meta name="description" content="The philosophy and prompts behind the standardized application blueprint.">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="prev" href="../01_testing/">
|
||||
|
||||
|
||||
|
||||
<link rel="icon" href="../../assets/images/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
|
||||
|
||||
|
||||
|
||||
<title>Releasing & Versioning - Aetos Standards — Wiki</title>
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../assets/stylesheets/main.84d31ad4.min.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan">
|
||||
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#releasing-versioning" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href="../.." title="Aetos Standards — Wiki" class="md-header__button md-logo" aria-label="Aetos Standards — Wiki" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Aetos Standards — Wiki
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
||||
</label>
|
||||
<div class="md-search" data-md-component="search" role="dialog">
|
||||
<label class="md-search__overlay" for="__search"></label>
|
||||
<div class="md-search__inner" role="search">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
||||
<label class="md-search__icon md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
|
||||
</label>
|
||||
<nav class="md-search__options" aria-label="Search">
|
||||
|
||||
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
|
||||
</a>
|
||||
|
||||
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
||||
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Initializing search
|
||||
</div>
|
||||
<ol class="md-search-result__list" role="presentation"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
|
||||
<div class="md-grid">
|
||||
<ul class="md-tabs__list">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../.." class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Home
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../../01_overview/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Overview
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../../02_components/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
App Components
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../../03_start_an_app/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Start an App
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../01_testing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Testing & Quality
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item md-tabs__item--active">
|
||||
<a href="./" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary md-nav--lifted md-nav--integrated" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href="../.." title="Aetos Standards — Wiki" class="md-nav__button md-logo" aria-label="Aetos Standards — Wiki" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
|
||||
|
||||
</a>
|
||||
Aetos Standards — Wiki
|
||||
</label>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../.." class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Home
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../../01_overview/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Overview
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../../02_components/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
App Components
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../../03_start_an_app/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Start an App
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../01_testing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Testing & Quality
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
|
||||
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
<a href="./" class="md-nav__link md-nav__link--active">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#before-you-start" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🧾 Before you start
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#pick-the-next-version" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🚦 Pick the next version
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#release-in-the-mr" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🌿 Release in the MR
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#tag-the-merged-commit" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🏷️ Tag the merged commit
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="🏷️ Tag the merged commit">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#agent-assisted-tagging" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🤖 Agent-assisted tagging
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#what-drone-does" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🤖 What Drone does
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#backfill-recovery" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🛟 Backfill / recovery
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#if-a-release-is-wrong" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
🔁 If a release is wrong
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#related" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Related
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1 id="releasing-versioning">Releasing & Versioning</h1>
|
||||
<p>How to cut a release of any Aetos repository. The rule lives in the reference
|
||||
page <a href="../lib/11_versioning_and_changelog/">Versioning & Changelog</a>; this is the
|
||||
runbook you follow.</p>
|
||||
<p>Every repository is one of two Drone shapes — a <strong>PyPI package</strong> or a <strong>Docker
|
||||
deployment</strong> (<a href="../lib/10_drone_pipelines/">Drone Pipelines</a>). Both release the
|
||||
same way: the version bump and changelog promotion go <strong>in the merge request</strong>,
|
||||
and the tag is created on the merged commit.</p>
|
||||
<hr />
|
||||
<h2 id="before-you-start">🧾 Before you start</h2>
|
||||
<ul>
|
||||
<li>You have an open <strong>merge request</strong> holding the change, and <code>main</code> is green
|
||||
(the Drone quality gate passed on the last run).</li>
|
||||
<li>You know whether this is a <strong>breaking</strong>, <strong>feature</strong>, or <strong>fix</strong> release.</li>
|
||||
<li>The version file exists:</li>
|
||||
<li>package → <code>version</code> in <code>pyproject.toml</code></li>
|
||||
<li>service / site → <code>VERSION</code> at the repo root</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="pick-the-next-version">🚦 Pick the next version</h2>
|
||||
<p>The version file and the tag must be identical. For <code>0.y.z</code>, <code>0.y</code> is the major
|
||||
line (see the reference page); once at <code>1.0.0</code>, normal SemVer applies.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Change</th>
|
||||
<th><code>0.y.z</code> →</th>
|
||||
<th><code>1.0.0+</code> →</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Breaking</td>
|
||||
<td><code>0.(y+1).0</code></td>
|
||||
<td><code>(x+1).0.0</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Feature</td>
|
||||
<td><code>0.y.(z+1)</code></td>
|
||||
<td><code>x.(y+1).0</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fix</td>
|
||||
<td><code>0.y.(z+1)</code></td>
|
||||
<td><code>x.y.(z+1)</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h2 id="release-in-the-mr">🌿 Release in the MR</h2>
|
||||
<p>The version is known while the change is still a merge request, so the bump
|
||||
rides along with it. Do both edits <strong>in the MR</strong>:</p>
|
||||
<ul>
|
||||
<li><strong>Promote the changelog</strong> in <code>CHANGELOG.md</code>: move the <code>[Unreleased]</code> content
|
||||
under a new <code>## [x.y.z] - YYYY-MM-DD</code> heading, leave a fresh empty
|
||||
<code>[Unreleased]</code> on top, and add the compare links — naming the <strong>version/tag</strong>,
|
||||
never a commit id:</li>
|
||||
</ul>
|
||||
<div class="language-markdown highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-1">1</a></span>
|
||||
<span class="normal"><a href="#__codelineno-0-2">2</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1"></a>[<span class="nl">Unreleased</span>]: <span class="na">https://git.aetoskia.com/aetos/<repo>/compare/x.y.z...HEAD</span>
|
||||
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2"></a>[<span class="nl">x.y.z</span>]: <span class="na">https://git.aetoskia.com/aetos/<repo>/compare/x.y.(z-1)...x.y.z</span>
|
||||
</span></code></pre></div></td></tr></table></div>
|
||||
<ul>
|
||||
<li><strong>Bump the version file</strong> to the intended release version: <code>version = "x.y.z"</code>
|
||||
in <code>pyproject.toml</code> (packages) or the <code>VERSION</code> file (services/sites).</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="tag-the-merged-commit">🏷️ Tag the merged commit</h2>
|
||||
<ol>
|
||||
<li><strong>Merge or squash</strong> the MR into <code>main</code>.</li>
|
||||
<li><strong>Create the tag</strong> on the resulting commit: <code>git tag x.y.z</code> (lightweight).</li>
|
||||
<li><strong>Push the tag</strong> (<code>git push origin x.y.z</code>) — Drone builds the release.</li>
|
||||
</ol>
|
||||
<h3 id="agent-assisted-tagging">🤖 Agent-assisted tagging</h3>
|
||||
<p>The agent does not author or merge the MR and never tags before the merge. After
|
||||
you confirm the MR is merged/squashed and tell it to proceed, the agent:</p>
|
||||
<ol>
|
||||
<li>Waits for that explicit go-ahead.</li>
|
||||
<li>Finds the commit that introduced the bump:</li>
|
||||
<li>package:
|
||||
<code>git log -S 'version = "x.y.z"' -n 1 --format='%H %s' -- pyproject.toml</code></li>
|
||||
<li>service / site:
|
||||
<code>git log -S 'x.y.z' -n 1 --format='%H %s' -- VERSION</code></li>
|
||||
<li>Verifies that commit's version file equals <code>x.y.z</code>, then tags <strong>only</strong> that
|
||||
commit: <code>git tag x.y.z <sha></code>.</li>
|
||||
<li>Does <strong>not</strong> push — it asks you to run <code>git push origin x.y.z</code>.</li>
|
||||
</ol>
|
||||
<hr />
|
||||
<h2 id="what-drone-does">🤖 What Drone does</h2>
|
||||
<ul>
|
||||
<li><strong>Type A (package):</strong> asserts <code>tag == pyproject version</code>, then skips if that
|
||||
version already exists on the index, runs the quality gate, builds, and
|
||||
uploads the wheel + sdist.</li>
|
||||
<li><strong>Type B (service):</strong> asserts <code>tag == VERSION</code>, resolves the tag, skips if the
|
||||
image already exists, runs the quality gate, builds, pushes, and restarts the
|
||||
container.</li>
|
||||
<li><strong>Type B (site):</strong> triggered on push, ships <code>:latest</code> and has no tag guard.</li>
|
||||
</ul>
|
||||
<p>If the guard fails, nothing is published — fix the version file, amend the
|
||||
commit, and move the tag <strong>only</strong> if it was never pushed.</p>
|
||||
<hr />
|
||||
<h2 id="backfill-recovery">🛟 Backfill / recovery</h2>
|
||||
<p>If an older tag never published (a past version-file mismatch, an index
|
||||
outage):</p>
|
||||
<ul>
|
||||
<li><strong>Package:</strong> run the <code>backfill-pypi-from-tags</code> pipeline (custom event). It
|
||||
checks out every tag, verifies <code>tag == pyproject version</code> at that commit,
|
||||
and uploads the ones missing from the index. Already-fixed history is never
|
||||
rewritten.</li>
|
||||
<li><strong>Service:</strong> rebuild the image for the missing tag with a fresh commit and a
|
||||
new patch version; do not move a published tag.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="if-a-release-is-wrong">🔁 If a release is wrong</h2>
|
||||
<ul>
|
||||
<li>Never reuse or force-move a pushed tag.</li>
|
||||
<li>Fix forward: bump to the next patch, promote the changelog, tag again.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="related">Related</h2>
|
||||
<ul>
|
||||
<li><a href="../01_testing/">Testing & Quality Gates</a> · <a href="../lib/11_versioning_and_changelog/">Versioning & Changelog</a> · <a href="../lib/10_drone_pipelines/">Drone Pipelines</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
|
||||
|
||||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
||||
</div>
|
||||
|
||||
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
|
||||
Back to top
|
||||
</button>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": ["navigation.sections", "navigation.expand", "navigation.top", "navigation.instant", "navigation.tracking", "navigation.indexes", "navigation.tabs", "toc.integrate", "header.autohide", "content.code.copy", "content.code.annotate", "content.tabs.link", "content.action.edit", "search.highlight", "search.share", "search.suggest"], "search": "../../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
||||
|
||||
|
||||
<script src="../../assets/javascripts/bundle.f55a23d4.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/mermaid@10.9.1/dist/mermaid.min.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -280,6 +280,25 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="/04_development/02_releasing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -425,6 +444,28 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/04_development/02_releasing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -289,6 +289,25 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="04_development/02_releasing/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Releasing & Versioning
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -503,6 +522,28 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="04_development/02_releasing/" class="md-nav__link">
|
||||
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Releasing & Versioning
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Reference in New Issue
Block a user