106 lines
4.4 KiB
YAML
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
|