Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions .github/scripts/run-smoke.sh
Comment thread
1Solon marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env bash
set -euo pipefail

# Assumptions:
# - Frontend has already been built (vite build) if needed
# - 'go run server.go' launches the application
# - Success condition: HTTPS port responds with any content OR log line 'Starting API services...'

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
LOG_DIR="$ROOT_DIR/smoke-logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/server.log"
RESULT_FILE="$LOG_DIR/result.txt"
STATUS_JSON="$LOG_DIR/status.json"
PORT="8443"
TIMEOUT_SECONDS=${SMOKE_TIMEOUT_SECONDS:-45}
GRACE_KILL_SECONDS=5

# Start server in background
(
cd "$ROOT_DIR"
echo "[smoke] launching server..." | tee -a "$LOG_FILE"
export LOG_LEVEL=20 # INFO
# Run server
nohup go run server.go > "$LOG_FILE" 2>&1 &
echo $! > "$LOG_DIR/server.pid"
) || true

PID=$(cat "$LOG_DIR/server.pid" 2>/dev/null || echo "")
if [[ -z "$PID" ]] || ! kill -0 "$PID" 2>/dev/null; then
echo "{\"status\":\"failed\",\"reason\":\"No valid server PID captured\"}" > "$STATUS_JSON"
exit 0
fi

echo "[smoke] server pid: $PID"

# Wait for readiness
START_TIME=$(date +%s)
READY=0
while true; do
NOW=$(date +%s)
ELAPSED=$((NOW-START_TIME))
if (( ELAPSED > TIMEOUT_SECONDS )); then
echo "[smoke] timeout after $ELAPSED seconds" | tee -a "$LOG_FILE"
break
fi
# Check log line
if grep -q "Starting API services" "$LOG_FILE"; then
READY=1
echo "[smoke] readiness via log line" | tee -a "$LOG_FILE"
break
fi
# Try HTTPS curl (ignore cert issues)
if curl -sk --max-time 2 https://localhost:$PORT/ >/dev/null 2>&1; then
READY=1
echo "[smoke] readiness via https response" | tee -a "$LOG_FILE"
break
fi
sleep 2
done

if [[ $READY -eq 1 ]]; then
STATUS="passed"
else
STATUS="failed"
fi

echo "[smoke] stopping server (status=$STATUS)" | tee -a "$LOG_FILE"
if kill "$PID" 2>/dev/null; then
# allow graceful shutdown
for i in $(seq 1 $GRACE_KILL_SECONDS); do
if kill -0 "$PID" 2>/dev/null; then
sleep 1
else
break
fi
done
if kill -0 "$PID" 2>/dev/null; then
echo "[smoke] force killing $PID" | tee -a "$LOG_FILE"
kill -9 "$PID" || true
fi
fi

echo "$STATUS" > "$RESULT_FILE"
cat > "$STATUS_JSON" <<EOF
{ "status": "$STATUS", "timeoutSeconds": $TIMEOUT_SECONDS }
EOF

echo "[smoke] done" | tee -a "$LOG_FILE"

# Always exit 0 so workflow can collect artifacts; status is in files.
exit 0
74 changes: 74 additions & 0 deletions .github/workflows/pr-smoke-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: PR Smoke Test

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
contents: read

jobs:
smoke:
name: Smoke (${{ matrix.distro }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- distro: ubuntu
image: ubuntu:24.04
pkg_update: apt-get update
install: apt-get install -y --no-install-recommends ca-certificates curl git build-essential wget nodejs npm bash tar
- distro: debian
image: debian:trixie
pkg_update: apt-get update
install: apt-get install -y --no-install-recommends ca-certificates curl git build-essential wget nodejs npm bash tar
- distro: arch
image: archlinux:base
pkg_update: pacman -Sy --noconfirm
install: pacman -S --noconfirm ca-certificates curl git wget tar nodejs npm base-devel bash
container:
image: ${{ matrix.image }}
env:
CGO_ENABLED: 0
steps:
- name: Prepare packages
run: |
set -e
${{ matrix.pkg_update }}
${{ matrix.install }}
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Node version
run: node --version && npm --version || true
- name: Install frontend deps
working-directory: frontend
run: |
if [ -f package.json ]; then npm ci || npm install; fi
- name: Build frontend
working-directory: frontend
run: |
if [ -f package.json ]; then npm run build || echo 'frontend build failed (continuing)'; fi
- name: Run smoke test
run: bash ./.github/scripts/run-smoke.sh
- name: Collect results
if: always()
id: collect
run: |
echo "status=$(cat smoke-logs/result.txt 2>/dev/null || echo 'missing')" >> $GITHUB_OUTPUT
echo "status_json=$(cat smoke-logs/status.json 2>/dev/null || echo '{}')" >> $GITHUB_OUTPUT
- name: Upload logs
if: always()
uses: actions/upload-artifact@v4
with:
name: smoke-${{ matrix.distro }}
path: |
smoke-logs/server.log
smoke-logs/status.json
smoke-logs/result.txt
if-no-files-found: warn