#!/bin/sh set -eu repo_url="ssh://git@ssh.github.com:443/pikasTech/HWLAB.git" repo_path="/cache/pikasTech/HWLAB.git" lock_dir="/cache/.hwlab-flush.lock" started_ms=$(node -e 'console.log(Date.now())') now_ms() { node -e 'console.log(Date.now())'; } emit_timing() { phase="$1" status="$2" started="$3" finished=$(now_ms) duration=$((finished - started)) printf '{"event":"git-mirror-flush-timing","phase":"%s","status":"%s","durationMs":%s,"repository":"pikasTech/HWLAB"} ' "$phase" "$status" "$duration" } if ! mkdir "$lock_dir" 2>/dev/null; then echo "git mirror flush already running" exit 0 fi trap 'rmdir "$lock_dir" 2>/dev/null || true' EXIT INT TERM mkdir -p /root/.ssh cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa chmod 0400 /root/.ssh/id_rsa # __HWLAB_GIT_MIRROR_SSH_PRELUDE__ /script/install-hooks.sh for gitops_branch in __HWLAB_GITOPS_BRANCH_ARGS__; do local_head=$(git -C "$repo_path" show-ref --verify --hash "refs/heads/$gitops_branch" 2>/dev/null || true) if [ -z "$local_head" ]; then echo "git mirror flush skips missing local refs/heads/$gitops_branch" continue fi fetch_started=$(now_ms) timeout 90 git -C "$repo_path" fetch --quiet "$repo_url" "refs/heads/$gitops_branch:refs/mirror-stage/heads/$gitops_branch" emit_timing "fetch-$gitops_branch" succeeded "$fetch_started" github_head=$(git -C "$repo_path" show-ref --verify --hash "refs/mirror-stage/heads/$gitops_branch" 2>/dev/null || true) if [ -n "$github_head" ] && [ "$github_head" != "$local_head" ] && ! git -C "$repo_path" merge-base --is-ancestor "$github_head" "$local_head"; then echo "git mirror flush rejected divergent $gitops_branch local=$local_head github=$github_head" >&2 exit 52 fi if [ "$local_head" != "$github_head" ]; then push_started=$(now_ms) timeout 120 git -C "$repo_path" push "$repo_url" "$local_head:refs/heads/$gitops_branch" emit_timing "push-$gitops_branch" succeeded "$push_started" else echo "git mirror flush $gitops_branch already matches GitHub" fi git -C "$repo_path" update-ref "refs/mirror-stage/heads/$gitops_branch" "$local_head" done git -C "$repo_path" update-server-info flushed_at=$(date -u +%Y-%m-%dT%H:%M:%SZ) export flushed_at export gitops_branches_json=__HWLAB_GITOPS_BRANCHES_JSON_SHELL__ node - <<'NODE' | tee /cache/HWLAB.last-flush.json const { execFileSync } = require("node:child_process"); const repo = "/cache/pikasTech/HWLAB.git"; const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]"); function rev(ref) { try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; } } const refs = {}; for (const branch of gitopsBranches) { refs["refs/heads/" + branch] = rev("refs/heads/" + branch); refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch); } const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/mirror-stage/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]); console.log(JSON.stringify({ event: "git-mirror-flush", status: "flushed", repository: "pikasTech/HWLAB", flushedAt: process.env.flushed_at, pendingFlush, refs })); NODE emit_timing total succeeded "$started_ms"