chore: bump version to 0.13.1 → 0.14.0 #60
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docker | |
| on: | |
| push: | |
| branches: [main] | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| - 'LICENSE' | |
| - '.gitignore' | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| jobs: | |
| # ── Lint & Typecheck ────────────────────────────────────────── | |
| code-quality: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| # version auto-read from packageManager field | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Typecheck | |
| run: pnpm typecheck | |
| - name: Lint | |
| run: pnpm lint | |
| # ── Build, test & publish ───────────────────────────────────── | |
| docker: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| # ── GHCR login (skipped on PRs) ─────────────────────────── | |
| - name: Log in to GHCR | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| if: github.event_name != 'pull_request' | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ghcr.io/${{ github.repository }} | |
| tags: | | |
| type=ref,event=branch | |
| type=raw,value=latest | |
| type=semver,pattern={{version}} | |
| type=sha,prefix=sha-,format=short | |
| # ── Test: build native platform, load, healthcheck ──────── | |
| - name: Build for testing | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| load: true | |
| tags: calino:test | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Start container | |
| run: | | |
| docker run -d --name calino-test \ | |
| -p 8080:8080 \ | |
| --tmpfs /tmp:rw,noexec,nosuid \ | |
| --health-cmd 'wget -qO- http://localhost:8080/ || exit 1' \ | |
| --health-interval 5s \ | |
| --health-timeout 3s \ | |
| --health-retries 5 \ | |
| calino:test | |
| - name: Wait for healthy | |
| run: | | |
| echo "Waiting for container to become healthy..." | |
| timeout 30 bash -c ' | |
| until docker inspect --format="{{.State.Health.Status}}" calino-test 2>/dev/null | grep -q healthy; do | |
| sleep 2 | |
| done | |
| ' | |
| echo "✅ Container is healthy" | |
| - name: Verify SPA response | |
| run: | | |
| # Root should return 200 with HTML | |
| STATUS=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/ || echo '000') | |
| if [ "$STATUS" != "200" ]; then | |
| echo "❌ Root returned $STATUS, expected 200" | |
| exit 1 | |
| fi | |
| echo "✅ Root returns 200" | |
| # SPA route should also return 200 (Caddy fallback) | |
| STATUS=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/week || echo '000') | |
| if [ "$STATUS" != "200" ]; then | |
| echo "❌ /week returned $STATUS, expected 200" | |
| exit 1 | |
| fi | |
| echo "✅ SPA route /week returns 200" | |
| # Verify security headers | |
| HEADERS=$(curl -s -I http://localhost:8080/ || echo '') | |
| for HEADER in "X-Frame-Options" "X-Content-Type-Options" "Referrer-Policy" "Permissions-Policy"; do | |
| if echo "$HEADERS" | grep -qi "$HEADER"; then | |
| echo "✅ $HEADER present" | |
| else | |
| echo "❌ $HEADER missing" | |
| exit 1 | |
| fi | |
| done | |
| # Verify server header is stripped (Caddy config removes it) | |
| if echo "$HEADERS" | grep -qi '^Server:'; then | |
| echo "❌ Server header present — should be stripped" | |
| exit 1 | |
| fi | |
| echo "✅ Server header stripped" | |
| - name: Dump logs on failure | |
| if: failure() | |
| run: docker logs calino-test | |
| - name: Cleanup | |
| if: always() | |
| run: docker rm -f calino-test | |
| # ── Publish: multi-arch push to GHCR ────────────────────── | |
| - name: Build & push multi-arch | |
| if: github.event_name != 'pull_request' | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |