name: Auto Update Build on: pull_request: types: [opened, synchronize] branches: - master jobs: build: # Only run for auto-update branches if: startsWith(github.head_ref, 'auto-update/') runs-on: nix steps: - name: Checkout repository uses: actions/checkout@v4 - name: Extract LXC hosts id: hosts run: | set -euo pipefail HOSTS=$(nix eval --json .#colmena --apply 'x: builtins.filter (n: n != "meta" && builtins.elem "lxc" (x.${n}.deployment.tags or [])) (builtins.attrNames x)') # Validate the output is a non-empty JSON array if ! echo "$HOSTS" | jq -e '. | if type == "array" and length > 0 then true else false end' > /dev/null 2>&1; then echo "Error: No LXC hosts found or invalid JSON output: $HOSTS" exit 1 fi echo "$HOSTS" > hosts.json echo "Discovered hosts: $HOSTS" - name: Build all hosts id: build run: | set -euo pipefail if [ ! -f hosts.json ]; then echo "Error: hosts.json not found" exit 1 fi HOSTS=$(cat hosts.json) echo "Building hosts: $HOSTS" FAILED_HOSTS="" SUCCESS_HOSTS="" declare -A BUILD_TIMES for HOST in $(echo "$HOSTS" | jq -r '.[]'); do echo "" echo "==========================================" echo "Building: $HOST" echo "==========================================" START_TIME=$(date +%s) if nix build ".#nixosConfigurations.${HOST}.config.system.build.toplevel" --no-link --quiet 2>&1 | tee "build-${HOST}.txt"; then END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) DURATION_FMT=$(printf '%dm %ds' $((DURATION/60)) $((DURATION%60))) BUILD_TIMES[$HOST]="$DURATION_FMT" echo "✓ Build succeeded: $HOST (${DURATION_FMT})" SUCCESS_HOSTS="$SUCCESS_HOSTS $HOST" else END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) DURATION_FMT=$(printf '%dm %ds' $((DURATION/60)) $((DURATION%60))) BUILD_TIMES[$HOST]="$DURATION_FMT" echo "✗ Build failed: $HOST (${DURATION_FMT})" FAILED_HOSTS="$FAILED_HOSTS $HOST" fi done echo "" echo "==========================================" echo "Build Summary" echo "==========================================" echo "Succeeded:$SUCCESS_HOSTS" echo "Failed:$FAILED_HOSTS" echo "" echo "Build times:" for HOST in "${!BUILD_TIMES[@]}"; do echo " $HOST: ${BUILD_TIMES[$HOST]}" done # Save failed hosts for the comment step echo "$FAILED_HOSTS" > failed_hosts.txt if [ -n "$FAILED_HOSTS" ]; then echo "Some builds failed" exit 1 fi continue-on-error: true - name: Upload build logs if: always() uses: forgejo/upload-artifact@v4 with: name: build-logs path: build-*.txt retention-days: 7 - name: Comment on PR with build failures if: steps.build.outcome == 'failure' env: PR_TOKEN: ${{ secrets.PR_TOKEN }} run: | set -euo pipefail if [ ! -f failed_hosts.txt ]; then echo "No failed hosts file found" exit 0 fi FAILED_HOSTS=$(cat failed_hosts.txt) # Build comment body { echo "## ❌ Build Failed" echo "" echo "The following hosts failed to build:" echo "" for HOST in $FAILED_HOSTS; do LOG_FILE="build-${HOST}.txt" if [ -f "$LOG_FILE" ]; then echo "
" echo "${HOST}" echo "" echo '```' tail -n 150 "$LOG_FILE" echo '```' echo "" echo "
" echo "" fi done } > comment_body.md # Post comment to PR using jq for proper JSON escaping jq -Rs '{body: .}' comment_body.md > payload.json curl -sf -X POST \ -H "Authorization: token $PR_TOKEN" \ -H "Content-Type: application/json" \ -d @payload.json \ "${{ forgejo.api_url }}/repos/${{ forgejo.repository }}/issues/${{ forgejo.event.pull_request.number }}/comments" - name: Check build result run: | if [ "${{ steps.build.outcome }}" == "failure" ]; then echo "Some builds failed - check build-logs artifact" exit 1 fi - name: Cleanup if: always() run: | nix-collect-garbage -d rm -rf result .direnv