diff --git a/.gitea/workflows/init.yml b/.gitea/workflows/init.yml new file mode 100644 index 0000000..c328c4a --- /dev/null +++ b/.gitea/workflows/init.yml @@ -0,0 +1,105 @@ +name: Init + +# One-shot bootstrap — runs on first push to main, skips if already initialised. +# Substitutes all __PROJECT_NAME__ / __MODULE_PATH__ placeholders (file contents +# and directory names), then runs context:sync to generate CLAUDE.md and friends. +# Deletes itself on completion so it never runs again. + +on: + push: + branches: [main] + +jobs: + init: + name: Bootstrap project from template + runs-on: self-hosted + + # One-shot guard: skip entirely if CLAUDE.md already exists + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITEA_TOKEN }} + fetch-depth: 0 + + - name: Check if already initialised + id: guard + run: | + if [ -f CLAUDE.md ]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Derive project variables + if: steps.guard.outputs.skip == 'false' + id: vars + run: | + # Repo name from git remote (e.g. macro-research) + PROJECT_NAME=$(basename "$(git rev-parse --show-toplevel)") + # Module path: gitea hostname + owner + project name + GITEA_HOST=$(git remote get-url origin | sed 's|http://||;s|https://||;s|/.*||') + OWNER=$(git remote get-url origin | sed 's|.*/\([^/]*\)/[^/]*\.git|\1|') + MODULE_PATH="${GITEA_HOST}/${OWNER}/${PROJECT_NAME}" + echo "project_name=${PROJECT_NAME}" >> "$GITHUB_OUTPUT" + echo "module_path=${MODULE_PATH}" >> "$GITHUB_OUTPUT" + echo "owner=${OWNER}" >> "$GITHUB_OUTPUT" + echo "→ PROJECT_NAME=${PROJECT_NAME}" + echo "→ MODULE_PATH=${MODULE_PATH}" + + - name: Substitute placeholders in file contents + if: steps.guard.outputs.skip == 'false' + env: + PROJECT_NAME: ${{ steps.vars.outputs.project_name }} + MODULE_PATH: ${{ steps.vars.outputs.module_path }} + run: | + set -euo pipefail + # Files to substitute (relative paths, including templated dir names) + FILES=$(git ls-files | grep -v '^\.gitea/workflows/init\.yml$') + for f in $FILES; do + if grep -qF '__PROJECT_NAME__\|__MODULE_PATH__' "$f" 2>/dev/null; then + sed -i \ + -e "s|__PROJECT_NAME__|${PROJECT_NAME}|g" \ + -e "s|__MODULE_PATH__|${MODULE_PATH}|g" \ + "$f" + echo " substituted: $f" + fi + done + + - name: Rename templated directories + if: steps.guard.outputs.skip == 'false' + env: + PROJECT_NAME: ${{ steps.vars.outputs.project_name }} + run: | + set -euo pipefail + # Rename cmd/__PROJECT_NAME__ → cmd/$PROJECT_NAME + if [ -d "cmd/__PROJECT_NAME__" ]; then + git mv "cmd/__PROJECT_NAME__" "cmd/${PROJECT_NAME}" + echo " renamed: cmd/__PROJECT_NAME__ → cmd/${PROJECT_NAME}" + fi + + - name: Install toolchain for context:sync + if: steps.guard.outputs.skip == 'false' + run: | + which task || go install github.com/go-task/task/v3/cmd/task@latest + + - name: Run context:sync + if: steps.guard.outputs.skip == 'false' + run: task context:sync + + - name: Remove this init workflow + if: steps.guard.outputs.skip == 'false' + run: | + git rm .gitea/workflows/init.yml + echo " removed: .gitea/workflows/init.yml" + + - name: Commit and push + if: steps.guard.outputs.skip == 'false' + env: + PROJECT_NAME: ${{ steps.vars.outputs.project_name }} + run: | + git config user.name "gitea-actions[bot]" + git config user.email "gitea-actions[bot]@noreply.local" + git add -A + git commit -m "chore: bootstrap ${PROJECT_NAME} from template" + git push origin main + echo "✓ project initialised"