diff --git a/governance/operations/collapse-archived.sh b/governance/operations/collapse-archived.sh new file mode 100644 index 0000000..d3bc05c --- /dev/null +++ b/governance/operations/collapse-archived.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# Unarchive all 24 archived repos and fold each into the perfops monorepo under +# archive// via git subtree (history-preserved). Sources are LEFT ACTIVE +# (unarchived) afterwards — no re-archive, no delete. +# +# Runs entirely with gh + git in YOUR shell (the MCP integration cannot +# unarchive or subtree-merge repos). Dry-run by default. +# +# Phases: +# 1. unarchive every source (gh repo unarchive) +# 2. git subtree add -> perfops/archive// +# 3. push branch + open one draft PR on perfops +# +# Usage: +# ./collapse-archived.sh # dry-run plan +# ./collapse-archived.sh --apply # execute +# SEED=perfops-platform ./collapse-archived.sh --apply # if not renamed yet +set -euo pipefail +OWNER="${OWNER:-muntianus}" +SEED="${SEED:-perfops}" # the monorepo (formerly perfops-platform) +APPLY=false +for a in "$@"; do [ "$a" = "--apply" ] && APPLY=true; done +GH="https://github.com/$OWNER" +WORKDIR="${WORKDIR:-$PWD/.collapse-archived}" + +log(){ printf '\033[0;36m[arch]\033[0m %s\n' "$*"; } +warn(){ printf '\033[0;33m[arch:warn]\033[0m %s\n' "$*" >&2; } +die(){ printf '\033[0;31m[arch:err]\033[0m %s\n' "$*" >&2; exit 1; } +command -v gh >/dev/null || die "gh not found" +command -v git >/dev/null || die "git not found" +gh auth status >/dev/null 2>&1 || die "run: gh auth login" +$APPLY || log "DRY-RUN (default). Add --apply to execute." + +# All 24 archived repos. Each is folded into perfops/archive//. +ARCHIVED=( + platform perfops-gateway perfops-ingest reportkit perfops-sdk + perfops-templates iac-monitoring-agent awesome-performance-engineering + telegram-reminder old-telegram-reminder old-globex + office office-workspace agent-control-office portfolio + krave-loadtest load-krave k6-nagibator2000 ragus-loader + tools pybot automation-stack ig-unfollow claude-agents +) + +# ---- Phase 1: unarchive (leave them active afterwards) ---- +for src in "${ARCHIVED[@]}"; do + if $APPLY; then + log "unarchive $OWNER/$src" + gh repo unarchive "$OWNER/$src" --yes 2>/dev/null || warn "unarchive $src skipped" + else + printf ' PLAN unarchive %s\n' "$src" + fi +done + +# ---- Phase 2: subtree-merge each into perfops/archive// ---- +branch="collapse/absorb-archived-$(date +%Y%m%d)" +if $APPLY; then + rm -rf "$WORKDIR"; mkdir -p "$WORKDIR" + log "clone monorepo $OWNER/$SEED" + git clone -q "$GH/$SEED.git" "$WORKDIR/$SEED" + cd "$WORKDIR/$SEED" + git checkout -q -b "$branch" +fi + +for src in "${ARCHIVED[@]}"; do + dest="archive/$src" + db="$(gh api "/repos/$OWNER/$src" --jq '.default_branch' 2>/dev/null || echo main)" + if ! $APPLY; then + printf ' PLAN subtree %-32s -> %s/%s (branch %s)\n' "$src" "$SEED" "$dest" "$db" + continue + fi + if git cat-file -e "HEAD:$dest" 2>/dev/null; then + warn "$dest already exists — skipping $src" + continue + fi + log "subtree $src ($db) -> $SEED/$dest" + git remote add "s-$src" "$GH/$src.git" 2>/dev/null || true + # One failed source must not abort the whole run; record and continue. + if git fetch -q "s-$src" "$db" 2>/dev/null && + git subtree add --prefix="$dest" "s-$src" "$db" \ + -m "absorb archived $src into $dest (history-preserved)"; then + : + else + warn "subtree-merge $src@$db failed — skipping (other repos continue)" + fi + git remote remove "s-$src" 2>/dev/null || true +done + +# ---- Phase 3: push + open one draft PR ---- +if $APPLY; then + git push -q -u origin "$branch" + # Resolve base branch locally (no extra API round-trip). + base_branch="$(git rev-parse --abbrev-ref origin/HEAD 2>/dev/null | cut -d/ -f2-)" + gh pr create --repo "$OWNER/$SEED" \ + --base "${base_branch:-main}" \ + --head "$branch" --draft \ + --title "absorb all archived repos into archive/ (history-preserved)" \ + --body "git-subtree merge of all 24 archived repos into archive//. Full history preserved. Sources were unarchived and left active per request." \ + || warn "PR create skipped (may already exist)" + log "Done. Sources were unarchived and LEFT ACTIVE (no re-archive, no delete)." + log "Review and merge the draft PR on $OWNER/$SEED." +else + log "DRY-RUN complete. Re-run with --apply to execute." +fi