diff --git a/.tekton/docker-build-multi-platform-oci-ta-pull-request.yaml b/.tekton/docker-build-multi-platform-oci-ta-pull-request.yaml index e54a637a..fa857a5a 100644 --- a/.tekton/docker-build-multi-platform-oci-ta-pull-request.yaml +++ b/.tekton/docker-build-multi-platform-oci-ta-pull-request.yaml @@ -10,6 +10,7 @@ metadata: pipelinesascode.tekton.dev/on-cel-expression: event == "pull_request" && target_branch == "main" && ( ".tekton/docker-build-multi-platform-oci-ta-pull-request.yaml".pathChanged() || "pipeline-tests".pathChanged() || "pipelines/docker-build-multi-platform-oci-ta.yaml".pathChanged() + || "tasks/get-version-from-configmap.yaml".pathChanged() ) pipelinesascode.tekton.dev/pipeline: pipelines/docker-build-multi-platform-oci-ta.yaml creationTimestamp: null diff --git a/.tekton/docker-build-oci-ta-pull-request.yaml b/.tekton/docker-build-oci-ta-pull-request.yaml index 924382a7..a316b397 100644 --- a/.tekton/docker-build-oci-ta-pull-request.yaml +++ b/.tekton/docker-build-oci-ta-pull-request.yaml @@ -10,7 +10,7 @@ metadata: pipelinesascode.tekton.dev/on-cel-expression: event == "pull_request" && target_branch == "main" && ( ".tekton/docker-build-oci-ta-pull-request.yaml".pathChanged() || "pipeline-tests".pathChanged() || "pipelines/docker-build-oci-ta.yaml".pathChanged() - || "tasks/go-unit-test-oci-ta.yaml".pathChanged() ) + || "tasks/go-unit-test-oci-ta.yaml".pathChanged() || "tasks/get-version-from-configmap.yaml".pathChanged() ) pipelinesascode.tekton.dev/pipeline: pipelines/docker-build-oci-ta.yaml creationTimestamp: null labels: diff --git a/.tekton/docker-build-pull-request.yaml b/.tekton/docker-build-pull-request.yaml index 8a485799..d037af2e 100644 --- a/.tekton/docker-build-pull-request.yaml +++ b/.tekton/docker-build-pull-request.yaml @@ -10,6 +10,7 @@ metadata: pipelinesascode.tekton.dev/on-cel-expression: event == "pull_request" && target_branch == "main" && ( ".tekton/docker-build-pull-request.yaml".pathChanged() || "pipeline-tests".pathChanged() || "pipelines/docker-build.yaml".pathChanged() + || "tasks/get-version-from-configmap.yaml".pathChanged() ) pipelinesascode.tekton.dev/pipeline: pipelines/docker-build.yaml creationTimestamp: null diff --git a/konflux-configs/README.md b/konflux-configs/README.md index 3b61f3b4..6994488c 100644 --- a/konflux-configs/README.md +++ b/konflux-configs/README.md @@ -264,6 +264,48 @@ konflux-configs/ └── README.md # This file ``` + +## Release Version Mappings + +Container image `version` labels are resolved centrally from the +`rhtas-repo-branch-versions` ConfigMap instead of per-repo Tekton params. +This allows bumping versions for all components and branches in a single PR +to this repository. + +### Source of truth + +Version mappings live in +[`base/config/rhtas-versions.properties`](base/config/rhtas-versions.properties) +and are deployed as ConfigMap `rhtas-repo-branch-versions` via the +configuration-as-code pipeline. + +**Key format:** + +| Pattern | Example | When used | +|---------|---------|-----------| +| `__` | `fulcio__release-1.4=1.4.2` | Exact repo + branch match | +| `` | `fulcio=1.5.0-dev` | Fallback when branch-specific key is missing | + +The repo name is derived from the component `git-url` (e.g. +`https://github.com/securesign/fulcio` → `fulcio`). The branch comes from +the Pipelines-as-Code `target_branch` annotation on each PipelineRun. + +### Bumping versions for a release + +1. Edit `base/config/rhtas-versions.properties` with the new semver values +2. Open a PR — only this repo needs to change (no per-component-repo PRs) +3. On merge to `main`, the CAC pipeline builds and deploys the updated ConfigMap +4. Subsequent builds on any branch pick up the new version automatically + +### Verifying a build + +Check the `get-version-from-configmap` task log for the resolved lookup key, +then confirm the built image label: + +```bash +skopeo inspect docker://quay.io/.../component@sha256:... | jq '.Labels.version' +``` + ## Customization See [Directory Structure](#directory-structure) for file locations diff --git a/konflux-configs/base/config/kustomization.yaml b/konflux-configs/base/config/kustomization.yaml index a9262ca6..0b6857cd 100644 --- a/konflux-configs/base/config/kustomization.yaml +++ b/konflux-configs/base/config/kustomization.yaml @@ -9,3 +9,9 @@ configMapGenerator: literals: - automerge="true" - platformAutomerge="true" + + # Release version mappings for repo+branch + # Versions are defined in rhtas-versions.properties + - name: rhtas-repo-branch-versions + envs: + - rhtas-versions.properties diff --git a/konflux-configs/base/config/rhtas-versions.properties b/konflux-configs/base/config/rhtas-versions.properties new file mode 100644 index 00000000..ef78dbf8 --- /dev/null +++ b/konflux-configs/base/config/rhtas-versions.properties @@ -0,0 +1,144 @@ +# RHTAS Release Version Mappings +# Format: __= +# Double underscore (__) separates repo from branch + +# ============================================================================ +# RHTAS OPERATOR CORE COMPONENTS +# These components are deployed and managed by the RHTAS operator +# ============================================================================ + + +# === Fulcio === +fulcio__main=1.5.0 +fulcio__release-1.4=1.4.2 +fulcio__release-1.3=1.3.6 + +# === Rekor === +rekor__main=1.5.0 +rekor__release-1.4=1.4.2 +rekor__release-1.3=1.3.6 + +# === Timestamp Server === +timestamp-authority__main=1.5.0 +timestamp-authority__release-1.4=1.4.2 +timestamp-authority__release-1.3=1.3.6 + +# === TUF Server === +tuf-server__main=1.5.0 +tuf-server__release-1.4=1.4.2 +tuf-server__release-1.3=1.3.6 + +# === Trillian === +trillian__main=1.5.0 +trillian__release-1.4=1.4.2 +trillian__release-1.3=1.3.6 + +# === RHTAS Operator (the operator itself) === +secure-sign-operator__main=1.5.0 +secure-sign-operator__release-1.4=1.4.2 +secure-sign-operator__release-1.3=1.3.6 + +# === RHTAS Console === +rhtas-console__main=1.5.0 +rhtas-console__release-1.4=1.4.2 +rhtas-console__release-1.3=1.3.6 + +# === RHTAS Console UI === +rhtas-console-ui__main=1.5.0 +rhtas-console-ui__release-1.4=1.4.2 +rhtas-console-ui__release-1.3=1.3.6 + +# === Cosign === +cosign__main=1.5.0 +cosign__release-1.4=1.4.2 +cosign__release-1.3=1.3.6 + +# === Gitsign === +gitsign__main=1.5.0 +gitsign__release-1.4=1.4.2 +gitsign__release-1.3=1.3.6 + +# === Certificate Transparency Go === +certificate-transparency-go__main=1.5.0 +certificate-transparency-go__release-1.4=1.4.2 +certificate-transparency-go__release-1.3=1.3.6 + +# === Model Transparency Go === +model-transparency-go__main=1.5.0 +model-transparency-go__release-1.4=1.4.2 +model-transparency-go__release-1.3=1.3.6 + +# === Rekor Search UI === +rekor-search-ui__main=1.5.0 +rekor-search-ui__release-1.4=1.4.2 +rekor-search-ui__release-1.3=1.3.6 +# ============================================================================ +# AUXILIARY COMPONENTS +# Supporting tools and utilities +# ============================================================================ + +# === Artifact Signer Ansible === +artifact-signer-ansible__main=1.5.0 +artifact-signer-ansible__release-1.4=1.4.2 +artifact-signer-ansible__release-1.3=1.3.6 + +# === Model Transparency === +model-transparency__main=0.1.0 + +# === Model Validation Operator === +model-validation-operator__main=0.1.0 + +# === Tough === +tough__develop=1.5.0 +tough__release-1.4=1.4.2 +tough__release-1.3=1.3.6 + +# === Rekor Monitor === +rekor-monitor__main=1.5.0-dev +rekor-monitor__release-1.4=1.4.2 +rekor-monitor__release-1.3=1.3.6 + +# === Segment Backup Job === +segment-backup-job__main=1.5.0-dev +segment-backup-job__release-1.4=1.4.2 +segment-backup-job__release-1.3=1.3.6 + +# ============================================================================ +# POLICY CONTROLLER COMPONENTS +# Separate release cycle from main RHTAS components +# ============================================================================ + +# === Policy Controller === +policy-controller__main=1.5.0 +policy-controller__release-1.0=1.4.2 + +# === Policy Controller Operator === +policy-controller-operator__main=1.5.0 +policy-controller-operator__release-1.0=1.4.2 + +# ============================================================================ +# REPO-ONLY FALLBACKS +# Used when exact repo__branch combination is not found +# ============================================================================ + +artifact-signer-ansible=1.5.0-dev +certificate-transparency-go=1.5.0-dev +cosign=1.5.0-dev +fulcio=1.5.0-dev +gitsign=1.5.0-dev +model-transparency=1.5.0-dev +model-transparency-go=1.5.0-dev +model-validation-operator=1.5.0-dev +policy-controller=1.5.0-dev +policy-controller-operator=1.5.0-dev +rekor=1.5.0-dev +rekor-monitor=1.5.0-dev +rekor-search-ui=1.5.0-dev +rhtas-console=1.5.0-dev +rhtas-console-ui=1.5.0-dev +secure-sign-operator=1.5.0-dev +segment-backup-job=1.5.0-dev +timestamp-authority=1.5.0-dev +tough=1.5.0-dev +trillian=1.5.0-dev +tuf-server=1.5.0-dev diff --git a/konflux-configs/base/project/base/ec/kustomization.yaml b/konflux-configs/base/project/base/ec/kustomization.yaml index 849a7e8f..a36550a8 100644 --- a/konflux-configs/base/project/base/ec/kustomization.yaml +++ b/konflux-configs/base/project/base/ec/kustomization.yaml @@ -20,6 +20,13 @@ patches: labelSelector: "build.rhtas.com/ec=registry-rhtas-operator" path: patch/registry-rhtas-operator.yaml + # For operator monorepos that inject cross-component digests into BUILD_ARGS. + # EC must run on the group snapshot so dependency digests are trusted. + - target: + kind: ProjectDevelopmentStreamTemplate + labelSelector: "build.rhtas.com/ec=registry-rhtas-operator-group-only" + path: patch/registry-rhtas-operator-group-only.yaml + # For templates with build.rhtas.com/ec=fbc-standard (FBC patch) - target: kind: ProjectDevelopmentStreamTemplate diff --git a/konflux-configs/base/project/base/ec/patch/registry-rhtas-operator-group-only.yaml b/konflux-configs/base/project/base/ec/patch/registry-rhtas-operator-group-only.yaml new file mode 100644 index 00000000..6e771322 --- /dev/null +++ b/konflux-configs/base/project/base/ec/patch/registry-rhtas-operator-group-only.yaml @@ -0,0 +1,27 @@ +- op: add + path: /spec/resources/- + value: + apiVersion: appstudio.redhat.com/v1beta2 + kind: IntegrationTestScenario + metadata: + annotations: + test.appstudio.openshift.io/kind: enterprise-contract + name: "{{.application}}{{.nameSuffix}}-enterprise-contract-group" + spec: + application: "{{.application}}{{.nameSuffix}}" + contexts: + - description: execute the integration test for a Snapshot of the `group` type + name: group + params: + - name: POLICY_CONFIGURATION + value: rhtap-releng-tenant/registry-rhtas + resolverRef: + params: + - name: url + value: https://github.com/konflux-ci/build-definitions + - name: revision + value: main + - name: pathInRepo + value: pipelines/enterprise-contract.yaml + resolver: git + resourceKind: pipeline diff --git a/konflux-configs/base/project/overlay/model-validation-operator/template.yaml b/konflux-configs/base/project/overlay/model-validation-operator/template.yaml index c2db12c5..d0a73351 100644 --- a/konflux-configs/base/project/overlay/model-validation-operator/template.yaml +++ b/konflux-configs/base/project/overlay/model-validation-operator/template.yaml @@ -3,7 +3,7 @@ kind: ProjectDevelopmentStreamTemplate metadata: name: model-validation-operator-template labels: - build.rhtas.com/ec: registry-rhtas-operator + build.rhtas.com/ec: registry-rhtas-operator-group-only build.rhtas.com/type: operator spec: project: model-validation-operator diff --git a/pipelines/bundle-build-oci-ta.yaml b/pipelines/bundle-build-oci-ta.yaml index e74f3504..215088ce 100644 --- a/pipelines/bundle-build-oci-ta.yaml +++ b/pipelines/bundle-build-oci-ta.yaml @@ -200,6 +200,25 @@ spec: workspace: git-auth - name: netrc workspace: netrc + - name: get-version-from-configmap + taskRef: + resolver: git + params: + - name: url + value: "https://github.com/securesign/pipelines.git" + - name: revision + value: main + - name: pathInRepo + value: tasks/get-version-from-configmap.yaml + params: + - name: git-url + value: $(params.git-url) + - name: configmap-name + value: rhtas-repo-branch-versions + - name: configmap-namespace + value: $(context.pipelineRun.namespace) + - name: default-version + value: $(params.release-version) - name: derive-product-version taskRef: resolver: git @@ -212,9 +231,11 @@ spec: value: tasks/derive-product-version.yaml params: - name: release-version - value: $(params.release-version) + value: $(tasks.get-version-from-configmap.results.release-version) - name: image-version value: $(params.image-version) + runAfter: + - get-version-from-configmap - name: generate-labels params: - name: label-templates diff --git a/pipelines/docker-build-multi-platform-oci-ta.yaml b/pipelines/docker-build-multi-platform-oci-ta.yaml index ab184666..08a66b91 100644 --- a/pipelines/docker-build-multi-platform-oci-ta.yaml +++ b/pipelines/docker-build-multi-platform-oci-ta.yaml @@ -119,7 +119,7 @@ spec: - description: The Go base image used to run the unit tests name: go_base_image type: string - default: registry.redhat.io/ubi9/go-toolset@sha256:bed6eea46459b3afbe9c46de513172ab08001a8a846ad29c0d7b124d6f81eeba + default: registry.redhat.io/ubi9/go-toolset@sha256:35f08031de19eb51d6b35ed62c6357d3529bc69a8db65cf623ea5f0b44051999 - name: enable-package-registry-proxy default: 'true' description: Use the package registry proxy when prefetching dependencies @@ -218,6 +218,25 @@ spec: workspace: git-auth - name: netrc workspace: netrc + - name: get-version-from-configmap + taskRef: + resolver: git + params: + - name: url + value: "https://github.com/securesign/pipelines.git" + - name: revision + value: main + - name: pathInRepo + value: tasks/get-version-from-configmap.yaml + params: + - name: git-url + value: $(params.git-url) + - name: configmap-name + value: rhtas-repo-branch-versions + - name: configmap-namespace + value: $(context.pipelineRun.namespace) + - name: default-version + value: $(params.release-version) - name: derive-product-version taskRef: resolver: git @@ -230,9 +249,11 @@ spec: value: tasks/derive-product-version.yaml params: - name: release-version - value: $(params.release-version) + value: $(tasks.get-version-from-configmap.results.release-version) - name: image-version value: $(params.image-version) + runAfter: + - get-version-from-configmap - name: generate-labels params: - name: label-templates diff --git a/pipelines/docker-build-oci-ta.yaml b/pipelines/docker-build-oci-ta.yaml index baa79743..93a59c81 100644 --- a/pipelines/docker-build-oci-ta.yaml +++ b/pipelines/docker-build-oci-ta.yaml @@ -82,7 +82,7 @@ spec: - description: The Go base image used to run the unit tests name: go_base_image type: string - default: registry.redhat.io/ubi9/go-toolset@sha256:bed6eea46459b3afbe9c46de513172ab08001a8a846ad29c0d7b124d6f81eeba + default: registry.redhat.io/ubi9/go-toolset@sha256:35f08031de19eb51d6b35ed62c6357d3529bc69a8db65cf623ea5f0b44051999 - name: buildah-format default: docker type: string @@ -201,6 +201,25 @@ spec: workspace: git-auth - name: netrc workspace: netrc + - name: get-version-from-configmap + taskRef: + resolver: git + params: + - name: url + value: "https://github.com/securesign/pipelines.git" + - name: revision + value: main + - name: pathInRepo + value: tasks/get-version-from-configmap.yaml + params: + - name: git-url + value: $(params.git-url) + - name: configmap-name + value: rhtas-repo-branch-versions + - name: configmap-namespace + value: $(context.pipelineRun.namespace) + - name: default-version + value: $(params.release-version) - name: derive-product-version taskRef: resolver: git @@ -213,9 +232,11 @@ spec: value: tasks/derive-product-version.yaml params: - name: release-version - value: $(params.release-version) + value: $(tasks.get-version-from-configmap.results.release-version) - name: image-version value: $(params.image-version) + runAfter: + - get-version-from-configmap - name: generate-labels params: - name: label-templates diff --git a/pipelines/docker-build.yaml b/pipelines/docker-build.yaml index c47f2bac..d6594b01 100644 --- a/pipelines/docker-build.yaml +++ b/pipelines/docker-build.yaml @@ -93,6 +93,10 @@ spec: default: docker type: string description: The format for the resulting image's mediaType. Valid values are oci or docker. + - name: image-version + default: "" + type: string + description: Image metadata version label. - name: release-version default: "1.3.1" type: string @@ -200,15 +204,51 @@ spec: workspace: git-auth - name: netrc workspace: netrc + - name: get-version-from-configmap + taskRef: + resolver: git + params: + - name: url + value: "https://github.com/securesign/pipelines.git" + - name: revision + value: main + - name: pathInRepo + value: tasks/get-version-from-configmap.yaml + params: + - name: git-url + value: $(params.git-url) + - name: configmap-name + value: rhtas-repo-branch-versions + - name: configmap-namespace + value: $(context.pipelineRun.namespace) + - name: default-version + value: $(params.release-version) + - name: derive-product-version + taskRef: + resolver: git + params: + - name: url + value: "https://github.com/securesign/pipelines.git" + - name: revision + value: "df75ceee623c9c7f1b330c19122a6e354641d019" + - name: pathInRepo + value: tasks/derive-product-version.yaml + params: + - name: release-version + value: $(tasks.get-version-from-configmap.results.release-version) + - name: image-version + value: $(params.image-version) + runAfter: + - get-version-from-configmap - name: generate-labels params: - name: label-templates value: - "release=$SOURCE_DATE_EPOCH" - - "version=$(params.release-version)" + - "version=$(tasks.derive-product-version.results.image-version)" - "vendor=Red Hat, Inc." - "maintainer=rhtas-support@redhat.com" - - "cpe=cpe:/a:redhat:trusted_artifact_signer:$(params.product-version)::el9" + - "cpe=cpe:/a:redhat:trusted_artifact_signer:$(tasks.derive-product-version.results.product-version)::el9" - "org.opencontainers.image.created=$SOURCE_DATE" - "com.redhat.license_terms=https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI" - "url=https://catalog.redhat.com/en/software/container-stacks/detail/6604180e80e2fa3e4947d1d5#overview" @@ -217,6 +257,7 @@ spec: value: '$(tasks.clone-repository.results.commit-timestamp)' runAfter: - clone-repository + - derive-product-version taskRef: params: - name: name diff --git a/tasks/get-version-from-configmap.yaml b/tasks/get-version-from-configmap.yaml new file mode 100644 index 00000000..fd5bf40b --- /dev/null +++ b/tasks/get-version-from-configmap.yaml @@ -0,0 +1,116 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: get-version-from-configmap +spec: + description: > + Looks up release version from ConfigMap based on git repository and branch. + Performs hierarchical lookup: __ → default fallback. + params: + - name: git-url + description: Git repository URL (e.g., https://github.com/securesign/fulcio) + type: string + - name: target-branch + description: Target git branch for version lookup; falls back to PipelineRun annotation when empty + type: string + default: "" + - name: configmap-name + description: Name of the ConfigMap containing version mappings + type: string + default: rhtas-repo-branch-versions + - name: configmap-namespace + description: Namespace where the ConfigMap is located + type: string + default: rhtas-tenant + - name: default-version + description: Fallback version if lookup fails + type: string + default: "0.0.0-dev" + results: + - name: release-version + description: The resolved release version from ConfigMap + - name: lookup-key + description: The key used for the successful lookup (for debugging) + steps: + - name: get-version + image: quay.io/openshift/origin-cli:4.15 + env: + - name: TASKRUN_NAME + value: $(context.taskRun.name) + - name: TASKRUN_NAMESPACE + value: $(context.taskRun.namespace) + - name: PAC_TARGET_BRANCH + value: $(context.pipelineRun.annotations['build.appstudio.redhat.com/target_branch']) + script: | + #!/bin/bash + set -e + + GIT_URL="$(params.git-url)" + CM_NAME="$(params.configmap-name)" + CM_NAMESPACE="$(params.configmap-namespace)" + DEFAULT_VERSION="$(params.default-version)" + + # Prefer explicit param; fall back to PAC annotation (via env — context refs + # are not substituted inside script blocks) + BRANCH="$(params.target-branch)" + if [ -z "${BRANCH}" ] && [ -n "${TASKRUN_NAME}" ]; then + PIPELINERUN_NAME=$(oc get taskrun "${TASKRUN_NAME}" -n "${TASKRUN_NAMESPACE}" \ + -o jsonpath='{.metadata.ownerReferences[?(@.kind=="PipelineRun")].name}' 2>/dev/null || echo "") + if [ -n "${PIPELINERUN_NAME}" ]; then + BRANCH=$(oc get pipelinerun "${PIPELINERUN_NAME}" -n "${TASKRUN_NAMESPACE}" \ + -o jsonpath="{.metadata.annotations['build\.appstudio\.redhat\.com/target_branch']}" 2>/dev/null || echo "") + fi + fi + + # Extract repository name from git URL + # Examples: + # https://github.com/securesign/fulcio → fulcio + # https://github.com/securesign/fulcio.git → fulcio + REPO_NAME=$(echo "${GIT_URL}" | sed 's|.*/||' | sed 's|\.git$||') + + echo "Git URL: ${GIT_URL}" + echo "Repository: ${REPO_NAME}" + echo "Branch: ${BRANCH}" + echo "ConfigMap: ${CM_NAMESPACE}/${CM_NAME}" + echo "" + + # Try hierarchical lookup: + # 1. Exact match: __ + # 2. Repo fallback: + # 3. Default fallback + + LOOKUP_KEY="${REPO_NAME}__${BRANCH}" + JSONPATH_KEY="${LOOKUP_KEY//./\\.}" + echo "Looking up key: ${LOOKUP_KEY}" + + # Use go-template index — JSONPath dot-notation breaks on keys with '.' + # (e.g. fulcio__release-1.4). + VERSION=$(oc get configmap "${CM_NAME}" -n "${CM_NAMESPACE}" \ + -o jsonpath="{.data['${JSONPATH_KEY}']}" 2>/dev/null || echo "") + + if [ -n "${VERSION}" ]; then + echo "✅ Found exact match: ${LOOKUP_KEY} = ${VERSION}" + echo -n "${VERSION}" > "$(results.release-version.path)" + echo -n "${LOOKUP_KEY}" > "$(results.lookup-key.path)" + exit 0 + fi + + # Fallback to repo-only key + LOOKUP_KEY="${REPO_NAME}" + JSONPATH_KEY="${LOOKUP_KEY//./\\.}" + echo "Exact match not found. Trying fallback key: ${LOOKUP_KEY}" + + VERSION=$(oc get configmap "${CM_NAME}" -n "${CM_NAMESPACE}" \ + -o jsonpath="{.data['${JSONPATH_KEY}']}" 2>/dev/null || echo "") + + if [ -n "${VERSION}" ]; then + echo "✅ Found repo fallback: ${LOOKUP_KEY} = ${VERSION}" + echo -n "${VERSION}" > "$(results.release-version.path)" + echo -n "${LOOKUP_KEY}" > "$(results.lookup-key.path)" + exit 0 + fi + + # Use default fallback + echo "⚠️ No ConfigMap entry found. Using default: ${DEFAULT_VERSION}" + echo -n "${DEFAULT_VERSION}" > "$(results.release-version.path)" + echo -n "default" > "$(results.lookup-key.path)"