Skip to content

chore(actions): bump docker/setup-buildx-action from 3 to 4 #91

chore(actions): bump docker/setup-buildx-action from 3 to 4

chore(actions): bump docker/setup-buildx-action from 3 to 4 #91

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_call:
# Least-privilege: this workflow only reads the repo and runs tests.
permissions:
contents: read
jobs:
static-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: secret-scanning with gitleaks
env:
GITLEAKS_VERSION: 8.30.1
GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
run: |
set -euo pipefail
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" -o /tmp/gitleaks.tgz
echo "${GITLEAKS_SHA256} /tmp/gitleaks.tgz" | sha256sum -c -
tar xz -C /tmp -f /tmp/gitleaks.tgz
/tmp/gitleaks detect --source . --verbose --redact
- uses: actions/setup-node@v6
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Check licenses
run: npm exec -- license-checker-evergreen --failOn "GPL-2.0;GPL-3.0;AGPL-3.0"
- name: Security audit
run: npm audit --audit-level=high
- name: Syntax check
run: npm run check
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# engines is ">=22 <25". Node 22 is Maintenance LTS (EOL 2027-04-30);
# Node 24 is Active LTS. Self-hosters on either should get CI signal.
node-version: ['22', '24']
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
# tests/ uses the node:test runner with zero deps — no install needed.
- name: Syntax check
run: npm run check
- name: Run tests
run: npm test
- name: Audit npm package metadata
run: npm audit --audit-level=high
# Validates the optional self-host path: image builds, container starts,
# HEALTHCHECK passes, /api/health responds, /api/divider returns SVG.
# Independent of the Node matrix above because the runtime inside the
# image is pinned by the Dockerfile (node:22-slim).
#
# No untrusted GitHub event data flows into any `run:` step — every
# shell variable below is initialized inside the script.
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
tags: profilekit:ci
load: true
- name: Run container and verify /api/health + /api/divider
run: |
set -euo pipefail
docker run -d --name pkit -p 3000:3000 profilekit:ci
# Wait up to ~30s for Docker's HEALTHCHECK (defined in the
# Dockerfile) to flip to "healthy".
for i in $(seq 1 30); do
status=$(docker inspect --format='{{.State.Health.Status}}' pkit 2>/dev/null || echo "unknown")
echo "attempt $i: health=$status"
if [ "$status" = "healthy" ]; then break; fi
sleep 1
done
# Independent verification from the host — don't trust HEALTHCHECK
# alone in case the probe itself is misconfigured.
body=$(curl -sf http://localhost:3000/api/health)
echo "$body"
echo "$body" | grep -q '"ok": true'
# Real card endpoint — proves the route adapter is wired, not
# just /api/health.
ctype=$(curl -s -o /dev/null -w '%{content_type}' \
'http://localhost:3000/api/divider?style=line&width=400')
echo "divider ctype: $ctype"
echo "$ctype" | grep -q 'image/svg+xml'
docker logs pkit
docker rm -f pkit
ci:
needs: [static-checks, test, docker]
if: always()
runs-on: ubuntu-latest
steps:
- name: Aggregate result
run: |
if [ "${{ needs.static-checks.result }}" != "success" ] || \
[ "${{ needs.test.result }}" != "success" ] || \
[ "${{ needs.docker.result }}" != "success" ]; then
echo "::error::CI failed (static-checks=${{ needs.static-checks.result }}, test=${{ needs.test.result }}, docker=${{ needs.docker.result }})"
exit 1
fi
echo "All checks passed."