Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitlab-ci-arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ publish_binaries:
before_script:
- docker login -u "${docker_user}" -p "${docker_password}" "${DOCKER_REGISTRY}"
- docker login -u "${quay_user}" -p "${quay_password}" "${QUAY_REGISTRY}"
# bash + mapfile is required by packaging/build-and-label.sh; the docker:20
# image is Alpine and only ships ash by default.
- apk add --no-cache bash

.publish_linux_docker:
extends: [ .docker_build ]
Expand All @@ -155,7 +158,8 @@ publish_binaries:
- prebuild_agent
script:
- export BUILD_TAG="${REPO}:${TAG}"
- docker build --build-arg EBPF_SUBFOLDER=$LLVM_ARCH --build-arg LONG_ARCH=$LONG_ARCH --build-arg SHORT_ARCH=$SHORT_ARCH -t "${BUILD_TAG}" -f BCI.dockerfile .
- export EBPF_SUBFOLDER="$LLVM_ARCH"
- bash ./packaging/build-and-label.sh
- ./packaging/publish_image.sh $BUILD_TAG $REPO $TAG $EXTRA_TAG

publish_k8s_docker:
Expand Down
6 changes: 5 additions & 1 deletion .gitlab-ci-x64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ publish_binaries:
before_script:
- docker login -u "${docker_user}" -p "${docker_password}" "${DOCKER_REGISTRY}"
- docker login -u "${quay_user}" -p "${quay_password}" "${QUAY_REGISTRY}"
# bash + mapfile is required by packaging/build-and-label.sh; the docker:20
# image is Alpine and only ships ash by default.
- apk add --no-cache bash

.publish_linux_docker:
extends: [ .docker_build ]
Expand All @@ -155,7 +158,8 @@ publish_binaries:
- prebuild_agent
script:
- export BUILD_TAG="${REPO}:${TAG}"
- docker build --build-arg EBPF_SUBFOLDER=$LLVM_ARCH --build-arg LONG_ARCH=$LONG_ARCH --build-arg SHORT_ARCH=$SHORT_ARCH -t "${BUILD_TAG}" -f BCI.dockerfile .
- export EBPF_SUBFOLDER="$LLVM_ARCH"
- bash ./packaging/build-and-label.sh
- ./packaging/publish_image.sh $BUILD_TAG $REPO $TAG $EXTRA_TAG

publish_k8s_docker:
Expand Down
39 changes: 39 additions & 0 deletions packaging/build-and-label.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash
# Wrapper around `docker build` for stackstate-k8s-process-agent that splices
# canonical SUSE Observability OCI labels via packaging/oci-labels.sh.
#
# Replaces the previous inline docker build line in .gitlab-ci-x64.yml and
# .gitlab-ci-arm.yml so the same recipe runs identically on both arches. The
# base image label is derived from BCI.dockerfile by oci-labels.sh itself.
#
# Required env (exported by the CI job):
# BUILD_TAG — full repo:tag for the local build (e.g. stackstate-k8s-process-agent:foo-amd64)
# EBPF_SUBFOLDER — kept as build-arg for BCI.dockerfile
# LONG_ARCH — kept as build-arg for BCI.dockerfile
# SHORT_ARCH — kept as build-arg for BCI.dockerfile

set -euo pipefail

helper="$(dirname "$0")/oci-labels.sh"

# BUILD_TAG has the form "<repo>:<tag>". The tag is what goes into
# org.opencontainers.image.version and the ref.name suffix.
tag="${BUILD_TAG##*:}"

mapfile -t labels < <(
"$helper" \
--image-name stackstate-k8s-process-agent \
--tag "$tag" \
--title "SUSE Observability Process Agent" \
--description "Process agent collecting per-process and per-container telemetry for SUSE Observability." \
--component stackstate-k8s-process-agent \
--dockerfile BCI.dockerfile
)

docker build "${labels[@]}" \
--build-arg EBPF_SUBFOLDER="$EBPF_SUBFOLDER" \
--build-arg LONG_ARCH="$LONG_ARCH" \
--build-arg SHORT_ARCH="$SHORT_ARCH" \
-t "${BUILD_TAG}" \
-f BCI.dockerfile \
.
153 changes: 153 additions & 0 deletions packaging/oci-labels.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/bin/bash
# Emit OCI label flags for `docker build` / `docker buildx build` / kaniko.
#
# Each line of stdout is one fully-formed `--label=key=value` argument.
# Capture and splice with:
# mapfile -t labels < <(./packaging/oci-labels.sh --image-name ... )
# docker build "${labels[@]}" ...

set -euo pipefail

product="suse-observability"
source_url="https://gitlab.com/stackvista/agent/stackstate-process-agent"
documentation_url="https://documentation.suse.com/cloudnative/suse-observability/latest/en/classic.html"
readme_url=""
image_name=""
tag=""
title=""
description=""
component=""
base_image=""
base_digest=""
dockerfile=""

