forgejo-mcp/.tekton/release-tools/tasks/build-image.yaml
Christoph Görn e1092cec49
fix: 🐛 avoid SIGPIPE (exit 141) capturing buildah image id
`buildah images --format '{{.ID}}' | head -1` lets head close the pipe
before buildah finishes writing, sending it SIGPIPE; under `set -o
pipefail` the step fails with exit 141 even though the image built and
tagged fine. Observed in the v2.27.0-alpha.2 run (image succeeded,
"Writing manifest"/"Successfully tagged", then 141).

Capture the full output and take the first line via shell expansion —
no pipe, no SIGPIPE.
2026-06-01 11:15:09 +02:00

90 lines
3.5 KiB
YAML

apiVersion: tekton.dev/v1
kind: Task
metadata:
name: release-tools-build-image
annotations:
tekton.dev/displayName: "buildah build — release-tools image (no push)"
spec:
params:
- name: IMAGE
description: Local image tag to assign to the built image (e.g. release-tools:pr-$(context.pipelineRun.name)).
type: string
- name: CONTEXT
description: Path within the workspace to pass as the build context.
type: string
default: image/release-tools
- name: CONTAINERFILE
description: Path to the Containerfile relative to CONTEXT.
type: string
default: Containerfile
- name: STORAGE_DRIVER
description: buildah storage driver.
type: string
default: vfs
- name: BUILD_ARGS
description: |
Whitespace-separated KEY=VALUE build args forwarded to `buildah bud`
as --build-arg flags. Empty by default — the release-tools image build
needs none. The forgejo-mcp app image release passes VERSION=<tag> so
the embedded binary reports the real release version instead of "dev"
(the Containerfile's ARG VERSION default). Values must not contain
spaces (release tags never do).
type: string
default: ""
workspaces:
- name: source
mountPath: /workspace/source
results:
- name: IMAGE_DIGEST
description: |
sha256 digest of the built image manifest. Empty for pre-push (PR)
builds; the real manifest digest is captured by push-image-by-digest.
- name: IMAGE_REF
description: Full image reference (tag@digest) of the built image.
steps:
- name: build
image: quay.io/buildah/stable:latest
securityContext:
privileged: true
workingDir: $(workspaces.source.path)
script: |
#!/usr/bin/env bash
set -euo pipefail
# Store in workspace PVC so subsequent tasks (push-by-digest) can access it.
BUILDAH_STORE="$(workspaces.source.path)/.buildah"
mkdir -p "${BUILDAH_STORE}"
buildah --version
# Forward optional KEY=VALUE build args as --build-arg flags. Unquoted
# expansion is intentional: empty BUILD_ARGS expands to nothing, and
# each token (--build-arg / KEY=VALUE) must word-split into its own
# argument. Release tags carry no spaces, so this is safe.
BUILD_ARG_FLAGS=""
for kv in $(params.BUILD_ARGS); do
BUILD_ARG_FLAGS="${BUILD_ARG_FLAGS} --build-arg ${kv}"
done
buildah --root "${BUILDAH_STORE}" bud \
--storage-driver="$(params.STORAGE_DRIVER)" \
${BUILD_ARG_FLAGS} \
--file="$(params.CONTEXT)/$(params.CONTAINERFILE)" \
--tag="$(params.IMAGE)" \
"$(params.CONTEXT)"
# Capture all image IDs, then take the first line via shell expansion.
# Piping `buildah images` into `head -1` lets head close the pipe early,
# sending buildah SIGPIPE; under `set -o pipefail` that fails the step
# with exit 141 (observed intermittently). Avoid the pipe entirely.
IMAGE_IDS=$(buildah --root "${BUILDAH_STORE}" \
--storage-driver="$(params.STORAGE_DRIVER)" images \
--no-trunc --format '{{.ID}}' 2>/dev/null)
IMAGE_ID=${IMAGE_IDS%%$'\n'*}
if [ -z "${IMAGE_ID}" ]; then
echo "ERROR: no images in local store after build" >&2
exit 1
fi
echo "Built: $(params.IMAGE) local-id=${IMAGE_ID}"
printf '' > "$(results.IMAGE_DIGEST.path)"
printf '%s' "$(params.IMAGE)" > "$(results.IMAGE_REF.path)"