#!/bin/bash # push_artifacts.sh — upload benchmark artifacts (galleries, montage frames) to the # Gitea generic package registry, decoupled from git history entirely. These are # NOT needed to run the main app — only for benchmarks/experiments/reports. # # Requires GITEA_TOKEN in the environment (a Gitea access token with package # read/write scope). Never hardcode the token; export it in your shell: # export GITEA_TOKEN=... # # Usage: # scripts/artifacts/push_artifacts.sh galleries # scripts/artifacts/push_artifacts.sh montage-frames # scripts/artifacts/push_artifacts.sh experiment-data # scripts/artifacts/push_artifacts.sh report-highlights # scripts/artifacts/push_artifacts.sh xsource # scripts/artifacts/push_artifacts.sh replay-fixtures # scripts/artifacts/push_artifacts.sh galleries montage-frames experiment-data report-highlights # # Package layout (owner=dtourolle, repo=scene-actor-extraction): # generic/galleries//gallery_.h5 (one file per model) # generic/replay-fixtures//replay-fixtures.zip (T2 dumps + their gallery) # generic/montage-frames//.zip (zipped per-film frames) # generic/experiment-data//experiment-data.zip (manifests/trajectories/results) # generic/report-highlights//.jpg (individual, hand-picked # illustrative frames referenced by docs/*.md that aren't reproducible via # the automated best/worst montage selection — see scripts/docs/build_site.sh) # version = current git short SHA, so artifacts are traceable to the code that # produced them. Re-running with the same SHA overwrites that version's files. set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" OWNER="dtourolle" PKG_REPO="scene-actor-extraction" # NOTE: the generic package registry lives under /api/packages/ (no /v1/) — # distinct from the regular REST API under /api/v1/packages/ used for listing. BASE_URL="https://gitea.tourolle.paris/api/packages/${OWNER}" VERSION="$(git -C "$REPO_ROOT" rev-parse --short HEAD)" if [ -z "${GITEA_TOKEN:-}" ]; then echo "error: GITEA_TOKEN is not set. export GITEA_TOKEN= and retry." >&2 exit 1 fi upload() { local package="$1" filename="$2" filepath="$3" local url="${BASE_URL}/generic/${package}/${VERSION}/${filename}" echo " uploading ${filename} -> ${package}/${VERSION}..." curl -sf -X PUT "$url" \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --upload-file "$filepath" \ -o /dev/null -w " HTTP %{http_code}\n" } push_replay_fixtures() { echo "=== replay-fixtures (version ${VERSION}) ===" # T2 replay fixtures: per-frame detections, landmarks and embeddings dumped # from a real run, so the tracker and identity stages can be replayed on CPU # with no GPU, no models and no film. Too large for git (superhero.h5 alone # is ~9 MB) and regenerating them needs the film plus a GPU, which CI has # neither of — so they ship as artifacts and CI pulls them. # # The gallery travels with them: a dump replays against the gallery it was # produced with, and pairing a dump with a different gallery silently # changes every identity decision in it. local dir="${REPO_ROOT}/tests/fixtures/dumps" if [ ! -d "$dir" ]; then echo " no tests/fixtures/dumps dir, skipping" >&2 return fi local tmp tmp="$(mktemp -d)" ( cd "$dir" && zip -qr "$tmp/replay-fixtures.zip" . ) upload "replay-fixtures" "replay-fixtures.zip" "$tmp/replay-fixtures.zip" rm -rf "$tmp" } push_galleries() { echo "=== galleries (version ${VERSION}) ===" local dir="${REPO_ROOT}/experiments/galleries" shopt -s nullglob for f in "$dir"/gallery_*.h5; do upload "galleries" "$(basename "$f")" "$f" done shopt -u nullglob } push_montage_frames() { echo "=== montage-frames (version ${VERSION}) ===" local root="${REPO_ROOT}/experiments/results/holdout/montage_bestworst" if [ ! -d "$root" ]; then echo " no montage_bestworst dir found, skipping" >&2 return fi local tmp tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' RETURN for filmdir in "$root"/*/; do [ -d "$filmdir" ] || continue local slug ascii_slug zipfile slug="$(basename "$filmdir")" # Gitea's generic package registry rejects non-ASCII filenames (verified: # a bare é in the name 400s). Transliterate for the upload name only — # the local directory name (with accents) is untouched. ascii_slug="$(echo "$slug" | iconv -f utf-8 -t ascii//translit 2>/dev/null || echo "$slug")" zipfile="${tmp}/${ascii_slug}.zip" (cd "$filmdir" && zip -qr "$zipfile" .) upload "montage-frames" "${ascii_slug}.zip" "$zipfile" done } push_experiment_data() { echo "=== experiment-data (version ${VERSION}) ===" # manifests/trajectories/results are all small text/JSON — no source paths # (manifests never carry a "movie" field; see experiments/file-lut.json) # so this is safe to share as one bundle. local tmp; tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' RETURN local zipfile="${tmp}/experiment-data.zip" (cd "$REPO_ROOT" && zip -qr "$zipfile" \ experiments/manifests experiments/trajectories experiments/results \ -x '*.log' -x '*/holdout/montage_bestworst/*' -x '*/holdout/frames/*' \ -x '*/holdout/montage/*' -x '*/holdout/*.jsonl' -x '*/holdout/pred_*.json' \ -x '*/holdout/raw_*.jsonl') upload "experiment-data" "experiment-data.zip" "$zipfile" } push_report_highlights() { echo "=== report-highlights (version ${VERSION}) ===" local src="${REPO_ROOT}/experiments/results/holdout/montage/many_saints/out_of_cast_fpi/10_t003641.jpg" if [ ! -f "$src" ]; then echo " [warn] $src not found, skipping" >&2 return fi upload "report-highlights" "germar_beats_xray.jpg" "$src" } push_xsource() { echo "=== xsource (version ${VERSION}) ===" local root="${REPO_ROOT}/experiments/xsource" if [ ! -d "$root/labelling" ]; then echo " no experiments/xsource/labelling found, skipping" >&2 return fi # Source recordings. Already compressed, so uploaded as-is rather than zipped. shopt -s nullglob for f in "$root"/clips/*.mp4; do upload "xsource" "$(basename "$f")" "$f" done shopt -u nullglob # The hand-sorted crops and their manifests. This is human ground truth and # the expensive part of the study — a person looked at every crop and put it # in a folder. Frames are deliberately NOT pushed: they are deterministic # from the clips, and pulling regenerates them. local tmp; tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' RETURN local zipfile="${tmp}/labelling.zip" (cd "$root" && zip -qr "$zipfile" labelling -x 'labelling/*.html' -x 'labelling/review_*.jpg' \ -x 'labelling/verify_*.jpg') upload "xsource" "labelling.zip" "$zipfile" } if [ $# -eq 0 ]; then echo "usage: $0 [...]" >&2 exit 1 fi for target in "$@"; do case "$target" in galleries) push_galleries ;; montage-frames) push_montage_frames ;; experiment-data) push_experiment_data ;; report-highlights) push_report_highlights ;; xsource) push_xsource ;; replay-fixtures) push_replay_fixtures ;; *) echo "unknown target: $target (expected galleries, montage-frames, experiment-data, report-highlights, xsource, or replay-fixtures)" >&2; exit 1 ;; esac done echo "Done. Browse at: https://gitea.tourolle.paris/${OWNER}/${PKG_REPO}/packages"