nix-hermes-agent/scripts/update-nightly.sh

96 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Generate a reviewable nightly candidate without pushing to main.
repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
nightly_file="$repo_root/nightly.nix"
report=${HERMES_UPDATE_REPORT:-/tmp/hermes-nightly-update.md}
# shellcheck source=scripts/update-common.sh
source "$repo_root/scripts/update-common.sh"
log() { printf '>> %s\n' "$*"; }
die() { printf 'error: %s\n' "$*" >&2; exit 1; }
command -v gh >/dev/null || die "gh is required"
command -v python3 >/dev/null || die "python3 is required"
head_sha=$(gh api /repos/NousResearch/hermes-agent/commits/main --jq '.sha')
[[ -n "$head_sha" ]] || die "failed to resolve upstream main"
current_rev=$(awk -F'"' '/pinRev = /{print $2; exit}' "$nightly_file")
current_version=$(awk -F'"' '/pinVersion = /{print $2; exit}' "$nightly_file")
[[ -n "$current_rev" && -n "$current_version" ]] || die "could not read current nightly pin"
if [[ "$current_rev" == "$head_sha" ]]; then
log "Nightly already tracks $head_sha"
set_output update_available false
set_output compatible true
exit 0
fi
upstream_version=$(
gh api -H "Accept: application/vnd.github.raw+json" \
"/repos/NousResearch/hermes-agent/contents/pyproject.toml?ref=${head_sha}" |
python3 -c 'import sys, tomllib; print(tomllib.load(sys.stdin.buffer)["project"]["version"])'
)
python3 - "$upstream_version" <<'PY' || die "upstream pyproject contains an invalid version"
import re, sys
raise SystemExit(0 if re.fullmatch(r"\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?", sys.argv[1]) else 1)
PY
nightly_version="${upstream_version}-unstable-$(date -u +%Y-%m-%d).${head_sha:0:8}"
set_output update_available true
before_source=$(realize_flake_source ".#hermes-agent-nightly")
backup=$(mktemp)
build_log=$(mktemp)
cp "$nightly_file" "$backup"
candidate_ready=false
cleanup() {
[[ "$candidate_ready" == true ]] || cp "$backup" "$nightly_file"
rm -f "$backup" "$build_log"
}
trap cleanup EXIT
log "Preparing nightly candidate ${current_rev:0:12} -> ${head_sha:0:12}"
[[ $(grep -c 'pinVersion = "' "$nightly_file") == 1 ]] || die "unexpected nightly version layout"
[[ $(grep -c 'pinRev = "' "$nightly_file") == 1 ]] || die "unexpected nightly revision layout"
[[ $(grep -c 'pinHash = "' "$nightly_file") == 1 ]] || die "unexpected nightly hash layout"
perl -0pi -e "s|pinVersion = \"[^\"]+\";|pinVersion = \"${nightly_version}\";|" "$nightly_file"
perl -0pi -e "s|pinRev = \"[^\"]+\";|pinRev = \"${head_sha}\";|" "$nightly_file"
perl -0pi -e 's|pinHash = "[^"]*";|pinHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";|' "$nightly_file"
grep -Fq "pinRev = \"${head_sha}\";" "$nightly_file" || die "failed to update nightly revision"
if nix build '.#hermes-agent-nightly.src' --no-link --accept-flake-config >"$build_log" 2>&1; then
cp "$backup" "$nightly_file"
die "the fake source hash unexpectedly succeeded"
fi
source_hash=$(extract_sri_hash "$build_log")
if [[ -z "$source_hash" ]]; then
cp "$backup" "$nightly_file"
tail -80 "$build_log" >&2
die "could not extract the candidate source hash"
fi
perl -0pi -e "s|pinHash = \"[^\"]*\";|pinHash = \"${source_hash}\";|" "$nightly_file"
after_source=$(realize_flake_source ".#hermes-agent-nightly")
system=$(current_nix_system)
build_status=$(
run_validation "$build_log" nix build ".#legacyPackages.${system}.nightlyChecks.all" --accept-flake-config
)
source_args=()
[[ -n "$before_source" ]] && source_args+=(--before-source "$before_source")
[[ -n "$after_source" ]] && source_args+=(--after-source "$after_source")
python3 "$repo_root/scripts/render-update-report.py" \
--channel nightly \
--current-version "$current_version" --candidate-version "$nightly_version" \
--current-rev "$current_rev" --candidate-rev "$head_sha" \
"${source_args[@]}" \
--build-status "$build_status" --build-log "$build_log" \
--upstream-url "https://github.com/NousResearch/hermes-agent/commit/${head_sha}" \
--output "$report"
publish_summary "$report"
set_output compatible "$([[ "$build_status" == passed ]] && echo true || echo false)"
candidate_ready=true
log "Candidate prepared; validation: $build_status. The workflow will open or update its PR."