Files
devx/docs/user/cli-commands.md
T
emilandemo 3d4b4940ff
Post-merge / detect-and-configure (push) Successful in 16s
Post-merge / release-and-maintain (push) Successful in 1m2s
DEVX-153: feat: sync missing features from v0.49.x line to master
Co-authored-by: emil User <emil.simeonov@tutanota.com>
2026-08-09 01:09:20 +00:00

22 KiB

CLI Commands

devx provides a CLI with three command groups: ci, tools, and molecule. Each subcommand delegates to the corresponding Python module via python -m devx.*, so devx ci release is equivalent to python -m devx.ci.release.

devx --help        # show all command groups
devx --version     # show package version
devx ci --help     # show CI commands
devx tools --help  # show tools commands
devx molecule --help  # show molecule commands

CI Commands

devx ci auto-merge

Auto-merge a PR when all CI checks pass. Reads the task ID from the branch name, validates the PR title format against the Vikunja task title, extracts the conventional commit message from PR commits, and squash-merges with {PREFIX}-N <conventional commit> title.

If the head branch is behind master (HTTP 405), automatically pulls master, rebases, force-pushes, and retries the merge.

devx ci auto-merge <branch> <pr_title> <owner/repo> <pr_number>
# Example:
devx ci auto-merge DEVX-12-add-feature "DEVX-12: Add feature" oblachno-oss/devx 42

devx ci check-translations

Check translation files for gaps, dead keys, and missing languages. Validates translation files against the Python source code that uses them. By default, checks src/devx/translations.json against src/devx/**/*.py.

Checks performed:

  • Missing keys — a _() call in code has no entry in the translations file
  • Dead keys — a key in the translations file is not used in any code
  • Missing languages — a key exists but is missing one of the six supported languages (en, bg, de, ru, zh, pl)
devx ci check-translations
devx ci check-translations --translations path/to/translations.json

devx ci classify-changes

Classify git changes as user-facing or workflow-only. Used to skip releases for infrastructure-only changes. Classification rules are configured in pyproject.toml under [tool.devx.classify].

devx ci classify-changes --base origin/master --head HEAD
devx ci classify-changes --base origin/master --head HEAD --github-output
devx ci classify-changes --quiet --check user-facing
devx ci classify-changes --check ansible  # custom tag from pyproject.toml

Options:

  • --base <ref> — base ref (default: latest tag)
  • --head <ref> — head ref (default: HEAD)
  • --quiet — only output true/false
  • --check <category> — check specific category: all (default), user-facing, or any tag name defined in [tool.devx.classify.tags]
  • --github-output — write results to $GITHUB_OUTPUT for CI workflow steps

Exit code 2 indicates workflow-only changes (no release needed).

devx ci detect-release-commit

Detect whether the latest git commit is a release commit (release: vX.Y.Z [skip ci]). Writes is-release=true or is-release=false to $GITHUB_OUTPUT for use in CI workflow conditionals.

devx ci detect-release-commit

devx ci discover-runners

Discover available Gitea Actions runners for dynamic job distribution. Queries the Gitea API for registered runners at repository, organization, and instance (administrator) levels. Falls back to MOLECULE_RUNNERS repo variable or DEFAULT_MAX_RUNNERS (3).

devx ci discover-runners --owner oblachno-oss --repo devx
devx ci discover-runners --owner oblachno-oss --repo devx --count
devx ci discover-runners --owner oblachno-oss --repo devx --indices

Options:

  • --count — print the number of available runners
  • --indices — print a JSON array [0, 1, ..., N-1] for use as a dynamic matrix in Gitea Actions

devx ci distribute-files

Distribute files across parallel runners (round-robin). Discovers files matching a glob pattern, sorts them for deterministic ordering, then assigns them round-robin to max_runners groups. The assigned group for runner_index is written to $GITHUB_ENV.

devx ci distribute-files --pattern "tests/integration/test_*.py" \
  --runner-index 1 --max-runners 3 --github-env

Options:

  • --pattern <glob> — glob pattern for files to distribute
  • --runner-index <i> — current runner index (0-based)
  • --max-runners <n> — total number of runners (default: 3)
  • --github-env — write file list to $GITHUB_ENV
  • --skip-if-excess — skip if fewer files than runners

