diff --git a/contributing.md b/contributing.md index 17a2106d..947ae8e7 100644 --- a/contributing.md +++ b/contributing.md @@ -10,13 +10,28 @@ Most files in the project are autogenerated by [openapi-generator](https://opena ## Commit messages -This project follows the [Conventional Commits](https://www.conventionalcommits.org/) standard. Each commit message should be structured as: +This project follows the [Conventional Commits](https://www.conventionalcommits.org/) standard. [commitlint](https://commitlint.js.org/) checks the messages of all commits in a pull request in the `Analyze Commit Messages` check, using the [@fingerprintjs/commit-lint-dx-team](https://www.npmjs.com/package/@fingerprintjs/commit-lint-dx-team/v/0.1.0) config. -``` -: +## Git hooks -[optional body] -``` +This repository has two optional hook setups. You can only use one of them at a time. + +- [install_hooks.sh](./install_hooks.sh) sets `core.hooksPath` to the [.git_hooks](./.git_hooks) folder and installs commitlint globally with npm, so you need Node.js. Its `commit-msg` hook checks the commit message with commitlint, and its `pre-push` hook tries to stop accidental pushes to `main`: + + ```shell + pnpm install + ./install_hooks.sh + ``` + +- [pre-commit](https://pre-commit.com/) runs Ruff (formatting and linting) and MyPy on every commit. Install it after `uv sync`: + + ```shell + uv run pre-commit install + ``` + +`pre-commit install` refuses to run while `core.hooksPath` is set, so it doesn't work after `./install_hooks.sh`. To switch to pre-commit, run `git config --unset-all core.hooksPath` first. + +Commit messages are also checked in CI. If the check fails, reword the offending commits (for example, with `git rebase -i`) and force-push the branch. ## Code generation @@ -96,7 +111,43 @@ uv run pytest ### How to publish -We use [changesets](https://github.com/changesets/changesets) for handling release notes. If there are relevant changes, please add them to changeset via `pnpm exec changeset`. You need to run `pnpm install` before doing so. +We use [changesets](https://github.com/changesets/changesets) to version the SDK and to write release notes. + +#### Adding a changeset + +If your PR changes the SDK's public API or behavior, add a changeset to it: + +```shell +pnpm install +pnpm exec changeset +``` + +Pick the bump type and write a short summary. The command creates a markdown file in the [.changeset](./.changeset) folder. Commit it together with the rest of your changes. The summary is copied as-is into `CHANGELOG.md` and the GitHub release notes, so write it for SDK users: + +```md +--- +'@fingerprint/python-sdk': minor +--- + +Add `device_details` smart signal to the event model +``` + +Pick the bump type that matches the commit type: + +| Change | Commit type | Changeset bump | Version change | +|---|---|---|---| +| Bug fix | `fix` | `patch` | 9.8.0 -> 9.8.1 | +| New backward-compatible feature | `feat` | `minor` | 9.8.0 -> 9.9.0 | +| Breaking change | Any `!` (for example, `feat!`) or a `BREAKING CHANGE:` footer | `major` | 9.8.0 -> 10.0.0 | +| Docs, tests, CI, refactoring and other internal changes | `docs`, `test`, `ci`, `refactor`, `chore`, ... | No changeset | No release | + +If a PR has several user-facing changes, add one changeset for each. When several changesets are released together, the highest bump wins. + +#### Release flow + +1. On every PR, a bot comments with a preview of the release notes that the PR's changesets will produce. If the PR has no changesets, the comment reminds you to add one. +2. After a PR with changesets is merged to `main`, the [Release](./.github/workflows/release.yml) workflow opens a `Release [changeset]` PR, or updates it if it's already open. That PR consumes all pending changesets, bumps the version and updates `CHANGELOG.md`. +3. Merging the `Release [changeset]` PR creates the Git tag and the GitHub release. The [Publish](./.github/workflows/publish.yml) workflow then uploads the package to PyPI. #### Pre-release flow