160 lines
5.4 KiB
YAML
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
|