Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 61 additions & 11 deletions .github/workflows/manual-publish-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@ env:
IMAGE_NAME: mtthwcmpbll/turtorial

jobs:
publish:
runs-on: ubuntu-latest
build-image:
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
arch: amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm
arch: arm64
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -22,11 +31,16 @@ jobs:
id: slug
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
with:
java-version: '25'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
cache: 'maven'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Native Binary
run: ./mvnw clean package -Pnative,prod -DskipTests

- name: Log in to the Container registry
uses: docker/login-action@v3
Expand All @@ -35,13 +49,49 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push Docker image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.native
build-args: BINARY=prebuilt
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}
platforms: linux/amd64, linux/arm64
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}-${{ matrix.arch }}

create-manifest:
needs: [build-image]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Get short SHA
id: slug
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Create Multi-Arch Manifest (latest)
run: |
docker buildx imagetools create -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}-amd64 \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}-arm64

- name: Create Multi-Arch Manifest (sha8)
run: |
docker buildx imagetools create -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }} \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}-amd64 \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}-arm64
119 changes: 98 additions & 21 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,17 @@ jobs:
run: npm run test
working-directory: src/main/frontend

release:
prepare-release:
runs-on: ubuntu-latest
needs: [test-backend, test-frontend]
outputs:
release-version: ${{ steps.calculate_version.outputs.release_version }}
sha8: ${{ steps.slug.outputs.sha8 }}
steps:
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
with:
Expand All @@ -85,7 +82,7 @@ jobs:
node-version: '24'
cache: 'npm'
cache-dependency-path: src/main/frontend/package-lock.json

- name: Get short SHA
id: slug
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT
Expand All @@ -97,46 +94,126 @@ jobs:
GITHUB_ACTOR: ${{ github.actor }}
run: |
VERSION=$(python3 .github/workflows/scripts/get-next-version.py ${{ inputs.release_type }})
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV
echo "release_version=$VERSION" >> $GITHUB_OUTPUT
echo "Next version: $VERSION"

- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Update POM to Release Version
run: mvn -B versions:set -DnewVersion=${{ env.RELEASE_VERSION }} -DgenerateBackupPoms=false
run: mvn -B versions:set -DnewVersion=${{ steps.calculate_version.outputs.release_version }} -DgenerateBackupPoms=false

- name: Build and Publish to Maven
env:
MAVEN_USERNAME: ${{ github.actor }}
MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: mvn -B deploy -Pprod

build-image:
needs: [prepare-release]
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
arch: amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm
arch: arm64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4

- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
with:
java-version: '25'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
cache: 'maven'

- name: Update POM to Release Version
run: mvn -B versions:set -DnewVersion=${{ needs.prepare-release.outputs.release-version }} -DgenerateBackupPoms=false

- name: Build Native Binary
run: ./mvnw clean package -Pnative,prod -DskipTests

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.IMAGE_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and Push Docker Image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.native
build-args: BINARY=prebuilt
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.slug.outputs.sha8 }}
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}
platforms: linux/amd64, linux/arm64
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.sha8 }}-${{ matrix.arch }}
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.release-version }}-${{ matrix.arch }}

create-manifest:
needs: [prepare-release, build-image]
runs-on: ubuntu-latest
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.IMAGE_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Create Multi-Arch Manifest (latest)
run: |
docker buildx imagetools create -t ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.sha8 }}-amd64 \
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.sha8 }}-arm64

- name: Create Multi-Arch Manifest (sha8)
run: |
docker buildx imagetools create -t ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.sha8 }} \
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.sha8 }}-amd64 \
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.sha8 }}-arm64

- name: Create Multi-Arch Manifest (release version)
run: |
docker buildx imagetools create -t ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.release-version }} \
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.release-version }}-amd64 \
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.release-version }}-arm64

finalize-release:
needs: [prepare-release, create-manifest]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}

- name: Set up JDK 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
cache: 'maven'

- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Calculate Next Snapshot Version
id: next_snapshot
run: |
IFS='.' read -r major minor patch <<< "${{ env.RELEASE_VERSION }}"
IFS='.' read -r major minor patch <<< "${{ needs.prepare-release.outputs.release-version }}"
NEXT_PATCH=$((patch + 1))
NEXT_SNAPSHOT="${major}.${minor}.${NEXT_PATCH}-SNAPSHOT"
echo "NEXT_SNAPSHOT=$NEXT_SNAPSHOT" >> $GITHUB_ENV
Expand All @@ -147,5 +224,5 @@ jobs:

- name: Commit and Push
run: |
git commit -am "Releasing version ${{ env.RELEASE_VERSION }}"
git commit -am "Releasing version ${{ needs.prepare-release.outputs.release-version }}"
git push
4 changes: 3 additions & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
fileignoreconfig:
- filename: .github/workflows/manual-publish-image.yml
checksum: 3eec99c37eae7cbd91743e7b266570b8be0c69b060abbd92951ae2383778cf3a
- filename: .github/workflows/release.yml
checksum: 5fc68c655ea8e84be2711ce3aef887505c98b1b0fb62f4cda642c8aaf7a7039a
checksum: cb5291091a8847e40b2f2050c5530c68f41255e9f59631ce03055ca746626070
- filename: backend.log
checksum: 0181e4eeae0ab15fe8369040796ba9fd135bbe90e7bd1f3e31fff736e0175c12
- filename: src/main/frontend/package-lock.json
Expand Down
25 changes: 14 additions & 11 deletions Dockerfile.native
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
# Stage 1: Build the native image inside a Linux GraalVM container
FROM ghcr.io/graalvm/native-image-community:25 AS builder
# Build arg to select binary source: "build" (compile from source) or "prebuilt" (use pre-built binary)
ARG BINARY=build

# Builder stage — compiles native image from source (local dev, default)
FROM ghcr.io/graalvm/native-image-community:25 AS build
WORKDIR /build

# Copy Maven wrapper and pom.xml first for better layer caching
COPY .mvn .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline -B

# Copy source code
COPY src src
RUN ./mvnw clean package -Pnative,prod -DskipTests && cp target/turtorial /turtorial

# Prebuilt stage — copies binary from build context (CI)
FROM scratch AS prebuilt
COPY target/turtorial /turtorial

# Build the native image with frontend assets (prod profile builds frontend via frontend-maven-plugin)
RUN ./mvnw clean package -Pnative,prod -DskipTests
# Select binary source based on ARG (BuildKit skips unused stages)
FROM ${BINARY} AS binary

# Stage 2: Runtime base image with tools for the tutorial environment
# Runtime base image with tools for the tutorial environment
FROM ubuntu:24.04 AS base

# Set install locations
Expand Down Expand Up @@ -50,8 +53,8 @@ RUN mkdir -p /home/turtorial/.ssh \
# Create app directory
WORKDIR /app

# Copy the native binary from the builder stage (now a Linux binary)
COPY --from=builder /build/target/turtorial /app/turtorial
# Copy the native binary from the selected source
COPY --from=binary /turtorial /app/turtorial

# Change ownership of the app directory
RUN chown -R turtorial:turtorial /app
Expand Down