diff --git a/task/source-build/0.1/README.md b/task/source-build/0.1/README.md index e1f45d9299..f81fac13aa 100644 --- a/task/source-build/0.1/README.md +++ b/task/source-build/0.1/README.md @@ -6,7 +6,7 @@ Source image build. |name|description|default value|required| |---|---|---|---| |BINARY_IMAGE|Binary image name from which to generate the source image name.||true| -|BASE_IMAGES|Base images used to build the binary image. Each image per line in the same order of FROM instructions specified in a multistage Dockerfile. Default to an empty string, which means to skip handling a base image.|""|false| +|BASE_IMAGES|By default, the task inspects the SBOM of the binary image to find the base image. With this parameter, you can override that behavior and pass the base image directly. The value should be a newline-separated list of images, in the same order as the FROM instructions specified in a multistage Dockerfile.|""|false| ## Results |name|description| diff --git a/task/source-build/0.1/source-build.yaml b/task/source-build/0.1/source-build.yaml index 9b6b88b040..6eecd521f2 100644 --- a/task/source-build/0.1/source-build.yaml +++ b/task/source-build/0.1/source-build.yaml @@ -16,9 +16,10 @@ spec: type: string - name: BASE_IMAGES description: >- - Base images used to build the binary image. Each image per line in the same order of FROM - instructions specified in a multistage Dockerfile. Default to an empty string, which means - to skip handling a base image. + By default, the task inspects the SBOM of the binary image to find the base image. + With this parameter, you can override that behavior and pass the base image directly. + The value should be a newline-separated list of images, in the same order as the FROM + instructions specified in a multistage Dockerfile. type: string default: "" results: @@ -34,7 +35,58 @@ spec: volumes: - name: source-build-work-place emptyDir: {} + stepTemplate: + env: + - name: BINARY_IMAGE + value: "$(params.BINARY_IMAGE)" + - name: BASE_IMAGES_FILE + value: /var/source-build/base-images.txt + volumeMounts: + - name: source-build-work-place + mountPath: /var/source-build steps: + - name: get-base-images + image: quay.io/konflux-ci/appstudio-utils:ab6b0b8e40e440158e7288c73aff1cf83a2cc8a9@sha256:24179f0efd06c65d16868c2d7eb82573cce8e43533de6cea14fec3b7446e0b14 + env: + - name: BASE_IMAGES + value: "$(params.BASE_IMAGES)" + script: | + #!/usr/bin/env bash + set -euo pipefail + + if [[ -n "$BASE_IMAGES" ]]; then + echo "BASE_IMAGES param received:" + printf "%s" "$BASE_IMAGES" | tee "$BASE_IMAGES_FILE" + exit + fi + + echo "BASE_IMAGES param is empty, inspecting the SBOM instead" + + raw_inspect=$(skopeo inspect --raw "docker://$BINARY_IMAGE") + if manifest_digest=$(jq -e -r '.manifests[0].digest' <<< "$raw_inspect"); then + # We're gonna assume the base images are the same or similar enough in all the SBOMs + # How would we even handle a build where each manifest in the list is built from different base images? + echo "BINARY_IMAGE ($BINARY_IMAGE) is a manifest list, picking an arbitrary image from the list" + image_without_digest=${BINARY_IMAGE%@*} + image_without_tag=${image_without_digest%:*} + image=${image_without_tag}@${manifest_digest} + else + image=$BINARY_IMAGE + fi + + echo "Downloading SBOM for $image" + sbom=$(cosign download sbom "$image") + + echo -n "Extracting base images from SBOM" + echo " (looking for .formulation[].components[] with 'konflux:container:is_base_image' properties)" + jq -r ' + .formulation[]? + | .components[]? + | select(any(.properties[]?; .name == "konflux:container:is_base_image")) + | (.purl | capture("^pkg:oci/.*?@(?.*?:[a-f0-9]*)")) as $matched + | .name + "@" + $matched.digest + ' <<< "$sbom" | tee "$BASE_IMAGES_FILE" + - name: build image: quay.io/konflux-ci/source-container-build:9ad131acf5154d2f280b7b46a1abc543952d325c@sha256:94271c32e4578208ac90308695d2b625d4e932d65f0cdd116b200c39228f5ece # per https://kubernetes.io/docs/concepts/containers/images/#imagepullpolicy-defaulting @@ -51,16 +103,9 @@ spec: capabilities: add: - SETFCAP - volumeMounts: - - name: source-build-work-place - mountPath: /var/source-build env: - - name: BINARY_IMAGE - value: "$(params.BINARY_IMAGE)" - name: SOURCE_DIR value: "$(workspaces.workspace.path)/source" - - name: BASE_IMAGES - value: "$(params.BASE_IMAGES)" - name: RESULT_FILE value: "$(results.BUILD_RESULT.path)" - name: CACHI2_ARTIFACTS_DIR @@ -91,7 +136,7 @@ spec: --output-binary-image "$BINARY_IMAGE" \ --workspace /var/source-build \ --source-dir "$SOURCE_DIR" \ - --base-images "$BASE_IMAGES" \ + --base-images "$(cat "$BASE_IMAGES_FILE")" \ --write-result-to "$RESULT_FILE" \ --cachi2-artifacts-dir "$CACHI2_ARTIFACTS_DIR" \ --registry-allowlist="$registry_allowlist"