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.
- Install dependencies
-
Install just (optional, for convenient local checks)
-
Authenticate with Azure (required for integration tests)
Branch Flow¶
- Branch off
mainfor every change. - Use descriptive branch names, e.g.
feat/add-table-commandorfix/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:
Or run individual checks:
Lint¶
Type checking¶
Unit tests¶
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 patchbuild_http_client/open_connectionat 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.
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¶
Build wheel/sdist¶
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)¶
- Tag: run
just tag X.Y.Z(e.g.just tag 2026.7.0) from a clean, up-to-date localmain. The version must followYYYY.M.N(year20xx, month1–12with no leading zero, patch0or a positive integer without a leading zero, no prerelease suffix). - Publish: the
PublishCI workflow fires on the tag push, ships the package to PyPI, and creates a GitHub Release. - Auto-bump: the
sync-plugin-manifestjob (in the same workflow) checks out the default branch, updates.claude-plugin/plugin.jsonto 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:
- 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_adminsis not set on this repo's main branch). - Store it as a secret: add the PAT as a repository secret named
RELEASE_BUMP_TOKENunder Settings > Secrets and variables > Actions. - 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 createv*tags. Add a tag protection rule under Settings > Tags matching the patternv*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.