Skip to content

Build Docker Image

Build Docker Image #33

Workflow file for this run

name: Build Docker Image
on:
push:
branches: [main]
tags: ['v*']
paths-ignore:
- 'site/**'
- 'docs/**'
- 'samples/**'
- '*.md'
- 'LICENSE'
- '.gitleaks*'
- '.github/workflows/pages.yml'
- '.github/workflows/docs.yml'
workflow_dispatch:
schedule:
# Weekly vulnerability check (Mondays 9am UTC)
- cron: '0 9 * * 1'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/hone-money
jobs:
# Security scans run in parallel with each other and with builds
security-scan-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@1.92.0
- name: Cache cargo-audit binary
id: cache-cargo-audit
uses: actions/cache@v4
with:
path: ~/.cargo/bin/cargo-audit
key: cargo-audit-0.22.0
- name: Install cargo-audit
if: steps.cache-cargo-audit.outputs.cache-hit != 'true'
run: cargo install cargo-audit --version 0.22.0 --locked
- name: Rust dependency audit
run: cargo audit
security-scan-node:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: |
ui/package.json
ui/package-lock.json
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '24'
- name: Node dependency audit
working-directory: ui
run: npm audit --audit-level=high
build-backend-amd64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@1.92.0
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-amd64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-amd64-
- name: Install OpenSSL (for SQLCipher)
run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev
- name: Build backend
run: cargo build --release --bin hone
- name: Set executable permission
run: chmod +x target/release/hone
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: hone-x86_64-unknown-linux-gnu
path: target/release/hone
build-backend-arm64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@1.92.0
with:
targets: aarch64-unknown-linux-gnu
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-arm64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-arm64-
- name: Install cross
run: |
if ! command -v cross &> /dev/null; then
cargo install cross --git https://github.com/cross-rs/cross --tag v0.2.5
fi
- name: Build backend
run: cross build --release --bin hone --target aarch64-unknown-linux-gnu
- name: Set executable permission
run: chmod +x target/aarch64-unknown-linux-gnu/release/hone
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: hone-aarch64-unknown-linux-gnu
path: target/aarch64-unknown-linux-gnu/release/hone
build-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: ui/package-lock.json
- name: Install dependencies
working-directory: ui
run: npm ci
- name: Build frontend
working-directory: ui
run: npm run build
- name: Upload frontend
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: ui/dist
build-image:
# Wait for all builds AND security scans before pushing
needs: [security-scan-rust, security-scan-node, build-backend-amd64, build-backend-arm64, build-frontend]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
security-events: write
actions: read
steps:
- uses: actions/checkout@v4
- name: Download AMD64 binary
uses: actions/download-artifact@v4
with:
name: hone-x86_64-unknown-linux-gnu
path: ./binaries/amd64
- name: Download ARM64 binary
uses: actions/download-artifact@v4
with:
name: hone-aarch64-unknown-linux-gnu
path: ./binaries/arm64
- name: Download frontend
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: ./ui/dist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DHI (Docker Hardened Images)
uses: docker/login-action@v3
with:
registry: dhi.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Set binary permissions
run: |
chmod +x binaries/amd64/hone
chmod +x binaries/arm64/hone
- name: Build image (amd64 for scanning)
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.release
platforms: linux/amd64
load: true
tags: ${{ env.IMAGE_NAME }}:scan
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@0.33.1
with:
image-ref: ${{ env.IMAGE_NAME }}:scan
format: 'table'
severity: 'CRITICAL,HIGH'
trivyignores: .trivyignore
exit-code: '1'
- name: Full vulnerability report (check for newly fixed CVEs)
if: github.event_name == 'schedule'
uses: aquasecurity/trivy-action@0.33.1
with:
image-ref: ${{ env.IMAGE_NAME }}:scan
format: 'table'
severity: 'CRITICAL,HIGH'
- name: Build and push (multi-arch)
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.release
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}