add annotations to container image #19
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 | |
env: | |
APP_NAME: fosdem-dl | |
GRAALVM_VERSION: 23.0.0 | |
HEAP_SIZE_AT_BUILD_TIME: '-R:MaximumHeapSizePercent=50' | |
JAVA_VERSION: 21 | |
OPTIMIZATION_LEVEL: '-O2' | |
jobs: | |
shared-outputs: | |
name: Shared outputs | |
runs-on: ubuntu-latest | |
outputs: | |
app_version: ${{ steps.set_outputs.outputs.app_version }} | |
is_prerelease: ${{ steps.set_outputs.outputs.is_prerelease }} | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: 🔧 Setup Babashka | |
uses: DeLaGuardo/[email protected] | |
with: | |
bb: 'latest' | |
# Note: if in bb.edn we declare a version of a pod using :path instead of | |
# :version (e.g. we have to do this when the pod is not registered on the | |
# pod registry), we can't run Babashka commands until we have downloaded | |
# that pod manually and moved it to the :path specified in bb.edn. | |
- name: Set job outputs | |
id: set_outputs | |
run: | | |
APP_VERSION=$(bb -e '(-> (slurp "deps.edn") edn/read-string :aliases :neil :project :version)' | tr -d '"') | |
echo "app_version=$APP_VERSION" >> $GITHUB_OUTPUT | |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then | |
echo "is_prerelease=false" >> $GITHUB_OUTPUT | |
else | |
echo "is_prerelease=true" >> $GITHUB_OUTPUT | |
fi | |
- name: Log job outputs | |
run: | | |
echo "app_version is ${{ steps.set_outputs.outputs.app_version }}" | |
echo "is_prerelease is ${{ steps.set_outputs.outputs.is_prerelease }}" | |
# echo "pod_jackdbd_jsoup_path_linux is ${{ steps.set_outputs.outputs.pod_jackdbd_jsoup_path_linux }}" | |
# echo "pod_jackdbd_jsoup_path_macos is ${{ steps.set_outputs.outputs.pod_jackdbd_jsoup_path_macos }}" | |
uberjar: | |
name: Uberjar | |
needs: [shared-outputs] | |
runs-on: ubuntu-latest | |
env: | |
APP_VERSION: ${{ needs.shared-outputs.outputs.app_version }} | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: 🔧 Setup Clojure CLI and Babashka | |
uses: DeLaGuardo/[email protected] | |
with: | |
cli: 'latest' | |
bb: 'latest' | |
# Downloading the pod manually is only necessary if in bb.edn we declare | |
# the pod with :path instead of :version (e.g. when we want a version of | |
# the pod that is not registered on pod registry). | |
# This action uses the GitHub CLI. | |
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-github-cli-in-workflows | |
# - name: ⬇️ Download com.github.jackdbd/pod-jackdbd-jsoup | |
# env: | |
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
# run: ./download_pod_jackdbd_jsoup.sh | |
- name: 📦 Build a Babashka uberjar | |
run: bb build:bb-uber | |
- name: "CLI talks --help" | |
run: bb target/${{env.APP_NAME }}-${{ env.APP_VERSION }}.jar talks --help | |
- name: "CLI tracks --help" | |
run: bb target/${{env.APP_NAME }}-${{ env.APP_VERSION }}.jar tracks --help | |
- name: ⬆️ Upload Babashka uberjar | |
uses: actions/upload-artifact@v4 | |
with: | |
name: bb-uberjar | |
path: target/${{ env.APP_NAME }}-${{ env.APP_VERSION }}.jar | |
if-no-files-found: error | |
- name: 📦 Build normal uberjar | |
run: | | |
clojure -T:build clean | |
clojure -T:build uber | |
- name: ⬆️ Upload uberjar | |
uses: actions/upload-artifact@v4 | |
with: | |
name: uberjar | |
path: target/${{ env.APP_NAME }}-${{ env.APP_VERSION }}-standalone.jar | |
if-no-files-found: error | |
test: | |
name: Test | |
needs: [] | |
runs-on: ubuntu-latest | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: 🔧 Setup Babashka | |
uses: DeLaGuardo/[email protected] | |
with: | |
bb: 'latest' | |
- name: 🔍 Run all tests | |
run: bb test_runner.clj | |
# https://github.com/liquidz/babashka-test-action/ | |
# - name: Run babashka-test-action | |
# uses: liquidz/babashka-test-action@v1 | |
# with: | |
# source-paths: 'src' | |
# test-paths: 'test' | |
# test-file-pattern: '_test.clj$' | |
container-image: | |
name: Container image | |
needs: [shared-outputs] | |
runs-on: ubuntu-latest | |
env: | |
REGISTRY: ghcr.io | |
IMAGE_NAME: ${{ github.repository }} | |
APP_VERSION: ${{ needs.shared-outputs.outputs.app_version }} | |
permissions: | |
contents: read | |
packages: write | |
attestations: write | |
id-token: write | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
# - name: 🔧 Setup Clojure CLI and Babashka | |
# uses: DeLaGuardo/[email protected] | |
# with: | |
# cli: 'latest' | |
# bb: 'latest' | |
# - name: 🐋 Build container image | |
# run: bb container:build | |
# # Print a few commands to double check that the CLI is working as expected | |
# - run: bb container:cli help | |
# - run: bb container:cli talks --help | |
# - run: bb container:cli tracks --help | |
# https://github.com/marketplace/actions/docker-login | |
- name: Log in to the Container registry | |
uses: docker/[email protected] | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
# https://github.com/marketplace/actions/docker-metadata-action | |
- name: Extract metadata (tags, labels) for Docker | |
id: meta | |
uses: docker/[email protected] | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
annotations: | | |
org.opencontainers.image.revision=${{ github.sha }} | |
# I don't know how to tell docker-metadata-action to extract the | |
# license, so I set it here explicitly. | |
# https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions/ | |
labels: | | |
org.opencontainers.image.description="CLI to download videos and slides from FOSDEM websites" | |
org.opencontainers.image.documentation=https://github.com/jackdbd/fosdem-dl/ | |
org.opencontainers.image.licenses=MIT | |
# https://github.com/marketplace/actions/build-and-push-docker-images | |
- name: Build and push Docker image | |
id: push | |
uses: docker/[email protected] | |
with: | |
context: . | |
push: true | |
build-args: | | |
APP_NAME=${{env.APP_NAME }} | |
APP_VERSION=${{env.APP_VERSION }} | |
BB_VERSION=1.4.192 | |
CREATED_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | |
JSOUP_POD_VERSION=0.4.0 | |
annotations: ${{ steps.meta.outputs.annotations }} | |
labels: ${{ steps.meta.outputs.labels }} | |
tags: ${{ steps.meta.outputs.tags }} | |
# https://github.com/marketplace/actions/attest-build-provenance | |
- name: Generate artifact attestation | |
uses: actions/attest-build-provenance@v1 | |
with: | |
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} | |
subject-digest: ${{ steps.push.outputs.digest }} | |
push-to-registry: true | |
linux-amd64-binary: | |
name: Linux amd64 binary | |
needs: [shared-outputs, uberjar] | |
runs-on: ubuntu-latest | |
env: | |
APP_VERSION: ${{ needs.shared-outputs.outputs.app_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-musl: true # Use musl to build a statically compiled binary (Linux only) | |
native-image-pr-reports: true | |
version: ${{ env.GRAALVM_VERSION }} | |
- name: 🔧 Setup Babashka | |
uses: DeLaGuardo/[email protected] | |
with: | |
bb: 'latest' | |
# Calling `bb tasks` is enough to let Babashka download all pods declared | |
# in the bb.edn file. Babashka downloads only the pod binary files that | |
# were compiled for the combination of OS & arch of this GitHub runner. | |
- run: bb tasks | |
- name: ⬇️ Download uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: uberjar | |
- name: Move uberjar to target/ | |
run: | | |
mkdir target | |
mv ${{ env.APP_NAME }}-${{ env.APP_VERSION }}-standalone.jar target/ | |
# Troubleshooting: Babashka pods should be somewhere here. | |
# - run: ls -1 -R ~/.babashka | |
- name: 📦 Compile uberjar to x86_64-linux binary with GraalVM native-image | |
run: ./script/compile.sh | |
- run: ls -1 -R | |
- name: ⬆️ Upload Linux amd64 binary | |
uses: actions/upload-artifact@v4 | |
with: | |
name: linux-amd64-binary | |
path: ${{ env.APP_NAME }} | |
if-no-files-found: error | |
macos-aarch64-binary: | |
name: macOS aarch64 binary | |
needs: [shared-outputs, uberjar] | |
runs-on: macos-latest | |
env: | |
APP_VERSION: ${{ needs.shared-outputs.outputs.app_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 Babashka | |
uses: DeLaGuardo/[email protected] | |
with: | |
bb: 'latest' | |
# We let Babashka download the pod for this OS & architecture. | |
- run: bb tasks | |
# - run: ls -1 -R ~/.babashka | |
- name: ⬇️ Download uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: uberjar | |
# TODO: bundle pod-jackdbd-jsoup when building with GraalVM native-image | |
- name: 📦 Compile uberjar to AArch64-macOS binary with GraalVM native-image | |
run: | | |
native-image -jar ${{ env.APP_NAME }}-${{ env.APP_VERSION }}-standalone.jar ${{ env.APP_NAME }} \ | |
'-H:ResourceConfigurationFiles=resource-config.json' \ | |
'-H:+UnlockExperimentalVMOptions' \ | |
'--gc=serial' \ | |
${{ env.HEAP_SIZE_AT_BUILD_TIME }} \ | |
${{ env.OPTIMIZATION_LEVEL }} \ | |
'-march=armv8-a' \ | |
'--initialize-at-run-time=fosdem_dl.cli' \ | |
'--native-image-info' \ | |
'--no-fallback' \ | |
'--verbose' | |
- name: ⬆️ Upload macOS aarch64 binary | |
uses: actions/upload-artifact@v4 | |
with: | |
name: macos-aarch64-binary | |
path: ${{ env.APP_NAME }} | |
if-no-files-found: error | |
github-release: | |
name: GitHub release | |
if: ${{ github.event_name != 'pull_request' }} | |
needs: [shared-outputs, uberjar, container-image, linux-amd64-binary, macos-aarch64-binary] | |
runs-on: ubuntu-latest | |
env: | |
APP_VERSION: ${{ needs.shared-outputs.outputs.app_version }} | |
IS_PRERELEASE: ${{ needs.shared-outputs.outputs.is_prerelease }} | |
permissions: | |
contents: write | |
steps: | |
- name: 🛎️ Checkout | |
uses: actions/checkout@v4 | |
- name: ⬇️ Download uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: uberjar | |
- name: ⬇️ Download bb-uberjar | |
uses: actions/download-artifact@v4 | |
with: | |
name: bb-uberjar | |
- name: ⬇️ Download linux-amd64-binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: linux-amd64-binary | |
- run: mv fosdem-dl linux-amd64-binary | |
- name: ⬇️ Download macos-aarch64-binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: macos-aarch64-binary | |
- run: mv fosdem-dl macos-aarch64-binary | |
- name: 📦 Create archives for all assets to be included in the GitHub release | |
run: | | |
mv linux-amd64-binary fosdem-dl && zip "${{ env.APP_NAME }}-${{ env.APP_VERSION }}-linux-amd64.zip" fosdem-dl && rm fosdem-dl | |
mv macos-aarch64-binary fosdem-dl && zip "${{ env.APP_NAME }}-${{ env.APP_VERSION }}-macos-aarch64.zip" fosdem-dl && rm fosdem-dl | |
# Troubleshooting: do we have every assets we want to include in the GitHub release? | |
- run: ls -la | |
# https://github.com/marketplace/actions/gh-release | |
- name: Add uberjar to GitHub release | |
uses: softprops/action-gh-release@v2 | |
id: github_release | |
with: | |
body_path: ${{ github.workspace }}/docs/release-body.md | |
# draft: true | |
fail_on_unmatched_files: true | |
# TODO: add all binaries compiled with GraalVM native-image | |
files: | | |
${{ env.APP_NAME }}-${{ env.APP_VERSION }}.jar | |
${{ env.APP_NAME }}-${{ env.APP_VERSION }}-standalone.jar | |
${{ env.APP_NAME }}-${{ env.APP_VERSION }}-linux-amd64.zip | |
${{ env.APP_NAME }}-${{ env.APP_VERSION }}-macos-aarch64.zip | |
# body is prepended to these automatically generated release notes. | |
# See here for how to configure these release notes: | |
# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes | |
generate_release_notes: true | |
name: v${{ env.APP_VERSION }} | |
prerelease: ${{ env.IS_PRERELEASE }} | |
tag_name: v${{ env.APP_VERSION }} |