feat: integrate framework files into monorepo under packages/mosaic/framework/
Moves all Mosaic framework runtime files from the separate bootstrap repo into the monorepo as canonical source. The @mosaic/mosaic npm package now ships the complete framework — bin scripts, runtime configs, tools, and templates — enabling standalone installation via npm install. Structure: packages/mosaic/framework/ ├── bin/ 28 CLI scripts (mosaic, mosaic-doctor, mosaic-sync-skills, etc.) ├── runtime/ Runtime adapters (claude, codex, opencode, pi, mcp) ├── tools/ Shell tooling (git, prdy, orchestrator, quality, etc.) ├── templates/ Agent and repo templates ├── defaults/ Default identity files (AGENTS.md, STANDARDS.md, SOUL.md, etc.) ├── install.sh Legacy bash installer └── remote-install.sh One-liner remote installer Key files with Pi support and recent fixes: - bin/mosaic: launch_pi() with skills-local loop - bin/mosaic-doctor: --fix auto-wiring for all 4 harnesses - bin/mosaic-sync-skills: Pi as 4th link target, symlink-aware find - bin/mosaic-link-runtime-assets: Pi settings.json patching - bin/mosaic-migrate-local-skills: Pi skill roots, symlink find - runtime/pi/RUNTIME.md + mosaic-extension.ts Package ships 251 framework files in the npm tarball (278KB compressed).
This commit is contained in:
493
packages/mosaic/framework/tools/bootstrap/init-project.sh
Executable file
493
packages/mosaic/framework/tools/bootstrap/init-project.sh
Executable file
@@ -0,0 +1,493 @@
|
||||
#!/bin/bash
|
||||
# init-project.sh - Bootstrap a project for AI-assisted development
|
||||
# Usage: init-project.sh [OPTIONS]
|
||||
#
|
||||
# Creates CLAUDE.md, AGENTS.md, and standard directories using templates.
|
||||
# Optionally initializes git labels and milestones.
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent"
|
||||
GIT_SCRIPT_DIR="$HOME/.config/mosaic/tools/git"
|
||||
SEQUENTIAL_MCP_SCRIPT="$HOME/.config/mosaic/bin/mosaic-ensure-sequential-thinking"
|
||||
|
||||
# Defaults
|
||||
PROJECT_NAME=""
|
||||
PROJECT_TYPE=""
|
||||
REPO_URL=""
|
||||
TASK_PREFIX=""
|
||||
PROJECT_DESCRIPTION=""
|
||||
SKIP_LABELS=false
|
||||
SKIP_CI=false
|
||||
CICD_DOCKER=false
|
||||
DRY_RUN=false
|
||||
declare -a CICD_SERVICES=()
|
||||
CICD_BRANCHES="main,develop"
|
||||
|
||||
show_help() {
|
||||
cat <<'EOF'
|
||||
Usage: init-project.sh [OPTIONS]
|
||||
|
||||
Bootstrap a project for AI-assisted development.
|
||||
|
||||
Options:
|
||||
-n, --name <name> Project name (required)
|
||||
-t, --type <type> Project type: nestjs-nextjs, django, generic (default: auto-detect)
|
||||
-r, --repo <url> Git remote URL
|
||||
-p, --prefix <prefix> Orchestrator task prefix (e.g., MS, UC)
|
||||
-d, --description <desc> One-line project description
|
||||
--skip-labels Skip creating git labels and milestones
|
||||
--skip-ci Skip copying CI pipeline files
|
||||
--cicd-docker Generate Docker build/push/link pipeline steps
|
||||
--cicd-service <name:path> Service for Docker CI (repeatable, requires --cicd-docker)
|
||||
--cicd-branches <list> Branches for Docker builds (default: main,develop)
|
||||
--dry-run Show what would be created without creating anything
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
# Full bootstrap with auto-detection
|
||||
init-project.sh --name "My App" --description "A web application"
|
||||
|
||||
# Specific type
|
||||
init-project.sh --name "My API" --type django --prefix MA
|
||||
|
||||
# Dry run
|
||||
init-project.sh --name "Test" --type generic --dry-run
|
||||
|
||||
# With Docker CI/CD pipeline
|
||||
init-project.sh --name "My App" --cicd-docker \
|
||||
--cicd-service "my-api:src/api/Dockerfile" \
|
||||
--cicd-service "my-web:src/web/Dockerfile"
|
||||
|
||||
Project Types:
|
||||
nestjs-nextjs NestJS + Next.js monorepo (pnpm + TurboRepo)
|
||||
django Django project (pytest + ruff + mypy)
|
||||
typescript Standalone TypeScript/Next.js project
|
||||
python-fastapi Python FastAPI project (pytest + ruff + mypy + uv)
|
||||
python-library Python library/SDK (pytest + ruff + mypy + uv)
|
||||
generic Generic project (uses base templates)
|
||||
auto Auto-detect from project files (default)
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-n|--name)
|
||||
PROJECT_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
-t|--type)
|
||||
PROJECT_TYPE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-r|--repo)
|
||||
REPO_URL="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--prefix)
|
||||
TASK_PREFIX="$2"
|
||||
shift 2
|
||||
;;
|
||||
-d|--description)
|
||||
PROJECT_DESCRIPTION="$2"
|
||||
shift 2
|
||||
;;
|
||||
--skip-labels)
|
||||
SKIP_LABELS=true
|
||||
shift
|
||||
;;
|
||||
--skip-ci)
|
||||
SKIP_CI=true
|
||||
shift
|
||||
;;
|
||||
--cicd-docker)
|
||||
CICD_DOCKER=true
|
||||
shift
|
||||
;;
|
||||
--cicd-service)
|
||||
CICD_SERVICES+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--cicd-branches)
|
||||
CICD_BRANCHES="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
echo "Run with --help for usage" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required args
|
||||
if [[ -z "$PROJECT_NAME" ]]; then
|
||||
echo "Error: --name is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Auto-detect project type if not specified
|
||||
detect_project_type() {
|
||||
# Monorepo (pnpm + turbo or npm workspaces with NestJS)
|
||||
if [[ -f "pnpm-workspace.yaml" ]] || [[ -f "turbo.json" ]]; then
|
||||
echo "nestjs-nextjs"
|
||||
return
|
||||
fi
|
||||
if [[ -f "package.json" ]] && grep -q '"workspaces"' package.json 2>/dev/null; then
|
||||
echo "nestjs-nextjs"
|
||||
return
|
||||
fi
|
||||
# Django
|
||||
if [[ -f "manage.py" ]] && [[ -f "pyproject.toml" ]]; then
|
||||
echo "django"
|
||||
return
|
||||
fi
|
||||
# FastAPI
|
||||
if [[ -f "pyproject.toml" ]] && grep -q "fastapi" pyproject.toml 2>/dev/null; then
|
||||
echo "python-fastapi"
|
||||
return
|
||||
fi
|
||||
# Standalone TypeScript
|
||||
if [[ -f "tsconfig.json" ]] && [[ -f "package.json" ]]; then
|
||||
echo "typescript"
|
||||
return
|
||||
fi
|
||||
# Python library/tool
|
||||
if [[ -f "pyproject.toml" ]]; then
|
||||
echo "python-library"
|
||||
return
|
||||
fi
|
||||
echo "generic"
|
||||
}
|
||||
|
||||
if [[ -z "$PROJECT_TYPE" || "$PROJECT_TYPE" == "auto" ]]; then
|
||||
PROJECT_TYPE=$(detect_project_type)
|
||||
echo "Auto-detected project type: $PROJECT_TYPE"
|
||||
fi
|
||||
|
||||
# Derive defaults
|
||||
if [[ -z "$REPO_URL" ]]; then
|
||||
REPO_URL=$(git remote get-url origin 2>/dev/null || echo "")
|
||||
fi
|
||||
|
||||
if [[ -z "$TASK_PREFIX" ]]; then
|
||||
# Generate prefix from project name initials
|
||||
TASK_PREFIX=$(echo "$PROJECT_NAME" | sed 's/[^A-Za-z ]//g' | awk '{for(i=1;i<=NF;i++) printf toupper(substr($i,1,1))}')
|
||||
if [[ -z "$TASK_PREFIX" ]]; then
|
||||
TASK_PREFIX="PRJ"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$PROJECT_DESCRIPTION" ]]; then
|
||||
PROJECT_DESCRIPTION="$PROJECT_NAME"
|
||||
fi
|
||||
|
||||
PROJECT_DIR=$(basename "$(pwd)")
|
||||
|
||||
# Detect quality gates, source dir, and stack info based on type
|
||||
case "$PROJECT_TYPE" in
|
||||
nestjs-nextjs)
|
||||
export QUALITY_GATES="pnpm typecheck && pnpm lint && pnpm test"
|
||||
export SOURCE_DIR="apps"
|
||||
export BUILD_COMMAND="pnpm build"
|
||||
export TEST_COMMAND="pnpm test"
|
||||
export LINT_COMMAND="pnpm lint"
|
||||
export TYPECHECK_COMMAND="pnpm typecheck"
|
||||
export FRONTEND_STACK="Next.js + React + TailwindCSS + Shadcn/ui"
|
||||
export BACKEND_STACK="NestJS + Prisma ORM"
|
||||
export DATABASE_STACK="PostgreSQL"
|
||||
export TESTING_STACK="Vitest + Playwright"
|
||||
export DEPLOYMENT_STACK="Docker + docker-compose"
|
||||
export CONFIG_FILES="turbo.json, pnpm-workspace.yaml, tsconfig.json"
|
||||
;;
|
||||
django)
|
||||
export QUALITY_GATES="ruff check . && mypy . && pytest tests/"
|
||||
export SOURCE_DIR="src"
|
||||
export BUILD_COMMAND="pip install -e ."
|
||||
export TEST_COMMAND="pytest tests/"
|
||||
export LINT_COMMAND="ruff check ."
|
||||
export TYPECHECK_COMMAND="mypy ."
|
||||
export FRONTEND_STACK="N/A"
|
||||
export BACKEND_STACK="Django / Django REST Framework"
|
||||
export DATABASE_STACK="PostgreSQL"
|
||||
export TESTING_STACK="pytest + pytest-django"
|
||||
export DEPLOYMENT_STACK="Docker + docker-compose"
|
||||
export CONFIG_FILES="pyproject.toml"
|
||||
export PROJECT_SLUG=$(echo "$PROJECT_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | sed 's/[^a-z0-9_]//g')
|
||||
;;
|
||||
typescript)
|
||||
PKG_MGR="npm"
|
||||
[[ -f "pnpm-lock.yaml" ]] && PKG_MGR="pnpm"
|
||||
[[ -f "yarn.lock" ]] && PKG_MGR="yarn"
|
||||
export QUALITY_GATES="$PKG_MGR run lint && $PKG_MGR run typecheck && $PKG_MGR test"
|
||||
export SOURCE_DIR="src"
|
||||
export BUILD_COMMAND="$PKG_MGR run build"
|
||||
export TEST_COMMAND="$PKG_MGR test"
|
||||
export LINT_COMMAND="$PKG_MGR run lint"
|
||||
export TYPECHECK_COMMAND="npx tsc --noEmit"
|
||||
export FRAMEWORK="TypeScript"
|
||||
export PACKAGE_MANAGER="$PKG_MGR"
|
||||
export FRONTEND_STACK="N/A"
|
||||
export BACKEND_STACK="N/A"
|
||||
export DATABASE_STACK="N/A"
|
||||
export TESTING_STACK="Vitest or Jest"
|
||||
export DEPLOYMENT_STACK="TBD"
|
||||
export CONFIG_FILES="tsconfig.json, package.json"
|
||||
# Detect Next.js
|
||||
if grep -q '"next"' package.json 2>/dev/null; then
|
||||
export FRAMEWORK="Next.js"
|
||||
export FRONTEND_STACK="Next.js + React"
|
||||
fi
|
||||
;;
|
||||
python-fastapi)
|
||||
export PROJECT_SLUG=$(echo "$PROJECT_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | sed 's/[^a-z0-9_]//g')
|
||||
export QUALITY_GATES="uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov"
|
||||
export SOURCE_DIR="src"
|
||||
export BUILD_COMMAND="uv sync --all-extras"
|
||||
export TEST_COMMAND="uv run pytest --cov"
|
||||
export LINT_COMMAND="uv run ruff check src/ tests/"
|
||||
export TYPECHECK_COMMAND="uv run mypy src/"
|
||||
export FRONTEND_STACK="N/A"
|
||||
export BACKEND_STACK="FastAPI"
|
||||
export DATABASE_STACK="TBD"
|
||||
export TESTING_STACK="pytest + httpx"
|
||||
export DEPLOYMENT_STACK="Docker"
|
||||
export CONFIG_FILES="pyproject.toml"
|
||||
;;
|
||||
python-library)
|
||||
export PROJECT_SLUG=$(echo "$PROJECT_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | sed 's/[^a-z0-9_]//g')
|
||||
export QUALITY_GATES="uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov"
|
||||
export SOURCE_DIR="src"
|
||||
export BUILD_COMMAND="uv sync --all-extras"
|
||||
export TEST_COMMAND="uv run pytest --cov"
|
||||
export LINT_COMMAND="uv run ruff check src/ tests/"
|
||||
export TYPECHECK_COMMAND="uv run mypy src/"
|
||||
export BUILD_SYSTEM="hatchling"
|
||||
export FRONTEND_STACK="N/A"
|
||||
export BACKEND_STACK="N/A"
|
||||
export DATABASE_STACK="N/A"
|
||||
export TESTING_STACK="pytest"
|
||||
export DEPLOYMENT_STACK="PyPI / Gitea Packages"
|
||||
export CONFIG_FILES="pyproject.toml"
|
||||
;;
|
||||
*)
|
||||
export QUALITY_GATES="echo 'No quality gates configured — update CLAUDE.md'"
|
||||
export SOURCE_DIR="src"
|
||||
export BUILD_COMMAND="echo 'No build command configured'"
|
||||
export TEST_COMMAND="echo 'No test command configured'"
|
||||
export LINT_COMMAND="echo 'No lint command configured'"
|
||||
export TYPECHECK_COMMAND="echo 'No typecheck command configured'"
|
||||
export FRONTEND_STACK="TBD"
|
||||
export BACKEND_STACK="TBD"
|
||||
export DATABASE_STACK="TBD"
|
||||
export TESTING_STACK="TBD"
|
||||
export DEPLOYMENT_STACK="TBD"
|
||||
export CONFIG_FILES="TBD"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Export common variables
|
||||
export PROJECT_NAME
|
||||
export PROJECT_DESCRIPTION
|
||||
export PROJECT_DIR
|
||||
export REPO_URL
|
||||
export TASK_PREFIX
|
||||
|
||||
echo "=== Project Bootstrap ==="
|
||||
echo " Name: $PROJECT_NAME"
|
||||
echo " Type: $PROJECT_TYPE"
|
||||
echo " Prefix: $TASK_PREFIX"
|
||||
echo " Description: $PROJECT_DESCRIPTION"
|
||||
echo " Repo: ${REPO_URL:-'(not set)'}"
|
||||
echo " Directory: $(pwd)"
|
||||
echo ""
|
||||
|
||||
# Select template directory
|
||||
STACK_TEMPLATE_DIR="$TEMPLATE_DIR/projects/$PROJECT_TYPE"
|
||||
if [[ ! -d "$STACK_TEMPLATE_DIR" ]]; then
|
||||
STACK_TEMPLATE_DIR="$TEMPLATE_DIR"
|
||||
echo "No stack-specific templates found for '$PROJECT_TYPE', using generic templates."
|
||||
fi
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo "[DRY RUN] Would create:"
|
||||
echo " - Validate sequential-thinking MCP hard requirement"
|
||||
echo " - CLAUDE.md (from $STACK_TEMPLATE_DIR/CLAUDE.md.template)"
|
||||
echo " - AGENTS.md (from $STACK_TEMPLATE_DIR/AGENTS.md.template)"
|
||||
echo " - docs/scratchpads/"
|
||||
echo " - docs/reports/qa-automation/{pending,in-progress,done,escalated}"
|
||||
echo " - docs/reports/deferred/"
|
||||
echo " - docs/tasks/"
|
||||
echo " - docs/releases/"
|
||||
echo " - docs/templates/"
|
||||
if [[ "$SKIP_CI" != true ]]; then
|
||||
echo " - .woodpecker/codex-review.yml"
|
||||
echo " - .woodpecker/schemas/*.json"
|
||||
fi
|
||||
if [[ "$SKIP_LABELS" != true ]]; then
|
||||
echo " - Standard git labels (epic, feature, bug, task, documentation, security, breaking)"
|
||||
echo " - Milestone: 0.0.1 - Pre-MVP Foundation"
|
||||
echo " - Milestone policy: 0.0.x pre-MVP, 0.1.0 for MVP release"
|
||||
fi
|
||||
if [[ "$CICD_DOCKER" == true ]]; then
|
||||
echo " - Docker build/push/link steps appended to .woodpecker.yml"
|
||||
for svc in "${CICD_SERVICES[@]}"; do
|
||||
echo " - docker-build-${svc%%:*}"
|
||||
done
|
||||
echo " - link-packages"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Enforce sequential-thinking MCP hard requirement.
|
||||
if [[ ! -x "$SEQUENTIAL_MCP_SCRIPT" ]]; then
|
||||
echo "Error: Missing sequential-thinking setup helper: $SEQUENTIAL_MCP_SCRIPT" >&2
|
||||
echo "Install/repair Mosaic at ~/.config/mosaic before bootstrapping projects." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if "$SEQUENTIAL_MCP_SCRIPT" >/dev/null 2>&1; then
|
||||
echo "Verified sequential-thinking MCP configuration"
|
||||
else
|
||||
echo "Error: sequential-thinking MCP setup failed (hard requirement)." >&2
|
||||
echo "Run: $SEQUENTIAL_MCP_SCRIPT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create CLAUDE.md
|
||||
if [[ -f "CLAUDE.md" ]]; then
|
||||
echo "CLAUDE.md already exists — skipping (rename or delete to recreate)"
|
||||
else
|
||||
if [[ -f "$STACK_TEMPLATE_DIR/CLAUDE.md.template" ]]; then
|
||||
envsubst < "$STACK_TEMPLATE_DIR/CLAUDE.md.template" > CLAUDE.md
|
||||
echo "Created CLAUDE.md"
|
||||
else
|
||||
echo "Warning: No CLAUDE.md template found at $STACK_TEMPLATE_DIR" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create AGENTS.md
|
||||
if [[ -f "AGENTS.md" ]]; then
|
||||
echo "AGENTS.md already exists — skipping (rename or delete to recreate)"
|
||||
else
|
||||
if [[ -f "$STACK_TEMPLATE_DIR/AGENTS.md.template" ]]; then
|
||||
envsubst < "$STACK_TEMPLATE_DIR/AGENTS.md.template" > AGENTS.md
|
||||
echo "Created AGENTS.md"
|
||||
else
|
||||
echo "Warning: No AGENTS.md template found at $STACK_TEMPLATE_DIR" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create directories
|
||||
mkdir -p \
|
||||
docs/scratchpads \
|
||||
docs/reports/qa-automation/pending \
|
||||
docs/reports/qa-automation/in-progress \
|
||||
docs/reports/qa-automation/done \
|
||||
docs/reports/qa-automation/escalated \
|
||||
docs/reports/deferred \
|
||||
docs/tasks \
|
||||
docs/releases \
|
||||
docs/templates
|
||||
echo "Created docs/scratchpads/, docs/reports/*, docs/tasks/, docs/releases/, docs/templates/"
|
||||
|
||||
# Set up CI/CD pipeline
|
||||
if [[ "$SKIP_CI" != true ]]; then
|
||||
CODEX_DIR="$HOME/.config/mosaic/tools/codex"
|
||||
if [[ -d "$CODEX_DIR/woodpecker" ]]; then
|
||||
mkdir -p .woodpecker/schemas
|
||||
cp "$CODEX_DIR/woodpecker/codex-review.yml" .woodpecker/
|
||||
cp "$CODEX_DIR/schemas/"*.json .woodpecker/schemas/
|
||||
echo "Created .woodpecker/ with Codex review pipeline"
|
||||
else
|
||||
echo "Codex pipeline templates not found — skipping CI setup"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generate Docker build/push/link pipeline steps
|
||||
if [[ "$CICD_DOCKER" == true ]]; then
|
||||
CICD_SCRIPT="$HOME/.config/mosaic/tools/cicd/generate-docker-steps.sh"
|
||||
if [[ -x "$CICD_SCRIPT" ]]; then
|
||||
# Parse org and repo from git remote
|
||||
CICD_REGISTRY=""
|
||||
CICD_ORG=""
|
||||
CICD_REPO_NAME=""
|
||||
if [[ -n "$REPO_URL" ]]; then
|
||||
# Extract host from https://host/org/repo.git or git@host:org/repo.git
|
||||
CICD_REGISTRY=$(echo "$REPO_URL" | sed -E 's|https?://([^/]+)/.*|\1|; s|git@([^:]+):.*|\1|')
|
||||
CICD_ORG=$(echo "$REPO_URL" | sed -E 's|https?://[^/]+/([^/]+)/.*|\1|; s|git@[^:]+:([^/]+)/.*|\1|')
|
||||
CICD_REPO_NAME=$(echo "$REPO_URL" | sed -E 's|\.git$||' | sed -E 's|.*/([^/]+)$|\1|')
|
||||
fi
|
||||
|
||||
if [[ -n "$CICD_REGISTRY" && -n "$CICD_ORG" && -n "$CICD_REPO_NAME" && ${#CICD_SERVICES[@]} -gt 0 ]]; then
|
||||
# Build service args
|
||||
SVC_ARGS=""
|
||||
for svc in "${CICD_SERVICES[@]}"; do
|
||||
SVC_ARGS="$SVC_ARGS --service $svc"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Generating Docker CI/CD pipeline steps..."
|
||||
|
||||
# Add kaniko_setup anchor to variables section if .woodpecker.yml exists
|
||||
if [[ -f ".woodpecker.yml" ]]; then
|
||||
# Append Docker steps to existing pipeline
|
||||
"$CICD_SCRIPT" \
|
||||
--registry "$CICD_REGISTRY" \
|
||||
--org "$CICD_ORG" \
|
||||
--repo "$CICD_REPO_NAME" \
|
||||
$SVC_ARGS \
|
||||
--branches "$CICD_BRANCHES" >> .woodpecker.yml
|
||||
echo "Appended Docker build/push/link steps to .woodpecker.yml"
|
||||
else
|
||||
echo "Warning: No .woodpecker.yml found — generate quality gates first, then re-run with --cicd-docker" >&2
|
||||
fi
|
||||
else
|
||||
if [[ ${#CICD_SERVICES[@]} -eq 0 ]]; then
|
||||
echo "Warning: --cicd-docker requires at least one --cicd-service" >&2
|
||||
else
|
||||
echo "Warning: Could not parse registry/org/repo from git remote — specify --repo" >&2
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Docker CI/CD generator not found at $CICD_SCRIPT — skipping" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Initialize labels and milestones
|
||||
if [[ "$SKIP_LABELS" != true ]]; then
|
||||
LABEL_SCRIPT="$SCRIPT_DIR/init-repo-labels.sh"
|
||||
if [[ -x "$LABEL_SCRIPT" ]]; then
|
||||
echo ""
|
||||
echo "Initializing git labels and milestones..."
|
||||
"$LABEL_SCRIPT"
|
||||
else
|
||||
echo "Label init script not found — skipping label setup"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Bootstrap Complete ==="
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Review and customize CLAUDE.md"
|
||||
echo " 2. Review and customize AGENTS.md"
|
||||
echo " 3. Update quality gate commands if needed"
|
||||
echo " 4. Commit: git add CLAUDE.md AGENTS.md docs/ .woodpecker/ && git commit -m 'feat: Bootstrap project for AI development'"
|
||||
if [[ "$SKIP_CI" != true ]]; then
|
||||
echo " 5. Add 'codex_api_key' secret to Woodpecker CI"
|
||||
fi
|
||||
if [[ "$CICD_DOCKER" == true ]]; then
|
||||
echo " 6. Add 'gitea_username' and 'gitea_token' secrets to Woodpecker CI"
|
||||
echo " (token needs package:write scope)"
|
||||
fi
|
||||
Reference in New Issue
Block a user