Skip to content

Update CI

Update CI #272

Workflow file for this run

name: πŸ—οΈ Build
# Trigger this workflow when changes happen to our core directories
on:
push:
paths:
- "engine/**" # Our Rust backend
- "web/**" # Our web frontend
- ".github/workflows/build.yaml"
# Set up some global variables we'll use throughout
env:
REGISTRY: ghcr.io
IMAGE_NAME: v3xlabs/v3x-property/engine
BINARY_NAME: v3x-property-engine
DOCKER_BUILDKIT: 1 # Enable BuildKit
COMPOSE_DOCKER_CLI_BUILD: 1
jobs:
# πŸ¦€ First job: Build our Rust backend for multiple architectures
build-engine:
strategy:
matrix:
platform:
- arch: x86_64-unknown-linux-musl
docker: linux/amd64
- arch: aarch64-unknown-linux-musl
docker: linux/arm64
timeout-minutes: 20 # Prevent hanging builds
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
# Set up Rust with the specific target we need
- name: Install Rust
run: rustup toolchain install stable --profile minimal --no-self-update
# Speed up builds by caching dependencies
- name: Cache Rust
uses: Swatinem/rust-cache@v2
with:
workspaces: engine
key: ${{ matrix.platform.arch }}
# Install cross
- name: Install cross
run: cargo install cross
# πŸ”¨ Build our static binary
- name: Build Rust binary
working-directory: ./engine
env:
BINARY_NAME: ${{ env.BINARY_NAME }}
SQLX_OFFLINE: true # Use prepared SQL queries
run: cross build --target ${{ matrix.platform.arch }} --release
# πŸ“¦ Save our binary for later
- name: Upload built binary as artifact
uses: actions/upload-artifact@v4
with:
name: engine-${{ matrix.platform.arch }}
path: engine/target/${{ matrix.platform.arch }}/release/${{ env.BINARY_NAME }}
retention-days: 1 # Save storage by cleaning up quickly
compression-level: 9 # Maximum compression
# 🌐 Second job: Build our web frontend
build-web:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
# Get our Node.js tools ready
- name: Install Tools & Dependencies
uses: ./.github/actions/install
# Build the web assets
- name: Build
working-directory: ./web
run: NODE_ENV=production pnpm run build
# πŸ“¦ Save our web assets for later
- name: Upload built web as artifact
uses: actions/upload-artifact@v4
with:
name: web
path: web/dist
# 🐳 Third job: Package everything into a multi-arch Docker digests
docker-build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
needs: # Wait for other jobs to finish
- build-engine
- build-web
strategy:
matrix:
platform:
- arch: x86_64-unknown-linux-musl
docker: linux/amd64
- arch: aarch64-unknown-linux-musl
docker: linux/arm64
steps:
- name: Checkout
uses: actions/checkout@v4
# πŸ“₯ Grab our built binary
- name: Download built binary
uses: actions/download-artifact@v4
id: engine-binary
with:
name: engine-${{ matrix.platform.arch }}
path: artifacts
# πŸ“₯ Grab our web assets
- name: Download built web
uses: actions/download-artifact@v4
id: web
with:
name: web
path: artifacts/web
- name: Prepare artifacts
run: |
chmod 755 ./artifacts/v3x-property-engine
ls -la ./artifacts
# Set up QEMU for multi-arch builds
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Log into GitHub's container registry
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# πŸš€ Build and push multi-arch Docker image
- name: Build Docker digests
uses: docker/build-push-action@v6
id: build
with:
context: ./artifacts
file: ./engine/.build/Dockerfile.scratch
platforms: ${{ matrix.platform.docker }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
build-args: |
BINARY_PATH=./v3x-property-engine
WEBUI_PATH=./web
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.platform.arch }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
# 🐳 Final job: Merge multi-arch digests into a single artifact
docker-merge:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')
permissions:
contents: read
packages: write
attestations: write # For security attestations
id-token: write
needs: # Wait for other jobs to finish
- docker-build
steps:
- name: Checkout
uses: actions/checkout@v4
# πŸ“₯ Grab our digests
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
# Log into GitHub's container registry
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Extract metadata
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=edge
type=sha
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}