chore: initial scaffold — workspace, docs, blueprint
Sets up the PiCloud monorepo as a Cargo workspace organised around the
three-service architecture (manager / orchestrator / executor), each
backed by a *-core library crate so the same logic powers both the MVP
all-in-one `picloud` binary and the future split-process cluster mode.
* crates/shared, executor-core, orchestrator-core, manager-core
define the library surface and trait seams between the three
services (`ExecutorClient`, `ScriptResolver`, `ScriptRepository`).
* crates/picloud is the MVP entrypoint; serves /healthz on 8080
(override via PICLOUD_BIND).
* crates/picloud-{manager,orchestrator,executor} are skeleton
binaries that keep the crate boundaries honest until cluster
mode is built out in v1.3+.
* docs/git-workflow.md defines the trunk-based workflow:
short-lived branches, Conventional Commits, separate hotfix
flow with mandatory reproduction tests.
* CLAUDE.md captures the working rules for future Claude sessions.
Workspace passes `cargo fmt`, `cargo clippy -D warnings` (with
pedantic enabled), and `cargo test --workspace`. The all-in-one
binary responds on `/healthz` and `/`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
202
docs/git-workflow.md
Normal file
202
docs/git-workflow.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Git Workflow
|
||||
|
||||
PiCloud uses **trunk-based development**: a single long-lived branch (`main`) that is always deployable, with short-lived branches for changes that need review.
|
||||
|
||||
This document defines how branches, commits, reviews, and releases work — and how bug fixes flow through the system.
|
||||
|
||||
---
|
||||
|
||||
## 1. Branches
|
||||
|
||||
| Branch | Purpose | Lifetime |
|
||||
|--------|---------|----------|
|
||||
| `main` | The trunk. Always green, always deployable. | Permanent |
|
||||
| `feat/<topic>` | New feature or non-trivial change. | ≤ 2 days |
|
||||
| `fix/<topic>` | Bug fix (non-critical). | ≤ 1 day |
|
||||
| `hotfix/<topic>` | Critical bug fix that needs to ship now. | Hours |
|
||||
| `chore/<topic>` | Refactor, deps update, CI tweak, docs. | ≤ 1 day |
|
||||
| `release/vX.Y` | Long-lived release branch for back-porting hotfixes to a shipped version. | Per minor version, once we tag releases |
|
||||
|
||||
**Rules:**
|
||||
|
||||
- Branch directly off `main`. Never branch off another feature branch.
|
||||
- Keep branches short. If a branch lives longer than 2 days, you're doing too much in one go — split it.
|
||||
- Branch names use `kebab-case` after the prefix: `feat/script-crud-endpoints`, `fix/executor-timeout-leak`.
|
||||
- Delete the branch after merge.
|
||||
|
||||
---
|
||||
|
||||
## 2. Commits
|
||||
|
||||
**Format: Conventional Commits.**
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body — optional, wrapped at 72 chars>
|
||||
|
||||
<footer — optional: BREAKING CHANGE, issue refs>
|
||||
```
|
||||
|
||||
**Types:** `feat`, `fix`, `chore`, `refactor`, `docs`, `test`, `perf`, `build`, `ci`.
|
||||
|
||||
**Scopes (current crates / areas):** `executor-core`, `orchestrator-core`, `manager-core`, `shared`, `picloud`, `dashboard`, `caddy`, `compose`, `ci`, `docs`.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```
|
||||
feat(executor-core): add operation budget enforcement
|
||||
|
||||
fix(orchestrator-core): release Postgres pool guard before dispatch
|
||||
|
||||
chore(ci): pin Rust toolchain to 1.92.0
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
|
||||
- One logical change per commit. If you can't describe it in one line, split it.
|
||||
- Subject line: imperative, ≤ 72 chars, no trailing period.
|
||||
- Body explains *why*, not *what* — the diff already shows what.
|
||||
- No `WIP`, `fixup`, or `oops` commits on `main`. Squash or rewrite before merging.
|
||||
|
||||
---
|
||||
|
||||
## 3. The Feature Loop
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ Pull latest main │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ Branch: feat/<name> │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ Commit small steps │◄────┐
|
||||
│ Run tests locally │ │
|
||||
└──────────┬──────────┘ │
|
||||
│ │
|
||||
┌──────────▼──────────┐ │
|
||||
│ Open PR to main │─────┘ (iterate on feedback)
|
||||
│ CI must be green │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ Squash-merge to main│
|
||||
│ Delete branch │
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
**Before opening a PR:**
|
||||
|
||||
```sh
|
||||
git fetch origin
|
||||
git rebase origin/main # keep history linear
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
**PR requirements:**
|
||||
|
||||
- CI green (fmt, clippy, tests, build).
|
||||
- At least one approving review for non-trivial changes. Solo dev exception: self-review the diff explicitly before merging.
|
||||
- PR description names *why* and links to any issue.
|
||||
- Squash-merge by default → one commit per PR on `main`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Bug-fix Workflow
|
||||
|
||||
Bugs are classified by severity:
|
||||
|
||||
### Non-critical bug — normal flow
|
||||
|
||||
1. Branch `fix/<topic>` from `main`.
|
||||
2. Write a failing test that reproduces the bug.
|
||||
3. Fix it. The test now passes.
|
||||
4. PR → review → squash-merge.
|
||||
|
||||
### Critical / production hotfix
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ Bug reported │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
┌───────────▼───────────┐
|
||||
│ Reproduce locally │ ← required before any fix
|
||||
│ Write failing test │
|
||||
└───────────┬───────────┘
|
||||
│
|
||||
┌───────────▼───────────┐
|
||||
│ Branch hotfix/<name> │
|
||||
│ from main │
|
||||
└───────────┬───────────┘
|
||||
│
|
||||
┌───────────▼───────────┐
|
||||
│ Minimal fix only │ ← no refactors, no unrelated changes
|
||||
│ Test passes │
|
||||
└───────────┬───────────┘
|
||||
│
|
||||
┌───────────▼───────────┐
|
||||
│ Fast-track review │
|
||||
│ Merge to main │
|
||||
└───────────┬───────────┘
|
||||
│
|
||||
┌───────────▼───────────┐
|
||||
│ Tag patch release │ (vX.Y.Z+1)
|
||||
│ Deploy │
|
||||
└───────────┬───────────┘
|
||||
│
|
||||
┌───────────▼───────────┐
|
||||
│ Cherry-pick to │ ← only if old releases are
|
||||
│ release/vX.Y if active│ still in use
|
||||
└───────────────────────┘
|
||||
```
|
||||
|
||||
**Critical hotfix rules:**
|
||||
|
||||
- A hotfix fixes one bug. Nothing else. No "while I'm here" cleanups.
|
||||
- The reproduction test stays in the suite forever — it's our guarantee the bug doesn't return.
|
||||
- If the fix can't be minimal (e.g. requires an architectural change), ship a *mitigation* as the hotfix (feature flag off, rate limit, revert), then schedule the real fix as a normal feature.
|
||||
|
||||
---
|
||||
|
||||
## 5. Keeping `main` Green
|
||||
|
||||
Trunk-based only works if `main` is always green. Mechanisms:
|
||||
|
||||
- **CI gate:** PRs cannot merge unless CI passes (`fmt`, `clippy -D warnings`, `cargo test --workspace`, dashboard build).
|
||||
- **Feature flags:** Code for incomplete features lives on `main` behind a flag, off by default. We finish features in small mergeable slices, not in long-lived branches.
|
||||
- **Reverts are cheap:** If something slips through and breaks `main`, revert first, debug after. `git revert <merge-sha>` and ship.
|
||||
- **No force-push to `main`.** Ever.
|
||||
|
||||
---
|
||||
|
||||
## 6. Releases
|
||||
|
||||
Until we ship publicly we deploy off `main` continuously. Once we have external users:
|
||||
|
||||
- Tag releases on `main`: `v0.1.0`, `v0.1.1`, `v0.2.0` (SemVer).
|
||||
- Patch releases (`v0.1.1`) come from hotfixes; bump the patch number on each fix.
|
||||
- Minor releases (`v0.2.0`) come from accumulated features on `main`.
|
||||
- For each minor version supported in the wild, create `release/v0.1` and cherry-pick patches there. Otherwise don't bother — single trunk is simpler.
|
||||
|
||||
**Tagging:**
|
||||
|
||||
```sh
|
||||
git tag -a v0.1.0 -m "v0.1.0 — MVP"
|
||||
git push origin v0.1.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. What We Do Not Do
|
||||
|
||||
- **No GitFlow.** No `develop`, no `release` branches by default, no `next`. They add merge overhead without buying anything at our scale.
|
||||
- **No long-lived feature branches.** If a feature is too big to land in 2 days, split it. Use a feature flag.
|
||||
- **No merge commits on `main` from feature branches.** Squash-merge keeps history linear and bisectable.
|
||||
- **No commits straight to `main`** — even for typo fixes. Go through a PR (it can take 30 seconds to review and merge).
|
||||
- **No `--no-verify`** to bypass hooks. If a hook fails, fix the underlying issue.
|
||||
Reference in New Issue
Block a user