220 lines
7.4 KiB
Markdown
220 lines
7.4 KiB
Markdown
---
|
|
title: Git Workflow
|
|
tags: [development]
|
|
---
|
|
|
|
# Git Workflow
|
|
|
|
How code moves from a developer's laptop to production.
|
|
|
|
---
|
|
|
|
## 1. Repositories & branches
|
|
|
|
Both repos are hosted on the self-hosted Gitea instance at **`git.manko.yoga`** (SSH on **port 222**, HTTPS on 443).
|
|
|
|
| Repo | Path | Branches |
|
|
|------|------|----------|
|
|
| Backend | `ssh://git@git.manko.yoga:222/nick/backend.git` | `main`, `development`, `feature/*`, `fix/*` |
|
|
| Frontend | `ssh://git@git.manko.yoga:222/nick/frontend.git` | `main`, `development`, `feature/*`, `fix/*` |
|
|
|
|
### Branch roles
|
|
|
|
| Branch | Role | Auto-deploy |
|
|
|--------|------|-------------|
|
|
| `main` (or `master`) | **Production.** Always deployable. | Yes — Gitea Actions builds + pushes `:latest`, Watchtower then pulls it. See [[CI-CD Pipeline]] and [[Deployment]]. |
|
|
| `development` | **Active dev.** Integration branch where features land before promotion. | Yes — builds + pushes `:dev` tag (not consumed by prod Watchtower). |
|
|
| `feature/<short-slug>` | One change in flight. Branched from `development`. | No |
|
|
| `fix/<short-slug>` | A bug fix. Branched from `development` (or `main` for a hotfix). | No |
|
|
| `hotfix/<slug>` | Urgent production fix branched from `main`. | No until merged |
|
|
|
|
```
|
|
main ─●────────●───────────────●───────► (prod, tagged v2.6.x)
|
|
▲ release merge
|
|
development ─●────●────●───●───●────●────●────●──► │
|
|
▲ ▲ ▲ ▲ ▲ │
|
|
│ │ │ │ │ │
|
|
feature/* branches off development │
|
|
hotfix/* ─────────────────────────────●──────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Day-to-day developer flow
|
|
|
|
```bash
|
|
# 1. Sync development
|
|
git checkout development
|
|
git pull --rebase
|
|
|
|
# 2. Create a branch
|
|
git checkout -b feature/add-seller-payouts
|
|
|
|
# 3. Hack
|
|
# ...
|
|
|
|
# 4. Verify locally
|
|
npm run lint && npm run typecheck && npm run test
|
|
# or for frontend
|
|
yarn lint && yarn test
|
|
|
|
# 5. Commit (Conventional Commits — see Coding Standards)
|
|
git commit -m "feat(payment): add seller payout history view"
|
|
|
|
# 6. Push & open PR
|
|
git push -u origin feature/add-seller-payouts
|
|
```
|
|
|
|
Open the PR in Gitea against `development`. CI will run on the PR if you have workflows enabled.
|
|
|
|
> [!tip] Use the `.gitmessage` template (`git config commit.template .gitmessage`) — it pre-fills the conventional-commit format with hints.
|
|
|
|
---
|
|
|
|
## 3. Commit message convention
|
|
|
|
Enforced on the frontend by `frontend/.commitlintrc.json` (and followed by convention on backend). See [[Coding Standards#commit-conventions]] for the full rules and examples.
|
|
|
|
Quick reference:
|
|
|
|
```
|
|
type(scope): subject
|
|
|
|
feat: add user authentication
|
|
fix(payment): handle missing tx hash
|
|
docs: clarify env vars table
|
|
chore: bump dependencies
|
|
feat!: redesign API endpoints # breaking change
|
|
```
|
|
|
|
Append `[skip-version]` to skip the auto-version bump when releasing.
|
|
|
|
---
|
|
|
|
## 4. PR review process
|
|
|
|
1. Open the PR with a description that covers **what**, **why**, and **how to test**.
|
|
2. Link to the related ticket / issue.
|
|
3. CI must be green (build, lint, tests where wired up).
|
|
4. **At least one reviewer** approves.
|
|
5. Squash-merge into `development` with a clean conventional-commit message.
|
|
6. Delete the source branch.
|
|
|
|
Reviewers check against [[Coding Standards#pr-review-checklist]].
|
|
|
|
> [!warning] Do **not** force-push to a PR branch after review starts — it invalidates review history. Use additional commits and let the squash-merge tidy up.
|
|
|
|
---
|
|
|
|
## 5. Releasing to production
|
|
|
|
The release path is `development → main → registry → production`.
|
|
|
|
```bash
|
|
# On a clean development that's ready to ship:
|
|
git checkout development
|
|
git pull --rebase
|
|
|
|
# Run AI-assisted version bump (chooses major/minor/patch from commit messages)
|
|
npm run smart-release
|
|
# This: bumps package.json, commits "chore: bump version to vX.Y.Z",
|
|
# creates a `vX.Y.Z` tag, and pushes commits + tags.
|
|
|
|
# Promote to main
|
|
git checkout main
|
|
git pull --rebase
|
|
git merge --ff-only development # fast-forward only — no merge commit
|
|
git push
|
|
```
|
|
|
|
What happens next:
|
|
|
|
- Pushing to `main` triggers the `docker-build-no-cache.yml` workflow on the backend (and `deploy.yml` on the frontend) — see [[CI-CD Pipeline]].
|
|
- That workflow builds the image and pushes both `:<version>` and `:latest` to `git.manko.yoga/manawenuz/escrow-backend`.
|
|
- **Watchtower** on the production host (see [[Deployment]]) polls the registry every interval, detects the new `:latest`, and rolls the production container.
|
|
|
|
### Manual builds
|
|
|
|
If you want to push a specific version without going through main, use:
|
|
|
|
```bash
|
|
# Backend
|
|
npm run release:patch # commits + tags + pushes; CI handles the rest
|
|
./scripts/build-and-push.sh # build locally and push dev tag
|
|
|
|
# Frontend
|
|
./scripts/deploy.sh # local build + push :latest
|
|
```
|
|
|
|
See [[Scripts]] for details.
|
|
|
|
---
|
|
|
|
## 6. Versioning
|
|
|
|
Semantic versioning, automated where possible.
|
|
|
|
- `package.json` `version` is the source of truth.
|
|
- The AI version scripts (`backend/scripts/ai-enhanced.sh`, `frontend/scripts/ai-enhanced.sh`) classify the last commit:
|
|
- `feat:` → minor
|
|
- `fix:` → patch
|
|
- `feat!:` or `BREAKING CHANGE:` → major
|
|
- `docs:`/`chore:`/`[skip-version]` → skip
|
|
- `auto-version.sh` applies the bump, commits, tags `v<version>`, and (with the npm wrappers) pushes.
|
|
|
|
Confidence levels (`high`/`medium`/`low`/`very-low`) gate the action — low confidence asks for a manual decision rather than auto-applying.
|
|
|
|
The CI workflows tag built images with both the `package.json` version and the moving tag (`:latest` for main, `:dev` for development).
|
|
|
|
---
|
|
|
|
## 7. Hotfix flow
|
|
|
|
```bash
|
|
# Branch from main
|
|
git checkout main && git pull --rebase
|
|
git checkout -b hotfix/critical-payment-bug
|
|
|
|
# Fix, test, commit
|
|
git commit -m "fix(payment): correct rounding on payout amount"
|
|
|
|
# Push + PR into main
|
|
git push -u origin hotfix/critical-payment-bug
|
|
# (open PR targeted at main; merge after review)
|
|
|
|
# After merge, port the fix back to development:
|
|
git checkout development && git pull --rebase
|
|
git merge --no-ff main
|
|
git push
|
|
```
|
|
|
|
Bump the patch version on `main` before merging so the new image gets a real tag, not just `:latest`.
|
|
|
|
---
|
|
|
|
## 8. SSH access on port 222
|
|
|
|
Gitea SSH listens on **222**, not 22, so the URL is always `ssh://git@git.manko.yoga:222/...`. Add this once to `~/.ssh/config`:
|
|
|
|
```ssh
|
|
Host git.manko.yoga
|
|
HostName git.manko.yoga
|
|
Port 222
|
|
User git
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
```
|
|
|
|
Then `git clone git@git.manko.yoga:nick/backend.git` "just works" without the explicit `:222`.
|
|
|
|
Container registry uses standard ports — `git.manko.yoga/manawenuz/escrow-backend:latest` over HTTPS — authenticated by a personal access token (`GITEATOKEN` secret in CI).
|
|
|
|
---
|
|
|
|
## 9. Rules of thumb
|
|
|
|
> [!tip] Keep PRs small. Anything > 500 LOC of net change is a candidate for splitting.
|
|
|
|
> [!warning] Never commit `.env*` files containing real secrets. The repos do already have committed `.env.development` / `.env.production` with **public** values — if you add a real secret, treat it as leaked and rotate.
|
|
|
|
> [!warning] Never force-push `main` or `development`. If you absolutely must rewrite history, coordinate with the team and re-tag the affected versions.
|