#!/usr/bin/env bash set -euo pipefail ci_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ci_dir/.." usage() { cat <&2; usage; exit 2 ;; esac done if [[ -z "${PRESET}" && -z "${CONFIGURE_OVERRIDE}" ]]; then echo "::error:: --preset or --configure-override is required" >&2 usage exit 2 fi if [[ -n "${CONFIGURE_OVERRIDE}" ]]; then if [[ -n "${PRESET}" ]]; then echo "::warning:: --preset ignored due to --configure-override" >&2 fi if [[ -n "${CMAKE_OPTIONS}" ]]; then echo "::warning:: --cmake-options ignored due to --configure-override" >&2 fi fi # Ensure the checkout has complete history and tags: git fetch --unshallow > /dev/null 2>&1 || : git fetch --tags > /dev/null 2>&1 || : # Resolve good and bad refs good_ref="${GOOD_REF}" bad_ref="${BAD_REF}" # Helper to resolve '-Nd' (N days ago on origin/main) to a SHA _resolve_days_ago() { local spec="$1" local base_branch="origin/main" local n="${spec#-}" n="${n%d}" if [[ -z "$n" || ! "$n" =~ ^[0-9]+$ ]]; then return 1 fi local when when=$(date -u -d "$n days ago" '+%Y-%m-%d %H:%M:%S %z') git rev-list -n 1 --before="$when" "$base_branch" } # Resolve good_ref if [[ -z "$good_ref" ]]; then good_ref=$(git tag --list 'v*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 || :) echo "Good ref defaulted to last release: $good_ref" fi if [[ "$good_ref" =~ ^-[0-9]+d$ ]]; then good_sha=$(_resolve_days_ago "$good_ref") if [[ -z "$good_sha" ]]; then echo "::error::Unable to resolve good_ref '$good_ref' to a commit on origin/main" >&2 exit 1 fi echo "Resolved good_ref '$good_ref' to origin/main @ $good_sha" else if [[ -z "$good_ref" ]]; then echo "::error::Unable to determine good ref" >&2 exit 1 fi good_sha=$(git rev-parse "$good_ref") fi # Resolve bad_ref if [[ -z "$bad_ref" ]]; then bad_ref="origin/main" echo "Bad ref defaulted to origin/main: $bad_ref" fi if [[ "$bad_ref" =~ ^-[0-9]+d$ ]]; then bad_sha=$(_resolve_days_ago "$bad_ref") if [[ -z "$bad_sha" ]]; then echo "::error::Unable to resolve bad_ref '$bad_ref' to a commit on origin/main" >&2 exit 1 fi echo "Resolved bad_ref '$bad_ref' to origin/main @ $bad_sha" else bad_sha=$(git rev-parse "$bad_ref") fi # Copy the build-and-test runner to a temp file so it remains available as HEAD changes: tmp_runner="$(mktemp /tmp/build-and-test-XXXXXX.sh)" cp "${ci_dir}/util/build_and_test_targets.sh" "${tmp_runner}" chmod +x "${tmp_runner}" # If --repeat > 1, wrap the runner to repeat successful runs to detect flakiness. bisect_runner="${tmp_runner}" if [[ "${REPEAT}" =~ ^[0-9]+$ ]] && [[ "${REPEAT}" -gt 1 ]]; then tmp_repeat="$(mktemp /tmp/build-and-test-repeat-XXXXXX.sh)" cat > "${tmp_repeat}" <