name: Native Image Release on: # Triggered by other workflows using workflow_call workflow_call: inputs: version: description: "Version to release" required: true type: string # Also allow manual triggering workflow_dispatch: inputs: version: description: "Version to release" required: true type: string jobs: build-and-upload: runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-latest arch: linux-amd64 - os: windows-latest arch: windows-amd64 - os: macos-13 arch: "darwin-amd64" - os: macos-latest arch: "darwin-arm64" timeout-minutes: 20 outputs: ubuntu: ${{ steps.set-output.outputs.ubuntu }} steps: - uses: actions/checkout@v4 - uses: graalvm/setup-graalvm@v1 with: java-version: "21" distribution: "graalvm-community" github-token: ${{ secrets.GITHUB_TOKEN }} cache: "maven" native-image-job-reports: "true" - name: Build MacOS Intel native if: matrix.arch == 'darwin-amd64' run: | echo "GRAALVM_HOME: $GRAALVM_HOME" echo "JAVA_HOME: $JAVA_HOME" java --version native-image -march=list mvn package -Pnative -DskipTests -Dnative.march="-march=x86-64" - name: Build MacOS Apple Silicon native if: matrix.arch == 'darwin-arm64' run: | echo "GRAALVM_HOME: $GRAALVM_HOME" echo "JAVA_HOME: $JAVA_HOME" java --version native-image -march=list mvn package -Pnative -DskipTests -Dnative.march="-march=armv8-a" - name: Build Windows native if: matrix.arch == 'windows-amd64' run: | echo "GRAALVM_HOME: %GRAALVM_HOME%" echo "JAVA_HOME: %JAVA_HOME%" java --version native-image.cmd -march=list mvn package -Pnative -DskipTests "-Dnative.march=-march=x86-64" - name: Build Linux native if: matrix.arch == 'linux-amd64' run: | echo "GRAALVM_HOME: $GRAALVM_HOME" echo "JAVA_HOME: $JAVA_HOME" java --version native-image -march=list mvn package -Pnative -DskipTests -Dnative.march="-march=x86-64" chmod +x core/target/restheart - name: Upload restheart-${{ matrix.arch }} native artifact uses: actions/upload-artifact@v4 with: name: restheart-${{ matrix.arch }} path: ${{ matrix.arch == 'windows-amd64' && 'core/target/restheart.exe' || 'core/target/restheart' }} overwrite: true - name: Upload restheart-${{ matrix.arch }} to Release uses: actions/github-script@v7 with: script: | const fs = require('fs').promises; const isWindows = '${{ matrix.os }}' === 'windows-latest'; const filePath = isWindows ? 'core/target/restheart.exe' : 'core/target/restheart'; const fileName = `restheart-${{ matrix.arch }}${isWindows ? '.exe' : ''}`; const releaseTag = '${{ inputs.version }}'; // Use the passed version input try { const content = await fs.readFile(filePath); const { data: releases } = await github.rest.repos.listReleases({ owner: context.repo.owner, repo: context.repo.repo }); const release = releases.find(r => r.tag_name === releaseTag); if (!release) { throw new Error(`Release with tag '${releaseTag}' not found.`); } // Check if an asset with the same name exists in the release const existingAsset = release.assets.find(asset => asset.name === fileName); if (existingAsset) { console.log(`Asset ${fileName} already exists. Deleting it...`); // Delete the existing asset await github.rest.repos.deleteReleaseAsset({ owner: context.repo.owner, repo: context.repo.repo, asset_id: existingAsset.id }); console.log(`Deleted asset ${fileName}`); } console.log(`Uploading ${fileName} to release ${releaseTag}...`); await github.rest.repos.uploadReleaseAsset({ owner: context.repo.owner, repo: context.repo.repo, release_id: release.id, name: fileName, data: content, headers: { 'content-type': 'application/octet-stream' } }); console.log(`Successfully uploaded ${fileName} to release ${releaseTag}`); } catch (error) { console.error('Error occurred:', error.message); process.exit(1); } env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Set Output for docker-publish-linux Job if: matrix.arch == 'linux-amd64' id: set-output run: echo "ubuntu=true" >> $GITHUB_OUTPUT docker-publish-linux: runs-on: ubuntu-latest needs: build-and-upload if: needs.build-and-upload.outputs.ubuntu == 'true' steps: - uses: actions/checkout@v4 - name: Download Binary Artifact uses: actions/download-artifact@v4 with: name: restheart-linux-amd64 path: core/target/restheart - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_TOKEN }} - name: Extract Version Components id: extract_version run: | MAJOR=$(echo "${{ inputs.version }}" | cut -d '.' -f 1) MINOR=$(echo "${{ inputs.version }}" | cut -d '.' -f 2) PATCH=$(echo "${{ inputs.version }}" | cut -d '.' -f 3) # Export the major, minor, and patch versions as environment variables echo "MAJOR=$MAJOR" >> $GITHUB_ENV echo "MINOR=$MINOR" >> $GITHUB_ENV echo "PATCH=$PATCH" >> $GITHUB_ENV - name: Build Docker Tags id: build_tags run: | # Construct all tags based on the MAJOR.MINOR.PATCH format TAGS="softinstigate/restheart:latest-native,softinstigate/restheart:${{ env.MAJOR }}-native,softinstigate/restheart:${{ env.MAJOR }}.${{ env.MINOR }}-native,softinstigate/restheart:${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.PATCH }}-native" echo "TAGS=$TAGS" >> $GITHUB_ENV - name: Build and Push multi-arch native Docker images uses: docker/build-push-action@v6 with: context: ./core/ file: ./core/Dockerfile.native platforms: | linux/amd64, linux/arm64, linux/ppc64le, linux/s390x push: true pull: true tags: ${{ env.TAGS }}