# 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 ]