ci-actions/docker-publish/action.yml
2026-06-06 14:44:53 +01:00

106 lines
4.4 KiB
YAML

name: Build & publish Docker image
description: >-
Build a Docker image and push it to this Forgejo instance's container
registry. Reimplements docker/login-action + docker/metadata-action +
docker/build-push-action in plain shell using the docker CLI — no
marketplace actions are fetched or run.
inputs:
context:
description: Docker build context.
default: "."
dockerfile:
description: Path to the Dockerfile (relative to the workspace). Empty = <context>/Dockerfile.
default: ""
image-suffix:
description: Appended to the derived image name <host>/<owner>/<repo>, e.g. "-server".
default: ""
build-args:
description: Newline-separated KEY=VALUE pairs passed as --build-arg.
default: ""
push:
description: Whether to log in and push ("true"/"false"). Set false for pull-request builds.
default: "true"
token:
description: Registry password/token (e.g. secrets.FORGEJO_PACKAGE_TOKEN).
required: true
registry-host:
description: Override the registry host. Defaults to github.server_url (vars.CONTAINER_REGISTRY_HOST is honoured if set in the env).
default: ""
runs:
using: composite
steps:
- name: Build and publish
shell: bash
env:
INPUT_CONTEXT: ${{ inputs.context }}
INPUT_DOCKERFILE: ${{ inputs.dockerfile }}
INPUT_IMAGE_SUFFIX: ${{ inputs.image-suffix }}
INPUT_BUILD_ARGS: ${{ inputs.build-args }}
INPUT_PUSH: ${{ inputs.push }}
INPUT_TOKEN: ${{ inputs.token }}
INPUT_REGISTRY_HOST: ${{ inputs.registry-host }}
REPO: ${{ github.repository }}
OWNER: ${{ github.repository_owner }}
SERVER_URL: ${{ github.server_url }}
SHA: ${{ github.sha }}
REF: ${{ github.ref }}
REF_TYPE: ${{ github.ref_type }}
REF_NAME: ${{ github.ref_name }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
set -euo pipefail
# --- Ensure the docker CLI exists (idempotent; the node:* runner image may lack it) ---
if ! command -v docker >/dev/null 2>&1; then
ARCH="$(uname -m)"
curl -fsSL --retry 3 --retry-connrefused \
"https://download.docker.com/linux/static/stable/${ARCH}/docker-27.5.1.tgz" \
| tar xz --strip-components=1 -C /usr/local/bin docker/docker
fi
docker --version
# --- Resolve the registry host (canonical form of the block copy-pasted across repos) ---
host="${INPUT_REGISTRY_HOST:-${CONTAINER_REGISTRY_HOST:-$SERVER_URL}}"
host="${host#https://}"; host="${host#http://}"; host="${host%/}"
# The job's docker daemon reaches the registry via the host-published port, not the
# internal service name; this is the same remap the old inline scripts performed.
[ "$host" = "forgejo:3000" ] && host="127.0.0.1:13000"
repo="$(printf '%s' "$REPO" | tr '[:upper:]' '[:lower:]')"
image="${host}/${repo}${INPUT_IMAGE_SUFFIX}"
echo "Target image: ${image}"
# --- Compute tags from the git ref (replaces docker/metadata-action) ---
tags=( -t "${image}:sha-$(printf '%s' "$SHA" | cut -c1-12)" )
if [ "$REF" = "refs/heads/${DEFAULT_BRANCH}" ]; then
tags+=( -t "${image}:latest" )
fi
if [ "$REF_TYPE" = "tag" ]; then
tags+=( -t "${image}:${REF_NAME}" )
if printf '%s' "$REF_NAME" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
v="${REF_NAME#v}"
tags+=( -t "${image}:${v}" -t "${image}:${v%.*}" -t "${image}:${v%%.*}" )
fi
fi
# --- Assemble extra build flags ---
extra=()
[ -n "${INPUT_DOCKERFILE}" ] && extra+=( -f "${INPUT_DOCKERFILE}" )
while IFS= read -r a; do
[ -n "$a" ] && extra+=( --build-arg "$a" )
done <<< "${INPUT_BUILD_ARGS}"
# --- Build ---
docker build "${extra[@]}" \
--label "org.opencontainers.image.source=${SERVER_URL}/${REPO}" \
--label "org.opencontainers.image.revision=${SHA}" \
--label "org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
"${tags[@]}" \
"${INPUT_CONTEXT}"
# --- Push (skipped on pull requests by passing push: false) ---
if [ "${INPUT_PUSH}" = "true" ]; then
printf '%s' "${INPUT_TOKEN}" | docker login "$host" -u "$OWNER" --password-stdin
docker push --all-tags "$image"
fi