diff --git a/pipelines/docker-build-multi-platform-oci-ta/README.md b/pipelines/docker-build-multi-platform-oci-ta/README.md index bef04dc68..07ae53d83 100644 --- a/pipelines/docker-build-multi-platform-oci-ta/README.md +++ b/pipelines/docker-build-multi-platform-oci-ta/README.md @@ -58,6 +58,7 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |IMAGE| Reference of the image buildah will produce.| None| '$(params.output-image)'| |IMAGE_APPEND_PLATFORM| Whether to append a sanitized platform architecture on the IMAGE tag| false| 'true'| |IMAGE_EXPIRES_AFTER| Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.| | '$(params.image-expires-after)'| +|LABELS| Additional key=value labels that should be applied to the image| []| | |PLATFORM| The platform to build on| None| | |PREFETCH_INPUT| In case it is not empty, the prefetched content should be made available to the build.| | '$(params.prefetch-input)'| |SKIP_UNUSED_STAGES| Whether to skip stages in Containerfile that seem unused by subsequent stages| true| | diff --git a/pipelines/docker-build-oci-ta/README.md b/pipelines/docker-build-oci-ta/README.md index e20112dfb..40910f5c1 100644 --- a/pipelines/docker-build-oci-ta/README.md +++ b/pipelines/docker-build-oci-ta/README.md @@ -56,6 +56,7 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |HERMETIC| Determines if build will be executed without network access.| false| '$(params.hermetic)'| |IMAGE| Reference of the image buildah will produce.| None| '$(params.output-image)'| |IMAGE_EXPIRES_AFTER| Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.| | '$(params.image-expires-after)'| +|LABELS| Additional key=value labels that should be applied to the image| []| | |PREFETCH_INPUT| In case it is not empty, the prefetched content should be made available to the build.| | '$(params.prefetch-input)'| |SKIP_UNUSED_STAGES| Whether to skip stages in Containerfile that seem unused by subsequent stages| true| | |SOURCE_ARTIFACT| The Trusted Artifact URI pointing to the artifact with the application source code.| None| '$(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)'| diff --git a/pipelines/docker-build/README.md b/pipelines/docker-build/README.md index 95fba6cb4..09897e47c 100644 --- a/pipelines/docker-build/README.md +++ b/pipelines/docker-build/README.md @@ -55,6 +55,7 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |HERMETIC| Determines if build will be executed without network access.| false| '$(params.hermetic)'| |IMAGE| Reference of the image buildah will produce.| None| '$(params.output-image)'| |IMAGE_EXPIRES_AFTER| Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.| | '$(params.image-expires-after)'| +|LABELS| Additional key=value labels that should be applied to the image| []| | |PREFETCH_INPUT| In case it is not empty, the prefetched content should be made available to the build.| | '$(params.prefetch-input)'| |SKIP_UNUSED_STAGES| Whether to skip stages in Containerfile that seem unused by subsequent stages| true| | |SQUASH| Squash all new and previous layers added as a part of this build, as per --squash| false| | diff --git a/pipelines/fbc-builder/README.md b/pipelines/fbc-builder/README.md index 24c6a32d4..d2f08821b 100644 --- a/pipelines/fbc-builder/README.md +++ b/pipelines/fbc-builder/README.md @@ -53,6 +53,7 @@ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/reposito |HERMETIC| Determines if build will be executed without network access.| false| '$(params.hermetic)'| |IMAGE| Reference of the image buildah will produce.| None| '$(params.output-image)'| |IMAGE_EXPIRES_AFTER| Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.| | '$(params.image-expires-after)'| +|LABELS| Additional key=value labels that should be applied to the image| []| | |PREFETCH_INPUT| In case it is not empty, the prefetched content should be made available to the build.| | | |SKIP_UNUSED_STAGES| Whether to skip stages in Containerfile that seem unused by subsequent stages| true| | |SQUASH| Squash all new and previous layers added as a part of this build, as per --squash| false| | diff --git a/task/buildah-oci-ta/0.2/README.md b/task/buildah-oci-ta/0.2/README.md index ff1099db5..1718940ae 100644 --- a/task/buildah-oci-ta/0.2/README.md +++ b/task/buildah-oci-ta/0.2/README.md @@ -21,6 +21,7 @@ When prefetch-dependencies task was activated it is using its artifacts to run b |HERMETIC|Determines if build will be executed without network access.|false|false| |IMAGE|Reference of the image buildah will produce.||true| |IMAGE_EXPIRES_AFTER|Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.|""|false| +|LABELS|Additional key=value labels that should be applied to the image|[]|false| |PREFETCH_INPUT|In case it is not empty, the prefetched content should be made available to the build.|""|false| |SKIP_UNUSED_STAGES|Whether to skip stages in Containerfile that seem unused by subsequent stages|true|false| |SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.||true| diff --git a/task/buildah-oci-ta/0.2/buildah-oci-ta.yaml b/task/buildah-oci-ta/0.2/buildah-oci-ta.yaml index 54cb0de56..7ab9e9cea 100644 --- a/task/buildah-oci-ta/0.2/buildah-oci-ta.yaml +++ b/task/buildah-oci-ta/0.2/buildah-oci-ta.yaml @@ -72,6 +72,11 @@ spec: hours, days, and weeks, respectively. type: string default: "" + - name: LABELS + description: Additional key=value labels that should be applied to the + image + type: array + default: [] - name: PREFETCH_INPUT description: In case it is not empty, the prefetched content should be made available to the build. @@ -226,7 +231,10 @@ spec: - name: build image: quay.io/konflux-ci/buildah-task:latest@sha256:860a239c5f25376a435a514ae6d53a5c75b1fa492461d17774e9b7cb32d1e275 args: + - --build-args - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) workingDir: /var/workdir volumeMounts: - mountPath: /var/lib/containers @@ -302,11 +310,34 @@ spec: sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" ) fi - # Append BUILD_ARGS - # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being - # passed to buildah. In that case, the *last* occurrence takes precedence. This is why - # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. - build_args+=("$@") + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. + while [[ $# -gt 0 && $1 != --* ]]; do + build_args+=("$1") + shift + done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do + LABELS+=("--label" "$1") + shift + done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done BUILD_ARG_FLAGS=() for build_arg in "${build_args[@]}"; do @@ -380,13 +411,16 @@ spec: VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" fi - LABELS=( + DEFAULT_LABELS=( "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" "--label" "architecture=$(uname -m)" "--label" "vcs-type=git" ) - [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") - [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") ACTIVATION_KEY_PATH="/activation-key" ENTITLEMENT_PATH="/entitlement" diff --git a/task/buildah-remote-oci-ta/0.2/buildah-remote-oci-ta.yaml b/task/buildah-remote-oci-ta/0.2/buildah-remote-oci-ta.yaml index 75775a872..4102439d5 100644 --- a/task/buildah-remote-oci-ta/0.2/buildah-remote-oci-ta.yaml +++ b/task/buildah-remote-oci-ta/0.2/buildah-remote-oci-ta.yaml @@ -72,6 +72,10 @@ spec: respectively. name: IMAGE_EXPIRES_AFTER type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array - default: "" description: In case it is not empty, the prefetched content should be made available to the build. @@ -212,7 +216,10 @@ spec: image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:e0e457b6af10e44ff6b90208a9e69adc863a865e1c062c4cb84bf3846037d74d name: use-trusted-artifact - args: + - --build-args - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) computeResources: limits: cpu: "4" @@ -337,11 +344,34 @@ spec: sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" ) fi - # Append BUILD_ARGS - # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being - # passed to buildah. In that case, the *last* occurrence takes precedence. This is why - # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. - build_args+=("$@") + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. + while [[ $# -gt 0 && $1 != --* ]]; do + build_args+=("$1") + shift + done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do + LABELS+=("--label" "$1") + shift + done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done BUILD_ARG_FLAGS=() for build_arg in "${build_args[@]}"; do @@ -415,13 +445,16 @@ spec: VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" fi - LABELS=( + DEFAULT_LABELS=( "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" "--label" "architecture=$(uname -m)" "--label" "vcs-type=git" ) - [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") - [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") ACTIVATION_KEY_PATH="/activation-key" ENTITLEMENT_PATH="/entitlement" diff --git a/task/buildah-remote/0.2/buildah-remote.yaml b/task/buildah-remote/0.2/buildah-remote.yaml index 1aeff9e56..4a22a47fb 100644 --- a/task/buildah-remote/0.2/buildah-remote.yaml +++ b/task/buildah-remote/0.2/buildah-remote.yaml @@ -115,6 +115,10 @@ spec: stages name: SKIP_UNUSED_STAGES type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array - description: The platform to build on name: PLATFORM type: string @@ -194,7 +198,10 @@ spec: name: shared steps: - args: + - --build-args - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) computeResources: limits: cpu: "4" @@ -319,11 +326,28 @@ spec: sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" ) fi - # Append BUILD_ARGS - # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being - # passed to buildah. In that case, the *last* occurrence takes precedence. This is why - # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. - build_args+=("$@") + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done BUILD_ARG_FLAGS=() for build_arg in "${build_args[@]}"; do @@ -397,13 +421,16 @@ spec: VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" fi - LABELS=( + DEFAULT_LABELS=( "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" "--label" "architecture=$(uname -m)" "--label" "vcs-type=git" ) - [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") - [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") ACTIVATION_KEY_PATH="/activation-key" ENTITLEMENT_PATH="/entitlement" diff --git a/task/buildah/0.2/buildah.yaml b/task/buildah/0.2/buildah.yaml index 8c8719b25..8869f9123 100644 --- a/task/buildah/0.2/buildah.yaml +++ b/task/buildah/0.2/buildah.yaml @@ -103,6 +103,10 @@ spec: description: Whether to skip stages in Containerfile that seem unused by subsequent stages type: string default: "true" + - name: LABELS + description: Additional key=value labels that should be applied to the image + type: array + default: [] results: - description: Digest of the image just built @@ -179,7 +183,11 @@ spec: - name: COMMIT_SHA value: $(params.COMMIT_SHA) args: + - --build-args - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + script: | #!/bin/bash set -e @@ -239,11 +247,28 @@ spec: sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" ) fi - # Append BUILD_ARGS - # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being - # passed to buildah. In that case, the *last* occurrence takes precedence. This is why - # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. - build_args+=("$@") + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE - they take precedence. + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done BUILD_ARG_FLAGS=() for build_arg in "${build_args[@]}"; do @@ -317,13 +342,16 @@ spec: VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" fi - LABELS=( + DEFAULT_LABELS=( "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" "--label" "architecture=$(uname -m)" "--label" "vcs-type=git" ) - [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") - [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") ACTIVATION_KEY_PATH="/activation-key" ENTITLEMENT_PATH="/entitlement" diff --git a/task/generate-labels/0.1/README.md b/task/generate-labels/0.1/README.md new file mode 100644 index 000000000..0f5085430 --- /dev/null +++ b/task/generate-labels/0.1/README.md @@ -0,0 +1,30 @@ +# generate-labels task + +Generate labels based on templates. + +Usage may look like the following. + +> - name: generate-labels +> params: +> - name: label-templates +> value: ["release=$SOURCE_DATE_EPOCH", "build-date=$SOURCE_DATE"] + +The following environment variables are defined for use in label-templates + +* ACTUAL_DATE - a date time string containing the time this task runs, formatted +'%Y-%m-%dT%H:%M:%SZ' +* ACTUAL_DATE_EPOCH - the timestamp at the time this task runs +* SOURCE_DATE - a date time string containing the provided source timestamp, formatted +'%Y-%m-%dT%H:%M:%SZ' +* SOURCE_DATE_EPOCH - the timestamp provided as a param meant to represent the timestamp at which the source was last modified + + +## Parameters +|name|description|default value|required| +|---|---|---|---| +|label-templates|An array of templates that should be rendered and exposed as an array of labels||true| +|source-date-epoch|A standardised environment variable for build tools to consume in order to produce reproducible output.|""|false| + +## Results +|name|description| +|---|---| +|labels|The rendered labels, rendered from the provided templates| + diff --git a/task/generate-labels/0.1/generate-labels.yaml b/task/generate-labels/0.1/generate-labels.yaml new file mode 100644 index 000000000..acb88def6 --- /dev/null +++ b/task/generate-labels/0.1/generate-labels.yaml @@ -0,0 +1,90 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + labels: + app.kubernetes.io/version: "0.1" + annotations: + tekton.dev/pipelines.minVersion: "0.12.1" + tekton.dev/tags: "konflux" + name: generate-labels +spec: + description: | + Generate labels based on templates. + + Usage may look like the following. + + > - name: generate-labels + > params: + > - name: label-templates + > value: ["release=$SOURCE_DATE_EPOCH", "build-date=$SOURCE_DATE"] + + The following environment variables are defined for use in label-templates + + * ACTUAL_DATE - a date time string containing the time this task runs, formatted +'%Y-%m-%dT%H:%M:%SZ' + * ACTUAL_DATE_EPOCH - the timestamp at the time this task runs + * SOURCE_DATE - a date time string containing the provided source timestamp, formatted +'%Y-%m-%dT%H:%M:%SZ' + * SOURCE_DATE_EPOCH - the timestamp provided as a param meant to represent the timestamp at which the source was last modified + + params: + - name: label-templates + description: An array of templates that should be rendered and exposed as an array of labels + type: array + - name: source-date-epoch + description: A standardised environment variable for build tools to consume in order to produce reproducible output. + default: "" + results: + - name: labels + description: The rendered labels, rendered from the provided templates + type: array + steps: + - name: render + image: quay.io/konflux-ci/yq:latest@sha256:91a7fe73fd28bbfd93ebdcc68cdfd7087d4f2612c627ccd0d5f984190eb7dba6 + env: + - name: SOURCE_DATE_EPOCH + value: "$(params.source-date-epoch)" + args: + - --templates + - $(params.label-templates[*]) + script: | + #!/bin/bash + + templates=() + while [[ $# -gt 0 ]]; do + case $1 in + --templates) + shift + while [[ $# -gt 0 && $1 != --* ]]; do templates+=("$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + ACTUAL_DATE_EPOCH=$(date -u +'%s') + ACTUAL_DATE=$(date -u --date=@"$ACTUAL_DATE_EPOCH" +'%Y-%m-%dT%H:%M:%SZ') + + if [ "$SOURCE_DATE_EPOCH" == "" ]; then + SOURCE_DATE_EPOCH="$ACTUAL_DATE_EPOCH" + fi + SOURCE_DATE=$(date -u --date=@"$SOURCE_DATE_EPOCH" +'%Y-%m-%dT%H:%M:%SZ') + + # Export, so that these are available to the subshell below + export ACTUAL_DATE + export ACTUAL_DATE_EPOCH + export SOURCE_DATE + export SOURCE_DATE_EPOCH + + printf "[]" > result.json + + export label + for template in "${templates[@]}"; do + echo "Processing template $template" + label=$(echo "$template" | envsubst) + echo "Yielding label $label" + yq -oj -i '. += [strenv(label)]' result.json + done + + echo "Created the following labels:" + tee "$(results.labels.path)" < result.json diff --git a/task/generate-labels/OWNERS b/task/generate-labels/OWNERS new file mode 100644 index 000000000..3d74ca650 --- /dev/null +++ b/task/generate-labels/OWNERS @@ -0,0 +1,7 @@ +# See the OWNERS docs: https://go.k8s.io/owners +approvers: + - build-team + - ralphbean +reviewers: + - build-team + - ralphbean