backend-infra-engineer: Release v0.3.3 snapshot
This commit is contained in:
101
scripts/agents/README.md
Normal file
101
scripts/agents/README.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Agent Helper Scripts
|
||||
|
||||
| Script | Description |
|
||||
|--------|-------------|
|
||||
| `run-gh-workflow.sh` | Wrapper for `gh workflow run`, prints the run URL for easy tracking. |
|
||||
| `get-gh-workflow-status.sh` | Checks the status of a GitHub Actions workflow run using `gh run view`. |
|
||||
| `smoke-build.sh` | Runs `cmake --preset` configure/build in place and reports timing. |
|
||||
| `run-tests.sh` | Configures the preset (if needed), builds `yaze_test`, and runs `ctest` with optional args. |
|
||||
| `test-http-api.sh` | Polls the HTTP API `/api/v1/health` endpoint using curl (defaults to localhost:8080). |
|
||||
| `windows-smoke-build.ps1` | PowerShell variant of the smoke build helper for Visual Studio/Ninja presets on Windows. |
|
||||
|
||||
Usage examples:
|
||||
```bash
|
||||
# Trigger CI workflow with artifacts and HTTP API tests enabled
|
||||
scripts/agents/run-gh-workflow.sh ci.yml --ref develop upload_artifacts=true enable_http_api_tests=true
|
||||
|
||||
# Get the status of a workflow run (using either a URL or just the ID)
|
||||
scripts/agents/get-gh-workflow-status.sh https://github.com/scawful/yaze/actions/runs/19529930066
|
||||
scripts/agents/get-gh-workflow-status.sh 19529930066
|
||||
|
||||
# Smoke build mac-ai preset
|
||||
scripts/agents/smoke-build.sh mac-ai
|
||||
|
||||
# Build & run tests for mac-dbg preset with verbose ctest output
|
||||
scripts/agents/run-tests.sh mac-dbg --output-on-failure
|
||||
|
||||
# Check HTTP API health (defaults to localhost:8080)
|
||||
scripts/agents/test-http-api.sh
|
||||
|
||||
# Windows smoke build using PowerShell
|
||||
pwsh -File scripts/agents/windows-smoke-build.ps1 -Preset win-ai -Target z3ed
|
||||
```
|
||||
|
||||
When invoking these scripts, log the results on the coordination board so other agents know which
|
||||
workflows/builds were triggered and where to find artifacts/logs.
|
||||
|
||||
## Reducing Build Times
|
||||
|
||||
Local builds can take 10-15+ minutes from scratch. Follow these practices to minimize rebuild time:
|
||||
|
||||
### Use Dedicated Build Directories
|
||||
Always use a dedicated build directory like `build_ai` or `build_agent` to avoid interfering with the user's `build` directory:
|
||||
```bash
|
||||
cmake --preset mac-dbg -B build_ai
|
||||
cmake --build build_ai -j8 --target yaze
|
||||
```
|
||||
|
||||
### Incremental Builds
|
||||
Once configured, only rebuild—don't reconfigure unless CMakeLists.txt changed:
|
||||
```bash
|
||||
# GOOD: Just rebuild (fast, only recompiles changed files)
|
||||
cmake --build build_ai -j8 --target yaze
|
||||
|
||||
# AVOID: Reconfiguring when unnecessary (triggers full dependency resolution)
|
||||
cmake --preset mac-dbg -B build_ai && cmake --build build_ai
|
||||
```
|
||||
|
||||
### Build Specific Targets
|
||||
Don't build everything when you only need to verify a specific component:
|
||||
```bash
|
||||
# Build only the main editor (skips CLI, tests, etc.)
|
||||
cmake --build build_ai -j8 --target yaze
|
||||
|
||||
# Build only the CLI tool
|
||||
cmake --build build_ai -j8 --target z3ed
|
||||
|
||||
# Build only tests
|
||||
cmake --build build_ai -j8 --target yaze_test
|
||||
```
|
||||
|
||||
### Parallel Compilation
|
||||
Always use `-j8` or higher based on CPU cores:
|
||||
```bash
|
||||
cmake --build build_ai -j$(sysctl -n hw.ncpu) # macOS
|
||||
cmake --build build_ai -j$(nproc) # Linux
|
||||
```
|
||||
|
||||
### Quick Syntax Check
|
||||
For rapid iteration on compile errors, build just the affected library:
|
||||
```bash
|
||||
# If fixing errors in src/app/editor/dungeon/, build just the editor lib
|
||||
cmake --build build_ai -j8 --target yaze_editor
|
||||
```
|
||||
|
||||
### Verifying Changes Before CI
|
||||
Before pushing to trigger CI builds (which take 15-20 minutes each):
|
||||
1. Run an incremental local build to catch obvious errors
|
||||
2. If you modified a specific component, build just that target
|
||||
3. Only push when local build succeeds
|
||||
|
||||
### ccache/sccache (Advanced)
|
||||
If available, these tools cache compilation results across rebuilds:
|
||||
```bash
|
||||
# Check if ccache is installed
|
||||
which ccache
|
||||
|
||||
# View cache statistics
|
||||
ccache -s
|
||||
```
|
||||
|
||||
The project's CMake configuration automatically uses ccache when available.
|
||||
35
scripts/agents/get-gh-workflow-status.sh
Executable file
35
scripts/agents/get-gh-workflow-status.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# A script to check the status of a GitHub Actions workflow run.
|
||||
#
|
||||
# Usage: ./get-gh-workflow-status.sh <run_url>
|
||||
#
|
||||
# Requires `gh` (GitHub CLI) and `jq` to be installed and authenticated.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <run_url_or_run_id>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RUN_ID_OR_URL="$1"
|
||||
|
||||
# Extract run ID from URL if a URL is provided
|
||||
if [[ "$RUN_ID_OR_URL" == *"github.com"* ]]; then
|
||||
RUN_ID=$(basename "$RUN_ID_OR_URL")
|
||||
else
|
||||
RUN_ID="$RUN_ID_OR_URL"
|
||||
fi
|
||||
|
||||
echo "Fetching status for workflow run ID: $RUN_ID..."
|
||||
|
||||
# Use GitHub CLI to get the run and its jobs, then format with jq
|
||||
gh run view "$RUN_ID" --json jobs,status,conclusion,name,url --jq '
|
||||
"Run: " + .name + " (" + .status + "/" + (.conclusion // "in_progress") + ")",
|
||||
"URL: " + .url,
|
||||
"",
|
||||
"Jobs:",
|
||||
"----",
|
||||
(.jobs[] | " - " + .name + ": " + .conclusion + " (" + (.status // "unknown") + ")")
|
||||
'
|
||||
50
scripts/agents/run-gh-workflow.sh
Normal file
50
scripts/agents/run-gh-workflow.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Wrapper for triggering GitHub Actions workflows via gh CLI.
|
||||
# Usage: scripts/agents/run-gh-workflow.sh <workflow_file> [--ref <ref>] [key=value ...]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if ! command -v gh >/dev/null 2>&1; then
|
||||
echo "error: gh CLI is required (https://cli.github.com/)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: $0 <workflow_file> [--ref <ref>] [key=value ...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WORKFLOW="$1"
|
||||
shift
|
||||
|
||||
REF=""
|
||||
INPUT_ARGS=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--ref)
|
||||
REF="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
INPUT_ARGS+=("-f" "$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
CMD=(gh workflow run "$WORKFLOW")
|
||||
if [[ -n "$REF" ]]; then
|
||||
CMD+=("--ref" "$REF")
|
||||
fi
|
||||
if [[ ${#INPUT_ARGS[@]} -gt 0 ]]; then
|
||||
CMD+=("${INPUT_ARGS[@]}")
|
||||
fi
|
||||
|
||||
echo "+ ${CMD[*]}"
|
||||
"${CMD[@]}"
|
||||
|
||||
RUN_URL=$(gh run list --workflow "$WORKFLOW" --limit 1 --json url -q '.[0].url')
|
||||
if [[ -n "$RUN_URL" ]]; then
|
||||
echo "Triggered workflow. Track progress at: $RUN_URL"
|
||||
fi
|
||||
81
scripts/agents/run-tests.sh
Executable file
81
scripts/agents/run-tests.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
# Helper script to configure, build, and run tests for a given CMake preset.
|
||||
# Usage: scripts/agents/run-tests.sh <preset> [ctest-args...]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: $0 <preset> [ctest-args...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PRESET="$1"
|
||||
shift
|
||||
|
||||
echo "Configuring preset: $PRESET"
|
||||
cmake --preset "$PRESET" || { echo "Configure failed for preset: $PRESET"; exit 1; }
|
||||
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
||||
read -r GENERATOR BUILD_CONFIG <<EOF
|
||||
$(python - <<'PY' "$PRESET" "$ROOT_DIR"
|
||||
import json, sys, os
|
||||
preset = sys.argv[1]
|
||||
root = sys.argv[2]
|
||||
with open(os.path.join(root, "CMakePresets.json")) as f:
|
||||
data = json.load(f)
|
||||
configure = {p["name"]: p for p in data.get("configurePresets", [])}
|
||||
build = {p["name"]: p for p in data.get("buildPresets", [])}
|
||||
|
||||
def parents(entry):
|
||||
inherits = entry.get("inherits", [])
|
||||
if isinstance(inherits, str):
|
||||
inherits = [inherits]
|
||||
return inherits
|
||||
|
||||
def resolve_generator(name, seen=None):
|
||||
if seen is None:
|
||||
seen = set()
|
||||
if name in seen:
|
||||
return None
|
||||
seen.add(name)
|
||||
entry = configure.get(name)
|
||||
if not entry:
|
||||
return None
|
||||
gen = entry.get("generator")
|
||||
if gen:
|
||||
return gen
|
||||
for parent in parents(entry):
|
||||
gen = resolve_generator(parent, seen)
|
||||
if gen:
|
||||
return gen
|
||||
return None
|
||||
|
||||
generator = resolve_generator(preset)
|
||||
build_preset = build.get(preset, {})
|
||||
config = build_preset.get("configuration")
|
||||
if not config:
|
||||
entry = configure.get(preset, {})
|
||||
cache = entry.get("cacheVariables", {})
|
||||
config = cache.get("CMAKE_BUILD_TYPE", "Debug")
|
||||
|
||||
print(generator or "")
|
||||
print(config or "")
|
||||
PY)
|
||||
EOF
|
||||
|
||||
echo "Building tests for preset: $PRESET"
|
||||
BUILD_CMD=(cmake --build --preset "$PRESET")
|
||||
if [[ "$GENERATOR" == *"Visual Studio"* && -n "$BUILD_CONFIG" ]]; then
|
||||
BUILD_CMD+=(--config "$BUILD_CONFIG")
|
||||
fi
|
||||
"${BUILD_CMD[@]}" || { echo "Build failed for preset: $PRESET"; exit 1; }
|
||||
|
||||
if ctest --preset "$PRESET" --show-only >/dev/null 2>&1; then
|
||||
echo "Running tests for preset: $PRESET"
|
||||
ctest --preset "$PRESET" "$@"
|
||||
else
|
||||
echo "Test preset '$PRESET' not found, falling back to 'all' tests."
|
||||
ctest --preset all "$@"
|
||||
fi
|
||||
|
||||
echo "All tests passed for preset: $PRESET"
|
||||
19
scripts/agents/smoke-build.sh
Normal file
19
scripts/agents/smoke-build.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
# Quick smoke build for a given preset in an isolated directory with timing info.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: $0 <preset> [build_dir]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PRESET="$1"
|
||||
|
||||
START=$(date +%s)
|
||||
cmake --preset "$PRESET"
|
||||
cmake --build --preset "$PRESET"
|
||||
END=$(date +%s)
|
||||
|
||||
ELAPSED=$((END - START))
|
||||
echo "Smoke build '$PRESET' completed in ${ELAPSED}s"
|
||||
28
scripts/agents/test-http-api.sh
Executable file
28
scripts/agents/test-http-api.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
# Basic health check for the HTTP API server.
|
||||
# Usage: scripts/agents/test-http-api.sh [host] [port]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HOST="${1:-127.0.0.1}"
|
||||
PORT="${2:-8080}"
|
||||
URL="http://${HOST}:${PORT}/api/v1/health"
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
echo "error: curl is required to test the HTTP API" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking HTTP API health endpoint at ${URL}"
|
||||
|
||||
for attempt in {1..10}; do
|
||||
if curl -fsS "${URL}" >/dev/null; then
|
||||
echo "HTTP API responded successfully (attempt ${attempt})"
|
||||
exit 0
|
||||
fi
|
||||
echo "Attempt ${attempt} failed; retrying..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "error: HTTP API did not respond at ${URL}" >&2
|
||||
exit 1
|
||||
70
scripts/agents/windows-smoke-build.ps1
Normal file
70
scripts/agents/windows-smoke-build.ps1
Normal file
@@ -0,0 +1,70 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Preset,
|
||||
[string]$Target = ""
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = Resolve-Path "$PSScriptRoot/.."
|
||||
Set-Location $repoRoot
|
||||
|
||||
function Get-GeneratorAndConfig {
|
||||
param([string]$PresetName)
|
||||
|
||||
$jsonPath = Join-Path $repoRoot "CMakePresets.json"
|
||||
$data = Get-Content $jsonPath -Raw | ConvertFrom-Json
|
||||
$configurePresets = @{}
|
||||
foreach ($preset in $data.configurePresets) {
|
||||
$configurePresets[$preset.name] = $preset
|
||||
}
|
||||
|
||||
$buildPresets = @{}
|
||||
foreach ($preset in $data.buildPresets) {
|
||||
$buildPresets[$preset.name] = $preset
|
||||
}
|
||||
|
||||
function Resolve-Generator([string]$name, [hashtable]$seen) {
|
||||
if ($seen.ContainsKey($name)) { return $null }
|
||||
$seen[$name] = $true
|
||||
if (-not $configurePresets.ContainsKey($name)) { return $null }
|
||||
$entry = $configurePresets[$name]
|
||||
if ($entry.generator) { return $entry.generator }
|
||||
$inherits = $entry.inherits
|
||||
if ($inherits -is [string]) { $inherits = @($inherits) }
|
||||
foreach ($parent in $inherits) {
|
||||
$gen = Resolve-Generator $parent $seen
|
||||
if ($gen) { return $gen }
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
$generator = Resolve-Generator $PresetName @{}
|
||||
|
||||
$config = $null
|
||||
if ($buildPresets.ContainsKey($PresetName) -and $buildPresets[$PresetName].configuration) {
|
||||
$config = $buildPresets[$PresetName].configuration
|
||||
} elseif ($configurePresets.ContainsKey($PresetName)) {
|
||||
$cache = $configurePresets[$PresetName].cacheVariables
|
||||
if ($cache.CMAKE_BUILD_TYPE) { $config = $cache.CMAKE_BUILD_TYPE }
|
||||
}
|
||||
|
||||
return @{ Generator = $generator; Configuration = $config }
|
||||
}
|
||||
|
||||
Write-Host "Configuring preset: $Preset"
|
||||
cmake --preset $Preset
|
||||
|
||||
$info = Get-GeneratorAndConfig -PresetName $Preset
|
||||
$buildCmd = @("cmake", "--build", "--preset", $Preset)
|
||||
if ($Target) { $buildCmd += @("--target", $Target) }
|
||||
if ($info.Generator -like "*Visual Studio*" -and $info.Configuration) {
|
||||
$buildCmd += @("--config", $info.Configuration)
|
||||
}
|
||||
|
||||
Write-Host "Building preset: $Preset"
|
||||
Write-Host "+ $($buildCmd -join ' ')"
|
||||
& $buildCmd
|
||||
|
||||
Write-Host "Smoke build completed for preset: $Preset"
|
||||
Reference in New Issue
Block a user