diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..f539807 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,48 @@ +name: Bug report +description: Something does not work as documented +labels: ["bug"] +body: + - type: textarea + id: what-happened + attributes: + label: What happened + description: What did you expect, and what happened instead? + validations: + required: true + - type: textarea + id: repro + attributes: + label: Reproduction + description: The command you ran and its full output. Include the migration SQL if relevant. + render: shell + validations: + required: true + - type: input + id: version + attributes: + label: PyClickHouseMigrator version + description: Output of `migrator --version` + placeholder: "2.1.0" + validations: + required: true + - type: input + id: clickhouse + attributes: + label: ClickHouse version + placeholder: "25.3" + validations: + required: true + - type: input + id: python + attributes: + label: Python version + placeholder: "3.13" + - type: dropdown + id: cluster + attributes: + label: Cluster mode + options: + - "No — single node" + - "Yes — ON CLUSTER" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4a7091a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: true +contact_links: + - name: Documentation + url: https://maksim-burtsev.github.io/PyClickHouseMigrator/ + about: Migration format, CI/CD, cluster mode, troubleshooting. + - name: Known limitations + url: https://maksim-burtsev.github.io/PyClickHouseMigrator/known-limitations/ + about: Check here before filing — some behavior is intentional. + - name: Security vulnerability + url: https://github.com/Maksim-Burtsev/PyClickHouseMigrator/security/advisories/new + about: Report privately, not as a public issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..89508c4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,31 @@ +name: Feature request +description: Suggest a change or addition +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: What problem are you hitting? + description: Describe the situation, not the solution. + validations: + required: true + - type: textarea + id: proposal + attributes: + label: What would you like it to do? + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: What are you doing today instead? + description: Workarounds, other tools, manual steps. + - type: checkboxes + id: scope + attributes: + label: Scope check + description: > + This tool intentionally stays small — it applies migrations, it is not a + schema platform. See docs/known-limitations.md. + options: + - label: I have read the known limitations and this is not one of them diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..04be1f3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ +## What + + + +## Checklist + +- [ ] `uv run ruff check . && uv run ruff format --check .` +- [ ] `uv run mypy py_clickhouse_migrator/` +- [ ] `uv run pytest` passes against a live ClickHouse +- [ ] Tests added or updated for the behavior change +- [ ] Docs / README / `llms.txt` updated if the CLI surface changed +- [ ] `CHANGELOG.md` entry added diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e3cbd4..45d68c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,17 +33,27 @@ jobs: run: uv run mypy py_clickhouse_migrator/ test: + # Keep this name stable: the master ruleset requires these exact check + # names. The ClickHouse version is reported by the step below instead. name: Test (Python ${{ matrix.python-version }}) needs: lint runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python-version: ["3.11", "3.12", "3.13", "3.14"] + include: + - python-version: "3.11" + clickhouse: "24.8" + - python-version: "3.12" + clickhouse: "25.3" + - python-version: "3.13" + clickhouse: "latest" + - python-version: "3.14" + clickhouse: "latest" services: clickhouse: - image: clickhouse/clickhouse-server:latest + image: clickhouse/clickhouse-server:${{ matrix.clickhouse }} ports: - 19000:9000 env: @@ -94,14 +104,14 @@ jobs: raise SystemExit(f"ClickHouse service did not become ready: {last_error}") PY - - name: Run tests + - name: Run tests (ClickHouse ${{ matrix.clickhouse }}) run: uv run pytest -v --cov=py_clickhouse_migrator --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v7 with: files: coverage.xml - flags: "python-${{ matrix.python-version }}" + flags: "python-${{ matrix.python-version }}-ch-${{ matrix.clickhouse }}" token: ${{ secrets.CODECOV_TOKEN }} test-cluster: diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml new file mode 100644 index 0000000..a3a11a3 --- /dev/null +++ b/.github/workflows/demo.yml @@ -0,0 +1,81 @@ +name: Demo GIF + +on: + workflow_dispatch: + push: + branches: [master] + paths: + - demo/** + - .github/workflows/demo.yml + +concurrency: + group: demo-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write + +jobs: + render: + name: Render assets/demo.gif + runs-on: ubuntu-latest + + services: + clickhouse: + image: clickhouse/clickhouse-server:latest + ports: + - 19000:9000 + env: + CLICKHOUSE_DB: test + CLICKHOUSE_USER: default + CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 + options: >- + --health-cmd "clickhouse-client --query 'SELECT 1'" + --health-interval 2s + --health-timeout 5s + --health-retries 10 + + steps: + - uses: actions/checkout@v7 + - uses: astral-sh/setup-uv@v10.0.1 + with: + enable-cache: true + - uses: actions/setup-python@v7 + with: + python-version: "3.14" + + - name: Install migrator + run: | + uv sync --dev + echo "$PWD/.venv/bin" >> "$GITHUB_PATH" + + - name: Wait for ClickHouse service + run: | + probe="from clickhouse_driver import Client; Client.from_url('clickhouse://default@localhost:19000/test').execute('SELECT 1')" + for i in $(seq 1 30); do + if .venv/bin/python -c "$probe" 2>/dev/null; then + echo "ClickHouse ready" + exit 0 + fi + echo "Waiting for ClickHouse... ($i/30)" + sleep 2 + done + echo "ClickHouse service did not become ready" >&2 + exit 1 + + - name: Render tape + uses: charmbracelet/vhs-action@v2 + with: + path: demo/demo.tape + + - name: Commit GIF + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add assets/demo.gif + if git diff --staged --quiet; then + echo "GIF unchanged" + else + git commit -m "chore: regenerate demo GIF [skip ci]" + git push + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1897315..ff720f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,10 +46,11 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 docker: - name: Docker Hub + name: Docker Hub + GHCR needs: publish runs-on: ubuntu-latest permissions: + contents: read packages: write steps: @@ -59,6 +60,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Set up QEMU uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx @@ -67,7 +74,9 @@ jobs: id: meta uses: docker/metadata-action@v6 with: - images: maksimburtsev/py-clickhouse-migrator + images: | + maksimburtsev/py-clickhouse-migrator + ghcr.io/maksim-burtsev/pyclickhousemigrator tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} diff --git a/.gitignore b/.gitignore index 2ff5f8f..26880da 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,6 @@ Thumbs.db # uv .python-version + +# Local article drafts (published elsewhere, not part of the package) +managing_clickhouse_migrations_devto*.md diff --git a/CHANGELOG.txt b/CHANGELOG.md similarity index 60% rename from CHANGELOG.txt rename to CHANGELOG.md index f0574a8..3f7824f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.md @@ -1,8 +1,20 @@ -Change log -========== +# Changelog -2.0.1 (02/08/2026) -------------------- +All notable changes to this project are documented here. +This project follows [Semantic Versioning](https://semver.org/): breaking changes only in major releases. + +## 2.1.0 — 2026-08-23 + +- Published the image to GitHub Container Registry (`ghcr.io/maksim-burtsev/pyclickhousemigrator`) alongside Docker Hub, with identical tags and both architectures +- Added ClickHouse 24.8 and 25.3 to the CI test matrix; previously only `latest` was tested +- Fixed the `org.opencontainers.image.licenses` label in the image (the singular `license` key is not valid OCI and was ignored) and added title, description, and documentation labels +- Added `SECURITY.md`, `CONTRIBUTING.md`, issue forms, and a pull request template +- Renamed `LICENCE.txt` to `LICENSE` so GitHub detects the license, and `CHANGELOG.txt` to `CHANGELOG.md` +- Added a demo GIF to the README, rendered from a VHS tape in CI +- Documented the comparison with golang-migrate, Atlas, dbt, and Alembic +- No CLI or migration behavior changes + +## 2.0.1 — 2026-08-02 - Added the hosted documentation site and linked it from README and package metadata - Added the `py.typed` marker for typed-package discovery @@ -11,8 +23,7 @@ Change log - Updated CI and documentation workflows - No CLI or migration behavior changes -2.0.0 (26/04/2026) -------------------- +## 2.0.0 — 2026-04-26 - SQL-first migration format: migrations are `.sql` files with `-- migrator:up`, `-- migrator:down`, and explicit `-- @stmt` blocks - Removed the old documented Python migration workflow from user-facing documentation @@ -25,8 +36,7 @@ Change log - Hardened lock cluster name validation - Full documentation refresh for README, llms.txt, llms-full.txt, and docs/* -1.1.0 (30/03/2026) -------------------- +## 1.1.0 — 2026-03-30 - New --send-receive-timeout option - Docker image (Docker Hub) @@ -35,8 +45,7 @@ Change log - Checksum computed from SQL output instead of file content - Removed unused termcolor dependency -1.0.0 (22/03/2026) -------------------- +## 1.0.0 — 2026-03-22 - Distributed locking with TTL - Checksum validation & repair @@ -47,17 +56,14 @@ Change log - CLI error handling - --version flag -0.3 (19/03/2024) ------------------- +## 0.3 — 2024-03-19 - Fix queries parsing -0.2 (26/12/2023) ------------------- +## 0.2 — 2023-12-26 - Add .env loading -0.1 (24/12/2023) ------------------- +## 0.1 — 2023-12-24 - First release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d6c9c29 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,54 @@ +# Contributing + +Thanks for taking the time. Small, focused pull requests are the easiest to merge. + +## Setup + +Requires [uv](https://docs.astral.sh/uv/) and Docker. + +```sh +git clone https://github.com/Maksim-Burtsev/PyClickHouseMigrator.git +cd PyClickHouseMigrator +uv sync --dev +``` + +## Running tests + +Most tests need a live ClickHouse: + +```sh +docker compose -f docker-compose.test.yml up -d --wait +uv run pytest -v +``` + +Cluster tests run against a separate two-node compose file: + +```sh +docker compose -f docker-compose.cluster.yml up -d --wait +uv run pytest tests/ -m cluster -v +``` + +## Before opening a PR + +The same three checks CI runs: + +```sh +uv run ruff check . +uv run ruff format --check . +uv run mypy py_clickhouse_migrator/ +``` + +## Guidelines + +- Add a test for any behavior change — the test suite is the reason this tool is + safe to point at a production schema. +- Keep the dependency set small. `click` and `clickhouse-driver` are the only + runtime dependencies, and that is a feature. +- Update `docs/` and `README.md` when you change CLI behavior, plus `llms.txt` / + `llms-full.txt` if the change affects the documented surface. +- Add an entry to `CHANGELOG.md` under an "Unreleased" heading. + +## Reporting bugs + +Open an issue with the migrator version (`migrator --version`), ClickHouse +version, the migration SQL if relevant, and the full command plus output. diff --git a/Dockerfile b/Dockerfile index aec9b25..168dd15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,11 @@ FROM python:3.14-slim LABEL maintainer="Maksim Burtsev " -LABEL description="Python CLI tool for ClickHouse schema migrations" +LABEL org.opencontainers.image.title="PyClickHouseMigrator" +LABEL org.opencontainers.image.description="SQL-first ClickHouse schema migration CLI with checksums, rollback, dry-run, advisory locking, and cluster support" LABEL org.opencontainers.image.source="https://github.com/Maksim-Burtsev/PyClickHouseMigrator" -LABEL org.opencontainers.image.license="MIT" +LABEL org.opencontainers.image.documentation="https://maksim-burtsev.github.io/PyClickHouseMigrator/" +LABEL org.opencontainers.image.licenses="MIT" ARG PACKAGE_VERSION RUN test -n "$PACKAGE_VERSION" && \ diff --git a/LICENCE.txt b/LICENSE similarity index 100% rename from LICENCE.txt rename to LICENSE diff --git a/README.md b/README.md index dbf2dbc..a9e6dd0 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,28 @@ PyClickHouseMigrator

