#!/usr/bin/env bash # Sync phase: clone/update depot_tools, clone the chromium-fork checkout, # gclient sync. Run via `hetzner-runner exec -script sync.sh` against a box # already provisioned by a separate `up` step -- see ../../.gitea/workflows # in chromium-fork for the phase breakdown this belongs to. set -euo pipefail : "${GITEA_TOKEN:?GITEA_TOKEN must be set}" : "${GITEA_REPO:=Cold-Air-Networks/chromium-fork}" : "${GITEA_REF:=main}" : "${MIRROR_READ_TOKEN:=$GITEA_TOKEN}" : "${CHROMIUM_ROOT:=/root/chromium-ci}" retry() { local desc="$1"; shift local attempt=1 local max=5 until "$@"; do if [ "$attempt" -ge "$max" ]; then echo "$desc failed after $attempt attempts, giving up" return 1 fi echo "$desc failed (attempt $attempt/$max); retrying in 5s" attempt=$((attempt + 1)) sleep 5 done } redact() { sed -E 's#x-access-token:[^@]*@#x-access-token:REDACTED@#g' } echo "===== base packages (file, strace) =====" # `file` is a hard requirement: install-build-deps.py's dev_list() shells # out to it (via `file -L `) to detect ELF architecture, and this # minimal Ubuntu cloud image doesn't ship it by default (confirmed: ci run # #61, 2026-08-05, FileNotFoundError: 'file'). strace is a diagnostic # nicety for stall-watch.py, not a build requirement -- best-effort only. if ! command -v file >/dev/null 2>&1 || ! command -v strace >/dev/null 2>&1; then apt-get update -qq fi command -v file >/dev/null 2>&1 || apt-get install -y file command -v strace >/dev/null 2>&1 || apt-get install -y strace \ || echo "strace install failed, continuing without it" echo "===== depot_tools =====" if [ ! -d "$HOME/depot_tools" ]; then retry "clone depot_tools" git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" fi export PATH="$HOME/depot_tools:$PATH" # Explicit bootstrap before anything else touches depot_tools' `python3` # wrapper. That wrapper hard-requires python3_bin_reldir.txt (see # depot_tools/python3), which is normally created by `update_depot_tools` # -- but update_depot_tools itself refuses to do anything as root # ("Running depot tools as root is sad", see depot_tools/update_depot_tools) # and we're root on this box. gclient sync still works without this # (confirmed: ci run #54, 2026-08-04, sync completed fully) because it goes # through vpython3, a separately-bootstrapped wrapper -- but any later # direct python3 invocation, e.g. install-build-deps.py's shebang, fails # with exactly this error otherwise. cipd_bin_setup and bootstrap_python3 # are the two functions update_depot_tools calls after its root check; # calling them straight sidesteps that check entirely. # # set +u around this block: these are third-party scripts (depot_tools' # own cipd/cipd_bin_setup.sh), not written to be safe under nounset -- # confirmed cipd itself references an unset var with no default and dies # under set -u. They're sourced (not exec'd), so they inherit our shell's # flags; restore -u immediately after. set +u source "$HOME/depot_tools/cipd_bin_setup.sh" cipd_bin_setup source "$HOME/depot_tools/bootstrap_python3" bootstrap_python3 set -u mkdir -p "$CHROMIUM_ROOT" cd "$CHROMIUM_ROOT" REPO_URL="https://x-access-token:${GITEA_TOKEN}@forge.quinefoundation.com/${GITEA_REPO}.git" # VK-GL-CTS against chromium.googlesource.com directly was the single # biggest source of sync flakiness in chromium-fork's original CI workflow # (corrupted packs, silent stalls). Redirect to the org's own mirror. VK_GL_CTS_UPSTREAM="https://chromium.googlesource.com/external/github.com/KhronosGroup/VK-GL-CTS" git config --global \ url."https://x-access-token:${MIRROR_READ_TOKEN}@forge.quinefoundation.com/Cold-Air-Networks/mirror-vk-gl-cts.git".insteadOf \ "$VK_GL_CTS_UPSTREAM" echo "===== registered url.insteadOf mappings =====" git config --global --get-regexp '^url\.' | redact echo "===== end registered url.insteadOf mappings =====" cat > .gclient <&1 | redact; then ATTEMPT_ELAPSED=$(( $(date +%s) - ATTEMPT_START )) echo "----- gclient sync attempt $ATTEMPT/$MAX_ATTEMPTS succeeded after ${ATTEMPT_ELAPSED}s -----" break fi ATTEMPT_ELAPSED=$(( $(date +%s) - ATTEMPT_START )) LOOP_ELAPSED=$(( $(date +%s) - SYNC_LOOP_START )) echo "----- gclient sync attempt $ATTEMPT/$MAX_ATTEMPTS failed after ${ATTEMPT_ELAPSED}s (${LOOP_ELAPSED}s total so far) -----" if [ "$ATTEMPT" -ge "$MAX_ATTEMPTS" ]; then echo "gclient sync failed after $ATTEMPT attempts, giving up" exit 1 fi if [ "$LOOP_ELAPSED" -ge "$SYNC_LOOP_BUDGET" ]; then echo "gclient sync retry loop exceeded its ${SYNC_LOOP_BUDGET}s wall-clock budget after attempt $ATTEMPT, giving up rather than continuing indefinitely" exit 1 fi echo "retrying ($((ATTEMPT + 1))/$MAX_ATTEMPTS)" ATTEMPT=$((ATTEMPT + 1)) done