|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +get_geant4_tag() { echo "11.4.0"; } # only one allowed |
| 5 | +get_gemc_tags() { echo "dev"; } |
| 6 | +get_cpu_architectures() { echo "arm64 amd64"; } # space separated list. |
| 7 | +get_runner() { |
| 8 | + local arch=$1 |
| 9 | + case "$arch" in |
| 10 | + "arm64") echo "ubuntu-24.04-arm" ;; |
| 11 | + "amd64") echo "ubuntu-latest" ;; |
| 12 | + *) |
| 13 | + echo "ERROR: unsupported arch $arch" >&2 |
| 14 | + return 2 |
| 15 | + ;; |
| 16 | + esac |
| 17 | +} |
| 18 | +lc() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]'; } # portable lowercasing |
| 19 | + |
| 20 | +# Single source of truth (order preserved) |
| 21 | +OS_VERSIONS=( |
| 22 | + "ubuntu=24.04" |
| 23 | + "fedora=40" |
| 24 | + "almalinux=9.4" |
| 25 | + "debian=12" |
| 26 | + "archlinux=latest" |
| 27 | +) |
| 28 | + |
| 29 | +# full sanitizers: |
| 30 | +# on macOS, LeakSanitizer (LSan) support is materially less uniform and |
| 31 | +# more fragile across toolchains and architectures than ASan/UBSan/TSan. |
| 32 | +# macos: address, thread, undefined |
| 33 | +# linux: address, thread, undefined, leak |
| 34 | +# |
| 35 | +# In the CI we first run one sanitizer at a time until all issues are solved |
| 36 | +# Then we can run them all |
| 37 | +get_sanitizers() { |
| 38 | + local choice_of_sanitizer="address" |
| 39 | + local baseos=$1 |
| 40 | + case "$baseos" in |
| 41 | + "macos") echo $choice_of_sanitizer ;; |
| 42 | + "ubuntu" | "fedora" | "almalinux" | "debian" | "archlinux") echo $choice_of_sanitizer ;; |
| 43 | + *) |
| 44 | + echo "ERROR: unsupported baseos $baseos" >&2 |
| 45 | + return 2 |
| 46 | + ;; |
| 47 | + esac |
| 48 | + |
| 49 | +} |
| 50 | + |
| 51 | +build_matrix_build() { |
| 52 | + |
| 53 | + local arch_list gemc_list |
| 54 | + arch_list="$(get_cpu_architectures)" |
| 55 | + gemc_list="$(get_gemc_tags)" |
| 56 | + |
| 57 | + local -a arch_tags gemc_tags |
| 58 | + read -r -a arch_tags <<<"$arch_list" |
| 59 | + read -r -a gemc_tags <<<"$gemc_list" |
| 60 | + |
| 61 | + g4v="$(get_geant4_tag)" |
| 62 | + |
| 63 | + local body="" sep="" pair os ver |
| 64 | + for cpuv in "${arch_tags[@]}"; do |
| 65 | + for gemcv in "${gemc_tags[@]}"; do |
| 66 | + for pair in "${OS_VERSIONS[@]}"; do |
| 67 | + os="${pair%%=*}" |
| 68 | + ver="${pair#*=}" |
| 69 | + |
| 70 | + local runner="$(get_runner "$cpuv")" |
| 71 | + |
| 72 | + local sanitizer_list="$(get_sanitizers "$os")" |
| 73 | + local sanitizer_tags |
| 74 | + read -r -a sanitizer_tags <<<"$sanitizer_list" |
| 75 | + for sanitizer in "${sanitizer_tags[@]}"; do |
| 76 | + |
| 77 | + # archlinux is amd64-only |
| 78 | + if [[ "$os" == "archlinux" && "$cpuv" == "arm64" ]]; then |
| 79 | + continue |
| 80 | + fi |
| 81 | + |
| 82 | + body+="${sep}{" |
| 83 | + body+="\"container\":\"ghcr.io/gemc/g4install:${g4v}-${os}-${ver}\"," |
| 84 | + body+="\"runner\":\"${runner}\"," |
| 85 | + body+="\"sanitizer\":\"${sanitizer}\"" |
| 86 | + body+="}" |
| 87 | + sep="," |
| 88 | + done |
| 89 | + done |
| 90 | + done |
| 91 | + done |
| 92 | + |
| 93 | + local json="{\"include\":[${body}]}" |
| 94 | + if command -v jq >/dev/null 2>&1; then |
| 95 | + # printf '%s' "$json" |
| 96 | + printf '%s' "$json" | jq -c . |
| 97 | + else |
| 98 | + printf '%s' "$json" |
| 99 | + fi |
| 100 | +} |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | +build_image_ref() { |
| 106 | + # Owner from env (Actions sets this). Fallback for local runs. |
| 107 | + local owner="${GITHUB_REPOSITORY_OWNER:-gemc}" |
| 108 | + |
| 109 | + # Repo name = LAST segment of GITHUB_REPOSITORY (strip any "owner/" prefix). |
| 110 | + # Fallback to a default if env is missing during local runs. |
| 111 | + local repo_full="${GITHUB_REPOSITORY:-gemc/src}" |
| 112 | + local repo="${repo_full##*/}" # strip anything up to and including the last slash |
| 113 | + |
| 114 | + # Lowercase both parts (GHCR requires lowercase) |
| 115 | + printf 'ghcr.io/%s/%s' "$(lc "$owner")" "$(lc "$repo")" |
| 116 | +} |
| 117 | + |
| 118 | +# the separate matrices are needed so that manifest is not run twice |
| 119 | +main() { |
| 120 | + local image_ref |
| 121 | + image_ref="$(build_image_ref)" |
| 122 | + |
| 123 | + if [[ -n "${GITHUB_OUTPUT:-}" ]]; then |
| 124 | + local DELIM_BUILD="MATRIX_BUILD_$(date +%s%N)" |
| 125 | + local DELIM_MANIFEST="MATRIX_MANIFEST_$(date +%s%N)" |
| 126 | + { |
| 127 | + echo "matrix_build<<$DELIM_BUILD" |
| 128 | + build_matrix_build |
| 129 | + echo "$DELIM_BUILD" |
| 130 | + |
| 131 | + echo "image=$image_ref" |
| 132 | + } >>"$GITHUB_OUTPUT" |
| 133 | + else |
| 134 | + echo "== matrix_sanitize ==" |
| 135 | + build_matrix_build |
| 136 | + echo |
| 137 | + fi |
| 138 | + |
| 139 | +} |
| 140 | + |
| 141 | +main "$@" |
0 commit comments