devx ci doc-coverage

Check documentation coverage for CLI commands and major modules. Parses Click commands from cli.py and checks if each has documentation in docs/user/cli-commands.md. Verifies core modules are documented in architecture.md and CI scripts in ci-cd-workflow.md.

devx ci doc-coverage
devx ci doc-coverage --docs-dir docs/ --source-dir src/ --fail-on-missing

Options:

  • --docs-dir <dir> — path to the docs directory (default: docs/)
  • --source-dir <dir> — path to the source directory (default: auto-detect)
  • --fail-on-missing — exit with non-zero status if any documentation is missing

devx ci lint-docs

Lint documentation files for structure, broken links, heading hierarchy, duplicate headings, TODO/FIXME markers, and trailing whitespace.

devx ci lint-docs
devx ci lint-docs --root . --fix
devx ci lint-docs --no-check-links --no-check-stale

Options:

  • --root <dir> — repository root directory (default: .)
  • --docs-dir <dir> — docs directory (default: <root>/docs)
  • --check-links/--no-check-links — check internal links (default: yes)
  • --check-headings/--no-check-headings — check heading hierarchy (default: yes)
  • --check-todo/--no-check-todo — check for TODO/FIXME markers (default: yes)
  • --check-stale/--no-check-stale — check for stale docs (default: no)
  • --check-trailing/--no-check-trailing — check trailing whitespace (default: yes)
  • --check-duplicates/--no-check-duplicates — check duplicate headings (default: yes)
  • --fix — auto-fix trailing whitespace

devx ci integration-guard

Run pytest with cross-runner failure detection. If any other integration-tests matrix runner reports failure, the current pytest subprocess is killed and this runner exits early with code 1.

devx ci integration-guard -- test_a.py test_b.py
devx ci integration-guard -- -x -v --tb=short test_a.py

Environment variables:

  • GITEA_URL — base URL of the Gitea instance
  • CI_GITEA_TOKEN — API token with repo access
  • RUN_ID — workflow run ID (GITHUB_RUN_ID)
  • JOB_NAME — base job name (GITHUB_JOB)
  • MATRIX_INDEX — current matrix index (runner-index)
  • GITEA_REPOSITORY — repository in owner/repo format

devx ci notify-failure

Create a Gitea issue when a CI workflow fails. Uses the tea CLI for issue creation with a bug label if available.

devx ci notify-failure --repo oblachno-oss/devx --run-id 123 \
  --workflow ci --commit abc123def456
devx ci notify-failure --repo oblachno-oss/devx --run-id 123 \
  --workflow post-merge/release --commit abc123def456 --auto-login

Options:

  • --repo <owner/repo> — repository (required)
  • --run-id <id> — CI run ID (required)
  • --workflow <name> — workflow name (required)
  • --commit <sha> — commit SHA (required)
  • --auto-login — configure tea CLI login from CI_GITEA_TOKEN before creating the issue

devx ci post-merge

Update Vikunja task after a merge to master. Extracts the task ID from the commit message, marks the task as done, and posts a comment with the merge SHA.

devx ci post-merge "DEVX-12 feat: add feature" --git-sha abc123def456

devx ci pr-review

Run automated PR review. Fetches the PR diff via the Gitea API and runs a series of checks, posting a structured review (COMMENT or REQUEST_CHANGES).

Checks: architecture compliance, best practices, security, i18n, resource management, documentation, test coverage, and commit conventions.

devx ci pr-review 42 oblachno-oss/devx

devx ci publish

Build package, publish to Gitea PyPI registry (or standard PyPI), and create a Gitea release with git-cliff-generated notes.

devx ci publish v1.0.0 oblachno-oss/devx
devx ci publish v1.0.0 oblachno-oss/devx --registry-url https://git.example.com/api/packages/owner/pypi
devx ci publish v1.0.0 oblachno-oss/devx --skip-build  # Gitea release only

