name: Build and deploy Havenllo on: push: branches: [main] workflow_dispatch: jobs: verify: name: Verify Go and frontend runs-on: runner-slim-amd64 steps: - name: Check out source uses: actions/checkout@v4 - name: Install Go and Node toolchain run: | apk add --no-cache nodejs npm # Try the packaged Go first; fall back to the official tarball if it's < 1.24 apk add --no-cache go 2>/dev/null || true if ! go version 2>/dev/null | grep -qE "go1\.(2[4-9]|[3-9][0-9])"; then apk add --no-cache wget wget -q https://go.dev/dl/go1.24.5.linux-amd64.tar.gz -O /tmp/go.tgz rm -rf /usr/local/go && tar -C /usr/local -xzf /tmp/go.tgz ln -sf /usr/local/go/bin/go /usr/bin/go fi go version node --version npm --version - name: Test Go run: go test ./... - name: Install frontend dependencies working-directory: web run: npm ci - name: Build frontend working-directory: web run: npm run build - name: Validate Kubernetes manifest run: | # Offline check only: the runner has no cluster. The real apply happens # in the deploy job using the KUBE_CONFIG secret. Node is already # installed in the verify job, so use it (no python on the slim image). node -e ' const fs = require("fs"); const txt = fs.readFileSync("deploy/havenllo.yaml", "utf8"); const docs = txt.split(/\n---\n/).map(s => s.trim()).filter(Boolean); const kinds = docs.map(d => { const m = d.match(/^kind:\s*(\S+)/m); return m ? m[1] : null; }); const req = ["PersistentVolumeClaim", "Deployment", "Service", "Ingress"]; const miss = req.filter(k => !kinds.includes(k)); console.log("docs:", docs.length, "kinds:", kinds.join(", ")); if (miss.length) { console.error("MISSING KINDS:", miss.join(", ")); process.exit(1); } ' build: name: Build and push image needs: verify runs-on: runner-slim-amd64 steps: - name: Check out source uses: actions/checkout@v4 - name: Build and push multi-architecture image uses: https://git.ivanch.me/ivanch/pipeline-actions/build-and-push@main with: image: git.ivanch.me/ivanch/havenllo image_tag: latest registry_password: ${{ secrets.REGISTRY_PASSWORD }} ssh_key: ${{ secrets.SSH_KEY_DOCKERBUILD }} deploy: name: Apply and restart Havenllo needs: build runs-on: runner-slim-amd64 steps: - name: Check out source uses: actions/checkout@v4 - name: Apply Kubernetes manifest uses: https://git.ivanch.me/ivanch/pipeline-actions/kubectl-apply@main with: manifest: deploy/havenllo.yaml kube_config: ${{ secrets.KUBE_CONFIG }} - name: Restart deployment uses: https://git.ivanch.me/ivanch/pipeline-actions/deploy-restart@main with: deployment_name: havenllo namespace: default kube_config: ${{ secrets.KUBE_CONFIG }}