From 3db8139856f24ac3f03935736768414551043beb Mon Sep 17 00:00:00 2001 From: Mohammad Ausaf Date: Sat, 27 Jun 2026 19:44:53 +0530 Subject: [PATCH 1/4] chore: prepare 0.1.0 package metadata --- plugins/cfg_impact/pyproject.toml | 13 +++++++++++-- pyproject.toml | 8 +++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/plugins/cfg_impact/pyproject.toml b/plugins/cfg_impact/pyproject.toml index a2b8b4e..febb385 100644 --- a/plugins/cfg_impact/pyproject.toml +++ b/plugins/cfg_impact/pyproject.toml @@ -1,13 +1,22 @@ [project] name = "cfg-impact" -version = "0.0.0" +version = "0.1.0" description = "Optional system-impact analysis plugin for cfgit" +readme = "README.md" requires-python = ">=3.11" +license = "Apache-2.0" +authors = [{ name = "Mohammad Ausaf" }] dependencies = [ - "cfg-vcs", + "cfg-vcs>=0.1.0,<0.2.0", "httpx>=0.27", ] +[project.urls] +Homepage = "https://github.com/AusafMo/cfgit" +Repository = "https://github.com/AusafMo/cfgit" +Issues = "https://github.com/AusafMo/cfgit/issues" +Documentation = "https://github.com/AusafMo/cfgit/tree/main/plugins/cfg_impact#readme" + [build-system] requires = ["hatchling"] build-backend = "hatchling.build" diff --git a/pyproject.toml b/pyproject.toml index 457173e..bb9d8d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cfg-vcs" -version = "0.0.0" +version = "0.1.0" description = "Non-custodial version control for live datastore records" readme = "README.md" requires-python = ">=3.11" @@ -32,6 +32,12 @@ mcp = ["mcp>=1.0"] impact = [] # the cfg-impact plugin declares its own model-client deps; never in core dev = ["pytest>=8.0", "pytest-asyncio", "ruff", "mypy", "httpx>=0.27"] +[project.urls] +Homepage = "https://github.com/AusafMo/cfgit" +Repository = "https://github.com/AusafMo/cfgit" +Issues = "https://github.com/AusafMo/cfgit/issues" +Documentation = "https://github.com/AusafMo/cfgit#readme" + [project.scripts] cfg = "cfg.cli.main:main" cfg-mcp = "cfg.mcp.server:main" From 5b77ed08a564ab51168c38df1f50856fae432dbc Mon Sep 17 00:00:00 2001 From: Mohammad Ausaf Date: Sat, 27 Jun 2026 19:46:20 +0530 Subject: [PATCH 2/4] chore: add PyPI publishing workflow --- .github/workflows/publish.yml | 54 +++++++++++++++++++++++++ docs/PUBLISHING.md | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 .github/workflows/publish.yml create mode 100644 docs/PUBLISHING.md diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..02aaaf6 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,54 @@ +name: Publish Python packages + +on: + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish-cfg-vcs: + name: Publish cfg-vcs + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Build + run: | + python -m pip install -U build twine + python -m build + python -m twine check dist/* + - name: Publish cfg-vcs to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ + + publish-cfg-impact: + name: Publish cfg-impact + runs-on: ubuntu-latest + needs: publish-cfg-vcs + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Build + working-directory: plugins/cfg_impact + run: | + python -m pip install -U build twine + python -m build + python -m twine check dist/* + - name: Publish cfg-impact to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: plugins/cfg_impact/dist/ diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md new file mode 100644 index 0000000..f63699c --- /dev/null +++ b/docs/PUBLISHING.md @@ -0,0 +1,75 @@ +# Publishing + +cfgit publishes two Python packages: + +- `cfg-vcs`: core library, CLI, adapters, UI, and MCP server entry point. +- `cfg-impact`: optional system-impact / LLM narration plugin. + +Current first release version: `0.1.0`. + +## One-Time PyPI Setup + +Create both projects on PyPI and configure Trusted Publishing for this repository. + +For `cfg-vcs`: + +- Owner: `AusafMo` +- Repository: `cfgit` +- Workflow: `publish.yml` +- Environment: leave blank + +For `cfg-impact`, use the same trusted publisher settings. + +The workflow uses PyPI OpenID Connect, so no PyPI API token is stored in GitHub +Secrets. + +## Local Build Check + +From the repository root: + +```bash +python -m pip install -U build twine +rm -rf dist plugins/cfg_impact/dist +python -m build +python -m twine check dist/* +cd plugins/cfg_impact +python -m build +python -m twine check dist/* +``` + +## Clean Install Smoke + +```bash +python -m venv /tmp/cfgit-publish-smoke +/tmp/cfgit-publish-smoke/bin/python -m pip install \ + 'dist/cfg_vcs-0.1.0-py3-none-any.whl[mcp]' \ + plugins/cfg_impact/dist/cfg_impact-0.1.0-py3-none-any.whl +/tmp/cfgit-publish-smoke/bin/cfg --help +/tmp/cfgit-publish-smoke/bin/python -c 'import cfg; import cfg.mcp.server; import cfg_impact; print("imports ok")' +``` + +## Publish + +After Trusted Publishing is configured on PyPI, publish by creating a GitHub +release from a tag: + +```bash +git checkout main +git pull origin main +git tag v0.1.0 +git push origin v0.1.0 +gh release create v0.1.0 --title "v0.1.0" --notes "First public cfgit release." +``` + +The release triggers `.github/workflows/publish.yml`, which publishes `cfg-vcs` +first and `cfg-impact` second. + +## Install + +```bash +pip install cfg-vcs +pip install 'cfg-vcs[mongo]' +pip install 'cfg-vcs[postgres]' +pip install 'cfg-vcs[mongo,postgres,mcp]' +pip install cfg-impact +``` From c744d1da13e213e0c91905c261edcaf7d1409ebc Mon Sep 17 00:00:00 2001 From: Mohammad Ausaf Date: Sat, 27 Jun 2026 20:24:01 +0530 Subject: [PATCH 3/4] chore: publish cfgit packages --- .github/workflows/ci.yml | 46 +++++++++++++++++++++++++++++++ .github/workflows/publish.yml | 16 ++++++----- README.md | 4 +-- docs/PUBLISHING.md | 33 ++++++++++++---------- plugins/cfg_impact/pyproject.toml | 4 +-- pyproject.toml | 4 +-- src/cfg/adapters/mongo.py | 2 +- src/cfg/adapters/postgres.py | 2 +- src/cfg/interfaces/actions.py | 2 +- src/cfg/mcp/server.py | 4 +-- 10 files changed, 85 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6ecc5ba --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + tests: + name: tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install + run: | + python -m pip install -U pip + python -m pip install -e '.[mongo,postgres,mcp,dev]' + python -m pip install -e plugins/cfg_impact + - name: Run tests + run: python -m pytest -q + + package-build: + name: package-build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Build and check distributions + run: | + python -m pip install -U build twine + rm -rf dist plugins/cfg_impact/dist + python -m build + python -m twine check dist/* + cd plugins/cfg_impact + python -m build + python -m twine check dist/* diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 02aaaf6..87907a3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,9 +9,10 @@ permissions: contents: read jobs: - publish-cfg-vcs: - name: Publish cfg-vcs + publish-cfgit: + name: Publish cfgit runs-on: ubuntu-latest + environment: pypi-cfgit permissions: id-token: write contents: read @@ -25,15 +26,16 @@ jobs: python -m pip install -U build twine python -m build python -m twine check dist/* - - name: Publish cfg-vcs to PyPI + - name: Publish cfgit to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist/ - publish-cfg-impact: - name: Publish cfg-impact + publish-cfgit-impact: + name: Publish cfgit-impact runs-on: ubuntu-latest - needs: publish-cfg-vcs + needs: publish-cfgit + environment: pypi-cfgit-impact permissions: id-token: write contents: read @@ -48,7 +50,7 @@ jobs: python -m pip install -U build twine python -m build python -m twine check dist/* - - name: Publish cfg-impact to PyPI + - name: Publish cfgit-impact to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: plugins/cfg_impact/dist/ diff --git a/README.md b/README.md index 58eee7b..d323681 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ cfgit is pre-1.0 software. The current implementation includes: - localhost web UI - MCP server - portable Codex or Claude Code skill -- optional `cfg-impact` plugin for deterministic impact summaries and opt-in LLM narration +- optional `cfgit-impact` plugin for deterministic impact summaries and opt-in LLM narration The engine is intentionally DB-neutral. Mongo and Postgres are the first two adapters to prove the storage seam. @@ -410,7 +410,7 @@ standardize the config so that database always uses one env name. paths, finds static references to changed values across configured records, and reports a risk level. -Optional LLM narration lives in the separate `cfg-impact` plugin. It reads the +Optional LLM narration lives in the separate `cfgit-impact` plugin. It reads the real before/after of the change plus a map of the surrounding records, then explains in plain language what the change does, what it ripples into, and how to roll it back: diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md index f63699c..158089b 100644 --- a/docs/PUBLISHING.md +++ b/docs/PUBLISHING.md @@ -2,8 +2,8 @@ cfgit publishes two Python packages: -- `cfg-vcs`: core library, CLI, adapters, UI, and MCP server entry point. -- `cfg-impact`: optional system-impact / LLM narration plugin. +- `cfgit`: core library, CLI, adapters, UI, and MCP server entry point. +- `cfgit-impact`: optional system-impact / LLM narration plugin. Current first release version: `0.1.0`. @@ -11,14 +11,19 @@ Current first release version: `0.1.0`. Create both projects on PyPI and configure Trusted Publishing for this repository. -For `cfg-vcs`: +For `cfgit`: - Owner: `AusafMo` - Repository: `cfgit` - Workflow: `publish.yml` -- Environment: leave blank +- Environment: `pypi-cfgit` -For `cfg-impact`, use the same trusted publisher settings. +For `cfgit-impact`: + +- Owner: `AusafMo` +- Repository: `cfgit` +- Workflow: `publish.yml` +- Environment: `pypi-cfgit-impact` The workflow uses PyPI OpenID Connect, so no PyPI API token is stored in GitHub Secrets. @@ -42,8 +47,8 @@ python -m twine check dist/* ```bash python -m venv /tmp/cfgit-publish-smoke /tmp/cfgit-publish-smoke/bin/python -m pip install \ - 'dist/cfg_vcs-0.1.0-py3-none-any.whl[mcp]' \ - plugins/cfg_impact/dist/cfg_impact-0.1.0-py3-none-any.whl + 'dist/cfgit-0.1.0-py3-none-any.whl[mcp]' \ + plugins/cfg_impact/dist/cfgit_impact-0.1.0-py3-none-any.whl /tmp/cfgit-publish-smoke/bin/cfg --help /tmp/cfgit-publish-smoke/bin/python -c 'import cfg; import cfg.mcp.server; import cfg_impact; print("imports ok")' ``` @@ -61,15 +66,15 @@ git push origin v0.1.0 gh release create v0.1.0 --title "v0.1.0" --notes "First public cfgit release." ``` -The release triggers `.github/workflows/publish.yml`, which publishes `cfg-vcs` -first and `cfg-impact` second. +The release triggers `.github/workflows/publish.yml`, which publishes `cfgit` +first and `cfgit-impact` second. ## Install ```bash -pip install cfg-vcs -pip install 'cfg-vcs[mongo]' -pip install 'cfg-vcs[postgres]' -pip install 'cfg-vcs[mongo,postgres,mcp]' -pip install cfg-impact +pip install cfgit +pip install 'cfgit[mongo]' +pip install 'cfgit[postgres]' +pip install 'cfgit[mongo,postgres,mcp]' +pip install cfgit-impact ``` diff --git a/plugins/cfg_impact/pyproject.toml b/plugins/cfg_impact/pyproject.toml index febb385..c8920b3 100644 --- a/plugins/cfg_impact/pyproject.toml +++ b/plugins/cfg_impact/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "cfg-impact" +name = "cfgit-impact" version = "0.1.0" description = "Optional system-impact analysis plugin for cfgit" readme = "README.md" @@ -7,7 +7,7 @@ requires-python = ">=3.11" license = "Apache-2.0" authors = [{ name = "Mohammad Ausaf" }] dependencies = [ - "cfg-vcs>=0.1.0,<0.2.0", + "cfgit>=0.1.0,<0.2.0", "httpx>=0.27", ] diff --git a/pyproject.toml b/pyproject.toml index bb9d8d9..5e4d58a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "cfg-vcs" +name = "cfgit" version = "0.1.0" description = "Non-custodial version control for live datastore records" readme = "README.md" @@ -29,7 +29,7 @@ mongo = ["pymongo>=4.6"] postgres = ["psycopg[binary]>=3.2"] cli = ["click>=8.1", "rich>=13.0"] mcp = ["mcp>=1.0"] -impact = [] # the cfg-impact plugin declares its own model-client deps; never in core +impact = [] # the cfgit-impact plugin declares its own model-client deps; never in core dev = ["pytest>=8.0", "pytest-asyncio", "ruff", "mypy", "httpx>=0.27"] [project.urls] diff --git a/src/cfg/adapters/mongo.py b/src/cfg/adapters/mongo.py index a806a1e..e94b166 100644 --- a/src/cfg/adapters/mongo.py +++ b/src/cfg/adapters/mongo.py @@ -27,7 +27,7 @@ from pymongo.client_session import ClientSession from pymongo.errors import OperationFailure except ModuleNotFoundError as exc: # pragma: no cover - raise ModuleNotFoundError("install cfg-vcs[mongo] to use MongoAdapter") from exc + raise ModuleNotFoundError("install cfgit[mongo] to use MongoAdapter") from exc class MongoAdapter: diff --git a/src/cfg/adapters/postgres.py b/src/cfg/adapters/postgres.py index 1371f85..7ed33a7 100644 --- a/src/cfg/adapters/postgres.py +++ b/src/cfg/adapters/postgres.py @@ -31,7 +31,7 @@ from psycopg.rows import dict_row from psycopg.types.json import Jsonb except ModuleNotFoundError as exc: # pragma: no cover - raise ModuleNotFoundError("install cfg-vcs[postgres] to use PostgresAdapter") from exc + raise ModuleNotFoundError("install cfgit[postgres] to use PostgresAdapter") from exc _IDENT_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") diff --git a/src/cfg/interfaces/actions.py b/src/cfg/interfaces/actions.py index 28b2c9d..71488fe 100644 --- a/src/cfg/interfaces/actions.py +++ b/src/cfg/interfaces/actions.py @@ -309,7 +309,7 @@ def impact( from cfg_impact.overview import overview except ModuleNotFoundError as exc: raise ValueError( - "cfg-impact plugin is not installed. Install plugins/cfg_impact or cfg-vcs[impact]." + "cfgit-impact plugin is not installed. Install plugins/cfg_impact or cfgit[impact]." ) from exc return ( overview(engine, record, a=a, b=b, use_llm=use_llm, provider=provider, model=model, against=against), diff --git a/src/cfg/mcp/server.py b/src/cfg/mcp/server.py index eb09d64..cb6addd 100644 --- a/src/cfg/mcp/server.py +++ b/src/cfg/mcp/server.py @@ -8,7 +8,7 @@ from cfg.interfaces import actions from cfg.interfaces.actions import ActionContext -try: # pragma: no cover - exercised when cfg-vcs[mcp] is installed +try: # pragma: no cover - exercised when cfgit[mcp] is installed from mcp.server.fastmcp import FastMCP except ModuleNotFoundError: # pragma: no cover FastMCP = None # type: ignore[assignment] @@ -16,7 +16,7 @@ def _mcp() -> Any: if FastMCP is None: - raise ModuleNotFoundError("install cfg-vcs[mcp] to run the cfgit MCP server") + raise ModuleNotFoundError("install cfgit[mcp] to run the cfgit MCP server") return FastMCP("cfgit") From 45c2373076261f16c8cebd4424e7edec17ca53ac Mon Sep 17 00:00:00 2001 From: Mohammad Ausaf Date: Sat, 27 Jun 2026 20:28:36 +0530 Subject: [PATCH 4/4] chore: improve package descriptions --- docs/PUBLISHING.md | 6 ++++-- plugins/cfg_impact/pyproject.toml | 2 +- pyproject.toml | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md index 158089b..ae38710 100644 --- a/docs/PUBLISHING.md +++ b/docs/PUBLISHING.md @@ -2,8 +2,10 @@ cfgit publishes two Python packages: -- `cfgit`: core library, CLI, adapters, UI, and MCP server entry point. -- `cfgit-impact`: optional system-impact / LLM narration plugin. +- `cfgit`: Git-style history, diff, drift detection, branch/PR review, and + rollback for live database records without migrating or owning the datastore. +- `cfgit-impact`: optional plugin for deterministic system-impact summaries and + opt-in LLM narration of database record diffs. Current first release version: `0.1.0`. diff --git a/plugins/cfg_impact/pyproject.toml b/plugins/cfg_impact/pyproject.toml index c8920b3..e604643 100644 --- a/plugins/cfg_impact/pyproject.toml +++ b/plugins/cfg_impact/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "cfgit-impact" version = "0.1.0" -description = "Optional system-impact analysis plugin for cfgit" +description = "Optional cfgit plugin for deterministic system-impact summaries and opt-in LLM narration of database record diffs" readme = "README.md" requires-python = ">=3.11" license = "Apache-2.0" diff --git a/pyproject.toml b/pyproject.toml index 5e4d58a..1cb5b2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "cfgit" version = "0.1.0" -description = "Non-custodial version control for live datastore records" +description = "Git-style history, diff, drift detection, and rollback for live database records without migrating or owning your datastore" readme = "README.md" requires-python = ">=3.11" license = { file = "LICENSE" } @@ -15,6 +15,9 @@ keywords = [ "postgres", "mcp", "agents", + "rollback", + "drift-detection", + "database-versioning", ] # Core has NO database driver and NO LLM SDK. That boundary is enforced in CI