86 lines
4.2 KiB
YAML
86 lines
4.2 KiB
YAML
name: Build and verify web migration
|
|
on:
|
|
push:
|
|
branches: [main, 'codex/**']
|
|
pull_request:
|
|
workflow_dispatch:
|
|
permissions:
|
|
contents: read
|
|
jobs:
|
|
verify:
|
|
runs-on: ubuntu-latest
|
|
services:
|
|
mongo:
|
|
image: mongo:8.0
|
|
ports: ['27017:27017']
|
|
options: >-
|
|
--health-cmd "mongosh --quiet --eval 'db.adminCommand({ping:1}).ok'"
|
|
--health-interval 10s --health-timeout 5s --health-retries 10
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-dotnet@v4
|
|
with: { dotnet-version: '10.0.x' }
|
|
- uses: actions/setup-node@v4
|
|
with: { node-version: '22', cache: npm, cache-dependency-path: web/package-lock.json }
|
|
- name: Build services
|
|
run: dotnet build src/GuestOps.Worker/GuestOps.Worker.csproj -c Release
|
|
- name: Verify backup validation and failure recovery
|
|
run: python3 -m unittest discover -s tests -p test_ops.py
|
|
- name: Build interface
|
|
working-directory: web
|
|
run: npm ci && npm run build
|
|
- name: Start isolated preview API
|
|
run: |
|
|
ASPNETCORE_ENVIRONMENT=Development Preview=true dotnet src/GuestOps.Api/bin/Release/net10.0/GuestOps.Api.dll --urls http://127.0.0.1:5180 > /tmp/guestops-api.log 2>&1 &
|
|
for i in $(seq 1 30); do curl -fsS http://127.0.0.1:5180/health && exit 0; sleep 1; done
|
|
cat /tmp/guestops-api.log
|
|
exit 1
|
|
- name: Verify MongoDB and HTTP boundaries
|
|
env:
|
|
MONGO_TEST_URI: mongodb://127.0.0.1:27017
|
|
TEST_API_URL: http://127.0.0.1:5180
|
|
run: dotnet run --project tests/GuestOps.Tests/GuestOps.Tests.csproj -c Release
|
|
- name: Build Linux images
|
|
run: |
|
|
docker build --target api -t guestops-api:${{ github.sha }} .
|
|
docker build --target worker -t guestops-worker:${{ github.sha }} .
|
|
- name: Package reviewed images
|
|
if: github.event_name != 'pull_request'
|
|
run: docker save guestops-api:${{ github.sha }} guestops-worker:${{ github.sha }} | gzip > guestops-images.tar.gz
|
|
- name: Smoke test production containers and restart persistence
|
|
env:
|
|
GUESTOPS_API_IMAGE: guestops-api:${{ github.sha }}
|
|
GUESTOPS_WORKER_IMAGE: guestops-worker:${{ github.sha }}
|
|
BOOTSTRAP_EMAIL: ci-owner@example.invalid
|
|
BOOTSTRAP_HOTEL: CI test hotel
|
|
run: |
|
|
export MONGO_ROOT_PASSWORD=$(openssl rand -hex 32)
|
|
export MONGO_APP_PASSWORD=$(openssl rand -hex 32)
|
|
export BOOTSTRAP_PASSWORD=$(openssl rand -hex 24)
|
|
trap 'docker compose down --volumes' EXIT
|
|
docker compose config --quiet
|
|
docker compose up -d --no-build
|
|
curl --retry 30 --retry-delay 2 --retry-all-errors --fail http://127.0.0.1:8080/health
|
|
docker compose run --rm --no-deps -e BOOTSTRAP_EMAIL -e BOOTSTRAP_HOTEL -e BOOTSTRAP_PASSWORD api --bootstrap
|
|
python3 tests/production_smoke.py
|
|
docker compose restart api worker
|
|
curl --retry 30 --retry-delay 2 --retry-all-errors --fail http://127.0.0.1:8080/health
|
|
python3 tests/production_smoke.py --read
|
|
install -m 600 /dev/null .env
|
|
python3 deploy/ops.py preflight --offline
|
|
mkdir -m 700 .guestops-test-keyring
|
|
export GNUPGHOME="$PWD/.guestops-test-keyring"
|
|
gpg --batch --pinentry-mode loopback --passphrase '' --quick-generate-key 'GuestOps CI <ci@example.invalid>' rsa2048 encr 1d
|
|
BACKUP_RECIPIENT=$(gpg --batch --with-colons --list-keys | awk -F: '$1=="fpr" {print $10; exit}')
|
|
backup_dir=$(mktemp -d)
|
|
python3 deploy/ops.py backup --recipient "$BACKUP_RECIPIENT" --output "$backup_dir/fixture.tar.gpg" --confirm-maintenance
|
|
python3 deploy/ops.py restore-drill "$backup_dir/fixture.tar.gpg" --api-image "$GUESTOPS_API_IMAGE"
|
|
curl --retry 30 --retry-delay 2 --retry-all-errors --fail http://127.0.0.1:8080/health/ready
|
|
python3 tests/production_smoke.py --read
|
|
- uses: actions/upload-artifact@v4
|
|
if: github.event_name != 'pull_request'
|
|
with:
|
|
name: guestops-linux-${{ github.run_number }}
|
|
path: guestops-images.tar.gz
|
|
retention-days: 7
|