shoc-pr-review-runner/scripts/checkout-repositories.sh

95 lines
3.8 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Check out the product repositories at exact SHAs (spec §10).
#
# Repos under review are checked out at their PR head SHA. The companion repo of
# a single-repo review is checked out at its default branch head for contract
# context (spec §10.2) and recorded as such.
#
# Auth: the read-only App installation token is injected ONLY as a host-scoped
# Basic http.extraHeader via GIT_CONFIG_* environment variables for the fetch
# commands. It is never placed in a URL, never Bearer, and never written to
# .git/config, so nothing credential-bearing persists after the run.
#
# Usage: checkout-repositories.sh
# Reads: GH_TOKEN, REVIEW_TYPE, FRONTEND_REPO, BACKEND_REPO,
# FRONTEND_SHA / BACKEND_SHA (empty when that side has no PR),
# COMPANION_BRANCH (default: dev)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"
require_env GH_TOKEN REVIEW_TYPE FRONTEND_REPO BACKEND_REPO
COMPANION_BRANCH="${COMPANION_BRANCH:-dev}"
# The Basic-auth header is a derived credential: GitHub masks the raw token it
# minted, but not this transformation of it. Register the mask explicitly so an
# accidental trace or debug flag cannot print a working credential to the log.
AUTH_HEADER_B64="$(printf 'x-access-token:%s' "$GH_TOKEN" | base64 | tr -d '\n')"
if [ -n "${GITHUB_ACTIONS:-}" ]; then
echo "::add-mask::$AUTH_HEADER_B64"
fi
auth_git() {
# git with the Basic auth header injected via env for this invocation only.
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0="http.https://github.com/.extraHeader" \
GIT_CONFIG_VALUE_0="Authorization: Basic $AUTH_HEADER_B64" \
GIT_TERMINAL_PROMPT=0 \
git "$@"
}
# fetch_at <dir> <repo> <ref-or-sha> <label>
fetch_at() {
local dir="$1" repo="$2" ref="$3" label="$4"
# Validate before use: the ref reaches git as an argument, so anything other
# than a resolved SHA or the configured companion branch is refused.
if ! [[ "$ref" =~ ^[0-9a-f]{40}$ ]] && [ "$ref" != "$COMPANION_BRANCH" ]; then
die "refusing to fetch unexpected ref '$ref'"
fi
rm -rf "$dir"
mkdir -p "$dir"
git -C "$dir" init -q
git -C "$dir" remote add origin -- "https://github.com/$repo.git"
auth_git -C "$dir" fetch -q --depth=1 origin -- "$ref" || die "fetch of $repo @ $ref failed"
git -C "$dir" checkout -q --detach FETCH_HEAD
local got
got="$(git -C "$dir" rev-parse HEAD)"
if [[ "$ref" =~ ^[0-9a-f]{40}$ ]] && [ "$got" != "$ref" ]; then
die "$repo checkout mismatch: wanted $ref got $got"
fi
log "$label: $repo @ $(git -C "$dir" rev-parse --short=7 HEAD) ($ref)"
}
frontend_dir="$WORKSPACE_DIR/frontend"
backend_dir="$WORKSPACE_DIR/backend"
case "$REVIEW_TYPE" in
frontend)
require_env FRONTEND_SHA
fetch_at "$frontend_dir" "$FRONTEND_REPO" "$FRONTEND_SHA" "frontend (PR head)"
fetch_at "$backend_dir" "$BACKEND_REPO" "$COMPANION_BRANCH" "backend (companion @ $COMPANION_BRANCH)"
;;
backend)
require_env BACKEND_SHA
fetch_at "$backend_dir" "$BACKEND_REPO" "$BACKEND_SHA" "backend (PR head)"
fetch_at "$frontend_dir" "$FRONTEND_REPO" "$COMPANION_BRANCH" "frontend (companion @ $COMPANION_BRANCH)"
;;
paired)
require_env FRONTEND_SHA BACKEND_SHA
fetch_at "$frontend_dir" "$FRONTEND_REPO" "$FRONTEND_SHA" "frontend (PR head)"
fetch_at "$backend_dir" "$BACKEND_REPO" "$BACKEND_SHA" "backend (PR head)"
;;
*) die "invalid REVIEW_TYPE '$REVIEW_TYPE'" ;;
esac
# Record companion context for evidence.
jq -n \
--arg review_type "$REVIEW_TYPE" \
--arg companion_branch "$COMPANION_BRANCH" \
--arg frontend_head "$(git -C "$frontend_dir" rev-parse HEAD)" \
--arg backend_head "$(git -C "$backend_dir" rev-parse HEAD)" \
'{review_type: $review_type, companion_branch: $companion_branch,
frontend_checkout: $frontend_head, backend_checkout: $backend_head}' \
>"$ARTIFACTS_DIR/checkout.json"