diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2ac93e..12191ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,9 +14,15 @@ on: branches: - main +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} + CARGO_TERM_COLOR: always + RUSTFLAGS: -C link-arg=-fuse-ld=lld jobs: test: @@ -32,19 +38,18 @@ jobs: toolchain: "1.91" components: rustfmt, clippy - - name: Install protobuf compiler - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - - - name: Cache cargo registry - uses: actions/cache@v4 + - name: Cache apt packages + uses: awalsh128/cache-apt-pkgs-action@latest with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo- + packages: protobuf-compiler lld + version: 1.0 + + - name: Rust cache + uses: Swatinem/rust-cache@v2 + with: + shared-key: "rust-cache" + cache-on-failure: true + cache-all-crates: true - name: Check run: cargo check --release @@ -83,18 +88,29 @@ jobs: - name: Extract branch name id: branch - run: echo "name=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT + run: | + BRANCH_NAME=${GITHUB_REF#refs/heads/} + # Sanitize branch name for Docker tag (replace / with -) + SAFE_BRANCH=$(echo "$BRANCH_NAME" | sed 's/\//-/g') + echo "name=$SAFE_BRANCH" >> $GITHUB_OUTPUT - name: Build and push uses: docker/build-push-action@v6 with: context: . push: true + provenance: false + build-args: | + BUILDKIT_INLINE_CACHE=1 tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.branch.outputs.name }} - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} - cache-from: type=gha - cache-to: type=gha,mode=max + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }} + cache-from: | + type=gha,scope=build-branch + type=gha,scope=build-main + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + cache-to: type=gha,scope=build-branch,mode=max build-main: name: Build (Main) @@ -137,16 +153,24 @@ jobs: context: . platforms: linux/amd64 push: true + provenance: false build-args: | VERSION=${{ steps.version.outputs.version }} + BUILDKIT_INLINE_CACHE=1 tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-${{ steps.version.outputs.short_sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-${{ steps.version.outputs.timestamp }} - cache-from: type=gha - cache-to: type=gha,mode=max + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + cache-from: | + type=gha,scope=build-main + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + cache-to: | + type=gha,scope=build-main,mode=max + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max - name: Summary run: | @@ -197,14 +221,22 @@ jobs: context: . platforms: linux/amd64,linux/arm64 push: true + provenance: false build-args: | VERSION=${{ steps.version.outputs.version }} + BUILDKIT_INLINE_CACHE=1 tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha,scope=build-main + type=gha,scope=release + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + cache-to: | + type=gha,scope=release,mode=max + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max - name: Summary run: | diff --git a/.gitignore b/.gitignore index 4a93cb1..3364e96 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ data/ # OS .DS_Store Thumbs.db + +# Local scripts +monitor-deploy.sh diff --git a/Dockerfile b/Dockerfile index 1dd577e..806671b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,10 @@ +# syntax=docker/dockerfile:1.4 # Build stage FROM rust:1.83-alpine AS builder # Build arguments provided by Docker buildx ARG TARGETPLATFORM +ARG TARGETARCH ARG VERSION=0.1.0-unknown WORKDIR /app @@ -26,8 +28,12 @@ COPY proto ./proto # Create a dummy main.rs to build dependencies RUN mkdir src && echo "fn main() {}" > src/main.rs -# Build dependencies (cached layer) -RUN RUST_TARGET=$(cat /tmp/rust-target) && \ +# Build dependencies (cached layer) with BuildKit cache mounts +# Cache is separated by target architecture for multi-platform builds +RUN --mount=type=cache,id=cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry \ + --mount=type=cache,id=cargo-git-${TARGETARCH},target=/usr/local/cargo/git \ + --mount=type=cache,id=cargo-target-${TARGETARCH},target=/app/target \ + RUST_TARGET=$(cat /tmp/rust-target) && \ BUILD_VERSION="$VERSION" cargo build --release --target "$RUST_TARGET" # Remove dummy src @@ -36,8 +42,11 @@ RUN rm -rf src # Copy actual source code COPY src ./src -# Build the actual application -RUN RUST_TARGET=$(cat /tmp/rust-target) && \ +# Build the actual application with BuildKit cache mounts +RUN --mount=type=cache,id=cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry \ + --mount=type=cache,id=cargo-git-${TARGETARCH},target=/usr/local/cargo/git \ + --mount=type=cache,id=cargo-target-${TARGETARCH},target=/app/target \ + RUST_TARGET=$(cat /tmp/rust-target) && \ touch src/main.rs && \ BUILD_VERSION="$VERSION" cargo build --release --target "$RUST_TARGET" && \ cp "target/$RUST_TARGET/release/towerops-agent" /tmp/towerops-agent