refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# load-project.sh — Load project config from a TOML file into env vars
|
|
|
|
|
#
|
|
|
|
|
# Usage (source, don't execute):
|
|
|
|
|
# source lib/load-project.sh projects/harb.toml
|
|
|
|
|
#
|
|
|
|
|
# Exports:
|
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
|
|
|
# PROJECT_NAME, FORGE_REPO, FORGE_API, FORGE_WEB, FORGE_URL,
|
|
|
|
|
# PROJECT_REPO_ROOT, PRIMARY_BRANCH, WOODPECKER_REPO_ID,
|
|
|
|
|
# PROJECT_CONTAINERS, CHECK_PRS, CHECK_DEV_AGENT,
|
2026-03-23 19:19:16 +00:00
|
|
|
# CHECK_PIPELINE_STALL, CI_STALE_MINUTES,
|
|
|
|
|
# MIRROR_NAMES, MIRROR_URLS, MIRROR_<NAME> (per configured mirror)
|
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
|
|
|
# (plus backwards-compat aliases: CODEBERG_REPO, CODEBERG_API, CODEBERG_WEB)
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
#
|
|
|
|
|
# If no argument given, does nothing (allows poll scripts to work with
|
|
|
|
|
# plain .env fallback for backwards compatibility).
|
|
|
|
|
|
|
|
|
|
_PROJECT_TOML="${1:-}"
|
|
|
|
|
|
|
|
|
|
if [ -z "$_PROJECT_TOML" ] || [ ! -f "$_PROJECT_TOML" ]; then
|
|
|
|
|
return 0 2>/dev/null || exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Parse TOML to shell variable assignments via Python
|
|
|
|
|
_PROJECT_VARS=$(python3 -c "
|
|
|
|
|
import sys, tomllib
|
|
|
|
|
|
|
|
|
|
with open(sys.argv[1], 'rb') as f:
|
|
|
|
|
cfg = tomllib.load(f)
|
|
|
|
|
|
|
|
|
|
def emit(key, val):
|
|
|
|
|
if isinstance(val, bool):
|
|
|
|
|
print(f'{key}={str(val).lower()}')
|
|
|
|
|
elif isinstance(val, list):
|
|
|
|
|
print(f'{key}={\" \".join(str(v) for v in val)}')
|
|
|
|
|
else:
|
|
|
|
|
print(f'{key}={val}')
|
|
|
|
|
|
|
|
|
|
# Top-level
|
|
|
|
|
emit('PROJECT_NAME', cfg.get('name', ''))
|
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
|
|
|
emit('FORGE_REPO', cfg.get('repo', ''))
|
|
|
|
|
emit('FORGE_URL', cfg.get('forge_url', ''))
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
|
|
|
|
|
if 'repo_root' in cfg:
|
|
|
|
|
emit('PROJECT_REPO_ROOT', cfg['repo_root'])
|
|
|
|
|
if 'primary_branch' in cfg:
|
|
|
|
|
emit('PRIMARY_BRANCH', cfg['primary_branch'])
|
|
|
|
|
|
|
|
|
|
# [ci] section
|
|
|
|
|
ci = cfg.get('ci', {})
|
|
|
|
|
if 'woodpecker_repo_id' in ci:
|
|
|
|
|
emit('WOODPECKER_REPO_ID', ci['woodpecker_repo_id'])
|
|
|
|
|
if 'stale_minutes' in ci:
|
|
|
|
|
emit('CI_STALE_MINUTES', ci['stale_minutes'])
|
|
|
|
|
|
|
|
|
|
# [services] section
|
|
|
|
|
svc = cfg.get('services', {})
|
|
|
|
|
if 'containers' in svc:
|
|
|
|
|
emit('PROJECT_CONTAINERS', svc['containers'])
|
|
|
|
|
|
2026-03-17 08:52:41 +00:00
|
|
|
# [matrix] section
|
|
|
|
|
mx = cfg.get('matrix', {})
|
|
|
|
|
if 'room_id' in mx:
|
|
|
|
|
emit('MATRIX_ROOM_ID', mx['room_id'])
|
|
|
|
|
if 'bot_user' in mx:
|
|
|
|
|
emit('MATRIX_BOT_USER', mx['bot_user'])
|
|
|
|
|
if 'token_env' in mx:
|
|
|
|
|
emit('MATRIX_TOKEN_ENV', mx['token_env'])
|
|
|
|
|
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
# [monitoring] section
|
|
|
|
|
mon = cfg.get('monitoring', {})
|
|
|
|
|
for key in ['check_prs', 'check_dev_agent', 'check_pipeline_stall']:
|
|
|
|
|
if key in mon:
|
|
|
|
|
emit(key.upper(), mon[key])
|
2026-03-23 19:19:16 +00:00
|
|
|
|
|
|
|
|
# [mirrors] section
|
|
|
|
|
mirrors = cfg.get('mirrors', {})
|
|
|
|
|
for name, url in mirrors.items():
|
|
|
|
|
emit(f'MIRROR_{name.upper()}', url)
|
|
|
|
|
if mirrors:
|
|
|
|
|
emit('MIRROR_NAMES', list(mirrors.keys()))
|
|
|
|
|
emit('MIRROR_URLS', list(mirrors.values()))
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
" "$_PROJECT_TOML" 2>/dev/null) || {
|
|
|
|
|
echo "WARNING: failed to parse project TOML: $_PROJECT_TOML" >&2
|
|
|
|
|
return 1 2>/dev/null || exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Export parsed variables
|
|
|
|
|
while IFS='=' read -r _key _val; do
|
|
|
|
|
[ -z "$_key" ] && continue
|
|
|
|
|
export "$_key=$_val"
|
|
|
|
|
done <<< "$_PROJECT_VARS"
|
|
|
|
|
|
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
|
|
|
# Derive FORGE_API and FORGE_WEB from forge_url + repo
|
|
|
|
|
# FORGE_URL: TOML forge_url > existing FORGE_URL > default
|
|
|
|
|
export FORGE_URL="${FORGE_URL:-http://localhost:3000}"
|
|
|
|
|
if [ -n "$FORGE_REPO" ]; then
|
|
|
|
|
export FORGE_API="${FORGE_URL}/api/v1/repos/${FORGE_REPO}"
|
|
|
|
|
export FORGE_WEB="${FORGE_URL}/${FORGE_REPO}"
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
fi
|
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
|
|
|
# Backwards-compat aliases
|
|
|
|
|
export CODEBERG_REPO="${FORGE_REPO}"
|
|
|
|
|
export CODEBERG_API="${FORGE_API:-}"
|
|
|
|
|
export CODEBERG_WEB="${FORGE_WEB:-}"
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
|
|
|
|
|
# Derive PROJECT_REPO_ROOT if not explicitly set
|
|
|
|
|
if [ -z "${PROJECT_REPO_ROOT:-}" ] && [ -n "${PROJECT_NAME:-}" ]; then
|
|
|
|
|
export PROJECT_REPO_ROOT="/home/${USER}/${PROJECT_NAME}"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-03-17 08:52:41 +00:00
|
|
|
# Resolve MATRIX_TOKEN from env var name (token_env points to an env var, not the token itself)
|
|
|
|
|
if [ -n "${MATRIX_TOKEN_ENV:-}" ]; then
|
|
|
|
|
export MATRIX_TOKEN="${!MATRIX_TOKEN_ENV:-}"
|
|
|
|
|
unset MATRIX_TOKEN_ENV
|
|
|
|
|
fi
|
|
|
|
|
|
refactor: split supervisor into infra + per-project, make poll scripts config-driven
Supervisor split (#26):
- Layer 1 (infra): P0 memory, P1 disk, P4 housekeeping — runs once, project-agnostic
- Layer 2 (per-project): P2 CI/dev-agent, P3 PRs/deps — iterates projects/*.toml
- Adding a new project requires only a new TOML file, no code changes
Poll scripts accept project TOML arg (#27):
- dev-poll.sh, review-poll.sh, gardener-poll.sh accept optional project TOML as $1
- env.sh loads PROJECT_TOML if set, overriding .env defaults
- Cron: `dev-poll.sh projects/versi.toml` targets that project
New files:
- lib/load-project.sh: TOML to env var loader (Python tomllib)
- projects/versi.toml: current project config extracted from .env
Backwards compatible: scripts without a TOML arg fall back to .env config.
Closes #26, Closes #27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:57:18 +01:00
|
|
|
unset _PROJECT_TOML _PROJECT_VARS _key _val
|