From 5c0798fe10c0da7df4fec3d108db22d69e4702e8 Mon Sep 17 00:00:00 2001 From: Dmitry Verkhoturov Date: Mon, 6 Jul 2026 00:32:56 +0100 Subject: [PATCH] docs(claude): document milestone + issue-label conventions Milestones: one vX.Y.Z per release; decide a PR's release by whether its merge commit is contained in a release tag (git tag --contains), not by dates; issues get a milestone only when closed by a code change. Plus the issue-label taxonomy (type / area / priority / contribution / resolution). --- CLAUDE.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 3a943bb2..a13a50fd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,6 +41,21 @@ GoReleaser must ignore `backend/*` tags in `.goreleaser.yml` so release notes an For local artifact runs, install GoReleaser, Go 1.25, Node 16+, PNPM 8, and Perl, then use `make release`. The target runs a snapshot/no-publish GoReleaser build, leaves local artifacts and metadata in `dist/`, and cleans generated frontend embed files after GoReleaser exits. Do not run raw `goreleaser release` for local artifacts unless you also run `./scripts/cleanup-release-assets.sh` afterward. +## Milestones and Issue Labels + +**Milestones** — one `vX.Y.Z` milestone per release. Assign every merged PR, and every issue closed by a code change, to the milestone of the release it shipped in. +- Decide which release a PR belongs to by whether its merge commit is **contained in a release tag** — not by comparing dates (a tag can be cut from an earlier commit, or moved). `git fetch --tags`, then `git tag --contains | grep '^v' | sort -V | head -1` is its release. If no release tag contains it yet, it belongs to the next (unreleased) version's milestone — create it if missing (`gh api repos/umputun/remark42/milestones -f title="vX.Y.Z"`). +- An **issue gets a milestone only when it was closed by a code change** (a linked closing PR/commit); take the milestone from that PR/commit (via the commit-in-tag rule). Issues closed as `duplicate`/`invalid`/`wontfix`/answered get no milestone. +- Find unassigned: `gh pr list --state merged --search "no:milestone"`, `gh issue list --state closed --search "no:milestone"`. Assign with `gh pr edit N --milestone "vX.Y.Z"` / `gh issue edit N --milestone "vX.Y.Z"`. + +**Issue labels** — classify each issue with a type and an area (add priority when relevant): +- Type: `bug`, `enhancement`, `question`, `documentation`, `discussion` +- Area: `backend`, `frontend`, `site`, `CI`, `design`, `localization` +- Priority: `important`, `minor`, `some day` +- Contribution: `help wanted`, `good-first-issue` +- Resolution (on close, when applicable): `duplicate`, `invalid`, `wontfix`, `no-action-needed` +- PR auto-labels (applied by Dependabot/Actions, not manual PRs): `dependencies`, `go`, `javascript`, `github_actions` + ## Code Style - **Backend**: Formatting with golangci-lint, strict error handling - **Frontend**: TypeScript with ESLint, Stylelint and Prettier