Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

on:
push:
branches: [main]
branches: [main, dev]
pull_request:
branches: [main]
branches: [main, dev]

permissions:
contents: read
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# Single automated release pipeline — push to main.
# Single automated release pipeline — push to dev.
#
# semantic-release (the `release` job) owns versioning: it analyses the
# Conventional-Commit history, bumps the version in pyproject.toml, updates
# CHANGELOG.md, creates the git tag, and publishes the GitHub Release (via the
# bundled @semantic-release/github plugin). It commits the bumped files back to
# main with [skip ci] so the pipeline does not re-trigger itself.
# dev with [skip ci] so the pipeline does not re-trigger itself.
#
# `dev` is the release-trigger branch (portfolio-wide convention). `main` is a
# stable mirror — it inherits the tagged release-commit via a separate forward
# merge from `dev` after each release. Regular-merge strategy on `dev → main`
# preserves SHA equality, so the tagged commit is reachable from both branches.
#
# When (and only when) semantic-release publishes a new version, the gated
# `publish` job checks out main HEAD (which now carries the bumped version),
# `publish` job checks out dev HEAD (which now carries the bumped version),
# runs the smoke gate, builds the sdist + wheel, and uploads to PyPI via
# trusted publishing (OIDC — no API token).
#
Expand All @@ -23,7 +28,7 @@ name: Release
on:
push:
branches:
- main
- dev

permissions:
contents: write # create tags + releases
Expand Down Expand Up @@ -99,7 +104,7 @@ jobs:
- name: Checkout released commit
uses: actions/checkout@v6
with:
ref: main
ref: dev
fetch-depth: 0
- uses: actions/setup-python@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion .releaserc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"branches": ["main"],
"branches": ["dev"],
"plugins": [
[
"@semantic-release/commit-analyzer",
Expand Down
30 changes: 15 additions & 15 deletions BRANCHING.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<!-- Generated by 0.1.0 (2026-05-21T09:09:55Z) from a shared template — do not edit directly. -->
# Branching — engrava

This repository uses a feature → integration → release → stable Git Flow.
This repository uses a feature → releaseintegration (release-trigger) → stable Git Flow: a change flows `feature/* → release/vX.Y.Z → dev → main`, with semantic-release firing on `dev`.

## Branches

| Branch | Role | Who pushes |
|---|---|---|
| `main` | Stable, tagged releases. Production-ready code. | Release process only |
| `dev` | Integration. Default PR target for features and fixes. | Maintainers (via PR) |
| `release/v<X.Y.Z>` | Release stabilisation. Branched from `dev`, merged forward to `dev` + cherry-picked into `main` at release time. | Maintainers |
| `dev` | Release-trigger and integration trunk. Default PR target for features and fixes. semantic-release runs on push to `dev` — the version tag `vX.Y.Z`, the release commit, the published artifact, and the GitHub Release are all produced from `dev`. | Maintainers (via PR) |
| `main` | Stable mirror. Production-ready code; the branch users land on when cloning. After each release, `main` is forward-merged from `dev` (regular merge), so the tagged commit is reachable from both branches (same SHA). `main` never originates a release on its own. | Release process only (forward-merge from `dev`) |
| `release/v<X.Y.Z>` | Per-version stabilisation. Branched from `main` (the last released state); accumulates one commit per change; merged into `dev` to fire the release; then deleted. | Maintainers |
| `<type>/<kebab-description>` | Feature, fix, chore, docs branches. | Contributors |

## Feature / fix / chore branch naming
Expand All @@ -36,27 +36,27 @@ This repository uses a feature → integration → release → stable Git Flow.
│ fix/* │
│ docs/* │
└──────┬───────┘
│ PR
┌──────────────┐
│ dev │ integration
└──────┬───────┘
│ release branch cut
│ PR (squash)
┌──────────────────┐
│ release/vX.Y.Z │ stabilisation
│ release/vX.Y.Z │ per-version stabilisation (cut from main)
└──────┬───────────┘
│ release + tag
│ merge
┌──────────────┐
│ dev │ release-trigger → semantic-release
│ vX.Y.Z tag │ (tag + publish created here)
└──────┬───────┘
│ forward-merge (regular)
┌──────────────┐
│ main │ stable
│ vX.Y.Z │
│ main │ stable mirror (inherits the tagged commit)
└──────────────┘
```

## Pull request expectations

- PRs target `dev` (not `main`).
- PRs target `dev` (not `main`). `main` is updated only by forward-merge from `dev` after a release — a `release/*` branch is never merged into `main` directly.
- CI must be green before review.
- Commits in the PR use Conventional Commits format.
- Squash-merge by default unless a maintainer requests preserving commit history.
Expand Down
10 changes: 6 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@ This repo follows a feature → release → integration → stable flow.

| Branch | Role |
|---|---|
| `main` | Stable, released. Tagged versions live here. |
| `dev` | Integration. Default PR target for features and fixes. |
| `release/v<X.Y.Z>` | Release stabilisation. Created from `dev`, merged forward. |
| `dev` | Release-trigger and integration trunk. semantic-release runs on push to `dev` — the version tag `vX.Y.Z`, the release-commit (CHANGELOG + `pyproject.toml` bump), the PyPI artifact, and the GitHub Release are all created on `dev`. |
| `main` | Stable mirror. The branch users land on when cloning. After each release, `main` is forward-merged from `dev` with a regular merge so the tagged commit is reachable from both branches (same SHA). `main` never originates a release on its own. |
| `release/v<X.Y.Z>` | Per-version stabilisation. Created from `main` (the last released state); accumulates one squash-commit per change; merged into `dev` to fire the release pipeline; then deleted. |
| `<type>/<kebab-description>` | Feature / fix / chore branches. Plain English; no internal identifiers; ≤ 50 chars. |

Open PRs targeting `dev`. Branch names should describe the change in plain English (`feature/priority-signal-hybrid-search`, `fix/empty-count-on-mindql`, `docs/quickstart-update`).
Open PRs from your feature branch targeting the active `release/v<X.Y.Z>` branch (or `dev` directly if no release branch is currently open). Branch names should describe the change in plain English (`feature/priority-signal-hybrid-search`, `fix/empty-count-on-mindql`, `docs/quickstart-update`).

Direct merge from a `release/*` branch into `main` is not used in this repo — `main` is updated exclusively via forward-merge from `dev` after a release publishes. This keeps the tagged commit reachable from both branches and prevents `main` from drifting ahead of the publisher branch.

## Contributions

Expand Down
Loading