Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .github/workflows/release-please.yml

This file was deleted.

65 changes: 58 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ name: Release
# Tag-triggered distribution. On a `vX.Y.Z` tag this publishes the user-facing
# install channels; docker.yml (gateway image) and release-airgap.yml (offline
# bundle) fire on the same tag, so one tag fans out to every channel.
#
# The tag is the version authority (ADR-0053): scripts/stamp_versions.py stamps
# X.Y.Z onto every workspace component + the rag-platform meta before building,
# npm stamps the TS SDK, and helm stamps the chart — so every artifact a tag
# produces carries the same platform version, and the meta's `==X.Y.Z` pins
# resolve against the component dists published from the very same run.
on:
push:
tags: ["v*.*.*"]
Expand All @@ -12,6 +18,10 @@ on:
description: "Build artifacts but skip publishing"
type: boolean
default: true
version:
description: "Platform version to stamp on non-tag builds"
type: string
default: "0.0.0"

permissions:
contents: read
Expand All @@ -21,7 +31,7 @@ env:

jobs:
pypi:
name: PyPI (rag-platform + SDK)
name: PyPI (components + rag-platform + SDK)
runs-on: ubuntu-22.04
permissions:
id-token: write # PyPI Trusted Publishing (OIDC) — no API token
Expand All @@ -30,11 +40,26 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install build
- name: Build meta-distribution + SDK
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Resolve platform version
id: ver
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
python -m build --outdir dist-pypi packaging/rag-platform
python -m build --outdir dist-pypi sdks/python
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
else
echo "version=${INPUT_VERSION}" >> "$GITHUB_OUTPUT"
fi
- name: Stamp the platform version onto every dist
run: python scripts/stamp_versions.py "${{ steps.ver.outputs.version }}"
- name: Build every workspace component + the Python SDK
run: uv build --all-packages --out-dir dist-pypi
- name: Build the rag-platform meta-distribution
run: uv build packaging/rag-platform --out-dir dist-pypi
- name: Publish to PyPI
if: ${{ github.event_name == 'push' || !inputs.dry_run }}
uses: pypa/gh-action-pypi-publish@release/v1
Expand All @@ -52,9 +77,20 @@ jobs:
with:
node-version: 20
registry-url: "https://registry.npmjs.org"
- name: Resolve platform version
id: ver
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
else
echo "version=${INPUT_VERSION}" >> "$GITHUB_OUTPUT"
fi
- working-directory: sdks/typescript
run: |
npm ci
npm version "${{ steps.ver.outputs.version }}" --no-git-tag-version --allow-same-version
npm run build
- name: Publish (with provenance)
if: ${{ github.event_name == 'push' || !inputs.dry_run }}
Expand Down Expand Up @@ -119,11 +155,26 @@ jobs:
- uses: actions/checkout@v6
- uses: azure/setup-helm@v4
- uses: sigstore/cosign-installer@v3
- name: Package + push + sign
- name: Resolve platform version
id: ver
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
else
echo "version=${INPUT_VERSION}" >> "$GITHUB_OUTPUT"
fi
- name: Package (chart version = platform version)
run: |
helm package infra/helm/rag-platform --destination . \
--version "${{ steps.ver.outputs.version }}" \
--app-version "${{ steps.ver.outputs.version }}"
- name: Push + sign
if: ${{ github.event_name == 'push' || !inputs.dry_run }}
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login "${REGISTRY}" -u "${{ github.actor }}" --password-stdin
repo="oci://${REGISTRY}/$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')/agentcontextos/charts"
helm package infra/helm/rag-platform --destination .
chart="$(ls rag-platform-*.tgz)"
out="$(helm push "${chart}" "${repo}" 2>&1)"; echo "${out}"
digest="$(echo "${out}" | awk '/Digest:/ {print $2}')"
Expand Down
4 changes: 0 additions & 4 deletions .release-please-manifest.json

This file was deleted.