Options:

  • --registry-url <url> — Gitea PyPI registry URL. Defaults to DEVX_PYPI_REGISTRY_URL env var or a URL derived from GITEA_API_URL. When set, publishes to Gitea PyPI instead of standard PyPI (unless PYPI_TOKEN is also set).
  • --skip-build — skip package build and PyPI publish (for non-Python repos that only need a Gitea release)

devx ci push-badges

Generate badge SVG files and push them to the badges branch. Also updates README.md and docs/index.md on master with cache-busting raw/commit/<sha>/ URLs.

devx ci push-badges
devx ci push-badges --output-dir .badges/ --branch master
devx ci push-badges --no-readme-update  # skip README update (local testing)
devx ci push-badges --retries 3  # retry on git push failures

Options:

  • --output-dir <dir> — temporary directory for badge files (default: .badges/)
  • --branch <branch> — branch to sync before generating badges (default: master)
  • --no-readme-update — skip updating README with cache-busting URLs
  • --retries <n> — number of attempts on git push failures (default: 1). Between attempts, fetches latest master and waits 10s.

devx ci release

Automated release: calculate next version, update files, tag, and push. Uses git-cliff to determine the next semver version from conventional commits.

devx ci release
devx ci release --dry-run          # preview without making changes
devx ci release --skip-tests       # skip lint and tests (emergency only)
devx ci release --verify           # check tag/version/changelog alignment

Options:

  • --dry-run — show what would happen without making changes
  • --skip-tests — skip lint and test verification (NOT recommended — only for emergency releases)
  • --verify — verify tag/version/changelog alignment and exit (no changes made)

devx ci sync-wiki

Sync documentation from docs/ to the Gitea wiki. Reads docs/mapping.json for file-to-page mapping. Pages that exist in the wiki but not in the mapping are left untouched.

devx ci sync-wiki --repo oblachno-oss/devx
devx ci sync-wiki --repo oblachno-oss/devx --dry-run
devx ci sync-wiki --repo oblachno-oss/devx --verify
devx ci sync-wiki --repo oblachno-oss/devx --strict

Options:

  • --dry-run — show what would happen without making changes
  • --repo <owner/repo> — repository (auto-detected if omitted)
  • --verify — after syncing, verify each page has non-empty content. Exit 1 if any page is empty or mismatched.
  • --strict — full integrity check: verify page count, missing pages, stale pages, and content. Implies --verify.

devx ci validate-commit-msg

Validate commit messages for conventional commit format. On feature branches: conventional commits only (no {PREFIX}-N prefix). On master: must have {PREFIX}-N prefix from auto-merge, followed by a conventional commit message.

devx ci validate-commit-msg commit-msg.txt
devx ci validate-commit-msg commit-msg.txt --branch master

Options:

  • --branch <branch> — override branch detection (for CI use)

devx ci cancel-superseded-runs

Cancel in-flight CI runs for the same PR branch when a new push triggers a new run. Uses the Gitea Actions API to list running pull_request runs and cancel those with a lower run ID on the same branch.

devx ci cancel-superseded-runs \
    --repo "$REPOSITORY" \
    --current-run-id "$GITHUB_RUN_ID" \
    --head-branch "$HEAD_REF"

Options:

  • --repo <owner/repo> — repository (required)
  • --current-run-id <id> — current run ID, not cancelled (required)
  • --head-branch <branch> — PR head branch name (required)
  • --dry-run — list superseded runs without cancelling
  • --base-url <url> — Gitea base URL (default: GITEA_API_URL env var)

devx ci check-workflow-artifact-deps

Verify that workflow jobs downloading artifacts depend on the uploading job. Prevents the class of bug where a download job runs in parallel with the upload job and fails because the artifact isn't available yet.

devx ci check-workflow-artifact-deps
devx ci check-workflow-artifact-deps --workflow .gitea/workflows/ci.yml

Options:

  • --workflow <path> — check a specific workflow file
  • --workflows-dir <path> — override workflows directory

devx ci check-workflow-tofu-init

Verify that workflow jobs using tofu state (tofu output/plan/apply or scripts that call them) have a tofu-init step in the same job.

devx ci check-workflow-tofu-init
devx ci check-workflow-tofu-init --workflow .gitea/workflows/deploy.yml

