init the mono repo
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
crearte/
|
||||
crearte-deploy/
|
||||
crearte-server/
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Repository role
|
||||
|
||||
Docker Compose orchestration for the crearte full stack. Three repos must stay siblings:
|
||||
|
||||
```
|
||||
repos/
|
||||
├── crearte/ # frontend (build context for web-* images)
|
||||
├── crearte-server/ # backend Go API (build context for api-* images)
|
||||
└── crearte-deploy/ # this repo — compose only, no app code
|
||||
```
|
||||
|
||||
Everything runs in containers. Do not introduce host-run workflows (no `npm run dev` / `go run` on the host) in docs, scripts, or compose.
|
||||
|
||||
## Safety Rules
|
||||
|
||||
- Branch naming: `{feat|fix|docs|chore}/{branch-name}` (e.g. `fix/compose-port-clash`).
|
||||
- Before `git commit`: run `git branch --show-current`. If on `master`, do NOT commit — ask the user for a branch name, create it, and commit there.
|
||||
- `.env` is gitignored and must stay that way. Never commit secrets. Any new secret must land in `.env.example` as an empty placeholder (with a comment) in the same commit that introduces it.
|
||||
- Changes → `docs/CHANGELOG.md` (this repo is not under `web/`, so `CHANGELOG_webui.md` never applies). Higher versions on top.
|
||||
- CHANGELOG entry format: same entry has English line then Chinese line on consecutive lines (no blank line between them); different entries are separated by a blank line.
|
||||
- Merging into `master`: always create a merge commit — `git merge --no-ff <branch>` (never fast-forward, the integration point must be recorded). Delete the merged branch afterwards.
|
||||
- Compose changes that alter usage must update `README.md` in the same commit.
|
||||
|
||||
## Compose invariants (breaking these loses data or breaks the stack)
|
||||
|
||||
- Sibling layout: build contexts are `../crearte` and `../crearte-server`. Never repoint them or inline copies of the app code.
|
||||
- dev and prod both publish host port `8080` — the profiles are mutually exclusive. Keep it that way unless README is updated accordingly.
|
||||
- Volume names are data identity: renaming a volume orphans its data. Never rename `pgdata-*`, `bundle-keys-*`, `minio-data-*`, or the `*_node_modules` volumes.
|
||||
- `db-test` (`pgdata-test`, 127.0.0.1:5432) is the integration-test database and is truncated freely. Never point `TEST_DATABASE_URL` at dev data — `db-debug` shares the `pgdata-dev` volume with `db-dev`, so a misdirected test run wipes development data.
|
||||
- Never run `docker compose ... down -v` unless the user explicitly asks: it destroys postgres data, bundle keys, and MinIO objects, and the MinIO bucket init must then be redone by hand.
|
||||
- Required secrets use `${VAR:?…}` so compose fails fast when missing. Keep the `:?` guard and `.env.example` in sync for every new secret.
|
||||
- The one-time MinIO bucket init (`mc mb local/crearte` + anonymous download) exists because the volume is empty on first creation — do not silently automate it away; document any change in README.
|
||||
- Keep `depends_on` health gating (api waits for `service_healthy` db); removing it makes first-boot races routine.
|
||||
|
||||
## Verification (required before claiming a compose change works)
|
||||
|
||||
1. `docker compose config -q` for each touched profile (`--profile dev|prod|debug|mock`).
|
||||
2. `docker compose --profile <p> up -d --build`, then `docker compose ps` — healthchecks must pass.
|
||||
3. Smoke-test the affected path (e.g. `docker compose exec api-dev wget -qO- http://127.0.0.1:8080/healthz`, or the upload flow through http://localhost:8080).
|
||||
4. Tear down with plain `down` (never `-v`) unless the task is specifically about destroying data.
|
||||
|
||||
## Layout notes
|
||||
|
||||
- `docs/superpowers/` (plans/specs) is tracked in this repo — unlike in `crearte`, where it is gitignored.
|
||||
- No app code, no tests, no build scripts live here; those belong to `crearte` / `crearte-server`.
|
||||
|
||||
Executable
+129
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# clone_all.sh — clone (or update) every project in this workspace.
|
||||
#
|
||||
# Idempotent, safe to re-run:
|
||||
# - directory missing / not a git repo -> git clone --branch <branch>
|
||||
# - directory already a git repo -> fetch + fast-forward to <branch>
|
||||
#
|
||||
# Usage:
|
||||
# ./clone_all.sh # clone or update all projects
|
||||
# CLONE_PROTO=https ./clone_all.sh # rewrite URLs to https (no SSH key needed)
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$ROOT_DIR" || exit 1
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Project list: "<dir-name>|<git-url>|<branch>"
|
||||
# ---------------------------------------------------------------------------
|
||||
REPOS=(
|
||||
"crearte|git@github.com:XingfenD/crearte.git|feat/submission-preview"
|
||||
"crearte-server|git@github.com:XingfenD/crearte-server.git|feat/submission-preview"
|
||||
"crearte-deploy|git@github.com:XingfenD/crearte-deploy.git|master"
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
if [ -t 1 ]; then
|
||||
C_OK=$'\033[32m'; C_WARN=$'\033[33m'; C_ERR=$'\033[31m'; C_OFF=$'\033[0m'
|
||||
else
|
||||
C_OK=''; C_WARN=''; C_ERR=''; C_OFF=''
|
||||
fi
|
||||
info() { printf '==> %s\n' "$*"; }
|
||||
ok() { printf "${C_OK} ok${C_OFF} %s\n" "$*"; }
|
||||
warn() { printf "${C_WARN} warn${C_OFF} %s\n" "$*"; }
|
||||
err() { printf "${C_ERR} error${C_OFF} %s\n" "$*" >&2; }
|
||||
|
||||
# ssh url -> https url when the caller asked for it
|
||||
resolve_url() {
|
||||
local url="$1"
|
||||
if [ "${CLONE_PROTO:-ssh}" = "https" ]; then
|
||||
url="${url#git@}"
|
||||
url="${url/://}"
|
||||
url="https://$url"
|
||||
fi
|
||||
printf '%s' "$url"
|
||||
}
|
||||
|
||||
has_local_changes() {
|
||||
local dir="$1"
|
||||
[ -n "$(git -C "$dir" status --porcelain 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Actions
|
||||
# ---------------------------------------------------------------------------
|
||||
clone_repo() {
|
||||
local dir="$1" url="$2" branch="$3"
|
||||
info "$dir: cloning $branch from $url"
|
||||
if git clone --branch "$branch" "$url" "$dir"; then
|
||||
ok "$dir cloned"
|
||||
return 0
|
||||
fi
|
||||
err "$dir clone failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
update_repo() {
|
||||
local dir="$1" branch="$2"
|
||||
info "$dir: updating $branch"
|
||||
|
||||
if ! git -C "$dir" fetch --prune origin; then
|
||||
err "$dir fetch failed (network or credentials?)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local current
|
||||
current="$(git -C "$dir" rev-parse --abbrev-ref HEAD)"
|
||||
if [ "$current" != "$branch" ]; then
|
||||
if has_local_changes "$dir"; then
|
||||
warn "$dir has uncommitted changes on '$current' — skipping branch switch to '$branch'"
|
||||
return 0
|
||||
fi
|
||||
if ! git -C "$dir" checkout "$branch"; then
|
||||
err "$dir could not switch to '$branch'"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! git -C "$dir" pull --ff-only origin "$branch"; then
|
||||
err "$dir not fast-forwardable — resolve manually (git -C $dir status)"
|
||||
return 1
|
||||
fi
|
||||
ok "$dir up to date"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
cloned=0 updated=0 skipped=0 failed=0
|
||||
|
||||
for entry in "${REPOS[@]}"; do
|
||||
IFS='|' read -r dir url branch <<< "$entry"
|
||||
|
||||
if [ -d "$dir/.git" ] || git -C "$dir" rev-parse --git-dir >/dev/null 2>&1; then
|
||||
if update_repo "$dir" "$branch"; then
|
||||
updated=$((updated + 1))
|
||||
else
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
elif [ -e "$dir" ]; then
|
||||
warn "$dir exists but is not a git repo — skipping (move it away or delete it)"
|
||||
skipped=$((skipped + 1))
|
||||
else
|
||||
if clone_repo "$dir" "$(resolve_url "$url")" "$branch"; then
|
||||
cloned=$((cloned + 1))
|
||||
else
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
printf '\nSummary: %d cloned, %d updated, %d skipped, %d failed\n' \
|
||||
"$cloned" "$updated" "$skipped" "$failed"
|
||||
|
||||
[ "$failed" -eq 0 ]
|
||||
Reference in New Issue
Block a user