From 7ade0ce306c5d76df7d1f46f0096c8075fecbfb3 Mon Sep 17 00:00:00 2001 From: Yuxiang Zhu Date: Mar 04 2019 06:51:55 +0000 Subject: [PATCH 1/2] CI/CD: Fix `scratch` field in ci.container-image.test.complete messages Following up https://pagure.io/waiverdb/pull-request/282. This PR changes the pagure polling job to pass the original branch name rather than commit ID to `waiverdb-dev` job on master branch changes. `waiverdb-dev` then passes commit ID to downstream container build and integration test jobs to ensure the exact same commit is processed. --- diff --git a/openshift/pipelines/templates/waiverdb-dev.Jenkinsfile b/openshift/pipelines/templates/waiverdb-dev.Jenkinsfile index 4314d0b..97ff1ce 100644 --- a/openshift/pipelines/templates/waiverdb-dev.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-dev.Jenkinsfile @@ -87,6 +87,7 @@ pipeline { branches: [[name: params.WAIVERDB_GIT_REF]], userRemoteConfigs: [[url: params.WAIVERDB_GIT_REPO, refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head']], ]) + env.WAIVERDB_GIT_COMMIT = scmVars.GIT_COMMIT // Generate a version-release number for the target Git commit def versions = sh(returnStdout: true, script: 'source ./version.sh && echo -en "$WAIVERDB_VERSION\n$WAIVERDB_CONTAINER_VERSION"').split('\n') env.WAIVERDB_VERSION = versions[0] @@ -219,7 +220,7 @@ pipeline { def processed = openshift.process(template, "-p", "NAME=${env.BUILDCONFIG_INSTANCE_ID}", '-p', "WAIVERDB_GIT_REPO=${params.WAIVERDB_GIT_REPO}", - '-p', "WAIVERDB_GIT_REF=${params.WAIVERDB_GIT_REF}", + '-p', "WAIVERDB_GIT_REF=${params.WAIVERDB_GIT_REF == params.WAIVERDB_MAIN_BRANCH ? env.WAIVERDB_GIT_COMMIT : params.WAIVERDB_GIT_REF}", '-p', "WAIVERDB_IMAGE_TAG=${env.TEMP_TAG}", '-p', "WAIVERDB_VERSION=${env.WAIVERDB_VERSION}", '-p', "WAIVERDB_IMAGESTREAM_NAME=${params.WAIVERDB_IMAGESTREAM_NAME}", @@ -290,7 +291,7 @@ pipeline { def buildSelector = testBcSelector.startBuild( '-e', "IMAGE=${env.RESULTING_IMAGE_REPO}:${env.RESULTING_TAG}", '-e', "WAIVERDB_GIT_REPO=${params.WAIVERDB_GIT_REPO}", - '-e', "WAIVERDB_GIT_REF=${params.WAIVERDB_GIT_REF}", + '-e', "WAIVERDB_GIT_REF=${params.WAIVERDB_GIT_REF == params.WAIVERDB_MAIN_BRANCH ? env.WAIVERDB_GIT_COMMIT : params.WAIVERDB_GIT_REF}", '-e', "IMAGE_IS_SCRATCH=${params.WAIVERDB_GIT_REF != params.WAIVERDB_MAIN_BRANCH}", ) echo 'Waiting for the integration test result...' diff --git a/openshift/pipelines/templates/waiverdb-polling-pagure.yaml b/openshift/pipelines/templates/waiverdb-polling-pagure.yaml index a8b0eb0..765d833 100644 --- a/openshift/pipelines/templates/waiverdb-polling-pagure.yaml +++ b/openshift/pipelines/templates/waiverdb-polling-pagure.yaml @@ -225,12 +225,9 @@ objects: openshift.withProject("${DEV_PIPELINE_BC_NAMESPACE}") { def bcSelector = openshift.selector('bc', "${DEV_PIPELINE_BC_NAME}") echo 'Starting a dev pipeline build...' - def isMaster = env.PAGURE_POLLING_FOR_PR != 'true' def devBuild = bcSelector.startBuild( '-e', "WAIVERDB_GIT_REPO=${env.GIT_URL}", - '-e', "WAIVERDB_GIT_REF=${isMaster? env.GIT_COMMIT : env.GIT_BRANCH}", - '-e', "FORCE_PUBLISH_IMAGE=${isMaster}", - '-e', "FORCE_PUBLISH_DOCS=${isMaster}", + '-e', "WAIVERDB_GIT_REF=${env.GIT_BRANCH}", '-e', "WAIVERDB_MAIN_BRANCH=${PAGURE_POLLED_BRANCH}", '-e', "BUILD_DISPLAY_RENAME_TO=${currentBuild.displayName}", ) From 4d902fc61b7d7cc450abfc32eee2e22789a93cc6 Mon Sep 17 00:00:00 2001 From: Yuxiang Zhu Date: Mar 04 2019 06:51:55 +0000 Subject: [PATCH 2/2] CI/CD: Trigger image promotion job when receive a Greenwave message When an image is ready to promote, Greenwave sends a CI message to `VirtualTopic.eng.greenwave.decision.update` topic. This PR adds a trigger job to consume that kind of messages and trigger a new build of image promotion job. --- diff --git a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env new file mode 100644 index 0000000..4640d5b --- /dev/null +++ b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env @@ -0,0 +1,5 @@ +NAME=waiverdb-greenwave-promote-to-prod +SOURCE_CONTAINER_REPO=quay.io/factory2/waiverdb +TARGET_TAG=prod +DECISION_CONTEXT_REGEX=c3i_promote_stage_to_prod +MESSAGING_TOPIC=Consumer.rh-jenkins-ci-plugin.c3i-waiverdb-promote-to-prod.VirtualTopic.eng.greenwave.decision.update diff --git a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.tmpl b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.tmpl new file mode 100644 index 0000000..aab28b4 --- /dev/null +++ b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.tmpl @@ -0,0 +1 @@ +waiverdb-greenwave-trigger.yaml diff --git a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env new file mode 100644 index 0000000..9f2647c --- /dev/null +++ b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env @@ -0,0 +1,5 @@ +NAME=waiverdb-greenwave-promote-to-stage +SOURCE_CONTAINER_REPO=quay.io/factory2/waiverdb +TARGET_TAG=prod +DECISION_CONTEXT_REGEX=c3i_promote_dev_to_stage +MESSAGING_TOPIC=Consumer.rh-jenkins-ci-plugin.c3i-waiverdb-promote-to-stage.VirtualTopic.eng.greenwave.decision.update diff --git a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.tmpl b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.tmpl new file mode 100644 index 0000000..aab28b4 --- /dev/null +++ b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.tmpl @@ -0,0 +1 @@ +waiverdb-greenwave-trigger.yaml diff --git a/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env b/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env index 7bab6c5..a974270 100644 --- a/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env +++ b/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env @@ -1,4 +1,3 @@ NAME=waiverdb-promoting-to-prod IMAGE=quay.io/factory2/waiverdb:stage -PROMOTING_DESTINATIONS=quay.io/factory2/waiverdb:prod,docker-registry.engineering.redhat.com/factory2/waiverdb:prod -DEST_IMAGESTREAM_TAG=prod +DEST_TAG=prod diff --git a/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env b/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env index 53bb03d..a8227b7 100644 --- a/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env +++ b/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env @@ -1,4 +1,3 @@ NAME=waiverdb-promoting-to-stage IMAGE=quay.io/factory2/waiverdb:latest -PROMOTING_DESTINATIONS=quay.io/factory2/waiverdb:stage,docker-registry.engineering.redhat.com/factory2/waiverdb:stage -DEST_IMAGESTREAM_TAG=stage +DEST_TAG=stage diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile b/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile new file mode 100644 index 0000000..15f8088 --- /dev/null +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile @@ -0,0 +1,85 @@ +// Use scripted syntax because CIBuildTrigger currently doesn't support the declarative syntax +properties([ + disableConcurrentBuilds(), + pipelineTriggers([ + // example: https://github.com/jenkinsci/jms-messaging-plugin/blob/9b9387c3a52f037ba0d019c2ebcf2a2796fc6397/src/test/java/com/redhat/jenkins/plugins/ci/integration/AmqMessagingPluginIntegrationTest.java + [$class: 'CIBuildTrigger', + providerData: [$class: 'ActiveMQSubscriberProviderData', + name: params.MESSAGING_PROVIDER, + overrides: [topic: params.MESSAGING_TOPIC], + checks: [ + [field: '$.subject_type', expectedValue: 'container-image'], + [field: '$.subject_identifier', expectedValue: params.SUBJECT_IDENTIFIER_REGEX], + [field: '$.decision_context', expectedValue: params.DECISION_CONTEXT_REGEX], + [field: '$.policies_satisfied', expectedValue: 'true'], + ], + ], + ], + ]), +]) + +if (!params.CI_MESSAGE) { + echo 'This build is not started by a CI message. Only configurations were done.' + return +} + +def label = "jenkins-slave-${UUID.randomUUID().toString()}" +podTemplate( + cloud: "${params.OPENSHIFT_CLOUD_NAME}", + label: label, + serviceAccount: "${env.JENKINS_AGENT_SERVICE_ACCOUNT}", + defaultContainer: 'jnlp', + yaml: """ + apiVersion: v1 + kind: Pod + metadata: + labels: + app: "jenkins-${env.JOB_BASE_NAME}" + factory2-pipeline-kind: "waiverdb-greenwave-trigger" + factory2-pipeline-build-number: "${env.BUILD_NUMBER}" + spec: + containers: + - name: jnlp + image: ${params.JENKINS_AGENT_IMAGE} + imagePullPolicy: Always + tty: true + resources: + requests: + memory: 256Mi + cpu: 200m + limits: + memory: 512Mi + cpu: 300m + """ +) { + node(label) { + stage('trigger promotion') { + def message = readJSON text: params.CI_MESSAGE + // Extract the digest of the image to be promoted. + // e.g. factory2/waiverdb@sha256:35201c572fc8a137862b7a256476add8d7465fa5043d53d117f4132402f8ef6b + // -> sha256:35201c572fc8a137862b7a256476add8d7465fa5043d53d117f4132402f8ef6b + def digest = (message.subject_identifier =~ /@(sha256:\w+)$/)[0][1] + // Generate the pull spec of the image + // e.g. quay.io/factory2/waiverdb@sha256:35201c572fc8a137862b7a256476add8d7465fa5043d53d117f4132402f8ef6b + def image = params.SOURCE_CONTAINER_REPO + '@' + digest + // The target tag name (stage, prod) is determined by `decision_context` field in the Greenwave message. + // e.g. If decision_context == 'c3i_promote_dev_to_stage', the image will be promoted to 'stage'. + def targetTag = params.TARGET_TAG + def promotionJob = params.IMAGE_PROMOTION_JOB ?: "waiverdb-promoting-to-${targetTag}" + + echo "Starting a new build to promote image ${image} to :${targetTag}..." + openshift.withCluster() { + def bcSelector = openshift.selector('bc', promotionJob) + def buildSelector = bcSelector.startBuild( + '-e', "IMAGE=${image}", + '-e', "DEST_TAG=${targetTag}", + ) + bcSelector.watch { + return !(it.object().status.phase in ["New", "Pending"]) + } + buildInfo = buildSelector.object() + echo "Build ${buildInfo.metadata.annotations['openshift.io/jenkins-build-uri'] ?: buildInfo.metadata.name} started." + } + } + } +} diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml new file mode 100644 index 0000000..bf90cac --- /dev/null +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml @@ -0,0 +1,113 @@ +# Template to produce a new OpenShift pipeline job for triggering a build on repotracker messages +# +--- +apiVersion: v1 +kind: Template +metadata: + name: waiverdb-greenwave-trigger +labels: + template: waiverdb-greenwave-trigger +parameters: +- name: NAME + displayName: Short unique identifier for the templated instances + description: This field is used to deploy multiple pipelines to one OpenShift project from this template. + value: waiverdb-greenwave-trigger +- name: WAIVERDB_GIT_REPO + displayName: WaiverDB Git repo URL + description: Default WaiverDB Git repo URL in which to run dev tests against + value: "https://pagure.io/waiverdb.git" +- name: WAIVERDB_GIT_REF + displayName: WaiverDB Git repo ref + description: Default WaiverDB Git repo ref in which to run dev tests against + value: master +- name: DECISION_CONTEXT_REGEX + displayName: Regex pattern for Greenwave decision context in CI message + required: true +- name: SUBJECT_IDENTIFIER_REGEX + displayName: Regex pattern for Greenwave subject identifier in CI message + value: ^factory2/waiverdb@ +- name: SOURCE_CONTAINER_REPO + displayName: Container repo of the image + value: quay.io/factory2/waiverdb +- name: TARGET_TAG + displayName: Tag name to promote the image to + required: true +- name: IMAGE_PROMOTION_JOB + displayName: Downstream image promotion job to trigger +- name: MESSAGING_PROVIDER + displayName: Name of the JMS messaging provider + value: Red Hat UMB +- name: MESSAGING_TOPIC + displayName: Name of the topic that the trigger subscribes to + value: "Consumer.rh-jenkins-ci-plugin.c3i-greenwave-trigger.VirtualTopic.eng.greenwave.decision.update" +- name: JENKINS_AGENT_IMAGE + displayName: Container image for Jenkins slave pods + value: docker-registry.engineering.redhat.com/factory2/waiverdb-jenkins-slave:latest +- name: OPENSHIFT_CLOUD_NAME + displayName: Name of OpenShift cloud in Jenkins master configuration + value: openshift +objects: +- kind: ServiceAccount + apiVersion: v1 + metadata: + name: "${NAME}-jenkins-slave" + labels: + app: "${NAME}" +- kind: RoleBinding + apiVersion: v1 + metadata: + name: "${NAME}-jenkins-slave_edit" + labels: + app: "${NAME}" + subjects: + - kind: ServiceAccount + name: "${NAME}-jenkins-slave" + roleRef: + name: edit +- kind: "BuildConfig" + apiVersion: "v1" + metadata: + name: "${NAME}" + labels: + app: "${NAME}" + spec: + runPolicy: "Serial" + completionDeadlineSeconds: 1800 + source: + git: + uri: "${WAIVERDB_GIT_REPO}" + ref: "${WAIVERDB_GIT_REF}" + strategy: + type: JenkinsPipeline + jenkinsPipelineStrategy: + env: + - name: WAIVERDB_GIT_REPO + value: "${WAIVERDB_GIT_REPO}" + - name: WAIVERDB_GIT_REF + value: "${WAIVERDB_GIT_REF}" + - name: OPENSHIFT_CLOUD_NAME + value: "${OPENSHIFT_CLOUD_NAME}" + - name: JENKINS_AGENT_IMAGE + value: "${JENKINS_AGENT_IMAGE}" + - name: JENKINS_AGENT_SERVICE_ACCOUNT + value: "${NAME}-jenkins-slave" + - name: SOURCE_CONTAINER_REPO + value: "${SOURCE_CONTAINER_REPO}" + - name: TARGET_TAG + value: "${TARGET_TAG}" + - name: IMAGE_PROMOTION_JOB + value: "${IMAGE_PROMOTION_JOB}" + - name: DECISION_CONTEXT_REGEX + value: "${DECISION_CONTEXT_REGEX}" + - name: SUBJECT_IDENTIFIER_REGEX + value: "${SUBJECT_IDENTIFIER_REGEX}" + - name: MESSAGING_PROVIDER + value: "${MESSAGING_PROVIDER}" + - name: MESSAGING_TOPIC + value: "${MESSAGING_TOPIC}" + # CI_MESSAGE and MESSAGE_HEADERS are used internally by JMS messaging plugin + - name: CI_MESSAGE + value: + - name: MESSAGE_HEADERS + value: + jenkinsfilePath: openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile diff --git a/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml b/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml index 891c2ff..2edbf20 100644 --- a/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml +++ b/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml @@ -20,10 +20,10 @@ parameters: description: This field must be in repo:tag or repo@sha256 format value: quay.io/factory2/waiverdb:latest - name: PROMOTING_DESTINATIONS - displayName: Comma seperated list of container repository:tag to which the image will be promoted + displayName: Comma seperated list of container repositories (without tags) to which the image will be promoted description: OpenShift registries must be prefixed with 'atomic:' required: false - value: "atomic:docker-registry.engineering.redhat.com/factory2/waiverdb:stage,quay.io/factory2/waiverdb:stage" + value: "quay.io/factory2/waiverdb,atomic:docker-registry.engineering.redhat.com/factory2/waiverdb" - name: CONTAINER_REGISTRY_CREDENTIALS displayName: Secret name of container registries used for pulling and pushing images value: factory2-pipeline-registry-credentials @@ -41,8 +41,8 @@ parameters: description: Leaving blank means using the same namespace as the pipeline build required: false value: waiverdb-stage -- name: DEST_IMAGESTREAM_TAG - displayName: Tag name of the ImageStream to be tagged +- name: DEST_TAG + displayName: Name of the new tag value: "stage" required: true - name: WAIVERDB_GIT_REPO @@ -112,8 +112,8 @@ objects: value: "${DEST_IMAGESTREAM_NAME}" - name: "DEST_IMAGESTREAM_NAMESPACE" value: "${DEST_IMAGESTREAM_NAMESPACE}" - - name: "DEST_IMAGESTREAM_TAG" - value: "${DEST_IMAGESTREAM_TAG}" + - name: "DEST_TAG" + value: "${DEST_TAG}" - name: JENKINS_AGENT_IMAGE value: "${JENKINS_AGENT_IMAGE}" - name: JENKINS_AGENT_CLOUD_NAME diff --git a/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile b/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile index d6f27a0..c76272d 100644 --- a/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile @@ -91,6 +91,7 @@ pipeline { if (!it.startsWith('atomic:') && !it.startsWith('docker://')) { dest = 'docker://' + it } + dest += ':' + params.DEST_TAG echo "Pushing container to ${dest}..." withEnv(["DEST_IMAGE_REF=${dest}"]) { /* Pushes to the internal registry can sometimes randomly fail @@ -115,7 +116,7 @@ pipeline { } steps { script { - def destRef = "${params.DEST_IMAGESTREAM_NAMESPACE ?: env.PIPELINE_NAMESPACE }/${params.DEST_IMAGESTREAM_NAME}:${params.DEST_IMAGESTREAM_TAG}" + def destRef = "${params.DEST_IMAGESTREAM_NAMESPACE ?: env.PIPELINE_NAMESPACE }/${params.DEST_IMAGESTREAM_NAME}:${params.DEST_TAG}" openshift.withCluster() { echo "Tagging ${params.IMAGE} into ${destRef}..." openshift.tag('--source=docker', params.IMAGE, destRef)