#!/bin/sh
set -eu
started_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
__GIT_MIRROR_PROXY_PRELUDE__
test -d "$repo/objects"
git --git-dir="$repo" remote set-url origin "$remote" || git --git-dir="$repo" remote add origin "$remote"
local_gitops=$(git --git-dir="$repo" rev-parse --verify "refs/heads/${gitops_branch}^{commit}" 2>/dev/null || true)
push_status=skipped
push_exit=0
fetch_status=skipped
fetch_exit=0
fetch_attempt=0
fetch_max_attempts=5
if [ -n "$local_gitops" ]; then
  set +e
  timeout 240 git --git-dir="$repo" -c remote.origin.mirror=false push origin "refs/heads/${gitops_branch}:refs/heads/${gitops_branch}"
  push_exit=$?
  set -e
  if [ "$push_exit" = "0" ]; then
    push_status=succeeded
    fetch_retry_delay=1
    while [ "$fetch_attempt" -lt "$fetch_max_attempts" ]; do
      fetch_attempt=$((fetch_attempt + 1))
      echo "git-mirror post-push fetch attempt ${fetch_attempt}/${fetch_max_attempts}" >&2
      set +e
      timeout 240 git --git-dir="$repo" fetch origin "+refs/heads/${gitops_branch}:refs/mirror-stage/heads/${gitops_branch}"
      fetch_exit=$?
      set -e
      if [ "$fetch_exit" = "0" ]; then fetch_status=succeeded; break; fi
      fetch_status=failed
      if [ "$fetch_attempt" -lt "$fetch_max_attempts" ]; then
        echo "git-mirror post-push fetch retry ${fetch_attempt}/${fetch_max_attempts} failed exit=${fetch_exit}; backoff=${fetch_retry_delay}s" >&2
        sleep "$fetch_retry_delay"
        if [ "$fetch_retry_delay" -lt 16 ]; then fetch_retry_delay=$((fetch_retry_delay * 2)); fi
      fi
    done
  else
    push_status=failed
  fi
fi
github_gitops=$(git --git-dir="$repo" rev-parse --verify "refs/mirror-stage/heads/${gitops_branch}^{commit}" 2>/dev/null || true)
pending=false; if [ -n "$local_gitops" ] && { [ -z "$github_gitops" ] || [ "$local_gitops" != "$github_gitops" ]; }; then pending=true; fi
status=succeeded
partial_success=
degraded_reason=
exit_code=0
if [ "$push_status" = "failed" ]; then
  status=failed
  degraded_reason=git-mirror-push-failed
  exit_code=$push_exit
elif [ "$push_status" = "succeeded" ] && [ "$fetch_status" = "failed" ]; then
  status=partial-success
  partial_success=push-succeeded-fetch-failed
  degraded_reason=git-mirror-post-push-fetch-failed
  exit_code=44
fi
export repository gitops_branch started_at local_gitops github_gitops pending push_status push_exit fetch_status fetch_exit fetch_attempt fetch_max_attempts status partial_success degraded_reason
summary_tmp=/tmp/HWLAB.last-flush.json.$$
node <<'NODE' > "$summary_tmp"
const payload = { event: 'git-mirror-flush', repo: process.env.repository, status: process.env.status || 'failed', partialSuccess: process.env.partial_success || null, degradedReason: process.env.degraded_reason || null, startedAt: process.env.started_at, flushedAt: new Date().toISOString(), gitopsBranch: process.env.gitops_branch, localGitops: process.env.local_gitops || null, githubGitops: process.env.github_gitops || null, pendingFlush: process.env.pending === 'true', stages: { push: process.env.push_status || null, pushExitCode: Number.parseInt(process.env.push_exit || '0', 10), postPushFetch: process.env.fetch_status || null, postPushFetchExitCode: Number.parseInt(process.env.fetch_exit || '0', 10), postPushFetchAttempts: Number.parseInt(process.env.fetch_attempt || '0', 10), postPushFetchMaxAttempts: Number.parseInt(process.env.fetch_max_attempts || '0', 10) } };
console.log(JSON.stringify(payload));
NODE
tee /cache/HWLAB.last-flush.json < "$summary_tmp"
rm -f "$summary_tmp"
if [ "$exit_code" != "0" ]; then exit "$exit_code"; fi
