From 43c972bbbfd173cf6949b7035fc0c1c1d3b4186a Mon Sep 17 00:00:00 2001 From: defiQUG Date: Tue, 12 May 2026 10:04:41 -0700 Subject: [PATCH] fix(gov-portals): rebase from Gitea before sync; add pull-rebase helper - sync-gov-portals-ct-7804-from-git.sh: default to pull --rebase after fetch; require clean monorepo/submodules; add --reset-hard for old mirror-to-origin behavior - gov-portals-git-pull-rebase.sh: operator script to integrate Gitea main + submodule pins; optional --submodules-latest to advance portal repos before pointer commit - Document Devin/multi-actor workflow in GOV_PORTALS_XOM_DEV_DEPLOYMENT.md; AGENTS pointer Co-authored-by: Cursor --- AGENTS.md | 2 +- .../GOV_PORTALS_XOM_DEV_DEPLOYMENT.md | 27 +++++- .../deployment/gov-portals-git-pull-rebase.sh | 97 +++++++++++++++++++ .../sync-gov-portals-ct-7804-from-git.sh | 31 +++++- 4 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 scripts/deployment/gov-portals-git-pull-rebase.sh diff --git a/AGENTS.md b/AGENTS.md index dc255465..59751af6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,7 @@ Orchestration for Proxmox VE, Chain 138 (`smom-dbis-138/`), explorers, NPMplus, | Submodule + explorer remotes | `docs/00-meta/SUBMODULE_HYGIENE.md` — `mcp-proxmox` uses **Gitea** `https://gitea.d-bis.org/d-bis/mcp-proxmox.git` (not the old GitHub-only URL). `cross-chain-pmm-lps-publish` is a **worktree** of `cross-chain-pmm-lps`, not a submodule. | | smom-dbis-138 `.env` in bash scripts | Prefer `source smom-dbis-138/scripts/lib/deployment/dotenv.sh` + `load_deployment_env --repo-root "$PROJECT_ROOT"` (trims RPC URL line endings). From an interactive shell: `source smom-dbis-138/scripts/load-env.sh`. Proxmox root scripts: `source scripts/lib/load-project-env.sh` (also trims common RPC vars). | | Sankofa portal → CT 7801 (build + restart) | `./scripts/deployment/sync-sankofa-portal-7801.sh` (`--dry-run` first); sets `NEXTAUTH_URL` on CT via `sankofa-portal-ensure-nextauth-on-ct.sh` | -| Gov Portals (CT **7804** @ `IP_GOV_PORTALS_DEV`, r630-04): git pull + build + sync | `./scripts/deployment/sync-gov-portals-ct-7804-from-git.sh` — requires `GITEA_TOKEN` in `.env` (or `export GITEA_TOKEN=…`); optional `--skip-fetch`. See `docs/04-configuration/GOV_PORTALS_XOM_DEV_DEPLOYMENT.md`. | +| Gov Portals (CT **7804** @ `IP_GOV_PORTALS_DEV`, r630-04): rebase from Gitea then build + sync | `./scripts/deployment/gov-portals-git-pull-rebase.sh` then `./scripts/deployment/sync-gov-portals-ct-7804-from-git.sh` — `GITEA_TOKEN` in `.env`; sync defaults to **pull --rebase** (use `--reset-hard` to mirror Gitea and discard local changes); optional `--skip-fetch`. See `docs/04-configuration/GOV_PORTALS_XOM_DEV_DEPLOYMENT.md`. | | CCIP relay (r630-01 host) | Unit: `config/systemd/ccip-relay.service` → `/etc/systemd/system/ccip-relay.service`; `systemctl enable --now ccip-relay` | | TsunamiSwap VM 5010 check | `./scripts/deployment/tsunamiswap-vm-5010-provision.sh` (inventory only until VM exists) | | Solana native SOL (robust JSON-RPC submit) | `scripts/lib/solana_jsonrpc.py` (stdlib `sendTransaction`), `./scripts/deployment/solana-transfer-native.py` (sign with `solders`). Install: `pip install -r scripts/lib/requirements-solana-ops.txt`. Avoids solana-py `SendTransactionResp` parse failures on RPCs that return only a signature string. Env: `SOLANA_RPC_URL`, `SOLANA_KEYPAIR_PATH` via `source scripts/lib/load-project-env.sh`. | diff --git a/docs/04-configuration/GOV_PORTALS_XOM_DEV_DEPLOYMENT.md b/docs/04-configuration/GOV_PORTALS_XOM_DEV_DEPLOYMENT.md index b7706f60..1ad396af 100644 --- a/docs/04-configuration/GOV_PORTALS_XOM_DEV_DEPLOYMENT.md +++ b/docs/04-configuration/GOV_PORTALS_XOM_DEV_DEPLOYMENT.md @@ -4,6 +4,28 @@ **VM:** LXC 7804 (gov-portals-dev) @ 192.168.11.54 **NPMplus:** Primary (192.168.11.167) — same as sankofa.nexus zone +## Git workflow (Gitea, Devin, operators) + +Multiple actors push to **Gov_Web_Portals** repos on Gitea. Before you commit locally or run sync, integrate remote `main` with a **rebase** so you are not deploying or layering work on a stale base. + +1. **Operator / LAN machine (recommended before sync)** + From proxmox repo root with `GITEA_TOKEN` in `.env` (or after `source scripts/lib/load-project-env.sh`): + + ```bash + bash scripts/deployment/gov-portals-git-pull-rebase.sh + ``` + + This runs `git fetch`, `git pull --rebase origin main` on the monorepo, then `git submodule update --init --recursive` so submodule checkouts match the **parent’s recorded SHAs** (includes commits from Devin once the monorepo pointer was updated). + + To also fast-forward each portal repo to **its** latest `origin/main` (then commit submodule bumps in the parent before deploy), use: + + ```bash + bash scripts/deployment/gov-portals-git-pull-rebase.sh --submodules-latest + ``` + +2. **Sync to CT 7804** + `scripts/deployment/sync-gov-portals-ct-7804-from-git.sh` now defaults to **`git pull --rebase`** after fetch (clean monorepo + clean DBIS/ICCC/OMNL/XOM submodules required). Use **`--reset-hard`** only when you intentionally want to match Gitea exactly and discard all local changes (previous default behavior). + --- ## Quick start @@ -70,9 +92,10 @@ Request Let's Encrypt certificates in NPMplus UI for each domain, or use a wildc - **502 Bad Gateway:** Ensure LXC 7804 is running and portals are built: `pct exec 7804 -- systemctl status gov-portal-DBIS gov-portal-ICCC gov-portal-OMNL gov-portal-XOM` -- **Rebuild a portal (after code change):** Prefer the repo script (git fetch + rsync + build on CT **7804** on r630-04): +- **Rebuild a portal (after code change):** Prefer the repo script (git fetch + rebase + rsync + build on CT **7804** on r630-04): `bash scripts/deployment/sync-gov-portals-ct-7804-from-git.sh` - Requires `GITEA_TOKEN` in project `.env` (or `export GITEA_TOKEN=…`). Use `--skip-fetch` to rebuild from an already-updated local `GOV_PORTALS_SOURCE` tree. + Requires `GITEA_TOKEN` in project `.env` (or `export GITEA_TOKEN=…`). The script **rebases** onto `origin/main` by default; use **`--reset-hard`** to discard all local monorepo/submodule changes and mirror Gitea exactly. Use **`--skip-fetch`** to rebuild from an already-updated local `GOV_PORTALS_SOURCE` tree. + Before sync when others (e.g. Devin) push first: `bash scripts/deployment/gov-portals-git-pull-rebase.sh` Manual one-liner on the **Proxmox node that runs CT 7804** (default `root@192.168.11.14`): `pct exec 7804 -- bash -c 'cd /srv/gov-portals/DBIS && git pull origin main && pnpm install && pnpm run build && systemctl restart gov-portal-DBIS'` (Only works if `/srv/gov-portals/DBIS` is a git checkout; tarball deploys omit `.git` — use the script above.) diff --git a/scripts/deployment/gov-portals-git-pull-rebase.sh b/scripts/deployment/gov-portals-git-pull-rebase.sh new file mode 100644 index 00000000..b9ba8041 --- /dev/null +++ b/scripts/deployment/gov-portals-git-pull-rebase.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# Rebase the Gov Portals monorepo (and submodule checkouts) onto Gitea before local +# commits or before sync-gov-portals-ct-7804-from-git.sh. Use when agents (e.g. Devin) +# push to Gitea and your clone is behind. +# +# From proxmox repo root: +# source scripts/lib/load-project-env.sh # optional; loads GITEA_TOKEN +# bash scripts/deployment/gov-portals-git-pull-rebase.sh +# +# Options: +# --submodules-latest After updating the parent, run `git pull --rebase origin main` +# inside each portal submodule (DBIS ICCC OMNL XOM). You must +# then commit submodule pointer bumps in the parent if you +# intend to ship those SHAs. +# --dry-run Print commands only +# +# Env: +# GOV_PORTALS_SOURCE Default: /home/intlc/projects/gov-portals-monorepo +# GOV_PORTALS_REF Default: main + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +# shellcheck disable=SC1090 +[ -f "$PROJECT_ROOT/.env" ] && set +u && source "$PROJECT_ROOT/.env" 2>/dev/null || true && set -u + +GOV_PORTALS_SOURCE="${GOV_PORTALS_SOURCE:-/home/intlc/projects/gov-portals-monorepo}" +GOV_PORTALS_REF="${GOV_PORTALS_REF:-main}" +SUBMODULES_LATEST=false +DRY_RUN=false + +for arg in "$@"; do + case "$arg" in + --submodules-latest) SUBMODULES_LATEST=true ;; + --dry-run) DRY_RUN=true ;; + esac +done + +die() { echo "ERROR: $*" >&2; exit 1; } +log() { echo "[$(date +%H:%M:%S)] $*"; } + +[[ -d "$GOV_PORTALS_SOURCE/.git" ]] || die "Not a git repo: $GOV_PORTALS_SOURCE" + +git_auth_args=() +if [[ -n "${GITEA_TOKEN:-}" ]]; then + git_auth_args=(-c "http.extraHeader=Authorization: token ${GITEA_TOKEN}") +fi +[[ ${#git_auth_args[@]} -gt 0 ]] || die "GITEA_TOKEN is unset. Add it to $PROJECT_ROOT/.env" + +run() { + if [[ "$DRY_RUN" == "true" ]]; then + echo "DRY: $*" + else + eval "$@" + fi +} + +ensure_on_branch() { + local repo="$1" + local ref="$2" + if ! git -C "$repo" symbolic-ref -q HEAD >/dev/null 2>&1; then + log "$repo: detached HEAD — checking out $ref" + run "git -C \"$repo\" checkout \"$ref\"" + fi +} + +log "Repo: $GOV_PORTALS_SOURCE (ref: $GOV_PORTALS_REF)" +ensure_on_branch "$GOV_PORTALS_SOURCE" "$GOV_PORTALS_REF" + +dirty="$(git -C "$GOV_PORTALS_SOURCE" status --porcelain)" +[[ -z "$dirty" ]] || die "Working tree not clean in $GOV_PORTALS_SOURCE — commit or stash before rebasing." + +for sub in DBIS ICCC OMNL XOM; do + d="$GOV_PORTALS_SOURCE/$sub" + [[ -d "$d/.git" ]] || continue + sd="$(git -C "$d" status --porcelain)" + [[ -z "$sd" ]] || die "Submodule $sub is dirty — commit or stash before rebasing." +done + +run "git -C \"$GOV_PORTALS_SOURCE\" \"${git_auth_args[@]}\" fetch origin" +run "git -C \"$GOV_PORTALS_SOURCE\" pull --rebase origin \"$GOV_PORTALS_REF\"" +run "git -C \"$GOV_PORTALS_SOURCE\" \"${git_auth_args[@]}\" submodule update --init --recursive" + +if [[ "$SUBMODULES_LATEST" == "true" ]]; then + for sub in DBIS ICCC OMNL XOM; do + d="$GOV_PORTALS_SOURCE/$sub" + [[ -d "$d/.git" ]] || continue + log "Pull --rebase $sub" + ensure_on_branch "$d" "$GOV_PORTALS_REF" + run "git -C \"$d\" \"${git_auth_args[@]}\" fetch origin" + run "git -C \"$d\" pull --rebase origin \"$GOV_PORTALS_REF\"" + done + log "Submodules are at latest origin/$GOV_PORTALS_REF. If parent shows modified submodules, commit pointer updates in the monorepo before sync." +fi + +log "Done. HEAD: $(git -C "$GOV_PORTALS_SOURCE" log -1 --oneline)" diff --git a/scripts/deployment/sync-gov-portals-ct-7804-from-git.sh b/scripts/deployment/sync-gov-portals-ct-7804-from-git.sh index 70d3a8e0..92723e3b 100755 --- a/scripts/deployment/sync-gov-portals-ct-7804-from-git.sh +++ b/scripts/deployment/sync-gov-portals-ct-7804-from-git.sh @@ -13,6 +13,10 @@ # Options: # --skip-fetch Use GOV_PORTALS_SOURCE as-is (no git fetch; no token required) # --dry-run Print steps only +# --reset-hard After fetch: git reset --hard origin/ + submodule update --force +# (old behavior; discards ALL local monorepo + submodule changes). +# Default without this flag: pull --rebase so Gitea commits (e.g. from +# Devin) are merged before deploy. Requires a clean working tree. # # Env: # GOV_PORTALS_SOURCE Default: /home/intlc/projects/gov-portals-monorepo @@ -38,9 +42,11 @@ PROXMOX_HOST="${DBIS_PORTAL_PROXMOX_HOST:-${PROXMOX_HOST_GOV_PORTALS:-192.168.11 SKIP_FETCH=false DRY_RUN=false +RESET_HARD=false for arg in "$@"; do [[ "$arg" == "--skip-fetch" ]] && SKIP_FETCH=true [[ "$arg" == "--dry-run" ]] && DRY_RUN=true + [[ "$arg" == "--reset-hard" ]] && RESET_HARD=true done die() { echo "ERROR: $*" >&2; exit 1; } @@ -59,12 +65,29 @@ if [[ "$SKIP_FETCH" != "true" ]]; then die "GITEA_TOKEN is unset. Add it to $PROJECT_ROOT/.env or run: export GITEA_TOKEN=... (Or use --skip-fetch.)" fi if [[ "$DRY_RUN" == "true" ]]; then - log "DRY: would git fetch $GOV_PORTALS_REF and submodule update in $GOV_PORTALS_SOURCE" + log "DRY: would git fetch $GOV_PORTALS_REF and update submodules in $GOV_PORTALS_SOURCE (reset-hard=$RESET_HARD)" else - log "Fetching $GOV_PORTALS_REF and updating submodules in $GOV_PORTALS_SOURCE" + log "Fetching $GOV_PORTALS_REF in $GOV_PORTALS_SOURCE (reset-hard=$RESET_HARD)" git -C "$GOV_PORTALS_SOURCE" "${git_auth_args[@]}" fetch origin - git -C "$GOV_PORTALS_SOURCE" reset --hard "origin/$GOV_PORTALS_REF" - git -C "$GOV_PORTALS_SOURCE" "${git_auth_args[@]}" submodule update --init --recursive --force + if [[ "$RESET_HARD" == "true" ]]; then + git -C "$GOV_PORTALS_SOURCE" reset --hard "origin/$GOV_PORTALS_REF" + git -C "$GOV_PORTALS_SOURCE" "${git_auth_args[@]}" submodule update --init --recursive --force + else + parent_dirty="$(git -C "$GOV_PORTALS_SOURCE" status --porcelain)" + [[ -z "$parent_dirty" ]] || die "Monorepo has uncommitted changes — stash/commit or pass --reset-hard (see scripts/deployment/gov-portals-git-pull-rebase.sh)." + for sub in DBIS ICCC OMNL XOM; do + d="$GOV_PORTALS_SOURCE/$sub" + [[ -d "$d/.git" ]] || continue + sd="$(git -C "$d" status --porcelain)" + [[ -z "$sd" ]] || die "Submodule $sub is dirty — commit/stash or use --reset-hard." + done + if ! git -C "$GOV_PORTALS_SOURCE" symbolic-ref -q HEAD >/dev/null 2>&1; then + log "Monorepo detached HEAD — checking out $GOV_PORTALS_REF" + git -C "$GOV_PORTALS_SOURCE" checkout "$GOV_PORTALS_REF" + fi + git -C "$GOV_PORTALS_SOURCE" pull --rebase origin "$GOV_PORTALS_REF" + git -C "$GOV_PORTALS_SOURCE" "${git_auth_args[@]}" submodule update --init --recursive + fi log "Monorepo HEAD: $(git -C "$GOV_PORTALS_SOURCE" log -1 --oneline)" if [[ -e "$GOV_PORTALS_SOURCE/DBIS/.git" ]]; then log "DBIS HEAD: $(git -C "$GOV_PORTALS_SOURCE/DBIS" log -1 --oneline)"