Add onboard and migrate-pr commands (v1.1.0)
New commands for safely onboarding existing subrepos into the monorepo without losing open PRs: - josh-sync onboard <target>: interactive, resumable 5-step flow (import → wait for merge → reset to new repo) - josh-sync migrate-pr <target> [PR#...] [--all]: migrate PRs from archived repo to new repo via patch application Also refactors create_pr() to wrap create_pr_number(), eliminating duplicated curl/jq logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
160
bin/josh-sync
160
bin/josh-sync
@@ -9,6 +9,8 @@
|
||||
# preflight Validate config, connectivity, auth
|
||||
# import <target> Initial import: pull subrepo into monorepo
|
||||
# reset <target> Reset subrepo to josh-filtered view
|
||||
# onboard <target> Import existing subrepo into monorepo (interactive)
|
||||
# migrate-pr <target> [PR#...] [--all] Move PRs from archived to new subrepo
|
||||
# status Show target config and sync state
|
||||
# state show|reset Manage sync state directly
|
||||
#
|
||||
@@ -39,6 +41,8 @@ source "${JOSH_LIB_DIR}/auth.sh"
|
||||
source "${JOSH_LIB_DIR}/state.sh"
|
||||
# shellcheck source=../lib/sync.sh
|
||||
source "${JOSH_LIB_DIR}/sync.sh"
|
||||
# shellcheck source=../lib/onboard.sh
|
||||
source "${JOSH_LIB_DIR}/onboard.sh"
|
||||
|
||||
# ─── Version ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -69,6 +73,8 @@ Commands:
|
||||
preflight Validate config, connectivity, auth, workflow coverage
|
||||
import <target> Initial import: pull existing subrepo into monorepo (creates PR)
|
||||
reset <target> Reset subrepo to josh-filtered view (after merging import PR)
|
||||
onboard <target> Import existing subrepo into monorepo (interactive, resumable)
|
||||
migrate-pr <target> [PR#...] [--all] Move PRs from archived to new subrepo
|
||||
status Show target config and sync state
|
||||
state show <target> [branch] Show sync state JSON
|
||||
state reset <target> [branch] Reset sync state to {}
|
||||
@@ -643,6 +649,146 @@ cmd_state() {
|
||||
esac
|
||||
}
|
||||
|
||||
# ─── Onboard Command ──────────────────────────────────────────────
|
||||
|
||||
cmd_onboard() {
|
||||
local config_file=".josh-sync.yml"
|
||||
local target_name=""
|
||||
local restart=false
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--config) config_file="$2"; shift 2 ;;
|
||||
--debug) export JOSH_SYNC_DEBUG=1; shift ;;
|
||||
--restart) restart=true; shift ;;
|
||||
-*) die "Unknown flag: $1" ;;
|
||||
*) target_name="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$target_name" ]; then
|
||||
echo "Usage: josh-sync onboard <target> [--restart]" >&2
|
||||
parse_config "$config_file"
|
||||
echo "Available targets:" >&2
|
||||
echo "$JOSH_SYNC_TARGETS" | jq -r '.[].name' | sed 's/^/ /' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
parse_config "$config_file"
|
||||
|
||||
local target_json
|
||||
target_json=$(echo "$JOSH_SYNC_TARGETS" | jq -c --arg n "$target_name" '.[] | select(.name == $n)')
|
||||
[ -n "$target_json" ] || die "Target '${target_name}' not found in config"
|
||||
|
||||
log "INFO" "══════ Onboard target: ${target_name} ══════"
|
||||
load_target "$target_json"
|
||||
onboard_flow "$target_json" "$restart"
|
||||
}
|
||||
|
||||
# ─── Migrate PR Command ──────────────────────────────────────────
|
||||
|
||||
cmd_migrate_pr() {
|
||||
local config_file=".josh-sync.yml"
|
||||
local target_name=""
|
||||
local all=false
|
||||
local pr_numbers=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--config) config_file="$2"; shift 2 ;;
|
||||
--debug) export JOSH_SYNC_DEBUG=1; shift ;;
|
||||
--all) all=true; shift ;;
|
||||
-*) die "Unknown flag: $1" ;;
|
||||
*)
|
||||
if [ -z "$target_name" ]; then
|
||||
target_name="$1"
|
||||
else
|
||||
pr_numbers+=("$1")
|
||||
fi
|
||||
shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$target_name" ]; then
|
||||
echo "Usage: josh-sync migrate-pr <target> [PR#...] [--all]" >&2
|
||||
parse_config "$config_file"
|
||||
echo "Available targets:" >&2
|
||||
echo "$JOSH_SYNC_TARGETS" | jq -r '.[].name' | sed 's/^/ /' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
parse_config "$config_file"
|
||||
|
||||
local target_json
|
||||
target_json=$(echo "$JOSH_SYNC_TARGETS" | jq -c --arg n "$target_name" '.[] | select(.name == $n)')
|
||||
[ -n "$target_json" ] || die "Target '${target_name}' not found in config"
|
||||
|
||||
load_target "$target_json"
|
||||
|
||||
# Load archived repo info from onboard state
|
||||
local onboard_state archived_api
|
||||
onboard_state=$(read_onboard_state "$target_name")
|
||||
archived_api=$(echo "$onboard_state" | jq -r '.archived_api')
|
||||
if [ -z "$archived_api" ] || [ "$archived_api" = "null" ]; then
|
||||
die "No archived repo info found. Run 'josh-sync onboard ${target_name}' first."
|
||||
fi
|
||||
|
||||
log "INFO" "Archived repo: ${archived_api}"
|
||||
|
||||
if [ "$all" = true ]; then
|
||||
# Migrate all open PRs from archived repo
|
||||
local prs
|
||||
prs=$(list_open_prs "$archived_api" "$SUBREPO_TOKEN") \
|
||||
|| die "Failed to list PRs on archived repo"
|
||||
local count
|
||||
count=$(echo "$prs" | jq 'length')
|
||||
log "INFO" "Found ${count} open PR(s) on archived repo"
|
||||
|
||||
echo "$prs" | jq -r '.[] | .number' | while read -r num; do
|
||||
migrate_one_pr "$num" || true
|
||||
done
|
||||
|
||||
elif [ ${#pr_numbers[@]} -gt 0 ]; then
|
||||
# Migrate specific PR numbers
|
||||
for num in "${pr_numbers[@]}"; do
|
||||
migrate_one_pr "$num" || true
|
||||
done
|
||||
|
||||
else
|
||||
# Interactive: list open PRs, let user pick
|
||||
local prs
|
||||
prs=$(list_open_prs "$archived_api" "$SUBREPO_TOKEN") \
|
||||
|| die "Failed to list PRs on archived repo"
|
||||
local count
|
||||
count=$(echo "$prs" | jq 'length')
|
||||
|
||||
if [ "$count" -eq 0 ]; then
|
||||
log "INFO" "No open PRs on archived repo"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "" >&2
|
||||
echo "Open PRs on archived repo:" >&2
|
||||
echo "$prs" | jq -r '.[] | " #\(.number): \(.title) (\(.base.ref) <- \(.head.ref))"' >&2
|
||||
echo "" >&2
|
||||
echo "Enter PR numbers to migrate (space-separated), or 'all':" >&2
|
||||
local selection
|
||||
read -r selection
|
||||
|
||||
if [ "$selection" = "all" ]; then
|
||||
echo "$prs" | jq -r '.[] | .number' | while read -r num; do
|
||||
migrate_one_pr "$num" || true
|
||||
done
|
||||
else
|
||||
for num in $selection; do
|
||||
migrate_one_pr "$num" || true
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
log "INFO" "PR migration complete"
|
||||
}
|
||||
|
||||
# ─── Main ───────────────────────────────────────────────────────────
|
||||
|
||||
main() {
|
||||
@@ -662,12 +808,14 @@ main() {
|
||||
esac
|
||||
|
||||
case "$command" in
|
||||
sync) cmd_sync "$@" ;;
|
||||
preflight) cmd_preflight "$@" ;;
|
||||
import) cmd_import "$@" ;;
|
||||
reset) cmd_reset "$@" ;;
|
||||
status) cmd_status "$@" ;;
|
||||
state) cmd_state "$@" ;;
|
||||
sync) cmd_sync "$@" ;;
|
||||
preflight) cmd_preflight "$@" ;;
|
||||
import) cmd_import "$@" ;;
|
||||
reset) cmd_reset "$@" ;;
|
||||
onboard) cmd_onboard "$@" ;;
|
||||
migrate-pr) cmd_migrate_pr "$@" ;;
|
||||
status) cmd_status "$@" ;;
|
||||
state) cmd_state "$@" ;;
|
||||
*)
|
||||
echo "Unknown command: ${command}" >&2
|
||||
usage
|
||||
|
||||
Reference in New Issue
Block a user