diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..aabb884 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,87 @@ +name: build + +on: + push: + branches: [main] + tags: ['v*'] + +env: + REGISTRY: harbor.pmagnus.cloud + IMAGE: harbor.pmagnus.cloud/btcprice/btcprice + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: pip + cache-dependency-path: | + requirements.txt + requirements-dev.txt + + - name: Test + run: | + python -m pip install -r requirements-dev.txt + python -m pytest tests/ + + - name: Generate immutable tags + id: tags + shell: bash + run: | + set -euo pipefail + SHA=$(git rev-parse --short HEAD) + case "$GITHUB_REF" in + refs/tags/v*) VERSION="${GITHUB_REF_NAME#v}" ;; + *) VERSION="main-$(date -u +%Y%m%d%H%M%S)" ;; + esac + echo "sha=$SHA" >> "$GITHUB_OUTPUT" + echo "primary=$IMAGE:$VERSION" >> "$GITHUB_OUTPUT" + echo "qualified=$IMAGE:$VERSION-$SHA" >> "$GITHUB_OUTPUT" + + # anvil is not a NetBird peer. Host networking makes BuildKit use the + # runner host's pinned Harbor address; keep this until anvil is enrolled. + - uses: docker/setup-buildx-action@v3 + with: + driver-opts: network=host + + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.HARBOR_ROBOT_USER }} + password: ${{ secrets.HARBOR_ROBOT_TOKEN }} + + - uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64 + push: true + # Harbor blocks manifest reads until Trivy has approved the image. + # Push one tag first, then add the companion tag after the scan. + tags: ${{ steps.tags.outputs.primary }} + build-args: | + BUILD_SHA=${{ steps.tags.outputs.sha }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max + + - name: Wait for Harbor policy, then add SHA tag + env: + PRIMARY: ${{ steps.tags.outputs.primary }} + QUALIFIED: ${{ steps.tags.outputs.qualified }} + run: | + for attempt in $(seq 1 60); do + if docker buildx imagetools inspect "$PRIMARY" >/dev/null 2>&1; then + docker buildx imagetools create --tag "$QUALIFIED" "$PRIMARY" + exit 0 + fi + echo "waiting for Harbor scan/pull policy ($attempt/60)" + sleep 10 + done + echo "Harbor did not approve $PRIMARY within 10 minutes" >&2 + exit 1 + + - name: Summary + run: echo "pushed ${{ steps.tags.outputs.primary }} and ${{ steps.tags.outputs.qualified }}" diff --git a/Dockerfile b/Dockerfile index 5cb9e66..ca8c42d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22-alpine AS css +FROM harbor.pmagnus.cloud/dockerhub-cache/library/node:22-alpine AS css WORKDIR /build COPY package.json package-lock.json ./ @@ -8,7 +8,7 @@ COPY app/ app/ COPY tailwind.config.js ./ RUN npm run css:build -FROM python:3.13-slim +FROM harbor.pmagnus.cloud/dockerhub-cache/library/python:3.13-slim WORKDIR /app COPY requirements.txt .