usage() {
cat >&2 <<'EOF'
usage: oci-labels.sh --image-name NAME --tag TAG --title TITLE \
--description DESC --component COMPONENT \
(--base-image REF | --dockerfile PATH)
[--base-digest sha256:...] [--readme-url URL]
[--product NAME] [--source-url URL] [--documentation-url URL]

Exactly one of --base-image or --dockerfile must be supplied. With --dockerfile,
each FROM is resolved through stage references and the last one wins; this is
the external base image of the stage Docker/kaniko ships by default (no
--target). Keeps the label in sync with the Dockerfile without a hardcoded
value.

When --base-digest is provided, the buildx call to resolve the base image
digest is skipped. Required when running inside a container without docker
CLI (e.g. kaniko-executor).
EOF
}

while [[ $# -gt 0 ]]; do
case "$1" in
--image-name) image_name=$2; shift 2 ;;
--tag) tag=$2; shift 2 ;;
--title) title=$2; shift 2 ;;
--description) description=$2; shift 2 ;;
--component) component=$2; shift 2 ;;
--base-image) base_image=$2; shift 2 ;;
--dockerfile) dockerfile=$2; shift 2 ;;
--base-digest) base_digest=$2; shift 2 ;;
--readme-url) readme_url=$2; shift 2 ;;
--product) product=$2; shift 2 ;;
--source-url) source_url=$2; shift 2 ;;
--documentation-url) documentation_url=$2; shift 2 ;;
-h|--help) usage; exit 0 ;;
*)
echo "oci-labels.sh: unknown argument: $1" >&2
usage
exit 64
;;
esac
done

for var in image_name tag title description component; do
if [[ -z "${!var}" ]]; then
echo "oci-labels.sh: missing required --${var//_/-}" >&2
usage
exit 64
fi
done

if [[ -z "$base_image" && -z "$dockerfile" ]]; then
echo "oci-labels.sh: one of --base-image or --dockerfile is required" >&2
usage
exit 64
fi
if [[ -n "$base_image" && -n "$dockerfile" ]]; then
echo "oci-labels.sh: --base-image and --dockerfile are mutually exclusive" >&2
usage
exit 64
fi

if [[ -n "$dockerfile" ]]; then
if [[ ! -f "$dockerfile" ]]; then
echo "oci-labels.sh: dockerfile not found: $dockerfile" >&2
exit 1
fi
base_image="$(awk '
toupper($1) == "FROM" {
src = $2; dst = ""
if (toupper($3) == "AS") dst = $4
resolved = (src in stage_base) ? stage_base[src] : src
if (dst != "") stage_base[dst] = resolved
last = resolved
}
END { print last }
' "$dockerfile")"
if [[ -z "$base_image" ]]; then
echo "oci-labels.sh: could not find an external FROM line in $dockerfile" >&2
exit 1
fi
fi

# Canonical reference: always the Rancher registry path, even when the artefact
# is actually pushed to quay.io. Matches apply-oci-labels and OciLabels.compute.
ref_name="registry.rancher.com/suse-observability/${image_name}:${tag}"
if [[ -z "$readme_url" ]]; then
readme_url="${source_url%/}/-/blob/master/README.md"
fi
revision="${CI_COMMIT_SHA:-$(git rev-parse HEAD)}"
source="${CI_PROJECT_URL:-$source_url}"
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

if [[ -z "$base_digest" ]]; then
# Resolve base.digest by parsing the default `buildx imagetools inspect` output.
# Avoids `--format` (added in buildx v0.11) and `jq`. For a multi-arch image the
# first `Digest:` line is the manifest-list digest, which is the canonical
# pull-by-digest reference.
base_digest="$(docker buildx imagetools inspect "$base_image" | awk '/^Digest:[[:space:]]+sha256:/ { print $2; exit }')"
fi
if [[ "$base_digest" != sha256:* ]]; then
echo "oci-labels.sh: could not resolve base digest for $base_image" >&2
exit 1
fi

emit() { printf -- '--label=%s=%s\n' "$1" "$2"; }

emit "org.opencontainers.image.title" "$title"
emit "org.opencontainers.image.description" "$description"
emit "org.opencontainers.image.version" "$tag"
emit "org.opencontainers.image.ref.name" "$ref_name"
emit "org.opencontainers.image.source" "$source"
emit "org.opencontainers.image.revision" "$revision"
emit "org.opencontainers.image.created" "$created"
emit "org.opencontainers.image.base.name" "$base_image"
emit "org.opencontainers.image.base.digest" "$base_digest"
emit "org.opencontainers.image.vendor" "SUSE LLC"
emit "org.opencontainers.image.authors" "suse-observability-ops@suse.com"
emit "org.opencontainers.image.url" "$documentation_url"
emit "org.opencontainers.image.documentation" "$documentation_url"
emit "org.opensuse.reference" "$ref_name"
emit "io.artifacthub.package.logo-url" ""
emit "io.artifacthub.package.readme-url" "$readme_url"
emit "org.openbuildservice.disturl" ""
emit "com.suse.observability.product" "$product"
emit "com.suse.observability.component" "$component"

if [[ -n "${CI_JOB_URL:-}" ]]; then
emit "published-by" "$CI_JOB_URL"
fi