4 changes: 4 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,7 @@ Add a **Documentation** section listing the doc file(s) added or updated so revi
- Every SPI method takes `ctx: RequestContext` first (Step 1.1a onward).
- Every retrieval / ingest / egress call site consults `PolicyEngine` (Step 1.1c onward).
- Hot-path discipline: Pydantic at SPI boundaries only; `model_construct()` / msgspec inside loops.
- One platform version (ADR-0053): every workspace member, literal `__version__`, and the
`rag-platform` meta (its `==` pins included) carry the same version in lockstep — never bump a
single package by hand. Re-stamp with `task version:stamp -- X.Y.Z`
(`scripts/stamp_versions.py`); gated by `tests/packaging/`. Release tags re-stamp in CI.
5 changes: 3 additions & 2 deletions TRACKER.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
| **Last updated** | 2026-06-10 |
| **Current phase** | Phase 7 — Pilot, Harden, GA (**10 / 10 steps ✅**) — **all phases complete** |
| **Overall** | **84 / 84 steps ✅ — v1.0.0 GA** |
| **Next action** | **🎉 GA reached.** Engineering scope (Phases 0–7) complete; `v1.0.0` cut. Remaining items are external/process (external pentest, SOC 2 audit, registry first-publish, signed referenceable customers, on-call staffing + status page, launch assets) — tracked in the [GA readiness checklist](docs/ga/ga-readiness-checklist.md). Post-GA: cut the **v1.0.1** patch tag (serve-path fix below; note: GitHub Actions runs are currently blocked by an account **billing/spending-limit** failure — every `docker.yml` run since GA failed at job start, so the GHCR image was never actually published), then the V1.1 backlog. |
| **Next action** | **🎉 GA reached.** Engineering scope (Phases 0–7) complete; `v1.0.0` cut. Remaining items are external/process (external pentest, SOC 2 audit, registry first-publish, signed referenceable customers, on-call staffing + status page, launch assets) — tracked in the [GA readiness checklist](docs/ga/ga-readiness-checklist.md). Post-GA: cut the **v1.0.1** patch tag (serve-path + PyPI lockstep-publishing fixes below; note: GitHub Actions runs are currently blocked by an account **billing/spending-limit** failure — every `docker.yml` run since GA failed at job start, so the GHCR image was never actually published; also **3 PyPI name collisions** — `rag-agent`/`rag-reranker`/`rag-retrieval` are owned by unrelated third-party projects, so rename those dists *before* the first publish — see the [registry item](docs/ga/ga-readiness-checklist.md#distribution)), then the V1.1 backlog. |

**Recently shipped**

- **v1.0.1** ✅ *(patch)* — **production serve path fixed end-to-end.** The image's default CMD (a Phase-0 placeholder that printed the version and exited) now serves via the new config-driven **`rag_gateway.serve:create_app`** uvicorn-factory entrypoint: `RAG_CONFIG_PATH` set → `build_app_from_config(load(path))`, unset → noop `build_app()`, set-but-broken → **fail fast** (`ConfigError`), never a silent noop fallback. The image **build** itself was also broken — the full `uv sync` needs every workspace member on disk but `sdks/python` was never copied (`Distribution not found`); both stages now copy it. New public **`GET /readyz`** backs the Helm chart's readiness probe (liveness stays `/healthz`). The chart's ConfigMap previously rendered an *invalid* `rag.yaml` (`env:/log_level:/service:` against the strict `extra='forbid'` schema → guaranteed CrashLoop); it now renders a minimal valid document with a **`config.ragYaml`** passthrough for full platform configs (`${VAR}` env interpolation keeps secrets out of the ConfigMap), chart `0.2.0` / `appVersion` `1.0.1` (the old `0.1.0` appVersion pointed the default image tag at a tag that never existed), `values.dev.yaml` `env: development` → `local`. Docs: image tags are published *without* the `v` prefix — `:v1.0.0`-style pulls in README/release-notes never matched. [release notes](docs/release-notes/v1.0.1.md) [#185](https://github.com/officialCodeWork/AgentContextOS/pull/185)
- **v1.0.1** ✅ *(patch)* — **production serve path fixed end-to-end.** The image's default CMD (a Phase-0 placeholder that printed the version and exited) now serves via the new config-driven **`rag_gateway.serve:create_app`** uvicorn-factory entrypoint: `RAG_CONFIG_PATH` set → `build_app_from_config(load(path))`, unset → noop `build_app()`, set-but-broken → **fail fast** (`ConfigError`), never a silent noop fallback. The image **build** itself was also broken — the full `uv sync` needs every workspace member on disk but `sdks/python` was never copied (`Distribution not found`); both stages now copy it. New public **`GET /readyz`** backs the Helm chart's readiness probe (liveness stays `/healthz`). The chart's ConfigMap previously rendered an *invalid* `rag.yaml` (`env:/log_level:/service:` against the strict `extra='forbid'` schema → guaranteed CrashLoop); it now renders a minimal valid document with a **`config.ragYaml`** passthrough for full platform configs (`${VAR}` env interpolation keeps secrets out of the ConfigMap), chart `0.2.0` / `appVersion` `1.0.1` (the old `0.1.0` appVersion pointed the default image tag at a tag that never existed), `values.dev.yaml` `env: development` → `local`. Docs: image tags are published *without* the `v` prefix — `:v1.0.0`-style pulls in README/release-notes never matched. **One reported version**: `rag_gateway.__version__` (0.7.0), the OpenAPI `info.version` (0.10.0), and `GET /v1/info` (0.9.0) had each hard-coded a different stale number — all now read the `rag-gateway` package version, single-sourced in `apps/gateway/pyproject.toml` (**1.0.1**, matching the platform release) via `importlib.metadata` (`rag_gateway._version`); `dist/openapi.*` + REST reference regenerated; `rag-platform` meta → `1.0.1` (its `rag-gateway==1.0.0` pin pointed at a version that never existed); a gateway test pins every surface to the package metadata. **PyPI channel actually publishes** ([ADR-0053](docs/adr/ADR-0053-lockstep-component-publishing.md)): `release.yml` only ever built the meta + SDK — none of the 16 pinned component dists were published, one pin named a dist that doesn't exist (`ragctl`; the workspace dist is `rag-ragctl`), 15 transitive components were unpinned, the `[backends]`/`[kms]` extras referenced extras `rag-backends` never declared, the metadata-only meta wheel didn't even build (hatchling needs `bypass-selection`), and workspace versions ranged 0.1.0–0.26.0 — so `pip install rag-platform` could **never resolve**. Now: **one lockstep platform version stamped from the tag** — `scripts/stamp_versions.py` rewrites every version site (member pyprojects + literal `__version__`s + the meta and all its `==` pins; `task version:stamp`), `release.yml` stamps then publishes the **complete closure (33 dists)** via `uv build --all-packages` + Trusted Publishing, npm (`npm version`) + Helm (`--version/--app-version`, chart version = platform version) stamp natively in the same run; the meta pins all **31** components exactly; `tests/packaging/test_meta_package.py` gates lockstep + closure-completeness + extras-validity; vestigial **release-please removed** (2/32 members, manifest frozen at 0.2.0, `core-v*` tags matched no workflow — the tag is the only version authority). Verified end-to-end: all 33 dists build and `pip install rag-platform==1.0.1` resolves + imports + runs `ragctl` from them. [release notes](docs/release-notes/v1.0.1.md) [#185](https://github.com/officialCodeWork/AgentContextOS/pull/185) [#186](https://github.com/officialCodeWork/AgentContextOS/pull/186)
- **7.10** ✅ **GA cutover — v1.0.0** 🎉 — the close of an 8-phase, 84-step build. Cut **`v1.0.0`** with **Semantic Versioning** over the drift-gated public contracts (REST/OpenAPI · gRPC proto · `rag.yaml` · SDKs · `ragctl`) + a deprecation policy ([ADR-0052](docs/adr/ADR-0052-ga-cutover.md)); the `rag-platform` meta bumped to 1.0.0. GA **release notes** ([v1.0.0](docs/release-notes/v1.0.0.md)) + a **GA readiness checklist** ([ga-readiness-checklist](docs/ga/ga-readiness-checklist.md)) that maps every Phase 7 exit gate to a CI gate / in-repo artifact, with inherently-external items (external pentest, SOC 2 audit, registry first-publish, signed customers, on-call staffing, launch assets) marked **(external)** — the same in-repo-machine vs external-deliverable split used across Phase 7. The `v1.0.0` tag fans out to every channel via `docker.yml` + `release.yml` + `release-airgap.yml`.
- **7.9** ✅ Billing & metering — per-tenant usage accounting, **mirroring the 5.6c cost pattern** (dataclasses in `rag-observability`, the gateway wraps a Pydantic response → **no `dist/schemas` churn**). New `rag_observability.billing`: a `UsageMeter` (observe-only per-tenant, per-dimension counters: queries / docs / storage / reranker / LLM tokens) fed O(1) from `record_request_usage` independent of quotas; `GET /v1/billing/usage` serves the per-tenant dashboard; pure `generate_invoice` + `PricingModel`/`load_pricing` price an invoice **from `marketplace/pricing.yaml`** (a price change is config) and **reconcile with metered usage ±0.5% by construction**; a `BillingProvider` Protocol seam for Stripe / marketplace metering (degrade-open). Inert by default (`cfg.billing`); `ragctl billing` drives meter→invoice→reconcile; **no governed SPI call** (policy-coverage linter unchanged); only `dist/openapi` + `dist/rag.schema` regenerate. Deferred: the concrete Stripe/marketplace adapters, the docs/reranker/storage feed points, an admin usage card. [ADR-0051](docs/adr/ADR-0051-billing-metering.md) [#182](https://github.com/officialCodeWork/AgentContextOS/pull/182)
- **7.8** ✅ Support, SLAs & on-call — the support model + ops runbooks, **grounded in the platform's own signals**. Four support tiers + per-tier SLA targets (matching `marketplace/pricing.yaml`) in [`support-sla.md`](docs/guides/support-sla.md); a new `docs/runbooks/` area with **one runbook per alert type** (`alerts.md` — acl/tenant escape · `breaker.opened` · `drift.detected` · cost anomaly · `quota.exceeded` · injection spike · gateway degraded · latency/availability SLO · `eval.regression` · ingest), each naming the exact event / `/v1/status/*` / SLO that raises it; an incident-response process + a blameless postmortem template; the status page reads **measured** health (`/v1/status/health` + Grafana SLOs), not manual toggles. **Paging reuses the Step 3.9 webhook system** (PagerDuty as a subscriber — no new code). Deferred: hosted status-page deploy, the PagerDuty account, staffing. [ADR-0050](docs/adr/ADR-0050-support-sla-oncall.md) [#181](https://github.com/officialCodeWork/AgentContextOS/pull/181)
Expand Down Expand Up @@ -1064,6 +1064,7 @@ Complete log of every PR. Routine Dependabot bumps are grouped; everything else
| [#183](https://github.com/officialCodeWork/AgentContextOS/pull/183) | 2026-06-10 | chore(release): GA cutover — v1.0.0 release notes + readiness checklist + SemVer policy (Step 7.10) |
| [#184](https://github.com/officialCodeWork/AgentContextOS/pull/184) | 2026-06-10 | docs: GA polish — site publishing scope, HLD v1.2, ragctl reference, port + link fixes |
| [#185](https://github.com/officialCodeWork/AgentContextOS/pull/185) | 2026-06-10 | fix(gateway): v1.0.1 — container/Helm serve path: config-driven entrypoint + /readyz + valid chart config |
| [#186](https://github.com/officialCodeWork/AgentContextOS/pull/186) | 2026-06-10 | fix(release): v1.0.1 — lockstep component publishing: stamp the tag version onto every dist, publish the complete closure (ADR-0053) |
| #78–#80, #116–#118 | Open | Dependabot bumps — awaiting merge |
| #81 | Closed | Dependabot bump — superseded |

Expand Down
13 changes: 13 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,19 @@ tasks:
cmds:
- uv run pip-audit

# ---------------------------------------------------------------------------
# Release engineering (ADR-0053) — one platform version, stamped from the tag
# ---------------------------------------------------------------------------
version:stamp:
desc: "Stamp the platform version onto every dist (usage: task version:stamp -- 1.0.2)"
cmds:
- "{{.PYTHON}} scripts/stamp_versions.py {{.CLI_ARGS}}"

version:check:
desc: Verify every version site agrees on one platform version (lockstep gate)
cmds:
- "{{.PYTHON}} scripts/stamp_versions.py --check"

# ---------------------------------------------------------------------------
# IaC — Terraform + Helm
# ---------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions apps/gateway/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ build-backend = "hatchling.build"

[project]
name = "rag-gateway"
version = "0.10.0"
description = "AgentContextOS — HTTP/gRPC/MCP API gateway (Step 4.4: per-backend circuit breakers)"
version = "1.0.1"
description = "AgentContextOS — REST/gRPC/MCP/OpenAI-compatible API gateway"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
Expand Down
4 changes: 2 additions & 2 deletions apps/gateway/src/rag_gateway/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
for the design.
"""

from rag_gateway._version import __version__
from rag_gateway.app import (
app,
build_app,
Expand All @@ -28,9 +29,8 @@
)
from rag_gateway.mcp import build_mcp_server

__version__ = "0.7.0"

__all__ = [
"__version__",
"app",
"build_app",
"build_default_embedder",
Expand Down
21 changes: 21 additions & 0 deletions apps/gateway/src/rag_gateway/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Single source of truth for the gateway's reported version.

The version is declared once, in ``apps/gateway/pyproject.toml``, and read
back here from the installed distribution metadata. Every surface that
reports a version imports this constant — ``rag_gateway.__version__``, the
FastAPI ``app.version`` (which becomes OpenAPI ``info.version`` in
``dist/openapi.*`` and the generated REST reference), and ``GET /v1/info`` —
so they cannot disagree. It tracks the platform release (SemVer,
[ADR-0052](../../../../docs/adr/ADR-0052-ga-cutover.md)): bump
``pyproject.toml``, ``uv sync``, then regenerate the drift-gated artifacts
(``task openapi:gen`` + ``task docs:api``).
"""

from __future__ import annotations

from importlib.metadata import PackageNotFoundError, version

try:
__version__ = version("rag-gateway")
except PackageNotFoundError: # pragma: no cover - source tree without an installed dist
__version__ = "0.0.0+unknown"
Loading
Loading