Skip to content

Contributing

Thank you for your interest in contributing to fabric-dw-mcp-cli!

Dev Setup

Recommended: open the repo in GitHub Codespaces or VS Code with the Remote-Containers extension. The devcontainer handles all of steps 1–2 automatically.

  1. Install dependencies
uv sync
  1. Install just (optional, for convenient local checks)

  2. Authenticate with Azure (required for integration tests)

az login

Branch Flow

  • Branch off main for every change.
  • Use descriptive branch names, e.g. feat/add-table-command or fix/connection-timeout.
  • Open a pull request back to main.
  • PR titles must follow Conventional Commits; they become the squash-merge commit message.
  • All PRs are squash-merged.

Conventional Commits

PR titles (and therefore merge commits) must use one of these types:

Type When to use
feat New user-facing feature
fix Bug fix
chore Maintenance, tooling, dependency updates
docs Documentation only
refactor Code change with no feature or fix
test Adding or updating tests
ci CI/CD pipeline changes
perf Performance improvement
revert Revert a previous commit

Example: feat: add DROP TABLE command

Breaking changes must append ! after the type, e.g. feat!: rename CLI entrypoint.

These prefixes are also used by the release-drafter workflow: every PR merged to main updates a running GitHub release draft, categorised by type (feat → Features, fix → Fixes, docs → Documentation, ci/chore → CI / Tooling). When a version tag is pushed, the draft becomes the published release.

Running Checks Locally

Run all gates with just before pushing:

just check

Or run individual checks:

Lint

just lint
# Auto-fix lint and format issues:
just fix

Type checking

just type

Unit tests

just test
# With coverage report:
just cov
# With HTML coverage report:
just cov-html

Unit test network policy: unit tests must not make real network calls. tests/unit/conftest.py installs an autouse fixture (_block_real_sockets) that uses pytest-socket to replace socket.socket with a stub that raises SocketBlockedError immediately. Any unit test that accidentally reaches a real HTTP client will fail loudly.

  • Mock HTTP calls with respx (preferred) or patch build_http_client / open_connection at the service boundary.
  • Unix-domain sockets (AF_UNIX) are permitted because asyncio's event loop requires them internally; they cannot reach the internet.
  • Integration tests (tests/integration/) are exempt; they legitimately call real Fabric APIs and are not subject to this fixture.

Integration tests

Requires a valid az login session and a reachable Fabric workspace.

just integration

Integration test policy: the integration suite is label-gated: it only runs in CI when the integration label is applied to a PR. This is intentional: the integration tests hit real Fabric APIs and consume capacity. Maintainers apply the label when a PR touches API-touching behaviour. The integration suite is not a required status check; it is a maintainer-controlled gate.

Security audit

just audit

Build wheel/sdist

just build

Releasing

The plugin version (plugin.json) is auto-bumped from stable git tags by the Publish CI workflow. No release-prep PR is required.

Stable release (normal flow)

  1. Tag: run just tag X.Y.Z (e.g. just tag 2026.7.0) from a clean, up-to-date local main. The version must follow YYYY.M.N (year 20xx, month 1–12 with no leading zero, patch 0 or a positive integer without a leading zero, no prerelease suffix).
  2. Publish: the Publish CI workflow fires on the tag push, ships the package to PyPI, and creates a GitHub Release.
  3. Auto-bump: the sync-plugin-manifest job (in the same workflow) checks out the default branch, updates .claude-plugin/plugin.json to match the tag, and commits directly using a PAT. No manual PR needed.

Optional: pre-bump via release-prep PR

If you prefer to commit the plugin.json bump before tagging (e.g. for review purposes), just release X.Y.Z is still available. It writes the version into plugin.json so you can open a release-prep PR. After the PR is merged, just tag X.Y.Z proceeds as normal. The CI sync-plugin-manifest job will detect that plugin.json is already correct and skip the auto-commit.

Required one-time repo setup

The sync-plugin-manifest job pushes a commit directly to the default branch. It uses a fine-grained PAT (stored as a repo secret) to bypass branch protection:

  1. Create the PAT: an admin account must create a fine-grained Personal Access Token scoped to this repository with Contents: Read and Write permission. This allows the push to bypass branch protection rules (because enforce_admins is not set on this repo's main branch).
  2. Store it as a secret: add the PAT as a repository secret named RELEASE_BUMP_TOKEN under Settings > Secrets and variables > Actions.
  3. Protect tags (strongly recommended): because a v* tag push now causes an automated commit straight to the default branch via a PAT, it is important that only authorised maintainers can create v* tags. Add a tag protection rule under Settings > Tags matching the pattern v* so that only repository admins or designated roles can push release tags.

Without RELEASE_BUMP_TOKEN, the auto-commit step will fail and plugin.json will remain at its previous value on the default branch (the PyPI publish and GitHub Release are unaffected).

Prerelease builds

Prerelease builds (.devN suffix derived by hatch-vcs from commits since the last tag) are published automatically on every push to main; plugin.json always reflects the latest stable release only. just release and just tag both reject any prerelease suffix (aN/bN/rcN/.devN).

Code of Conduct

By participating in this project you agree to abide by the Code of Conduct.