Options:

  • --workflow <path> — check a specific workflow file
  • --workflows-dir <path> — override workflows directory
  • --state-script <name> — add a script that uses tofu state (repeatable)

Tools Commands

devx tools check-test-speed

Run unit tests and enforce execution-time budgets. Two quality gates:

  • Total suite time must not exceed --max-seconds (default: 10s)
  • Per-test time — no individual test may exceed --max-single-seconds (default: 0.5s, 0 to turn off)

Runs make test-unit with PYTEST_ADDOPTS=--durations=0 so pytest emits per-test timing lines.

devx tools check-test-speed
devx tools check-test-speed --max-seconds 10
devx tools check-test-speed --max-seconds 4 --max-single-seconds 0.5

devx tools check-test-isolation

Statically analyze test files for un-hermetic patterns that cause slow or flaky tests. Also available as a pytest plugin (auto-discovered via the pytest11 entry point when devx is installed — runs automatically on every pytest invocation and fails on violations).

Detected patterns (hard errors — exit non-zero):

  • unpatched-subprocess: subprocess.run/call/Popen/check_call/check_output called in a test function without @patch or with patch(...)
  • unpatched-sleep: time.sleep called without @patch
  • unpatched-helper: known subprocess-spawning helpers (update_doc_versions, run_cmd, run_tests) called without @patch or patching their internal deps
  • excessive-iterations: for _ in range(N) where N > 100
  • heavy-module-import: httpx, ansible, etc. imported at module level
  • reload-without-cleanup: importlib.reload() called an odd number of times

Advisory patterns (exit 0 — runtime audit is authoritative):

  • transitive-subprocess: CliRunner.invoke(target) where target transitively calls subprocess.run without being patched. Detected via static call-graph analysis. The runtime subprocess audit catches actual leaks — if a real subprocess runs without @patch, the test fails.
devx tools check-test-isolation
devx tools check-test-isolation --test-path tests/
devx tools check-test-isolation --categories unpatched-subprocess,transitive-subprocess
devx tools check-test-isolation --max-loop-iterations 50
devx tools check-test-isolation --src-dir src/

Pytest plugin options (automatic when devx is installed):

  • --no-test-isolation — turn off static analysis and runtime subprocess audit
  • --test-isolation-max-loop N — max iterations per loop (default: 100)

devx tools configure-repo

Configure repository: branch protection and labels via the Gitea REST API. Sets up master branch protection (required status checks, block on rejected reviews, block on outdated branch) and creates standard labels.

devx tools configure-repo --repo devx --owner oblachno-oss

Status check contexts are read from DEVX_STATUS_CHECKS (comma-separated) or default to CI / quality (pull_request).

devx tools generate-badges

Generate self-contained SVG badge files from project metrics. Runs pytest-cov, doc-coverage, lint checks, and version extraction, then writes SVG files that can be served as static files from the Gitea raw file API.

Badges generated: coverage.svg, tests.svg, docs.svg, quality.svg, version.svg, python.svg.

devx tools generate-badges
devx tools generate-badges --output-dir .badges/

devx tools generate-cliff-config

Generate a cliff.toml configuration file with the correct task ID prefix preprocessor. Eliminates the need to manually duplicate and maintain cliff.toml across repos that use devx.

devx tools generate-cliff-config --prefix GRM
devx tools generate-cliff-config --prefix GRM --output cliff.toml
devx tools generate-cliff-config --prefix GRM --force  # overwrite existing

Options:

  • --prefix <prefix> — task ID prefix (default: DEVX_TASK_PREFIX env var or DEVX)
  • --output <file> — output path (default: cliff.toml)
  • --force — overwrite existing file

devx tools install-checkmake

Install checkmake (Makefile linter) if not already present. Tries go install first if Go is available, otherwise downloads the latest pre-built Linux binary from the official GitHub releases.

devx tools install-checkmake

devx tools install-tools

Install CI/CD development tools that are not Python packages: actionlint, git-cliff, act_runner, and tea. Each tool is installed to ~/.local/bin if not already on PATH. Idempotent: skips tools that are already available.

devx tools install-tools                    # install all
devx tools install-tools --tool actionlint  # install one
devx tools install-tools --tool git-cliff --tool tea  # install specific
devx tools install-tools --list             # list status

