--- id: MRKD-WP-0006 type: workplan domain: markitect repo: marki-docx status: active state_hub_workstream_id: 7e255145-8d18-4f22-b1ca-31f02944b890 created: 2026-03-16 updated: 2026-03-16 --- # MRKD-WP-0006 — Packaging & Distribution Make markidocx installable from PyPI and runnable as a containerised REST service. Add a CI/CD pipeline that enforces quality gates on every push and automates release artefact production. **Scope:** CI/CD pipeline, PyPI packaging, Docker REST image, release process **Out of scope:** functional changes — this workstream is purely infrastructure **Depends on:** MRKD-WP-0001, MRKD-WP-0002, MRKD-WP-0003 — all complete --- ## T01 — CI pipeline — GitHub Actions ```task id: MRKD-WP-0006-T01 status: todo priority: high state_hub_task_id: cfca0094-b5ae-45ec-80c9-e7705f37bd12 ``` Create a GitHub Actions workflow that runs on every push and pull request to `main`. File: `.github/workflows/ci.yml` Jobs: 1. **test** — matrix: Python 3.11, 3.12 - `pip install -e ".[dev]"` - `ruff check .` - `mypy src/` - `pytest --tb=short -q` 2. **coverage** (optional, on `main` only) — `pytest --cov=markidocx --cov-report=xml`; upload to Codecov or similar 3. Cache pip downloads between runs using `actions/cache` Quality gate: the `test` job must pass before any PR can be merged. Deliverable: `.github/workflows/ci.yml` present; CI passes on a clean push to `main`. --- ## T02 — PyPI packaging and version management ```task id: MRKD-WP-0006-T02 status: todo priority: high state_hub_task_id: 44f60455-b144-48e3-93a0-74869018c2ea ``` Prepare markidocx for publication to PyPI and establish a version management convention. - Adopt **semantic versioning** (`MAJOR.MINOR.PATCH`); initial release: `0.1.0` - Single source of truth for version: `src/markidocx/__init__.py` (`__version__ = "0.1.0"`) - `pyproject.toml`: - `[project] version` reads from `__init__.py` via `importlib.metadata` or static - `[project.optional-dependencies]` groups: `dev`, `diagram-mermaid`, `diagram-graphviz`, `diagram-plantuml` - `[project.urls]`: homepage, source, tracker - Add `.github/workflows/publish.yml`: - Triggered on `push` to tags matching `v*.*.*` - Builds with `python -m build` - Publishes to PyPI using `pypa/gh-action-pypi-publish` - Uses a trusted-publisher setup (OIDC, no API token in repo secrets) - Dry-run test: `python -m build && twine check dist/*` must pass locally Deliverable: `pip install markidocx` works after first PyPI release; `markidocx --version` returns the correct version string. --- ## T03 — Docker image for REST service ```task id: MRKD-WP-0006-T03 status: todo priority: medium state_hub_task_id: 05ff77b0-6347-4c96-9fcd-c2b2baaf0fce ``` Provide a Docker image that runs the markidocx REST service, making it easy to deploy in pipeline and automation contexts. File: `Dockerfile` - Base: `python:3.12-slim` - Install markidocx with `pip install markidocx` (or from local wheel in CI) - `ENTRYPOINT ["markidocx", "serve"]` - Default `CMD ["--host", "0.0.0.0", "--port", "8080"]` - Expose port 8080 - Non-root user for security - `.dockerignore`: exclude tests, docs, `.git`, `*.pyc`, `dist/` Add `.github/workflows/docker.yml`: - Triggered on `push` to tags matching `v*.*.*` - Build and push to GitHub Container Registry (`ghcr.io`) - Tag as `latest` and `v` Usage documented in README: ```bash docker run -p 8080:8080 ghcr.io//marki-docx:latest ``` Deliverable: `docker build . && docker run -p 8080:8080 ` starts the REST service; `curl http://localhost:8080/health` returns `{"status": "ok"}`. --- ## T04 — Release process and changelog convention ```task id: MRKD-WP-0006-T04 status: todo priority: medium state_hub_task_id: 177e4861-d153-4b1d-85d4-a272da14bfe5 ``` Document the release process and establish a changelog convention so that releases are repeatable and traceable. - `CHANGELOG.md` with **Keep a Changelog** format (`Unreleased`, `Added`, `Changed`, `Fixed`, `Deprecated`, `Removed`) - Populate with a retrospective entry for `v0.1.0` covering WP-0001 through WP-0003 - `docs/release-process.md`: - Checklist: all tests pass, ruff+mypy clean, SBOM updated, CHANGELOG populated, version bumped, corpus regression passes - Tag: `git tag -s v -m "Release v"` - Push tag → triggers `publish.yml` and `docker.yml` automatically - Update `CLAUDE.md` with a pointer to the release process doc Deliverable: `CHANGELOG.md` present with `v0.1.0` entry; `docs/release-process.md` present; release checklist is executable end-to-end. --- ## How to Work - T01 and T02 are independent — can be worked in parallel - T03 depends on T02 being sufficiently complete (needs a buildable package) - T04 can be worked alongside any other task — it is primarily documentation ## Updating Task Status ``` status: todo → status: in_progress (when you start it) status: in_progress → status: done (when verified complete) ``` When every task is `done`, set the frontmatter `status: done`. ## Success Criteria Before marking the workplan done: 1. Every task block has `status: done` 2. Workplan frontmatter `status: done` 3. CI passes on `main` (GitHub Actions green) 4. `python -m build && twine check dist/*` passes locally 5. `docker build .` produces a working image 6. `CHANGELOG.md` and `docs/release-process.md` present