-# PyClickHouseMigrator +

PyClickHouseMigrator

-[![CI](https://github.com/Maksim-Burtsev/PyClickHouseMigrator/actions/workflows/ci.yml/badge.svg)](https://github.com/Maksim-Burtsev/PyClickHouseMigrator/actions) -[![PyPI](https://img.shields.io/pypi/v/py-clickhouse-migrator)](https://pypi.org/project/py-clickhouse-migrator/) -[![Python](https://img.shields.io/badge/python-3.11%20|%203.12%20|%203.13%20|%203.14-blue)](https://pypi.org/project/py-clickhouse-migrator/) -[![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://maksim-burtsev.github.io/PyClickHouseMigrator/) -[![codecov](https://codecov.io/gh/Maksim-Burtsev/PyClickHouseMigrator/branch/master/graph/badge.svg)](https://codecov.io/gh/Maksim-Burtsev/PyClickHouseMigrator) -[![Downloads](https://static.pepy.tech/personalized-badge/py-clickhouse-migrator?period=total&units=INTERNATIONAL_SYSTEM&left_color=grey&right_color=brightgreen&left_text=downloads)](https://pepy.tech/projects/py-clickhouse-migrator) +

SQL-first ClickHouse migrations for Python teams.
+Plain .sql files, ordered applies, checksums, rollback, dry-run — no ORM, no diff engine.

-**SQL-first ClickHouse migrations for Python teams.** +

+ migrator init, new, up --dry-run, up, show, rollback +

+ +```sh +uv tool install py-clickhouse-migrator +``` + +

+CI +PyPI +Python +Tested ClickHouse versions +Docs +codecov +Downloads +

PyClickHouseMigrator is a small, predictable migration runner for ClickHouse. It keeps schema changes in plain `.sql` files, applies them in order, stores migration state inside ClickHouse, validates checksums, supports rollback SQL, and fits naturally into CI/CD. @@ -396,6 +408,12 @@ clickhouse://user:password@host:9440/database?secure=True docker pull maksimburtsev/py-clickhouse-migrator:latest ``` +Also published to GHCR, if Docker Hub is rate-limited or blocked in your infra: + +```sh +docker pull ghcr.io/maksim-burtsev/pyclickhousemigrator:latest +``` + Run migrations: ```sh @@ -527,6 +545,25 @@ See [Python API](docs/python-api.md). See [Known limitations](docs/known-limitations.md). +## Versioning and stability + +PyClickHouseMigrator follows [Semantic Versioning](https://semver.org/). + +- The CLI surface, the migration file format, and the service table schema are + the public API. Breaking changes to any of them only happen in a major release. +- `2.x` is production-ready. It is tested on every release against ClickHouse + 24.8, 25.3, and `latest`, on Python 3.11 through 3.14, in both single-node and + `ON CLUSTER` mode. +- Pin a major tag (`py-clickhouse-migrator>=2,<3`, or the Docker tag `:2`) and + upgrades stay safe. + +Changes per release are in [CHANGELOG.md](CHANGELOG.md). + +## Contributing + +Bug reports and pull requests are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). +Security issues should go through a [private advisory](SECURITY.md), not a public issue. + ## Documentation - [Migration format](docs/migration-format.md) @@ -541,4 +578,4 @@ See [Known limitations](docs/known-limitations.md). ## License -[MIT](LICENCE.txt) +[MIT](LICENSE) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..ccf0500 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,29 @@ +# Security Policy + +## Supported versions + +| Version | Supported | +| ------- | --------- | +| 2.x | ✅ | +| 1.x | ❌ | +| < 1.0 | ❌ | + +Security fixes are released for the latest `2.x` version only. + +## Reporting a vulnerability + +Please **do not open a public issue** for security problems. + +Report privately through GitHub Security Advisories: +[Report a vulnerability](https://github.com/Maksim-Burtsev/PyClickHouseMigrator/security/advisories/new) + +Include the version, ClickHouse version, a description of the problem, and a +reproduction if you have one. You should get a first response within a week. + +## Scope + +PyClickHouseMigrator connects to ClickHouse and executes SQL you wrote. The +migration SQL itself is trusted input — this tool does not sandbox it. Relevant +security concerns are things like credential handling (`--url`, +`CLICKHOUSE_MIGRATE_URL`, `.env` loading), credential leakage into logs, and +checksum/lock validation being bypassable. diff --git a/assets/demo.gif b/assets/demo.gif new file mode 100644 index 0000000..29eaaae Binary files /dev/null and b/assets/demo.gif differ diff --git a/demo/demo.tape b/demo/demo.tape new file mode 100644 index 0000000..ba1b46b --- /dev/null +++ b/demo/demo.tape @@ -0,0 +1,75 @@ +# Demo GIF for the README. +# +# Rendered in CI by .github/workflows/demo.yml. To render locally: +# +# docker compose -f docker-compose.test.yml up -d --wait +# uv sync --dev && export PATH="$PWD/.venv/bin:$PATH" +# vhs demo/demo.tape +# +# Run it from the repository root — the tape resolves demo/events.sql +# relative to the current directory before switching to a temp workspace. + +Output assets/demo.gif + +Require migrator + +Set FontSize 16 +Set Width 1000 +Set Height 440 +Set Padding 18 +Set TypingSpeed 45ms +Set Theme "Catppuccin Mocha" + +# Setup: point at ClickHouse and work in a throwaway directory. +Hide +Type "export CLICKHOUSE_MIGRATE_URL=clickhouse://default@localhost:19000/test" +Enter +Type "FIXTURE=$PWD/demo/events.sql; cd $(mktemp -d)" +Enter +Type "clear" +Enter +Show + +Sleep 500ms + +Type "migrator init" +Enter +Sleep 1500ms + +Type "migrator new add_events" +Enter +Sleep 1500ms + +# Write the DDL — off camera, this is just an editor step. +Hide +Type "cp $FIXTURE db/migrations/*_add_events.sql" +Enter +Type "clear" +Enter +Show + +Type "cat db/migrations/*_add_events.sql" +Enter +Sleep 3s + +Type "clear" +Enter + +Type "migrator up --dry-run" +Enter +Sleep 3s + +Type "clear" +Enter + +Type "migrator up" +Enter +Sleep 1500ms + +Type "migrator show" +Enter +Sleep 3s + +Type "migrator rollback" +Enter +Sleep 2500ms diff --git a/demo/events.sql b/demo/events.sql new file mode 100644 index 0000000..b5cd425 --- /dev/null +++ b/demo/events.sql @@ -0,0 +1,13 @@ +-- migrator:up +-- @stmt +CREATE TABLE IF NOT EXISTS events ( + id UInt64, + user_id UInt64, + name String, + ts DateTime +) ENGINE = MergeTree +ORDER BY (ts, id) + +-- migrator:down +-- @stmt +DROP TABLE IF EXISTS events diff --git a/docs/docker.md b/docs/docker.md index 19edfa7..1a30e2f 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -8,6 +8,16 @@ PyClickHouseMigrator can run as a containerized CLI. docker pull maksimburtsev/py-clickhouse-migrator:latest ``` +The same image is published to GitHub Container Registry, which is useful if +your infrastructure rate-limits or blocks Docker Hub: + +```sh +docker pull ghcr.io/maksim-burtsev/pyclickhousemigrator:latest +``` + +Both registries carry identical tags: `latest`, `2`, `2.1`, `2.1.0`, for +`linux/amd64` and `linux/arm64`. + Use `latest` for a quick start. For repeatable automation, pin to a major version tag: ```text @@ -17,7 +27,7 @@ maksimburtsev/py-clickhouse-migrator:2 Or pin an exact version: ```text -maksimburtsev/py-clickhouse-migrator:2.0.1 +maksimburtsev/py-clickhouse-migrator:2.1.0 ``` ## Run migrations diff --git a/docs/why-pyclickhousemigrator.md b/docs/why-pyclickhousemigrator.md index 68d247d..43ced4c 100644 --- a/docs/why-pyclickhousemigrator.md +++ b/docs/why-pyclickhousemigrator.md @@ -1,6 +1,6 @@ --- title: Why PyClickHouseMigrator? -description: Decide whether PyClickHouseMigrator fits your ClickHouse schema migration workflow, and compare it with raw SQL, Goose, Flyway, Liquibase, and clickhouse-migrations for Python. +description: How to run ClickHouse migrations in Python, and how PyClickHouseMigrator compares with golang-migrate, Atlas, Goose, Flyway, Liquibase, dbt, Alembic, and clickhouse-migrations. --- # Why PyClickHouseMigrator? @@ -9,6 +9,8 @@ PyClickHouseMigrator is a focused migration runner for Python teams that want to It is deliberately not an ORM, schema diff engine, database provisioning tool, or deployment platform. +If you arrived here looking for "an Alembic for ClickHouse" or "golang-migrate but in Python": this is a runner in that family, built for ClickHouse only. The comparison table below says plainly where the alternatives are the better choice. + !!! note This is a decision guide, not a benchmark. It compares documented operating models and trade-offs. Follow the linked project documentation when evaluating current versions. @@ -53,6 +55,10 @@ No migration runner can make ClickHouse DDL transactional. Design multi-statemen | [**Flyway**](https://documentation.red-gate.com/fd/supported-databases-for-flyway-143754067.html) | An organization already standardizes migrations and governance around Flyway or JVM tooling. | ClickHouse is listed for foundational migration capabilities; verify the exact capability and licensing level your workflow requires. | | [**Liquibase**](https://github.com/MEDIARITHMICS/liquibase-clickhouse) | An organization already uses Liquibase across databases and values one consistent process. | ClickHouse support uses an extension; validate extension compatibility, cluster behavior, and the operational footprint for your environment. | | [**clickhouse-migrations for Python**](https://pypi.org/project/clickhouse-migrations/) | A Python 3.9+ team wants a file-based runner with native and HTTP drivers, a GitHub Action, Docker image, dry-run, and paired down files. | Its file format and safety model differ. Compare statement splitting, checksum behavior, rollback semantics, validation, baseline, and locking against your requirements. | +| [**golang-migrate**](https://github.com/golang-migrate/migrate) | A polyglot team already runs `migrate` for Postgres or MySQL and wants one binary and one file convention across engines. | Its ClickHouse driver is one of many; check how it handles `ON CLUSTER`, multi-statement files, and checksum drift, none of which are ClickHouse-specific in a generic runner. | +| [**Atlas**](https://atlasgo.io/) | You want a declarative desired-state schema and machine-generated diffs, with lint and CI policies on top. | Atlas plans changes for you; that is the opposite trade-off from hand-written reviewed SQL. Evaluate its ClickHouse coverage and the paid-tier boundary for the features you need. | +| [**dbt**](https://github.com/ClickHouse/dbt-clickhouse) | Your problem is analytics transformations — models, tests, and incremental tables built from queries. | dbt manages the objects it creates, not your base schema. It is complementary to a migration runner, not a replacement: dbt is for transformations, migrations are for DDL. | +| [**Alembic**](https://alembic.sqlalchemy.org/) | Your team lives in SQLAlchemy and wants one migration story for the whole stack. | Alembic is built around SQLAlchemy and OLTP semantics. ClickHouse support is third-party (`clickhouse-sqlalchemy`), and autogenerate does not map cleanly onto MergeTree engines, `ON CLUSTER`, or ClickHouse's non-transactional DDL. | diff --git a/pyproject.toml b/pyproject.toml index 45bec3a..d4b7b15 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "py-clickhouse-migrator" -version = "2.0.1" +version = "2.1.0" description = "SQL-first ClickHouse schema migration CLI for Python with checksums, rollback, dry-run, advisory locking, and cluster support." readme = "README.md" license = "MIT" @@ -49,7 +49,7 @@ Homepage = "https://github.com/Maksim-Burtsev/PyClickHouseMigrator" Documentation = "https://maksim-burtsev.github.io/PyClickHouseMigrator/" Repository = "https://github.com/Maksim-Burtsev/PyClickHouseMigrator" Issues = "https://github.com/Maksim-Burtsev/PyClickHouseMigrator/issues" -Changelog = "https://github.com/Maksim-Burtsev/PyClickHouseMigrator/releases" +Changelog = "https://github.com/Maksim-Burtsev/PyClickHouseMigrator/blob/master/CHANGELOG.md" Docker = "https://hub.docker.com/r/maksimburtsev/py-clickhouse-migrator" [dependency-groups] diff --git a/uv.lock b/uv.lock index 92da62f..ae2075f 100644 --- a/uv.lock +++ b/uv.lock @@ -524,7 +524,7 @@ wheels = [ [[package]] name = "py-clickhouse-migrator" -version = "2.0.1" +version = "2.1.0" source = { editable = "." } dependencies = [ { name = "click" },