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
20 changes: 18 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ jobs:
- 'detekt.yml'
- '.github/workflows/ci.yml'

# Enforce Conventional Commits across a PR's commits (convco skips merge commits).
# Runs on pull_request only; on push to master it is skipped (the `required` gate
# treats skipped as pass). Tooling is pinned in the root mise.toml.
commit-lint:
name: Commit lint (convco)
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up mise tools (convco)
uses: jdx/mise-action@v2
- name: Check commits follow Conventional Commits
run: convco check --first-parent --ignore-reverts ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}

rust:
name: Rust (fmt + clippy + build)
needs: changes
Expand Down Expand Up @@ -300,12 +316,12 @@ jobs:
required:
name: required
if: always()
needs: [changes, rust, rust-test, rust-cross, web, docs, vision, markdown, kotlin]
needs: [changes, commit-lint, rust, rust-test, rust-cross, web, docs, vision, markdown, kotlin]
runs-on: ubuntu-latest
steps:
- name: Verify required jobs succeeded
run: |
for r in "${{ needs.rust.result }}" "${{ needs.rust-cross.result }}" \
for r in "${{ needs.commit-lint.result }}" "${{ needs.rust.result }}" "${{ needs.rust-cross.result }}" \
"${{ needs.web.result }}" \
"${{ needs.docs.result }}" "${{ needs.vision.result }}" \
"${{ needs.markdown.result }}" "${{ needs.kotlin.result }}"; do
Expand Down
44 changes: 44 additions & 0 deletions .versionrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# convco configuration (auto-discovered as `.versionrc`).
# Drives `convco check` (commit linting), `convco version` (next semver), and
# `convco changelog` (CHANGELOG.md generation). YAML or JSON are both accepted.
host: github.com
owner: Capsulsaurus
repository: Capsule

# Pre-1.0: breaking changes bump the minor (0.x), not the major.
preMajor: true

# Changelog sections. The commit types already in use across the repo all get a
# home; scope is left optional (conventional commits permit scope-less subjects,
# e.g. `chore: bump dependencies`).
types:
- type: feat
section: Features
hidden: false
- type: fix
section: Bug Fixes
hidden: false
- type: perf
section: Performance
hidden: false
- type: refactor
section: Refactoring
hidden: false
- type: build
section: Build System
hidden: false
- type: ci
section: Continuous Integration
hidden: false
- type: docs
section: Documentation
hidden: false
- type: style
section: Styling
hidden: true
- type: test
section: Tests
hidden: true
- type: chore
section: Chores
hidden: true
22 changes: 22 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,28 @@ lint-md:
lint-check-md:
bunx markdownlint-cli2

# ── Commits / release ────────────────────────────────────────────────────────
# convco enforces Conventional Commits (https://www.conventionalcommits.org).
# `commit-check` validates a single in-progress message (commit-msg hook);
# `check-commits` validates a range (pre-push and CI on PRs). convco skips merge
# commits in a range on its own; the single-message path skips the auto-generated
# merge/revert/fixup/squash subjects that tooling — not the author — writes.

[group('release')]
commit-check msg_file:
#!/usr/bin/env bash
set -euo pipefail
# Skip the auto-generated subjects tooling writes (merge/revert/fixup/squash);
# everything else must be conventional. `--strip` drops comments/whitespace.
case "$(sed -n '1p' "{{ msg_file }}")" in
Merge\ *|Revert\ *|fixup!\ *|squash!\ *) exit 0 ;;
esac
convco check --from-stdin --strip < "{{ msg_file }}"

[group('release')]
check-commits base="origin/master":
convco check --first-parent --ignore-reverts {{ base }}..HEAD

# ── Setup ────────────────────────────────────────────────────────────────────

[group('setup')]
Expand Down
11 changes: 11 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ pre-commit:
pre-push:
parallel: false
commands:
# Priority 0: Conventional Commits check over the range being pushed.
check-commits:
priority: 0
run: just check-commits

# Priority 1: all format/lint checks (read-only, no writes)
format-check-rust:
priority: 1
Expand Down Expand Up @@ -128,3 +133,9 @@ pre-push:
priority: 2
glob: "capsule-web/**/*.{ts,tsx,js,jsx}"
run: just test-web

# Validate the message of the commit being written (Conventional Commits).
commit-msg:
commands:
convco:
run: just commit-check {1}
15 changes: 15 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Repo-wide dev tooling, pinned so local and CI install identical versions.
# Install everything with: mise install (run from the repo root)
#
# Scope: the release/commit toolchain shared across every package. Language
# toolchains stay where they belong — Rust in /rust-toolchain.toml, the Apple
# client's Swift tools in capsule-swift/mise.toml (mise layers child configs on
# top of this one).
[tools]
just = "1"
lefthook = "2"
# convco isn't in the mise registry. Its GitHub release assets aren't named in a way the
# `ubi` backend can resolve on Linux (ambiguous ubuntu/deb zips), so use the `cargo`
# backend — it fetches a prebuilt binary via cargo-binstall when possible and otherwise
# builds from source, working uniformly on every OS in CI and locally.
"cargo:convco" = "0.6.4"
Loading