Files
actions/publish-container/action.yaml
T

229 lines
7.4 KiB
YAML

# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-action.json
name: "publish-container"
description: "Publishes a Container to a Gitea-hosted Container registry."
inputs:
project:
description: "Name of the project to containerize eg. fvcomkit"
required: true
container-token:
description: "Token with which to authenticate to the Container registry."
required: true
registry:
description: "Gitea registry domain, e.g. git.oceanbox.io"
required: true
default: "git.oceanbox.io"
registry-owner:
description: "Registry owner/organization name, e.g. oceanbox."
required: true
default: "oceanbox"
deploy:
description: "Whether to deploy to manifests repository (staging/prod)"
required: false
default: "false"
manifests-repo:
description: "Manifests repository to deploy to"
required: false
default: "platform/manifests"
push-token:
description: "Token for pushing to manifests repository"
required: false
apptainer:
description: "Whether to build for apptainer format. When present, skips manifests deployment."
required: false
default: "false"
runs:
using: "composite"
steps:
- name: Set image metadata
id: envvars
shell: bash
run: |
SHA="${{ github.sha }}"
REPO="${{ github.repository }}"
# To lowercase
REPO_NAME="${REPO,,}"
if [ "${{ github.ref_type }}" == "tag" ]; then
IMAGE_TAG="${{ github.ref_name }}"
ENV="Release"
else
IMAGE_TAG="${SHA:0:8}-debug"
ENV="Debug"
fi
IMAGE_NAME="${{ inputs.registry }}/$REPO_NAME/${{ inputs.project }}:$IMAGE_TAG"
echo "IMAGE_TAG=$IMAGE_TAG" >> "$GITHUB_OUTPUT"
echo "IMAGE_NAME=$IMAGE_NAME" >> "$GITHUB_OUTPUT"
echo "ENV=$ENV" >> "$GITHUB_OUTPUT"
- name: Build and push container
if: github.event_name != 'pull_request'
shell: bash
run: |
# Configure container policy to accept insecure registry
mkdir -p ~/.config/containers
echo '{"default":[{"type":"insecureAcceptAnything"}]}' > ~/.config/containers/policy.json
# Skopeo temp dirs
mkdir -p /tmp/skopeo
chmod 755 /tmp/skopeo || true
export TMPDIR=/tmp/skopeo
export TMP=/tmp/skopeo
export TEMP=/tmp/skopeo
export XDG_RUNTIME_DIR=/tmp/skopeo
# Login to registry
skopeo login \
--username "${{ github.actor }}" \
--password "${{ inputs.container-token }}" \
"${{ inputs.REGISTRY }}"
# Build container
nix build --file . containers."${{ inputs.project }}" --log-format bar-with-logs -L \
--argstr env "${{ steps.envvars.outputs.ENV }}"
# The Nix build creates a compressed tar.gz file, we need to extract it first
IMAGE_TAR="$(readlink -f result)"
cd /tmp/skopeo
if file "${IMAGE_TAR}" | grep -qi gzip; then
echo "Detected gzip-compressed image"
cp "${IMAGE_TAR}" docker-image.tar.gz
gunzip docker-image.tar.gz
else
echo "Detected uncompressed image"
cp "${IMAGE_TAR}" docker-image.tar
fi
echo "Pushing image: ${{ steps.envvars.outputs.IMAGE_NAME }}"
skopeo copy \
--tmpdir /tmp/skopeo \
docker-archive:/tmp/skopeo/docker-image.tar \
docker://${{ steps.envvars.outputs.IMAGE_NAME }}
- name: Checkout manifests repository
if: inputs.deploy == 'true' && inputs.apptainer != 'true'
uses: actions/checkout@v6
with:
repository: ${{ inputs.manifests-repo }}
path: manifests
token: ${{ inputs.push-token }}
- name: Configure git credentials
if: inputs.deploy == 'true' && inputs.apptainer != 'true'
shell: bash
run: |
cd manifests
git config user.name "Gitea Actions"
git config user.email "actions@gitea.local"
git remote set-url origin https://x-access-token:${{ inputs.push-token }}@git.oceanbox.io/${{ inputs.manifests-repo }}
- name: Deploy to production
if: inputs.deploy == 'true' && github.ref_type == 'tag' && inputs.apptainer != 'true'
shell: bash
run: |
set -euo pipefail
cd manifests/charts/${{ inputs.project }}
IMAGE_TAG="${{ steps.envvars.outputs.IMAGE_TAG }}"
echo "=== Deploying production with image.tag=$IMAGE_TAG ==="
if [ -z "$IMAGE_TAG" ]; then
echo "::error::IMAGE_TAG is empty"
exit 1
fi
nix-shell -p yq-go --run '
set -euo pipefail
yq eval ".image.tag = \"'"$IMAGE_TAG"'\"" -i values.yaml
yq eval ".version = \"'"$IMAGE_TAG"'\" | .appVersion = \"'"$IMAGE_TAG"'\"" -i Chart.yaml
'
echo "=== Git diff ==="
git diff values.yaml Chart.yaml
git add values.yaml Chart.yaml
if git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
git commit -m "ci(prod): deploy ${{ inputs.project }} $IMAGE_TAG"
# CURSED: Retry logic from head foo
retry=0; git push || retry=1
[ $retry = 0 ] || for i in 1 2 3; do
if [ $retry = 1 ]; then
sleep 1; retry=0
git pull --rebase
git push || retry=1
else
break
fi
done
[ $retry = 0 ]
- name: Deploy to staging
if: inputs.deploy == 'true' && github.ref_type == 'branch' && github.ref_name == 'main' && inputs.apptainer != 'true'
shell: bash
run: |
set -euo pipefail
cd manifests/values/${{ inputs.project }}
IMAGE_TAG="${{ steps.envvars.outputs.IMAGE_TAG }}"
echo "=== Deploying staging with image.tag=$IMAGE_TAG ==="
if [ -z "$IMAGE_TAG" ]; then
echo "::error::IMAGE_TAG is empty"
exit 1
fi
# Find and update staging file
if [ -f values-staging.yaml ]; then
TARGET_FILE="values-staging.yaml"
elif [ -f values/values-staging.yaml ]; then
TARGET_FILE="values/values-staging.yaml"
elif [ -f values/${{ inputs.project }}-staging.yaml ]; then
TARGET_FILE="values/${{ inputs.project }}-staging.yaml"
elif [ -f values/values-staging.yaml.gotmpl ]; then
TARGET_FILE="values/values-staging.yaml.gotmpl"
elif [ -f values/${{ inputs.project }}-staging.yaml.gotmpl ]; then
TARGET_FILE="values/${{ inputs.project }}-staging.yaml.gotmpl"
else
echo "::error::No staging values file found"
TARGET_FILE="values/values.yaml"
fi
echo "=== Updating $TARGET_FILE ==="
nix-shell -p yq-go --run '
set -euo pipefail
yq eval ".image.tag = \"'"$IMAGE_TAG"'\"" -i "'"$TARGET_FILE"'"
'
echo "=== Git diff ==="
git diff "$TARGET_FILE"
git add "$TARGET_FILE"
if git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
git commit -m "ci(staging): deploy ${{ inputs.project }} $IMAGE_TAG"
# CURSED: Retry logic from head foo
retry=0; git push || retry=1
[ $retry = 0 ] || for i in 1 2 3; do
if [ $retry = 1 ]; then
sleep 1; retry=0
git pull --rebase
git push || retry=1
else
break
fi
done
[ $retry = 0 ]