From d041c3cefe81652c1d4081337ef5868d8c36f8f6 Mon Sep 17 00:00:00 2001 From: Harshit Jain Date: Tue, 3 Nov 2026 05:33:07 +0000 Subject: [PATCH 1/2] Add Cloud Build recipe (cloudbuild-gcr.yaml) for gcr.io/cdapio/cdap-controller; retire previous nightly 'latest' Moves the Cloud Build configuration for the gcr.io/cdapio/cdap-controller image out of the Cloud Source Repositories repo `cdap-oss-build` (End of Sale, no review gate) into this repository as `cloudbuild-gcr.yaml`, so the build recipe is reviewed alongside the Dockerfile it builds. The same file serves the nightly `latest` build and manual release builds (`_VERSION=`). Behavioural change vs. the CSR recipe: after a new nightly `latest` is pushed, the digest that was previously `latest` is tagged `no-new-use-public-image-`, so vulnerability scanning stops filing new findings against superseded nightly images. Guards: no-op when `_VERSION` is not `latest`, when there is no previous `latest`, or when the digest did not change; `_TAG_PREVIOUS=false` gives a dry run. --- README.md | 11 +++++++ cloudbuild-gcr.yaml | 75 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 cloudbuild-gcr.yaml diff --git a/README.md b/README.md index 4a16afe9..322f2ae4 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,17 @@ You can also build a docker image containing the CDAP controller and deploy it t make deploy ``` +### Published images (`gcr.io/cdapio/cdap-controller`) + +`gcr.io/cdapio/cdap-controller:latest` is built nightly from the `develop` +branch, and release tags are built on demand, by the Cloud Build triggers +`cdap-controller-docker-nightly` and `cdap-controller-docker` in GCP project +`cdapio`, using [`cloudbuild-gcr.yaml`](cloudbuild-gcr.yaml) from this +repository. After pushing a new nightly `latest`, the build tags the previous +`latest` digest with `no-new-use-public-image-` so that vulnerability +scanning stops reporting against superseded nightly images. See the header of +`cloudbuild-gcr.yaml` for how to dry-run it. + ### Using CDAP operator to manage CDAP instances in Kubernetes A step by step guide of running CDAP in Kubernetes using CDAP operator can be found in the [blog post](https://link.medium.com/hpPbiUYT9X). diff --git a/cloudbuild-gcr.yaml b/cloudbuild-gcr.yaml new file mode 100644 index 00000000..c2ed5d5c --- /dev/null +++ b/cloudbuild-gcr.yaml @@ -0,0 +1,75 @@ +# Cloud Build recipe for the gcr.io/cdapio/cdap-controller image. +# +# Used by two Cloud Build triggers in GCP project `cdapio`: +# * `cdap-controller-docker-nightly` - daily build of `latest` from `develop` +# (fired by Cloud Scheduler job `cdap-controller-docker-nightly-schedule`). +# * `cdap-controller-docker` - release builds, run manually with +# `_VERSION` overridden (e.g. `_VERSION=1.6.0`). +# This file replaces `cloudbuild-operator.yaml` from the retired Cloud Source +# Repositories repo `cdap-oss-build`, so that the build recipe is reviewed in +# the same pull requests as the Dockerfile it builds. +# +# For nightly (`_VERSION=latest`) builds only, after pushing the new `latest` +# the build retires the digest that *was* `latest` before this run by adding +# the tag `no-new-use-public-image-` to it. Vulnerability scanning +# treats that tag as "superseded, do not file new findings", so nightly +# rebuilds stop accumulating open vulnerability bugs against stale images. +# Release builds never retire anything. +# +# Dry run from a checkout (prints what would be retired, tags nothing): +# gcloud builds submit --project=cdapio --config=cloudbuild-gcr.yaml \ +# --substitutions=_TAG_PREVIOUS=false . + +steps: +# Remember which digest is '${_VERSION}' BEFORE anything is built or pushed +# (only acted upon when _VERSION is 'latest'). +- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim' + id: 'record-previous' + entrypoint: 'bash' + args: + - '-c' + - | + gcloud container images describe ${_CDAP_OPERATOR_IMAGE}:${_VERSION} \ + --format='value(image_summary.digest)' > /workspace/prev_digest 2>/dev/null || true + echo "previous ${_VERSION}: $(cat /workspace/prev_digest)" +# Build the CDAP controller docker image from the checked-out source. +- name: 'gcr.io/cloud-builders/docker' + id: 'build-docker' + args: ['build', '-t', '${_CDAP_OPERATOR_IMAGE}:${_VERSION}', '.'] +# Explicit push so the retire step provably runs AFTER the new image exists. +- name: 'gcr.io/cloud-builders/docker' + id: 'push' + args: ['push', '${_CDAP_OPERATOR_IMAGE}:${_VERSION}'] +# Retire the previous nightly 'latest' so vulnerability scanning stops filing +# bugs against it. Only ever adds one tag to one digest; never deletes anything. +- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim' + id: 'tag-previous-latest' + entrypoint: 'bash' + args: + - '-c' + - | + set -euo pipefail + if [ "${_VERSION}" != "latest" ]; then + echo "release build (${_VERSION}) - not a nightly, nothing to retire"; exit 0 + fi + PREV=$(cat /workspace/prev_digest 2>/dev/null || true) + NEW=$(gcloud container images describe ${_CDAP_OPERATOR_IMAGE}:latest --format='value(image_summary.digest)') + if [ -z "$${PREV}" ]; then echo "no previous latest - nothing to retire"; exit 0; fi + if [ "$${PREV}" = "$${NEW}" ]; then echo "latest unchanged ($${NEW}) - refusing to tag the live image"; exit 0; fi + TAG="no-new-use-public-image-$${PREV#sha256:}" + if [ "${_TAG_PREVIOUS}" = "true" ]; then + gcloud container images add-tag "${_CDAP_OPERATOR_IMAGE}@$${PREV}" "${_CDAP_OPERATOR_IMAGE}:$${TAG}" --quiet + echo "retired $${PREV} as $${TAG}" + else + echo "DRY RUN: would tag $${PREV} as $${TAG}" + fi + +options: + machineType: 'N1_HIGHCPU_8' +substitutions: + _CDAP_OPERATOR_IMAGE: 'gcr.io/cdapio/cdap-controller' + _VERSION: 'latest' + _TAG_PREVIOUS: 'true' # set to 'false' for a dry run +images: + - '${_CDAP_OPERATOR_IMAGE}:${_VERSION}' +timeout: 2h From a466349fd5ca2235e3f4f3c60035b9b49a7bfc1d Mon Sep 17 00:00:00 2001 From: Harshit Jain Date: Tue, 3 Nov 2026 06:50:50 +0000 Subject: [PATCH 2/2] Address review: skip registry lookups when nothing can be retired * record-previous: only query the registry for the previous digest on nightly (_VERSION=latest) builds. Release builds never retire anything, so the lookup was a wasted call; the step now matches its own comment. * tag-previous-latest: check for a previous digest *before* describing the new `latest`. With `set -euo pipefail`, a transient lookup failure could previously fail a first-ever run that had nothing to retire. No behaviour change when a previous digest exists: the lookup still runs and a failure there still fails the build loudly (intended - the image is already pushed and a red build is the signal that the retire did not happen). --- cloudbuild-gcr.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cloudbuild-gcr.yaml b/cloudbuild-gcr.yaml index c2ed5d5c..7fff8d98 100644 --- a/cloudbuild-gcr.yaml +++ b/cloudbuild-gcr.yaml @@ -29,9 +29,11 @@ steps: args: - '-c' - | - gcloud container images describe ${_CDAP_OPERATOR_IMAGE}:${_VERSION} \ - --format='value(image_summary.digest)' > /workspace/prev_digest 2>/dev/null || true - echo "previous ${_VERSION}: $(cat /workspace/prev_digest)" + if [ "${_VERSION}" = "latest" ]; then + gcloud container images describe ${_CDAP_OPERATOR_IMAGE}:${_VERSION} \ + --format='value(image_summary.digest)' > /workspace/prev_digest 2>/dev/null || true + fi + echo "previous ${_VERSION}: $(cat /workspace/prev_digest 2>/dev/null || true)" # Build the CDAP controller docker image from the checked-out source. - name: 'gcr.io/cloud-builders/docker' id: 'build-docker' @@ -53,8 +55,8 @@ steps: echo "release build (${_VERSION}) - not a nightly, nothing to retire"; exit 0 fi PREV=$(cat /workspace/prev_digest 2>/dev/null || true) - NEW=$(gcloud container images describe ${_CDAP_OPERATOR_IMAGE}:latest --format='value(image_summary.digest)') if [ -z "$${PREV}" ]; then echo "no previous latest - nothing to retire"; exit 0; fi + NEW=$(gcloud container images describe ${_CDAP_OPERATOR_IMAGE}:latest --format='value(image_summary.digest)') if [ "$${PREV}" = "$${NEW}" ]; then echo "latest unchanged ($${NEW}) - refusing to tag the live image"; exit 0; fi TAG="no-new-use-public-image-$${PREV#sha256:}" if [ "${_TAG_PREVIOUS}" = "true" ]; then