ci: set SNAPSHOT_SUFFIX when not on main branch #39
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: 'CI/CD' | |
on: | |
pull_request: | |
push: | |
branches: | |
- canary | |
- main | |
# GitHub hosted runners are available for Linux x64, Windows x64, and macOS (x64 and arm). | |
# https://docs.github.com/en/actions/using-github-hosted-runners/using-larger-runners/about-larger-runners#runner-images | |
# https://github.com/actions/runner-images | |
# There are other providers that offer ARM runners for Linux (e.g. WarpBuild). | |
# https://github.com/neysofu/awesome-github-actions-runners#list-of-providers | |
env: | |
GRAALVM_VERSION: 23.0.0 | |
HEAP_SIZE_AT_BUILD_TIME: '-R:MaxHeapSize=1024m' | |
JAVA_VERSION: 21 | |
OPTIMIZATION_LEVEL: '-O2' | |
POD_ID: pod.jackdbd.jsoup | |
POD_NAME: pod-jackdbd-jsoup | |
jobs: | |
build-uberjar: | |
name: Build uberjar | |
runs-on: ubuntu-latest | |
# strategy: | |
# matrix: | |
# os: [ubuntu-latest, macOS-latest, windows-latest] | |
# runs-on: ${{ matrix.os }} | |
outputs: | |
pod_version: ${{ steps.set_pod_version.outputs.pod_version }} | |
snapshot_suffix: ${{ steps.set_snapshot_suffix.outputs.snapshot_suffix }} | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: Set SNAPSHOT_SUFFIX (environment variable) and snapshot_suffix (job output) | |
id: set_snapshot_suffix | |
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables | |
run: | | |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then | |
echo "SNAPSHOT_SUFFIX=${GITHUB_SHA}" >> $GITHUB_ENV | |
else | |
echo "SNAPSHOT_SUFFIX=" >> $GITHUB_ENV | |
fi | |
echo "snapshot_suffix=$SNAPSHOT_SUFFIX" >> $GITHUB_OUTPUT | |
echo "SNAPSHOT_SUFFIX is ${{ env.SNAPSHOT_SUFFIX }}" | |
# https://github.com/marketplace/actions/github-action-for-graalvm | |
- name: 🔧 Setup GraalVM | |
uses: graalvm/setup-graalvm@v1 | |
with: | |
check-for-updates: true | |
distribution: graalvm-community | |
java-version: ${{ env.JAVA_VERSION }} | |
version: ${{ env.GRAALVM_VERSION }} | |
# It's important to install java before installing clojure tools, because | |
# clojure tools needs java exclusions: babashka, clj-kondo and cljstyle. | |
# https://github.com/marketplace/actions/setup-clojure | |
- name: 🔧 Setup Clojure tools | |
uses: DeLaGuardo/setup-clojure@12.5 | |
with: | |
cli: 'latest' # Clojure CLI based on tools.deps | |
bb: 'latest' # Babashka | |
# https://github.com/actions/cache | |
- name: Cache clojure dependencies | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.m2/repository | |
~/.gitlibs | |
~/.deps.clj | |
# List all files containing dependencies: | |
# key: cljdeps-${{ hashFiles('deps.edn') }} | |
key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }} | |
restore-keys: cljdeps- | |
# Example of an uberjar of a standard release: | |
# pod.jackdbd.jsoup-0.1.2-standalone.jar | |
# Example of an uberjar of a snapshot release: | |
# pod.jackdbd.jsoup-0.1.2-345-SNAPSHOT-standalone.jar | |
- name: Set POD_VERSION (environment variable) and pod_version (job output) | |
id: set_pod_version | |
run: | | |
PROJECT_VERSION=$(bb -e '(-> (slurp "deps.edn") edn/read-string :aliases :neil :project :version)' | tr -d '"') | |
if [ -z "${SNAPSHOT_SUFFIX}" ]; then | |
POD_VERSION=$PROJECT_VERSION | |
else | |
POD_VERSION="${PROJECT_VERSION}-${SNAPSHOT_SUFFIX}" | |
fi | |
echo "POD_VERSION=$POD_VERSION" >> $GITHUB_ENV | |
echo "pod_version=$POD_VERSION" >> $GITHUB_OUTPUT | |
echo "POD_VERSION is ${{ env.POD_VERSION }}" | |
- name: 📦 Compile pod into an uberjar | |
run: | | |
if [ -n "${SNAPSHOT_SUFFIX}" ]; then | |
clojure -T:build uber :snapshot-suffix ${{ env.SNAPSHOT_SUFFIX }} | |
else | |
clojure -T:build uber | |
fi | |
- name: ⬆️ Upload uberjar | |
uses: actions/upload-artifact@v4 | |
with: | |
name: uberjar | |
path: target/${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar | |
linux: | |
name: Compile ubuntu-latest-x86_64-binary, Test | |
runs-on: ubuntu-latest | |
needs: [build-uberjar] | |
env: | |
POD_VERSION: ${{ needs.build-uberjar.outputs.pod_version }} | |
SNAPSHOT_SUFFIX: ${{ needs.build-uberjar.outputs.snapshot_suffix }} | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
# https://github.com/marketplace/actions/github-action-for-graalvm | |
- name: 🔧 Setup GraalVM | |
uses: graalvm/setup-graalvm@v1 | |
with: | |
check-for-updates: true | |
distribution: graalvm-community | |
java-version: ${{ env.JAVA_VERSION }} | |
native-image-job-reports: true | |
native-image-musl: true # Use musl to build a statically compiled binary (Linux only) | |
native-image-pr-reports: true | |
version: ${{ env.GRAALVM_VERSION }} | |
# It's important to install java before installing clojure tools, because | |
# clojure tools needs java exclusions: babashka, clj-kondo and cljstyle. | |
# https://github.com/marketplace/actions/setup-clojure | |
- name: 🔧 Setup Clojure tools | |
uses: DeLaGuardo/setup-clojure@12.5 | |
with: | |
cli: 'latest' # Clojure CLI based on tools.deps | |
bb: 'latest' # Babashka | |
- name: Cache clojure dependencies | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.m2/repository | |
~/.gitlibs | |
~/.deps.clj | |
# List all files containing dependencies: | |
# key: cljdeps-${{ hashFiles('deps.edn') }} | |
key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }} | |
restore-keys: cljdeps- | |
# This takes ~7 minutes both on my laptop and on GitHub Actions. Maybe look for an alternative. | |
# - name: 🛡️ Audit deps.edn dependencies | |
# run: clojure -M:clj-nvd check | |
- name: ⬇️ Download uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: uberjar | |
- name: 📦 Compile uberjar to x86_64-linux binary with GraalVM native-image | |
run: ./script/compile.sh | |
env: | |
BABASHKA_STATIC: true | |
BABASHKA_MUSL: true | |
# The tests expect the uberjar and the binary to be in a directory called "target" | |
- name: Copy the uberjar and the binary to the target directory | |
run: | | |
mkdir target | |
cp ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar target/${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar | |
cp ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone target/${{ env.POD_NAME }} | |
- name: ⬆️ Upload the x86_64 Linux binary | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ubuntu-latest-x86_64-binary | |
path: target/${{ env.POD_NAME }} | |
- name: 🔍 Run all tests | |
run: clojure -X:test | |
macos: | |
name: Compile macos-latest-aarch64-binary, Test | |
runs-on: macOS-latest | |
needs: [build-uberjar] | |
env: | |
POD_VERSION: ${{ needs.build-uberjar.outputs.pod_version }} | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: 🔧 Setup GraalVM | |
uses: graalvm/setup-graalvm@v1 | |
with: | |
check-for-updates: true | |
distribution: graalvm-community | |
java-version: ${{ env.JAVA_VERSION }} | |
native-image-job-reports: true | |
native-image-pr-reports: true | |
version: ${{ env.GRAALVM_VERSION }} | |
- name: 🔧 Setup Clojure tools | |
uses: DeLaGuardo/setup-clojure@12.5 | |
with: | |
cli: 'latest' | |
- name: Cache clojure dependencies | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.m2/repository | |
~/.gitlibs | |
~/.deps.clj | |
key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }} | |
restore-keys: cljdeps- | |
- name: ⬇️ Download uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: uberjar | |
- name: 📦 Compile uberjar to AArch64-macOS binary with GraalVM native-image | |
# I tried setting -march=x86_64 and the GitHub hosted runner macos-latest | |
# gave me this error: | |
# On AArch64, only 'ARMV8_A', 'ARMV8_1_A', 'COMPATIBILITY', 'NATIVE' are available. | |
run: | | |
native-image \ | |
-jar ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar \ | |
'-H:ReflectionConfigurationFiles=reflection.json' \ | |
'-H:+ReportExceptionStackTraces' \ | |
'-J-Dclojure.compiler.direct-linking=true' \ | |
${{ env.HEAP_SIZE_AT_BUILD_TIME }} \ | |
${{ env.OPTIMIZATION_LEVEL }} \ | |
'-march=armv8-a' \ | |
'--initialize-at-build-time' \ | |
'--native-image-info' \ | |
'--no-fallback' \ | |
'--report-unsupported-elements-at-runtime' | |
# The tests expect the uberjar and the binary to be in a directory called "target" | |
- name: Copy the uberjar and the binary to the target directory | |
run: | | |
mkdir target | |
cp ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar target/${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar | |
cp ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone target/${{ env.POD_NAME }} | |
- name: ⬆️ Upload the aarch64 macOS binary | |
uses: actions/upload-artifact@v4 | |
with: | |
name: macos-latest-aarch64-binary | |
path: target/${{ env.POD_NAME }} | |
- name: 🔍 Run all tests | |
run: clojure -X:test | |
windows: | |
name: Compile windows-latest-x86_64-binary, Test | |
runs-on: windows-latest | |
needs: [build-uberjar] | |
env: | |
POD_VERSION: ${{ needs.build-uberjar.outputs.pod_version }} | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: 🔧 Setup GraalVM | |
uses: graalvm/setup-graalvm@v1 | |
with: | |
check-for-updates: true | |
distribution: graalvm-community | |
java-version: ${{ env.JAVA_VERSION }} | |
native-image-job-reports: true | |
native-image-pr-reports: true | |
version: ${{ env.GRAALVM_VERSION }} | |
- name: 🔧 Setup Clojure tools | |
uses: DeLaGuardo/setup-clojure@12.5 | |
with: | |
cli: 'latest' | |
- name: Cache clojure dependencies | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.m2/repository | |
~/.gitlibs | |
~/.deps.clj | |
key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }} | |
restore-keys: cljdeps- | |
- name: ⬇️ Download uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: uberjar | |
# See: https://github.com/babashka/pod-babashka-buddy/blob/main/script/compile.bat | |
- name: 📦 Compile uberjar to x86_64-windows binary with GraalVM native-image | |
run: > | |
native-image | |
-jar ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar | |
'-H:ReflectionConfigurationFiles=reflection.json' | |
'-H:+ReportExceptionStackTraces' | |
'-J-Dclojure.compiler.direct-linking=true' | |
${{ env.HEAP_SIZE_AT_BUILD_TIME }} | |
${{ env.OPTIMIZATION_LEVEL }} | |
'-march=x86-64-v3' | |
'--initialize-at-build-time' | |
'--native-image-info' | |
'--no-fallback' | |
'--report-unsupported-elements-at-runtime' | |
- name: Copy the uberjar and the binary to the target directory | |
run: | | |
mkdir target | |
move ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar target\\${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar | |
move "${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.exe" ".\\target\\${{ env.POD_NAME }}.exe" | |
shell: cmd | |
- name: ⬆️ Upload the x86_64 Windows binary | |
uses: actions/upload-artifact@v4 | |
with: | |
name: windows-latest-x86_64-binary | |
path: ".\\target\\${{ env.POD_NAME }}.exe" | |
- name: 🔍 Run all tests | |
run: clojure -X:test | |
release: | |
name: Release | |
if: ${{ github.event_name != 'pull_request' }} | |
needs: [build-uberjar, linux, macos, windows] | |
concurrency: deploy-group # Ensures that only a single instance of this job is running at any given time. | |
runs-on: ubuntu-latest | |
env: | |
POD_VERSION: ${{ needs.build-uberjar.outputs.pod_version }} | |
permissions: | |
contents: write | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: 🔧 Setup Clojure tools | |
uses: DeLaGuardo/setup-clojure@12.5 | |
with: | |
cli: 'latest' | |
bb: 'latest' | |
- name: 🌐 Publish to Clojars | |
env: | |
CLOJARS_USERNAME: jackdbd | |
CLOJARS_PASSWORD: ${{ secrets.CLOJARS_PASSWORD }} | |
run: | | |
if [ -n "${SNAPSHOT_SUFFIX}" ]; then | |
clojure -T:build uber :snapshot-suffix ${{ env.SNAPSHOT_SUFFIX }} | |
clojure -T:build deploy :snapshot-suffix ${{ env.SNAPSHOT_SUFFIX }} | |
else | |
clojure -T:build uber | |
clojure -T:build deploy | |
fi | |
- name: ⬇️ Download x86_64 Linux binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: ubuntu-latest-x86_64-binary | |
path: ubuntu-latest-x86_64 | |
- name: ⬇️ Download aarch64 macOS binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: macos-latest-aarch64-binary | |
path: macos-latest-aarch64 | |
- name: ⬇️ Download x86_64 Windows binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: windows-latest-x86_64-binary | |
path: windows-latest-x86_64 | |
# Troubleshooting: let's see if we have actually downloaded everything | |
# - run: ls -R | |
- name: 📦 Create zip archives for all binaries compiled with GraalVM native-image | |
run: | | |
pushd . && cd ubuntu-latest-x86_64 && zip "${{ env.POD_NAME }}-${{ env.POD_VERSION }}-ubuntu-latest-x86_64.zip" "pod-jackdbd-jsoup" && popd | |
pushd . && cd macos-latest-aarch64 && zip "${{ env.POD_NAME }}-${{ env.POD_VERSION }}-macos-latest-aarch64.zip" "pod-jackdbd-jsoup" && popd | |
pushd . && cd windows-latest-x86_64 && zip "${{ env.POD_NAME }}-${{ env.POD_VERSION }}-windows-latest-x86_64.zip" "pod-jackdbd-jsoup.exe" && popd | |
mv ubuntu-latest-x86_64/${{ env.POD_NAME }}-${{ env.POD_VERSION }}-ubuntu-latest-x86_64.zip . | |
mv macos-latest-aarch64/${{ env.POD_NAME }}-${{ env.POD_VERSION }}-macos-latest-aarch64.zip . | |
mv windows-latest-x86_64/${{ env.POD_NAME }}-${{ env.POD_VERSION }}-windows-latest-x86_64.zip . | |
# Troubleshooting: let's see if we have actually created all zip archives and moved them to the correct place | |
- run: ls -R | |
# https://github.com/marketplace/actions/gh-release | |
# See also this workflow that uses the bruceadams/get-release action: | |
# https://github.com/juji-io/datalevin/blob/master/.github/workflows/release.binaries.yml | |
# https://github.com/bruceadams/get-release | |
- name: 🚀 Create GitHub release | |
uses: softprops/action-gh-release@v2 | |
id: github_release | |
with: | |
body: | | |
This is a release of **${{ env.POD_NAME }}** version `${{ env.POD_VERSION }}`. | |
The pod is also [published as an uberjar to Clojars](https://clojars.org/com.github.jackdbd/pod.jackdbd.jsoup). | |
draft: true | |
fail_on_unmatched_files: true | |
files: | | |
${{ env.POD_NAME }}-${{ env.POD_VERSION }}-macos-latest-aarch64.zip | |
${{ env.POD_NAME }}-${{ env.POD_VERSION }}-ubuntu-latest-x86_64.zip | |
${{ env.POD_NAME }}-${{ env.POD_VERSION }}-windows-latest-x86_64.zip | |
generate_release_notes: false # TODO: decide whether to use this or not | |
name: v${{ env.POD_VERSION }} | |
prerelease: true # maybe if SNAPSHOT is true set this to true as well | |
tag_name: v${{ env.POD_VERSION }} | |
# ATTENTION: the order of `steps.github_release.outputs.assets` depends on the order of the `files` defined in the `github_release` step. | |
# https://github.com/marketplace/actions/gh-release#outputs | |
- name: 📄 Create manifest.edn for Babashka pod registry | |
run: | | |
RELEASE_URL=${{ steps.github_release.outputs.url }} | |
RELEASE_ID=${{ steps.github_release.outputs.id }} | |
UPLOAD_URL=${{ steps.github_release.outputs.upload_url }} | |
ASSETS=${{ steps.github_release.outputs.assets }} | |
MACOS_LATEST_AARCH64_ZIP_URL=${{ fromJSON(steps.github_release.outputs.assets)[0].browser_download_url }} | |
UBUNTU_LATEST_x86_64_ZIP_URL=${{ fromJSON(steps.github_release.outputs.assets)[1].browser_download_url }} | |
WINDOWS_LATEST_x86_64_ZIP_URL=${{ fromJSON(steps.github_release.outputs.assets)[2].browser_download_url }} | |
echo "RELEASE_URL is $RELEASE_URL" | |
echo "MACOS_LATEST_AARCH64_ZIP_URL is $MACOS_LATEST_AARCH64_ZIP_URL" | |
echo "UBUNTU_LATEST_x86_64_ZIP_URL is $UBUNTU_LATEST_x86_64_ZIP_URL" | |
echo "WINDOWS_LATEST_x86_64_ZIP_URL is $WINDOWS_LATEST_x86_64_ZIP_URL" | |
bb bb/manifest.bb --license MIT --pod-id com.github.jackdbd/pod.jackdbd.jsoup --version ${{ env.POD_VERSION }} --uberjar $UBERJAR_URL --linux-x86_64 $UBUNTU_LATEST_x86_64_ZIP_URL --macos-aarch64 $MACOS_LATEST_AARCH64_ZIP_URL --windows-x86_64 $WINDOWS_LATEST_x86_64_ZIP_URL | |
echo "Here is the manifest.edn generated" | |
cat manifest.edn | |
- name: ⬆️ Upload manifest.edn (TODO Download it and make a PR on Babashka pod registry?) | |
uses: actions/upload-artifact@v4 | |
with: | |
name: manifest-edn | |
path: manifest.edn |