Skip to content

Building hyakvnc-freesurfer-ubuntu22.04: #99

Building hyakvnc-freesurfer-ubuntu22.04:

Building hyakvnc-freesurfer-ubuntu22.04: #99

name: Build and Deploy Apptainer Container
run-name: "Building ${{ inputs.image_name }}:${{ inputs.image_tag }}"
on:
workflow_dispatch:
inputs:
image_name:
description: 'Name of the container to build and deploy'
required: true
type: string
image_tags:
description: 'Tags of the container to build and deploy'
required: false
default: 'latest'
type: string
base_image_tag:
description: 'Tag of the base image to use'
required: false
default: 'latest'
type: string
build_args:
description: 'Build arguments to pass to the container build'
required: false
default: ''
type: string
defaults:
run:
shell: bash
env:
APPTAINER_VERSION: 1.2.5
SETUP_DOWNLOADS_DIR: .setup-downloads
GH_TOKEN: ${{ github.token }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
name: Build and Deploy Apptainer Container
permissions:
contents: read
packages: write
steps:
- name: Check out code for the container build
uses: actions/checkout@v4
- name: Create SETUP_DOWNLOADS_DIR
run: |
set -euxo pipefail
mkdir -p "${SETUP_DOWNLOADS_DIR}"
- name: Cache downloads in SETUP_DOWNLOADS_DIR
uses: actions/cache@v3
with:
path: ${{ env.SETUP_DOWNLOADS_DIR }}
key: ${{ runner.os }}-${{ inputs.image_name }}
- name: Get container name
run: |
set -euxo pipefail
IMAGE_NAME="${{ inputs.image_name }}"
[[ -n "${IMAGE_NAME:-}" ]] || { echo "No container name found." ; exit 1; }
echo "Container name is \"${IMAGE_NAME:-}\""
echo "IMAGE_NAME="${IMAGE_NAME}"" >> $GITHUB_ENV
[[ -d "${DEF_DIR:=def/${IMAGE_NAME}}" ]] || { echo "No directory found for DEF_DIR at \"${DEF_DIR:-}\"" ; exit 1; }
[[ -f "${DEF_DIR}/Singularity" ]] || { echo "No definition file found at \"${DEF_DIR}/Singularity\"" ; exit 1; }
echo "DEF_DIR=${DEF_DIR}" >> $GITHUB_ENV
all_image_tags=()
all_image_tags+=("${{ inputs.image_tags }}")
IMAGE_TAG="${all_image_tags[0]:-latest}"
echo "Container tag is \"${IMAGE_TAG:-}\""
echo "IMAGE_TAG="${IMAGE_TAG}"" >> $GITHUB_ENV
# Get the base image name and tag from the container
BOOTSTRAP_FROM_IMAGE="$(sed -nE '0,/^\s*BOOTSTRAP_FROM_IMAGE=(\S*).*$/s//\1/p' "${DEF_DIR}/Singularity" || true)"
if [[ -n "${BOOTSTRAP_FROM_IMAGE}" ]]; then
BASE_IMAGE_NAME="${BOOTSTRAP_FROM_IMAGE}"
echo "Base image name is \"${BASE_IMAGE_NAME}\""
echo "BASE_IMAGE_NAME=\"${BASE_IMAGE_NAME}\"" >> $GITHUB_ENV
BASE_IMAGE_TAG="${{ inputs.base_image_tag }}"
BASE_IMAGE_TAG="${BASE_IMAGE_TAG:-latest}"
echo "Base image tag is \"{BASE_IMAGE_TAG}\"" && echo "BASE_IMAGE_TAG=\"${BASE_IMAGE_TAG}\"" >> $GITHUB_ENV
fi
# Add bootstrap args for derived containers
echo "BOOTSTRAP_SOURCE=oras" >> "${DEF_DIR}/.build-arg-file"
echo "BOOTSTRAP_IMAGE_NAME=${BASE_IMAGE_NAME:-}" >> "${DEF_DIR}/.build-arg-file"
echo "BOOTSTRAP_FROM_REPO=ghcr.io/${{ github.repository }}" >> "${DEF_DIR}/.build-arg-file"
echo "BOOTSTRAP_FROM_SUFFIX=:${BASE_IMAGE_TAG:-latest}" >> "${DEF_DIR}/.build-arg-file"
if [[ -n "${{ inputs.build_args }}" ]]; then
echo "Found build args: \"${{ inputs.build_args }}\""
echo "${{ inputs.build_args }}" >> "${DEF_DIR}/.build-arg-file"
fi
echo ".build-arg-file contents:"
cat "${DEF_DIR}/.build-arg-file" 2>/dev/null || echo "No build-arg-file found."
- name: Delete misc tools to free space
run: |
set -uxo pipefail
echo "Disk space before:" && df -hlT -x tmpfs
sudo rm -rf \
/opt/hostedtoolcache \
/usr/share/dotnet \
/opt/ghc \
/usr/local/lib/android \
/usr/local/share/powershell \
/usr/share/swift \
/usr/local/.ghcup \
/usr/lib/jvm || true
echo "Disk space after:" && df -hlT -x tmpfs
echo
- name: Remove packages to free space
run: |
echo "Disk space before:" && df -hlT -x tmpfs
set -uo pipefail
export DEBIAN_FRONTEND=noninteractive
for x in \
aria2 \
ansible \
azure-cli \
shellcheck \
rpm \
xorriso \
zsync \
esl-erlang \
firefox \
gfortran-8 \
gfortran-9 \
google-chrome-stable \
google-cloud-sdk \
imagemagick \
libmagickcore-dev \
libmagickwand-dev \
libmagic-dev \
ant \
ant-optional \
kubectl \
mercurial \
apt-transport-https \
mono-complete \
libmysqlclient \
unixodbc-dev \
yarn \
chrpath \
libssl-dev \
libxft-dev \
libfreetype6 \
libfreetype6-dev \
libfontconfig1 \
libfontconfig1-dev \
snmp \
pollinate \
libpq-dev \
postgresql-client \
powershell \
ruby-full \
sphinxsearch \
subversion \
mongodb-org \
azure-cli \
microsoft-edge-stable \
google-cloud-sdk \
; do
sudo apt-get purge -y "${x}" >/dev/null 2>&1 || true
done
sudo apt-get autoremove -y >/dev/null 2>&1
sudo apt-get autoclean -y >/dev/null 2>&1
echo "Disk space after:" && df -hlT -x tmpfs
echo
- name: Download and Install Apptainer
run: |
set -euxo pipefail
APPTAINER_LATEST_TAGNAME="$(gh release view --repo apptainer/apptainer --json tagName -t '{{.tagName}}' | head -n 1)"
[[ -n "${APPTAINER_LATEST_TAGNAME}" ]] || { echo "No latest tag found for apptainer/apptainer"; exit 1; }
echo "Latest tag for apptainer/apptainer is \"${APPTAINER_LATEST_TAGNAME}\""
gh release download --repo apptainer/apptainer --pattern 'apptainer_*_amd64.deb' --skip-existing -O "${SETUP_DOWNLOADS_DIR}/apptainer_${APPTAINER_LATEST_TAGNAME}.deb" "${APPTAINER_LATEST_TAGNAME}"
sudo dpkg --install --force-depends "${SETUP_DOWNLOADS_DIR}/apptainer_${APPTAINER_LATEST_TAGNAME}.deb" && sudo apt-get install --fix-broken --yes --quiet
apptainer --version
- name: Download and Install oras-cli
run: |
set -euxo pipefail
ORAS_LATEST_TAGNAME="$(gh release view --repo oras-project/oras --json tagName -t '{{.tagName}}' | head -n 1)"
[[ -n "${ORAS_LATEST_TAGNAME}" ]] || { echo "No latest tag found for oras-project/oras"; exit 1; }
echo "Latest tag for oras-project/oras is \"${ORAS_LATEST_TAGNAME}\""
gh release download --repo oras-project/oras --pattern '*linux_amd64.tar.gz' --skip-existing -O "${SETUP_DOWNLOADS_DIR}/oras_${ORAS_LATEST_TAGNAME}.tar.gz" "${ORAS_LATEST_TAGNAME}"
sudo mkdir -p /opt/local/bin
sudo tar -xzf "${SETUP_DOWNLOADS_DIR}/oras_${ORAS_LATEST_TAGNAME}.tar.gz" -C /opt/local/bin oras && sudo chmod +x /opt/local/bin/oras
export PATH="/opt/local/bin:${PATH}"
echo "PATH=${PATH}" >> $GITHUB_ENV
oras version
- name: Build Container
run: |
set -euxo pipefail
mkdir -p sif
pushd "${DEF_DIR}"
echo "Building \"${IMAGE_NAME}.sif\""
touch .build-arg-file
apptainer build --warn-unused-build-args --disable-cache --fix-perms --force --build-arg-file .build-arg-file ../../sif/"${IMAGE_NAME}.sif" Singularity || { echo "Failed to build \"${IMAGE_NAME}.sif\""; exit 1; }
echo "Built \"${IMAGE_NAME}.sif\""
popd
- name: Login and Deploy Container
run: |
set -euxo pipefail
[[ -r "sif/${IMAGE_NAME}.sif" ]] || { echo "No container named sif/${IMAGE_NAME:-}.sif found."; exit 1; }
echo "Container size:"
du -h "sif/${IMAGE_NAME}.sif"
echo "Disk usage:"
df -hlt -x tmpfs
echo "Pushing \"sif/${IMAGE_NAME}.sif\" to ghcr.io/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}"
apptainer remote login -u ${{ github.actor }} -p ${{ secrets.TOKEN }} oras://ghcr.io
apptainer push -U "sif/${IMAGE_NAME}.sif" oras://ghcr.io/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG} || { echo "Failed to push \"sif/${IMAGE_NAME}.sif\' to ghcr.io/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}"; exit 1; }
echo "Pushed \"sif/${IMAGE_NAME}.sif\" to ghcr.io/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}"
# Add "latest" tag if IMAGE_TAG is not latest
if [[ "${IMAGE_TAG}" != "latest" ]]; then
oras login -u ${{ github.actor }} -p ${{ secrets.TOKEN }} ghcr.io
oras tag ghcr.io/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG} latest
fi