devx tools setup

Project setup: install Python dependencies (editable mode with extras), Ansible Galaxy collections (if ansible/requirements.yml exists in the target repo), pre-commit hooks (pre-commit, commit-msg, pre-push), and configure the tea CLI login profile from .env.

devx tools setup --bin .venv/bin
devx tools setup --bin .venv/bin --extras "ci,lint"
devx tools setup --bin .venv/bin --no-pre-commit --no-tea-login

Options:

  • --bin <dir> — virtualenv bin directory (required)
  • --extras <groups> — pip extras to install (default: dev)
  • --no-pre-commit — skip pre-commit hook installation
  • --no-tea-login — skip tea CLI login configuration

devx tools rebase

Rebase the current branch onto origin/master and force-push with --force-with-lease. Checks if the branch is behind master first — if up-to-date, exits without doing anything.

devx tools rebase                          # rebase + force-push
devx tools rebase -- --no-push             # rebase locally only

Options (pass after --):

  • --no-push — rebase locally without pushing

devx tools pr-rebase

Rebase a pull request's head branch onto master via the Gitea API (server-side). This triggers a new pull_request synchronize event, which starts a new CI run. Useful when you don't have the branch checked out locally.

devx tools pr-rebase -- --pr 42            # rebase PR #42
devx tools pr-rebase                       # auto-detect PR from current branch

Options (pass after --):

  • --pr <N> — PR number (auto-detected from current branch if omitted)

devx tools check-docker-init

Check that Docker Compose services with healthchecks have init: true. Without init: true, CMD-SHELL healthchecks spawn child processes that become zombies when PID 1 doesn't reap them.

devx tools check-docker-init
devx tools check-docker-init --path path/to/docker-compose.yml.j2

Options:

  • --path <path> — check a specific file or directory
  • --templates-dir <path> — override templates directory (default: ansible/roles/)

devx tools check-ansible-set-fact-to-json

Check that Ansible set_fact tasks don't misuse | to_json. Using to_json in set_fact converts native Python types to JSON strings, causing iteration bugs (for example, iterating over characters instead of list items).

devx tools check-ansible-set-fact-to-json
devx tools check-ansible-set-fact-to-json --path path/to/playbook.yml

Options:

  • --path <path> — check a specific file or directory
  • --ansible-dir <path> — override ansible directories (repeatable)

devx tools check-alert-rules

Validate rendered Prometheus alert rules with promtool check rules. Renders a Jinja2 template with test values and validates the output. Skips (exits 0) if promtool is not on PATH.

devx tools check-alert-rules \
    --template-path ansible/roles/observability/templates
devx tools check-alert-rules \
    --template-path ansible/roles/observability/templates \
    --var grafana_base_url=https://grafana.example.com

Options:

  • --template-path <path> — path to templates directory (required)
  • --template-name <name> — template filename (default: alert-rules.yml.j2)
  • --var key=value — template variables (repeatable)

Molecule Commands

Molecule commands require the molecule extra (pip install devx[molecule]).

devx molecule all

Run all molecule scenarios on all supported OS platforms. Sequential execution — CI uses the parallel matrix instead.

devx molecule all
devx molecule all --bin .venv/bin

devx molecule discover-runners

Discover available Gitea Actions runners for molecule tests. Same logic as devx ci discover-runners but intended for molecule-specific workflows.

devx molecule discover-runners --owner oblachno-oss --repo devx --indices

devx molecule distribute

Distribute molecule (scenario, platform) pairs across N parallel runners. Discovers scenarios under ansible/roles/*/molecule/ and crosses them with the supported OS platform matrix.

devx molecule distribute --runner-index 1 --max-runners 3
devx molecule distribute --list              # list all scenarios
devx molecule distribute --list-platforms    # list platforms
devx molecule distribute --roles-root ansible/roles  # multi-role repos

Options:

  • --runner-index <i> — current runner index (0-based)
  • --max-runners <n> — total number of runners (default: 3)
  • --list — list all scenarios, one per line
  • --list-platforms — list all platforms, one per line
  • --roles-root <dir> — roles root directory for multi-role repos (default: ansible/roles)