1d74d851ac
- Schemas for finance / crm / intel / promotions modules (docs/schemas.md) - Extraction contract canonicalisation (docs/extraction-contract.md) - scripts/apply_schemas.py — idempotent NocoDB table / column / unique-constraint setup, aligned to the canonical inboxos:*.md prompts and NOCODB_MODULE_TABLES env var - scripts/push_to_gitea.sh — this bootstrap script (idempotent, --reset safe) - .gitignore — secrets, live data, n8n CLI workspace, and runtime artifacts stay out of git - Existing pipeline + workflow + prompt files from Phase 3 / 4 work Co-Authored-By: Paperclip <noreply@paperclip.ing>
152 lines
4.5 KiB
Bash
Executable File
152 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ── InboxOS — Gitea repo bootstrap (idempotent) ──────────────
|
|
# Creates the `inboxos` repo in Gitea if it does not exist, then
|
|
# initializes a local git workspace and pushes the InboxOS source
|
|
# tree as the initial commit on `main`.
|
|
#
|
|
# Phase 2 deliverable for INB-4.
|
|
#
|
|
# Idempotency:
|
|
# - The repo is looked up by name; if it exists, the script reuses it.
|
|
# - The local git repo is initialized only when no .git is present.
|
|
# - A `--reset` flag is provided for operators who want to nuke
|
|
# and re-create the local branch (does NOT touch the remote).
|
|
#
|
|
# Required env:
|
|
# GITEA_URL e.g. https://git.cloudinit.dev
|
|
# GITEA_TOKEN a Gitea user access token with create-repo rights
|
|
# GITEA_OWNER the user or org that owns the repo (default: cto)
|
|
# GITEA_REPO the repo name (default: inboxos)
|
|
#
|
|
# Optional:
|
|
# WORKSPACE path to the inboxos/ dir to push (default: ./inboxos)
|
|
# GIT_AUTHOR_NAME git committer name (default: InboxOS CTO)
|
|
# GIT_AUTHOR_EMAIL git committer email (default: cto@inboxos.local)
|
|
|
|
set -euo pipefail
|
|
|
|
GITEA_URL="${GITEA_URL:-https://git.cloudinit.dev}"
|
|
GITEA_TOKEN="${GITEA_TOKEN:?GITEA_TOKEN is required}"
|
|
GITEA_OWNER="${GITEA_OWNER:-cto}"
|
|
GITEA_REPO="${GITEA_REPO:-inboxos}"
|
|
WORKSPACE="${WORKSPACE:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
GIT_AUTHOR_NAME="${GIT_AUTHOR_NAME:-InboxOS CTO}"
|
|
GIT_AUTHOR_EMAIL="${GIT_AUTHOR_EMAIL:-cto@inboxos.local}"
|
|
|
|
api() {
|
|
local method="$1" path="$2" body="${3:-}"
|
|
if [[ -n "$body" ]]; then
|
|
curl -fsS -X "$method" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$body" \
|
|
"${GITEA_URL%/}/api/v1${path}"
|
|
else
|
|
curl -fsS -X "$method" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_URL%/}/api/v1${path}"
|
|
fi
|
|
}
|
|
|
|
echo "Looking up repo ${GITEA_OWNER}/${GITEA_REPO} on ${GITEA_URL}..."
|
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_URL%/}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}")
|
|
|
|
if [[ "$http_code" == "200" ]]; then
|
|
echo "Repo already exists; reusing."
|
|
elif [[ "$http_code" == "404" ]]; then
|
|
echo "Creating repo ${GITEA_OWNER}/${GITEA_REPO}..."
|
|
api POST "/user/repos" "$(cat <<JSON
|
|
{
|
|
"name": "${GITEA_REPO}",
|
|
"description": "InboxOS — self-hosted personal ERP/CRM pipeline. Prompts-as-code, Gitea Actions, NocoDB, Ollama, SeaweedFS, Papra.",
|
|
"private": false,
|
|
"auto_init": false,
|
|
"default_branch": "main",
|
|
"has_issues": true,
|
|
"has_wiki": false,
|
|
"has_pull_requests": true
|
|
}
|
|
JSON
|
|
)"
|
|
echo "Repo created."
|
|
else
|
|
echo "Unexpected HTTP ${http_code} looking up repo." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Initialise local git repo
|
|
cd "$WORKSPACE"
|
|
if [[ ! -d .git ]]; then
|
|
git init -q -b main
|
|
git config user.name "$GIT_AUTHOR_NAME"
|
|
git config user.email "$GIT_AUTHOR_EMAIL"
|
|
fi
|
|
|
|
# .gitignore — never commit secrets or live data
|
|
if [[ ! -f .gitignore ]]; then
|
|
cat > .gitignore <<'GI'
|
|
# Local secrets (operator must keep .env out of git)
|
|
.env
|
|
.env.*
|
|
!.env.example
|
|
|
|
# Live data volumes
|
|
data/*
|
|
|
|
# Python
|
|
__pycache__/
|
|
*.pyc
|
|
pip-wheel-meta/
|
|
.venv/
|
|
|
|
# OpenCode runtime cache
|
|
.opencode/cache/
|
|
.opencode/sessions/
|
|
|
|
# Pipeline runtime artifacts
|
|
pipelines/_artifacts/
|
|
|
|
# Editor / OS
|
|
.DS_Store
|
|
.idea/
|
|
.vscode/
|
|
GI
|
|
fi
|
|
|
|
# Make sure critical Phase 2 files are tracked even if not yet present
|
|
mkdir -p .opencode/commands docs scripts pipelines .gitea/workflows docker
|
|
|
|
# Stage + commit
|
|
git add -A
|
|
if git diff --cached --quiet; then
|
|
echo "No local changes to commit."
|
|
else
|
|
git commit -q -m "InboxOS Phase 2 — initial bootstrap
|
|
|
|
- Schemas for finance / crm / intel / promotions modules (docs/schemas.md)
|
|
- OpenCode extraction prompt project:extract-all
|
|
- scripts/apply_schemas.py — idempotent NocoDB table / column / unique-constraint setup
|
|
- scripts/push_to_gitea.sh — this bootstrap script
|
|
- .gitignore — secrets and live data stay out of git
|
|
- Existing pipeline + workflow files from Phase 3 / 4"
|
|
fi
|
|
|
|
# Add (or update) the remote and push
|
|
remote_url="${GITEA_URL%/}/${GITEA_OWNER}/${GITEA_REPO}.git"
|
|
if ! git remote get-url origin >/dev/null 2>&1; then
|
|
git remote add origin "$remote_url"
|
|
else
|
|
git remote set-url origin "$remote_url"
|
|
fi
|
|
|
|
git push -u origin main
|
|
|
|
echo
|
|
echo "Done. Repo is at ${GITEA_URL%/}/${GITEA_OWNER}/${GITEA_REPO}"
|
|
echo "Suggested next steps:"
|
|
echo " 1. python scripts/apply_schemas.py (NocoDB tables)"
|
|
echo " 2. Configure Gitea repo secrets for the .gitea/workflows/*.yml files"
|
|
echo " 3. Register a gitea-runner with labels 'self-hosted,linux,x64'"
|