Files
2026-07-17 23:02:13 +03:30

160 lines
5.4 KiB
YAML

name: Build and publish runner image
description: Build, verify, and publish a runner image to a private Gitea registry.
inputs:
registry:
description: Registry hostname, for example mahgit.ir.
required: true
image:
description: Fully qualified image name without a tag.
required: true
base-image:
description: Base image used by the default Dockerfile.
required: false
default: mahgit.ir/meghdadfadaee/build-runner-image-base:node-20-bookworm
context:
description: Docker build context relative to the checked-out repository.
required: false
default: .
requirements-file:
description: Requirements lock path relative to the Docker build context.
required: false
default: requirements.lock
dockerfile:
description: Optional caller Dockerfile path; defaults to the action Dockerfile.
required: false
default: ""
source-url:
description: Repository URL stored in the OCI source label.
required: true
registry-username:
description: Registry username.
required: true
registry-token:
description: Registry token with package Read and Write permission.
required: true
verify-commands:
description: Shell commands that verify the candidate image using IMAGE_REF.
required: false
default: ""
outputs:
image:
description: Fully qualified image name without a tag.
value: ${{ steps.publish.outputs.image }}
revision:
description: Twelve-character Git revision used as the immutable tag.
value: ${{ steps.publish.outputs.revision }}
revision_tag:
description: Fully qualified immutable image reference.
value: ${{ steps.publish.outputs.revision_tag }}
latest_tag:
description: Fully qualified latest image reference.
value: ${{ steps.publish.outputs.latest_tag }}
runs:
using: composite
steps:
- name: Install Docker client
shell: sh
run: |
set -eu
if command -v docker >/dev/null 2>&1; then
docker version --format 'Docker client {{.Client.Version}}, server {{.Server.Version}}'
exit 0
fi
if ! command -v apt-get >/dev/null 2>&1; then
echo "Docker is unavailable and this job image does not provide apt-get"
exit 1
fi
for attempt in 1 2 3; do
if apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
--no-install-recommends docker.io; then
break
fi
if [ "$attempt" -eq 3 ]; then
echo "Unable to install the Docker client after 3 attempts"
exit 1
fi
sleep "$((attempt * 5))"
done
rm -rf /var/lib/apt/lists/*
docker version --format 'Docker client {{.Client.Version}}, server {{.Server.Version}}'
- name: Build, verify, and publish image
id: publish
shell: sh
env:
INPUT_REGISTRY: ${{ inputs.registry }}
INPUT_IMAGE: ${{ inputs.image }}
INPUT_BASE_IMAGE: ${{ inputs.base-image }}
INPUT_CONTEXT: ${{ inputs.context }}
INPUT_REQUIREMENTS_FILE: ${{ inputs.requirements-file }}
INPUT_DOCKERFILE: ${{ inputs.dockerfile }}
INPUT_SOURCE_URL: ${{ inputs.source-url }}
INPUT_REGISTRY_USERNAME: ${{ inputs.registry-username }}
INPUT_REGISTRY_TOKEN: ${{ inputs.registry-token }}
INPUT_VERIFY_COMMANDS: ${{ inputs.verify-commands }}
ACTION_PATH: ${{ gitea.action_path }}
run: |
set -eu
: "${INPUT_REGISTRY:?registry is required}"
: "${INPUT_IMAGE:?image is required}"
: "${INPUT_BASE_IMAGE:?base-image is required}"
: "${INPUT_CONTEXT:?context is required}"
: "${INPUT_REQUIREMENTS_FILE:?requirements-file is required}"
: "${INPUT_SOURCE_URL:?source-url is required}"
: "${INPUT_REGISTRY_USERNAME:?registry-username is required}"
: "${INPUT_REGISTRY_TOKEN:?registry-token is required}"
revision="$(git rev-parse --short=12 HEAD)"
candidate="$INPUT_IMAGE:$revision"
latest="$INPUT_IMAGE:latest"
dockerfile="$INPUT_DOCKERFILE"
if [ -z "$dockerfile" ]; then
dockerfile="$ACTION_PATH/runner-image/Dockerfile"
fi
if [ ! -f "$dockerfile" ]; then
echo "Dockerfile does not exist: $dockerfile"
exit 1
fi
cleanup() {
docker logout "$INPUT_REGISTRY" >/dev/null 2>&1 || true
}
trap cleanup EXIT
printf '%s' "$INPUT_REGISTRY_TOKEN" | docker login "$INPUT_REGISTRY" \
--username "$INPUT_REGISTRY_USERNAME" \
--password-stdin
docker build \
--pull \
--label "org.opencontainers.image.revision=$revision" \
--label "org.opencontainers.image.source=$INPUT_SOURCE_URL" \
--build-arg "BASE_IMAGE=$INPUT_BASE_IMAGE" \
--build-arg "REQUIREMENTS_FILE=$INPUT_REQUIREMENTS_FILE" \
--file "$dockerfile" \
--tag "$candidate" \
"$INPUT_CONTEXT"
if [ -n "$INPUT_VERIFY_COMMANDS" ]; then
export IMAGE_REF="$candidate"
sh -eu -c "$INPUT_VERIFY_COMMANDS"
fi
docker push "$candidate"
docker tag "$candidate" "$latest"
docker push "$latest"
if [ -n "${GITHUB_OUTPUT:-}" ]; then
{
echo "image=$INPUT_IMAGE"
echo "revision=$revision"
echo "revision_tag=$candidate"
echo "latest_tag=$latest"
} >> "$GITHUB_OUTPUT"
fi