From b98d57774e4ff023713aab792e17b33ad79dfe32 Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:53 +0000 Subject: [PATCH 1/11] Integrate pipeline-as-a-service Pipeline-as-a-service replaces deployer from factory2-segment-tests. JIRA: C3I-53 --- diff --git a/openshift/pipelines/jobs/waiverdb-prod-integration-test.env b/openshift/pipelines/jobs/waiverdb-prod-integration-test.env index 435af76..da61e7b 100644 --- a/openshift/pipelines/jobs/waiverdb-prod-integration-test.env +++ b/openshift/pipelines/jobs/waiverdb-prod-integration-test.env @@ -1,5 +1,3 @@ NAME=waiverdb-prod-integration-test IMAGE=quay.io/factory2/waiverdb:prod ENVIRONMENT=prod -BACKEND_INTEGRATION_TEST_JOB=factory2-prod-integration-test -BACKEND_INTEGRATION_TEST_JOB_NAMESPACE=c3i diff --git a/openshift/pipelines/jobs/waiverdb-stage-integration-test.env b/openshift/pipelines/jobs/waiverdb-stage-integration-test.env index 907bd88..153fc8b 100644 --- a/openshift/pipelines/jobs/waiverdb-stage-integration-test.env +++ b/openshift/pipelines/jobs/waiverdb-stage-integration-test.env @@ -1,5 +1,3 @@ NAME=waiverdb-stage-integration-test IMAGE=quay.io/factory2/waiverdb:stage ENVIRONMENT=stage -BACKEND_INTEGRATION_TEST_JOB=factory2-stage-integration-test -BACKEND_INTEGRATION_TEST_JOB_NAMESPACE=c3i diff --git a/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml b/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml index e0423a4..51673ea 100644 --- a/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml +++ b/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml @@ -13,6 +13,9 @@ parameters: description: This field is used to deploy multiple pipelines to one OpenShift project from this template. required: true value: waiverdb-full-integration-test +- name: PIPELINEAAS_PROJECT + displayName: OpenShift project of pipeline-as-a-Service jobs + value: "c3i" - name: IMAGE displayName: The container image to be tested description: This field must be in repo:tag or repo@sha256 format @@ -46,13 +49,24 @@ parameters: - name: MESSAGING_PROVIDER displayName: Name of the JMS messaging provider value: Red Hat UMB -- name: BACKEND_INTEGRATION_TEST_JOB - displayName: backend integration test job to trigger +- name: BACKEND_INTEGRATION_TEST_REPO + displayName: backend integration test repo required: true -- name: BACKEND_INTEGRATION_TEST_JOB_NAMESPACE - displayName: backend integration test job to trigger - required: false - value: c3i + value: https://gitlab.cee.redhat.com/devops/factory2-segment-tests.git +- name: BACKEND_INTEGRATION_TEST_REPO_BRANCH + displayName: backend integration test repo + required: true + value: master +- name: BACKEND_INTEGRATION_TEST_FILE + displayName: backend integration test file + required: true + value: greenwave-segment-test/greenwave-segment-test-c3i.sh +- name: NO_CLEANUP_AFTER_TEST + displayName: Keep environment after test + value: "false" +- name: MAIL_ADDRESS + displayName: If set, build failure messages to this mail address. +{% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount apiVersion: v1 @@ -78,7 +92,7 @@ objects: labels: app: "${NAME}" spec: - runPolicy: "Serial" # FIXME: Parallel is supported, but we have limited quota in UpShift. + runPolicy: "Parallel" completionDeadlineSeconds: 1800 source: git: @@ -100,18 +114,26 @@ objects: value: "${CONTAINER_REGISTRY_CREDENTIALS}" - name: "TEST_ID" value: "" + - name: "PIPELINEAAS_PROJECT" + value: "${PIPELINEAAS_PROJECT}" - name: JENKINS_AGENT_IMAGE value: "${JENKINS_AGENT_IMAGE}" - name: JENKINS_AGENT_CLOUD_NAME value: "${JENKINS_AGENT_CLOUD_NAME}" - name: JENKINS_AGENT_SERVICE_ACCOUNT value: "${NAME}-jenkins-slave" + - name: "NO_CLEANUP_AFTER_TEST" + value: "${NO_CLEANUP_AFTER_TEST}" - name: ENVIRONMENT value: "${ENVIRONMENT}" + - name: MAIL_ADDRESS + value: "{MAIL_ADDRESS}" - name: MESSAGING_PROVIDER value: "${MESSAGING_PROVIDER}" - - name: BACKEND_INTEGRATION_TEST_JOB - value: "${BACKEND_INTEGRATION_TEST_JOB}" - - name: BACKEND_INTEGRATION_TEST_JOB_NAMESPACE - value: "${BACKEND_INTEGRATION_TEST_JOB_NAMESPACE}" + - name: BACKEND_INTEGRATION_TEST_REPO + value: "${BACKEND_INTEGRATION_TEST_REPO}" + - name: BACKEND_INTEGRATION_TEST_REPO_BRANCH + value: "${BACKEND_INTEGRATION_TEST_REPO_BRANCH}" + - name: BACKEND_INTEGRATION_TEST_FILE + value: "${BACKEND_INTEGRATION_TEST_FILE}" jenkinsfilePath: openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile diff --git a/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile b/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile index d42e345..cc205bd 100644 --- a/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile @@ -1,5 +1,6 @@ library identifier: 'c3i@master', changelog: false, retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) +def pipeline_data pipeline { agent { kubernetes { @@ -34,52 +35,100 @@ pipeline { timestamps() timeout(time: 30, unit: 'MINUTES') } + environment { + TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim() + } stages { - stage('Run integration test') { + stage('Request Pipeline') { + openshift.withCluster() { + openshift.withProject(env.TRIGGER_NAMESPACE) { + def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') + def testhost = testroute.object().spec.host + env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") + testroute.delete() + } + } + echo "Routes end with ${env.PAAS_DOMAIN}" steps { script { - env.IMAGE_DIGEST = getImageDigest(env.IMAGE) - if (!env.IMAGE_DIGEST) { - env.IMAGE_URI = env.IMAGE - if (!env.IMAGE_URI.startsWith('atomic:') && !env.IMAGE_URI.startsWith('docker://')) { - env.IMAGE_URI = 'docker://' + env.IMAGE_URI - } - echo "Image URI ${env.IMAGE_URI} doesn't contain the image digest. Fetching from the registry..." - def metadataText = sh(returnStdout: true, script: 'skopeo inspect ${IMAGE_URI}').trim() - def metadata = readJSON text: metadataText - env.IMAGE_DIGEST = metadata.Digest - } - if (!env.IMAGE_DIGEST) { - error "Couldn't get digest of image '${env.IMAGE}'" - } - echo "Digest of image '${env.IMAGE}': ${env.IMAGE_DIGEST}" - - // TODO: in the short term, we don't run integration tests here - // but trigger the integration test job in the c3i project. + env.PIPELINE_ID = 'c3i-pipeline-' + UUID.randomUUID().toString().substring(0,4) openshift.withCluster() { - openshift.withProject(params.BACKEND_INTEGRATION_TEST_JOB_NAMESPACE) { - c3i.buildAndWait(script: this, objs: "bc/${params.BACKEND_INTEGRATION_TEST_JOB}", + openshift.withProject(params.PIPELINEAAS_PROJECT) { + c3i.buildAndWait(script: this, objs: "bc/pipeline-as-a-service", + '-e', "DEFAULT_IMAGE_TAG=${env.ENVIRONMENT}", '-e', "WAIVERDB_IMAGE=${env.IMAGE}", - '-e', "TARGET_IMAGE_REPO=factory2/waiverdb", - '-e', "TARGET_IMAGE_DIGEST=${env.IMAGE_DIGEST}", - '-e', "TARGET_IMAGE_IS_SCRATCH=${env.IMAGE_IS_SCRATCH}", - '-e', "TARGET_IMAGE_VERREL=${env.BUILD_TAG}", - '-e', "TESTCASE_CATEGORY=${env.ENVIRONMENT}", - ) - echo "Integration test passed." + '-e', "PIPELINE_ID=${env.PIPELINE_ID}", + '-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}" + '-e', "KOJI_HUB_IMAGE=", + '-e', "MBS_BACKEND_IMAGE=", + '-e', "MBS_FRONTEND_IMAGE=", + '-e', "KOJI_HUB_IMAGE=" + ) } } } } } + stage('Run integration test') { + steps { + script { + c3i.clone(repo: params.BACKEND_INTEGRATION_TEST_REPO, + branch: params.BACKEND_INTEGRATION_TEST_REPO_BRANCH) + pipeline_data = readJSON(text: controller.getVars()) + sh "${env.WORKSPACE}/${BACKEND_INTEGRATION_TEST_FILE} https://${env.PIPELINE_ID}.${env.PAAS_DOMAIN}" + } + } + } + } + post { + changed { + script { + if (params.MAIL_ADDRESS) { + emailext to: "${env.MAIL_ADDRESS}", + subject: "${env.JOB_NAME} ${env.BUILD_NUMBER} changed: ${currentBuild.result}", + body: "${env.JOB_NAME} ${env.BUILD_NUMBER} changed. Current status: ${currentBuild.result}. You can check it out: ${env.BUILD_URL}" + } + } + } + always { + script { + if (!env.MESSAGING_PROVIDER) { + // Don't send a message if messaging provider is not configured + return + } + c3i.sendResultToMessageBus( + pipeline_data.WAIVERDB_IMAGE, + pipeline_data.WAIVERDB_IMAGE_DIGEST, + env.BUILD_TAG, + env.TARGET_IMAGE_IS_SCRATCH == "true", + env.MESSAGING_PROVIDER + ) + } + } + failure { + script { + openshift.withCluster() { + openshift.withProject(env.PIPELINE_ID) { + echo 'Getting logs from all pods...' + openshift.selector('pods').logs('--tail=100') + } + } + } + } + cleanup { + script { + if (env.NO_CLEANUP_AFTER_TEST == 'true') { + return + } + openshift.withCluster() { + openshift.withProject(env.PIPELINE_ID) { + /* Tear down everything we just created */ + echo 'Tearing down test resources...' + openshift.selector('all,pvc,configmap,secret', + ['c3i.redhat.com/pipeline': env.PIPELINE_ID]).delete('--ignore-not-found=true') + } + } + } + } } -} - -// Extract digest from the image URI -// e.g. factory2/waiverdb@sha256:35201c572fc8a137862b7a256476add8d7465fa5043d53d117f4132402f8ef6b -// -> sha256:35201c572fc8a137862b7a256476add8d7465fa5043d53d117f4132402f8ef6b -@NonCPS -def getImageDigest(String image) { - def matcher = (env.IMAGE =~ /@(sha256:\w+)$/) - return matcher ? matcher[0][1] : '' } From ff15480fec78ffefd8bf16f2f647e3f13470925e Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:53 +0000 Subject: [PATCH 2/11] C3I - template usage Use jinja2 templates for: c3i-library include agent include - secret is taken using openshift, not as variable include jenkinsfiles directly not as a refence to repository --- diff --git a/openshift/pipelines/Makefile b/openshift/pipelines/Makefile index 993653c..beb43ad 100644 --- a/openshift/pipelines/Makefile +++ b/openshift/pipelines/Makefile @@ -22,7 +22,7 @@ install: @for job in $(JOBS); do \ echo "[PIPELINE] Updating pipeline job \"$${job}\"..." ; \ template_file=$$(cat ./$(JOBS_DIR)/$${job}.tmpl); \ - $(OC_CMD) process --local -f ./$(TEMPLATES_DIR)/$${template_file} \ + jinja2 ./$(TEMPLATES_DIR)/$${template_file} | $(OC_CMD) process --local -f - \ --param-file ./$(JOBS_DIR)/$${job}.env | $(OC_CMD) apply -f -; \ echo "[PIPELINE] Pipeline job \"$${job}\" updated" ; \ done diff --git a/openshift/pipelines/templates/snippets/c3i-library-parameters.yaml b/openshift/pipelines/templates/snippets/c3i-library-parameters.yaml new file mode 100644 index 0000000..5f96d60 --- /dev/null +++ b/openshift/pipelines/templates/snippets/c3i-library-parameters.yaml @@ -0,0 +1,8 @@ +- name: C3I_LIB_URL + displayName: C3I library git url + required: true + value: "https://pagure.io/c3i-library.git" +- name: C3I_LIB_BRANCH + displayName: C3I library branch + required: true + value: "master" diff --git a/openshift/pipelines/templates/snippets/c3i-library.groovy b/openshift/pipelines/templates/snippets/c3i-library.groovy new file mode 100644 index 0000000..e752c81 --- /dev/null +++ b/openshift/pipelines/templates/snippets/c3i-library.groovy @@ -0,0 +1,2 @@ +library identifier: "c3i@${C3I_LIB_BRANCH}", changelog: false, + retriever: modernSCM([$class: 'GitSCMSource', remote: "${C3I_LIB_URL}"]) diff --git a/openshift/pipelines/templates/snippets/default-agent.groovy b/openshift/pipelines/templates/snippets/default-agent.groovy new file mode 100644 index 0000000..c6f5180 --- /dev/null +++ b/openshift/pipelines/templates/snippets/default-agent.groovy @@ -0,0 +1,29 @@ +agent { + kubernetes { + cloud "${params.JENKINS_AGENT_CLOUD_NAME}" + label "jenkins-slave-${UUID.randomUUID().toString()}" + serviceAccount "${params.JENKINS_AGENT_SERVICE_ACCOUNT}" + defaultContainer 'jnlp' + yaml """ + apiVersion: v1 + kind: Pod + metadata: + labels: + app: "${env.JOB_BASE_NAME}" + factory2-pipeline-build-number: "${env.BUILD_NUMBER}" + spec: + containers: + - name: jnlp + image: "${params.JENKINS_AGENT_IMAGE}" + imagePullPolicy: Always + tty: true + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 768Mi + cpu: 300m + """ + } +} diff --git a/openshift/pipelines/templates/waiverdb-build-template.yaml b/openshift/pipelines/templates/waiverdb-build-template.yaml index 6a7ec15..ab6f6b6 100644 --- a/openshift/pipelines/templates/waiverdb-build-template.yaml +++ b/openshift/pipelines/templates/waiverdb-build-template.yaml @@ -114,6 +114,7 @@ parameters: value: 'pagure-api-key' - name: MAIL_ADDRESS displayName: If set, build failure messages to this mail address. +{% include "snippets/c3i-library-parameters.yaml" %} labels: template: waiverdb-build objects: @@ -179,10 +180,6 @@ objects: spec: runPolicy: "Serial" completionDeadlineSeconds: 1800 - source: - git: - uri: "${WAIVERDB_GIT_REPO}" - ref: "${WAIVERDB_MAIN_BRANCH}" strategy: type: JenkinsPipeline jenkinsPipelineStrategy: @@ -233,4 +230,5 @@ objects: value: "${PAGURE_API_KEY_SECRET_NAME}" - name: MAIL_ADDRESS value: "${MAIL_ADDRESS}" - jenkinsfilePath: openshift/pipelines/templates/waiverdb-build.Jenkinsfile + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-build.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile index b16dfaa..95cc2aa 100644 --- a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile @@ -1,5 +1,4 @@ -library identifier: 'c3i@master', changelog: false, - retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) +{% include "snippets/c3i-library.groovy" %} import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; pipeline { agent { @@ -23,11 +22,6 @@ pipeline { imagePullPolicy: Always tty: true env: - - name: REGISTRY_CREDENTIALS - valueFrom: - secretKeyRef: - name: "${params.CONTAINER_REGISTRY_CREDENTIALS}" - key: '.dockerconfigjson' # Required by unit tests: Set up NSS Wrapper to generate a fake user name for the random UID assigned by OpenShift - name: LD_PRELOAD value: '/usr/lib64/libnss_wrapper.so' @@ -355,10 +349,11 @@ pipeline { env.WAIVERDB_DEV_IMAGE_DESTINATIONS.split(',') : [] openshift.withCluster() { def sourceImage = env.RESULTING_IMAGE_REPO + ":" + env.RESULTING_TAG - if (env.REGISTRY_CREDENTIALS) { - dir ("${env.HOME}/.docker") { - writeFile file:'config.json', text: env.REGISTRY_CREDENTIALS - } + if (params.CONTAINER_REGISTRY_CREDENTIALS) { + dir ("${env.HOME}/.docker") { + def dockerconf = openshift.selector('secret', params.CONTAINER_REGISTRY_CREDENTIALS).object().data['.dockerconfigjson'] + writeFile file: 'config.json', text: dockerconf, encoding: "Base64" + } } // pull the built image from imagestream echo "Pulling container from ${sourceImage}..." diff --git a/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml b/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml index 51673ea..33f7a7e 100644 --- a/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml +++ b/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml @@ -94,10 +94,6 @@ objects: spec: runPolicy: "Parallel" completionDeadlineSeconds: 1800 - source: - git: - uri: "${WAIVERDB_GIT_REPO}" - ref: "${WAIVERDB_GIT_REF}" strategy: type: JenkinsPipeline jenkinsPipelineStrategy: @@ -136,4 +132,5 @@ objects: value: "${BACKEND_INTEGRATION_TEST_REPO_BRANCH}" - name: BACKEND_INTEGRATION_TEST_FILE value: "${BACKEND_INTEGRATION_TEST_FILE}" - jenkinsfilePath: openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-full-integration-test.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile b/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile index cc205bd..adedde9 100644 --- a/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile @@ -1,36 +1,7 @@ -library identifier: 'c3i@master', changelog: false, - retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) +{% include "snippets/c3i-library.groovy" %} def pipeline_data pipeline { - agent { - kubernetes { - cloud "${params.JENKINS_AGENT_CLOUD_NAME}" - label "jenkins-slave-${UUID.randomUUID().toString()}" - serviceAccount "${params.JENKINS_AGENT_SERVICE_ACCOUNT}" - defaultContainer 'jnlp' - yaml """ - apiVersion: v1 - kind: Pod - metadata: - labels: - app: "${env.JOB_BASE_NAME}" - factory2-pipeline-kind: "waiverdb-integration-test-pipeline" - factory2-pipeline-build-number: "${env.BUILD_NUMBER}" - spec: - containers: - - name: jnlp - image: "${params.JENKINS_AGENT_IMAGE}" - imagePullPolicy: Always - resources: - requests: - memory: 512Mi - cpu: 200m - limits: - memory: 768Mi - cpu: 300m - """ - } - } + {% include "snippets/default-agent.groovy" %} options { timestamps() timeout(time: 30, unit: 'MINUTES') diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile b/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile index 221ec41..0de83ec 100644 --- a/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile @@ -1,7 +1,5 @@ // Use scripted syntax because CIBuildTrigger currently doesn't support the declarative syntax -library identifier: 'c3i@master', changelog: false, - retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) - +{% include "snippets/c3i-library.groovy" %} properties([ disableConcurrentBuilds(), pipelineTriggers([ diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml index 77ae946..9796a91 100644 --- a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml @@ -47,6 +47,7 @@ parameters: - name: OPENSHIFT_CLOUD_NAME displayName: Name of OpenShift cloud in Jenkins master configuration value: openshift +{% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount apiVersion: v1 @@ -74,10 +75,6 @@ objects: spec: runPolicy: "Serial" completionDeadlineSeconds: 1800 - source: - git: - uri: "${WAIVERDB_GIT_REPO}" - ref: "${WAIVERDB_GIT_REF}" strategy: type: JenkinsPipeline jenkinsPipelineStrategy: @@ -111,4 +108,5 @@ objects: value: - name: MESSAGE_HEADERS value: - jenkinsfilePath: openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-greenwave-trigger.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml b/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml index 2575933..53c2447 100644 --- a/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml +++ b/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml @@ -63,6 +63,7 @@ parameters: displayName: Name of OpenShift cloud in Jenkins master configuration required: true value: openshift +{% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount apiVersion: v1 @@ -90,10 +91,6 @@ objects: spec: runPolicy: "Serial" # FIXME: Parallel is supported, but we have limited quota in UpShift. completionDeadlineSeconds: 1800 - source: - git: - uri: "${WAIVERDB_GIT_REPO}" - ref: "${WAIVERDB_GIT_REF}" strategy: type: JenkinsPipeline source: @@ -120,4 +117,5 @@ objects: value: "${JENKINS_AGENT_CLOUD_NAME}" - name: JENKINS_AGENT_SERVICE_ACCOUNT value: "${NAME}-jenkins-slave" - jenkinsfilePath: openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-image-promotion.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile b/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile index c76272d..5b7c230 100644 --- a/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile @@ -1,40 +1,5 @@ pipeline { - agent { - kubernetes { - cloud "${params.JENKINS_AGENT_CLOUD_NAME}" - label "jenkins-slave-${UUID.randomUUID().toString()}" - serviceAccount "${params.JENKINS_AGENT_SERVICE_ACCOUNT}" - defaultContainer 'jnlp' - yaml """ - apiVersion: v1 - kind: Pod - metadata: - labels: - app: "jenkins-${env.JOB_BASE_NAME}" - factory2-pipeline-kind: "waiverdb-image-promotion-pipeline" - factory2-pipeline-build-number: "${env.BUILD_NUMBER}" - spec: - containers: - - name: jnlp - image: "${params.JENKINS_AGENT_IMAGE}" - imagePullPolicy: Always - tty: true - env: - - name: REGISTRY_CREDENTIALS - valueFrom: - secretKeyRef: - name: "${params.CONTAINER_REGISTRY_CREDENTIALS}" - key: '.dockerconfigjson' - resources: - requests: - memory: 512Mi - cpu: 200m - limits: - memory: 768Mi - cpu: 500m - """ - } - } + {% include "snippets/default-agent.groovy" %} options { timestamps() timeout(time: 30, unit: 'MINUTES') @@ -56,9 +21,13 @@ pipeline { 'auth': sh(returnStdout: true, script: 'set +x; echo -n "serviceaccount:$SERVICE_ACCOUNT_TOKEN" | base64 -').trim() ] // merging user specified credentials - if (env.REGISTRY_CREDENTIALS) { - toBeMerged = readJSON text: env.REGISTRY_CREDENTIALS - dockerConfig.auths.putAll(toBeMerged.auths) + if (params.CONTAINER_REGISTRY_CREDENTIALS) { + openshift.withCluster() { + def dockerconf = openshift.selector('secret', params.CONTAINER_REGISTRY_CREDENTIALS).object().data['.dockerconfigjson'] + def dockerString = new String(dockerconf.decodeBase64()) + toBeMerged = readJSON text: dockerString + dockerConfig.auths.putAll(toBeMerged.auths) + } } // writing to ~/.docker/config.json writeJSON file: 'config.json', json: dockerConfig diff --git a/openshift/pipelines/templates/waiverdb-integration-test-template.yaml b/openshift/pipelines/templates/waiverdb-integration-test-template.yaml index 696f9e4..c309f04 100644 --- a/openshift/pipelines/templates/waiverdb-integration-test-template.yaml +++ b/openshift/pipelines/templates/waiverdb-integration-test-template.yaml @@ -46,6 +46,7 @@ parameters: - name: MESSAGING_PROVIDER displayName: Name of the JMS messaging provider value: Red Hat UMB +{% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount apiVersion: v1 @@ -73,10 +74,6 @@ objects: spec: runPolicy: "Serial" # FIXME: Parallel is supported, but we have limited quota in UpShift. completionDeadlineSeconds: 1800 - source: - git: - uri: "${WAIVERDB_GIT_REPO}" - ref: "${WAIVERDB_GIT_REF}" strategy: type: JenkinsPipeline jenkinsPipelineStrategy: @@ -103,4 +100,5 @@ objects: value: "${ENVIRONMENT}" - name: MESSAGING_PROVIDER value: "${MESSAGING_PROVIDER}" - jenkinsfilePath: openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-integration-test.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile b/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile index 8d4c7da..1de5da9 100644 --- a/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile @@ -1,44 +1,8 @@ import java.text.* -library identifier: 'c3i@master', changelog: false, - retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) +{% include "snippets/c3i-library.groovy" %} pipeline { - agent { - kubernetes { - cloud "${params.JENKINS_AGENT_CLOUD_NAME}" - label "jenkins-slave-${UUID.randomUUID().toString()}" - serviceAccount "${params.JENKINS_AGENT_SERVICE_ACCOUNT}" - defaultContainer 'jnlp' - yaml """ - apiVersion: v1 - kind: Pod - metadata: - labels: - app: "${env.JOB_BASE_NAME}" - factory2-pipeline-kind: "waiverdb-integration-test-pipeline" - factory2-pipeline-build-number: "${env.BUILD_NUMBER}" - spec: - containers: - - name: jnlp - image: "${params.JENKINS_AGENT_IMAGE}" - imagePullPolicy: Always - tty: true - env: - - name: REGISTRY_CREDENTIALS - valueFrom: - secretKeyRef: - name: "${params.CONTAINER_REGISTRY_CREDENTIALS}" - key: '.dockerconfigjson' - resources: - requests: - memory: 512Mi - cpu: 200m - limits: - memory: 768Mi - cpu: 300m - """ - } - } + {% include "snippets/default-agent.groovy" %} options { timestamps() timeout(time: 30, unit: 'MINUTES') diff --git a/openshift/pipelines/templates/waiverdb-polling-pagure.Jenkinsfile b/openshift/pipelines/templates/waiverdb-polling-pagure.Jenkinsfile new file mode 100644 index 0000000..dec4684 --- /dev/null +++ b/openshift/pipelines/templates/waiverdb-polling-pagure.Jenkinsfile @@ -0,0 +1,136 @@ +{% include "snippets/c3i-library.groovy" %} +pipeline { + agent { + kubernetes { + cloud "${OPENSHIFT_CLOUD_NAME}" + label "jenkins-slave-${UUID.randomUUID().toString()}" + serviceAccount "${NAME}-jenkins-slave" + defaultContainer 'jnlp' + yaml """ + apiVersion: v1 + kind: Pod + metadata: + labels: + app: "jenkins-${env.JOB_BASE_NAME}" + factory2-pipeline-kind: "waiverdb-polling-to-pagure-pipeline" + factory2-pipeline-build-number: "${env.BUILD_NUMBER}" + spec: + containers: + - name: jnlp + image: "${JENKINS_AGENT_IMAGE}" + imagePullPolicy: Always + tty: true + resources: + requests: + memory: 378Mi + cpu: 200m + limits: + memory: 768Mi + cpu: 500m + """ + } + } + options { + timestamps() + } + environment { + PIPELINE_NAMESPACE = readFile('/run/secrets/kubernetes.io/serviceaccount/namespace').trim() + PAGURE_URL = "${PAGURE_URL}" + PAGURE_REPO_IS_FORK = "${PAGURE_REPO_IS_FORK}" + PAGURE_POLLING_FOR_PR = "${PAGURE_POLLING_FOR_PR}" + PAGURE_REPO_HOME = "${env.PAGURE_URL}${env.PAGURE_REPO_IS_FORK == 'true' ? '/fork' : ''}/${PAGURE_REPO_NAME}" + GIT_URL = "${env.PAGURE_URL}/${env.PAGURE_REPO_IS_FORK == 'true' ? 'forks/' : ''}${PAGURE_REPO_NAME}.git" + PREMERGE_JOB_NAME = "${PREMERGE_JOB_NAME}" + POSTMERGE_JOB_NAME = "${POSTMERGE_JOB_NAME}" + } + triggers { pollSCM("${PAGURE_POLLING_SCHEDULE}") } + stages { + stage('Prepare') { + agent { label 'master' } + steps { + script { + // checking out the polled branch + def polledBranch = env.PAGURE_POLLING_FOR_PR == 'true' ? 'origin/pull/*/head' : "origin/${PAGURE_POLLED_BRANCH}" + def scmVars = checkout([$class: 'GitSCM', + branches: [[name: polledBranch]], + userRemoteConfigs: [ + [ + name: 'origin', + url: env.GIT_URL, + refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head', + ], + ], + extensions: [[$class: 'CleanBeforeCheckout']], + ]) + env.WAIVERDB_GIT_COMMIT = scmVars.GIT_COMMIT + // setting build display name + def prefix = 'origin/' + def branch = scmVars.GIT_BRANCH.startsWith(prefix) ? scmVars.GIT_BRANCH.substring(prefix.size()) + : scmVars.GIT_BRANCH // origin/pull/1234/head -> pull/1234/head, origin/master -> master + env.WAIVERDB_GIT_BRANCH = branch + echo "Build on branch=${env.WAIVERDB_GIT_BRANCH}, commit=${env.WAIVERDB_GIT_COMMIT}" + if (env.PAGURE_POLLING_FOR_PR == 'false') { + currentBuild.displayName = "${env.WAIVERDB_GIT_BRANCH}: ${env.WAIVERDB_GIT_COMMIT.substring(0, 7)}" + currentBuild.description = """${currentBuild.displayName}""" + } + else if (env.PAGURE_POLLING_FOR_PR == 'true' && branch ==~ /^pull\/[0-9]+\/head$/) { + env.PR_NO = branch.split('/')[1] + env.PR_URL = "${env.PAGURE_REPO_HOME}/pull-request/${env.PR_NO}" + // To HTML syntax in build description, go to `Jenkins/Global Security/Markup Formatter` and select 'Safe HTML'. + def pagureLink = """PR#${env.PR_NO}""" + echo "Building PR #${env.PR_NO}: ${env.PR_URL}" + currentBuild.displayName = "PR#${env.PR_NO}" + currentBuild.description = pagureLink + } else { // This shouldn't happen. + error("Build is aborted due to unexpected polling trigger actions.") + } + } + } + } + stage('Update pipeline jobs') { + when { + expression { + return "${PIPELINE_UPDATE_JOBS_DIR}" && env.PAGURE_POLLING_FOR_PR == 'false' && env.WAIVERDB_GIT_BRANCH == "${PAGURE_POLLED_BRANCH}" + } + } + steps { + checkout([$class: 'GitSCM', + branches: [[name: env.WAIVERDB_GIT_COMMIT]], + userRemoteConfigs: [ + [ + name: 'origin', + url: env.GIT_URL, + refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head', + ], + ], + extensions: [[$class: 'CleanBeforeCheckout']], + ]) + script { + dir('openshift/pipelines') { + sh ''' + make install JOBS_DIR="${PIPELINE_UPDATE_JOBS_DIR}" + ''' + } + } + } + } + stage('Build') { + steps { + script { + openshift.withCluster() { + def bc = env.PAGURE_POLLING_FOR_PR == 'true' ? env.PREMERGE_JOB_NAME : env.POSTMERGE_JOB_NAME + def build = c3i.build(script: this, objs: "bc/${bc}", + '-e', "WAIVERDB_GIT_REF=${env.WAIVERDB_GIT_BRANCH}", + ) + c3i.waitForBuildStart(script: this, build: build) + def devBuildInfo = build.object() + def downstreamBuildName = devBuildInfo.metadata.name + def downstreamBuildUrl = devBuildInfo.metadata.annotations['openshift.io/jenkins-build-uri'] + echo "Downstream build ${downstreamBuildName}(${downstreamBuildUrl}) started." + } + } + } + } + } +} + diff --git a/openshift/pipelines/templates/waiverdb-polling-pagure.yaml b/openshift/pipelines/templates/waiverdb-polling-pagure.yaml index 06b6293..194abf3 100644 --- a/openshift/pipelines/templates/waiverdb-polling-pagure.yaml +++ b/openshift/pipelines/templates/waiverdb-polling-pagure.yaml @@ -58,6 +58,7 @@ parameters: displayName: Name of OpenShift cloud in Jenkins master configuration required: true value: openshift +{% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount apiVersion: v1 @@ -88,141 +89,5 @@ objects: strategy: type: JenkinsPipeline jenkinsPipelineStrategy: - jenkinsfile: |- - // Don't use external Jenkinsfile here, or Jenkins will also poll on that repo and branch - library identifier: 'c3i@master', changelog: false, - retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) - pipeline { - agent { - kubernetes { - cloud "${OPENSHIFT_CLOUD_NAME}" - label "jenkins-slave-${UUID.randomUUID().toString()}" - serviceAccount "${NAME}-jenkins-slave" - defaultContainer 'jnlp' - yaml """ - apiVersion: v1 - kind: Pod - metadata: - labels: - app: "jenkins-${env.JOB_BASE_NAME}" - factory2-pipeline-kind: "waiverdb-polling-to-pagure-pipeline" - factory2-pipeline-build-number: "${env.BUILD_NUMBER}" - spec: - containers: - - name: jnlp - image: "${JENKINS_AGENT_IMAGE}" - imagePullPolicy: Always - tty: true - resources: - requests: - memory: 378Mi - cpu: 200m - limits: - memory: 768Mi - cpu: 500m - """ - } - } - options { - timestamps() - } - environment { - PIPELINE_NAMESPACE = readFile('/run/secrets/kubernetes.io/serviceaccount/namespace').trim() - PAGURE_URL = "${PAGURE_URL}" - PAGURE_REPO_IS_FORK = "${PAGURE_REPO_IS_FORK}" - PAGURE_POLLING_FOR_PR = "${PAGURE_POLLING_FOR_PR}" - PAGURE_REPO_HOME = "${env.PAGURE_URL}${env.PAGURE_REPO_IS_FORK == 'true' ? '/fork' : ''}/${PAGURE_REPO_NAME}" - GIT_URL = "${env.PAGURE_URL}/${env.PAGURE_REPO_IS_FORK == 'true' ? 'forks/' : ''}${PAGURE_REPO_NAME}.git" - PREMERGE_JOB_NAME = "${PREMERGE_JOB_NAME}" - POSTMERGE_JOB_NAME = "${POSTMERGE_JOB_NAME}" - } - triggers { pollSCM("${PAGURE_POLLING_SCHEDULE}") } - stages { - stage('Prepare') { - agent { label 'master' } - steps { - script { - // checking out the polled branch - def polledBranch = env.PAGURE_POLLING_FOR_PR == 'true' ? 'origin/pull/*/head' : "origin/${PAGURE_POLLED_BRANCH}" - def scmVars = checkout([$class: 'GitSCM', - branches: [[name: polledBranch]], - userRemoteConfigs: [ - [ - name: 'origin', - url: env.GIT_URL, - refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head', - ], - ], - extensions: [[$class: 'CleanBeforeCheckout']], - ]) - env.WAIVERDB_GIT_COMMIT = scmVars.GIT_COMMIT - // setting build display name - def prefix = 'origin/' - def branch = scmVars.GIT_BRANCH.startsWith(prefix) ? scmVars.GIT_BRANCH.substring(prefix.size()) - : scmVars.GIT_BRANCH // origin/pull/1234/head -> pull/1234/head, origin/master -> master - env.WAIVERDB_GIT_BRANCH = branch - echo "Build on branch=${env.WAIVERDB_GIT_BRANCH}, commit=${env.WAIVERDB_GIT_COMMIT}" - if (env.PAGURE_POLLING_FOR_PR == 'false') { - currentBuild.displayName = "${env.WAIVERDB_GIT_BRANCH}: ${env.WAIVERDB_GIT_COMMIT.substring(0, 7)}" - currentBuild.description = """${currentBuild.displayName}""" - } - else if (env.PAGURE_POLLING_FOR_PR == 'true' && branch ==~ /^pull\/[0-9]+\/head$/) { - env.PR_NO = branch.split('/')[1] - env.PR_URL = "${env.PAGURE_REPO_HOME}/pull-request/${env.PR_NO}" - // To HTML syntax in build description, go to `Jenkins/Global Security/Markup Formatter` and select 'Safe HTML'. - def pagureLink = """PR#${env.PR_NO}""" - echo "Building PR #${env.PR_NO}: ${env.PR_URL}" - currentBuild.displayName = "PR#${env.PR_NO}" - currentBuild.description = pagureLink - } else { // This shouldn't happen. - error("Build is aborted due to unexpected polling trigger actions.") - } - } - } - } - stage('Update pipeline jobs') { - when { - expression { - return "${PIPELINE_UPDATE_JOBS_DIR}" && env.PAGURE_POLLING_FOR_PR == 'false' && env.WAIVERDB_GIT_BRANCH == "${PAGURE_POLLED_BRANCH}" - } - } - steps { - checkout([$class: 'GitSCM', - branches: [[name: env.WAIVERDB_GIT_COMMIT]], - userRemoteConfigs: [ - [ - name: 'origin', - url: env.GIT_URL, - refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head', - ], - ], - extensions: [[$class: 'CleanBeforeCheckout']], - ]) - script { - dir('openshift/pipelines') { - sh ''' - make install JOBS_DIR="${PIPELINE_UPDATE_JOBS_DIR}" - ''' - } - } - } - } - stage('Build') { - steps { - script { - openshift.withCluster() { - def bc = env.PAGURE_POLLING_FOR_PR == 'true' ? env.PREMERGE_JOB_NAME : env.POSTMERGE_JOB_NAME - def build = c3i.build(script: this, objs: "bc/${bc}", - '-e', "WAIVERDB_GIT_REF=${env.WAIVERDB_GIT_BRANCH}", - ) - c3i.waitForBuildStart(script: this, build: build) - def devBuildInfo = build.object() - def downstreamBuildName = devBuildInfo.metadata.name - def downstreamBuildUrl = devBuildInfo.metadata.annotations['openshift.io/jenkins-build-uri'] - echo "Downstream build ${downstreamBuildName}(${downstreamBuildUrl}) started." - } - } - } - } - } - } + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-polling-pagure.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile b/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile index 1dacd5f..e66e89e 100644 --- a/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile @@ -1,7 +1,5 @@ // Use scripted syntax because CIBuildTrigger currently doesn't support the declarative syntax -library identifier: 'c3i@master', changelog: false, - retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://pagure.io/c3i-library.git']) - +{% include "snippets/c3i-library.groovy" %} properties([ disableConcurrentBuilds(), pipelineTriggers([ diff --git a/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml b/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml index 0b0caa0..d7b231c 100644 --- a/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml +++ b/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml @@ -41,6 +41,7 @@ parameters: - name: TEST_JOB_NAME displayName: Name of integration test job to trigger required: true +{% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount apiVersion: v1 @@ -68,10 +69,6 @@ objects: spec: runPolicy: "Serial" completionDeadlineSeconds: 1800 - source: - git: - uri: "${WAIVERDB_GIT_REPO}" - ref: "${WAIVERDB_GIT_REF}" strategy: type: JenkinsPipeline jenkinsPipelineStrategy: @@ -97,4 +94,5 @@ objects: value: - name: MESSAGE_HEADERS value: - jenkinsfilePath: openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile + jenkinsfile: | + {% filter indent(width=10) %}{% include "waiverdb-repotracker-trigger.Jenkinsfile" %}{% endfilter %} From c689c153a6874eb990c3a431a4ab226c77ea0db8 Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:53 +0000 Subject: [PATCH 3/11] Use pagure functions from c3i-library --- diff --git a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile index 95cc2aa..49593a8 100644 --- a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile @@ -70,7 +70,7 @@ pipeline { timeout(time: 30, unit: 'MINUTES') } environment { - PIPELINE_NAMESPACE = readFile('/run/secrets/kubernetes.io/serviceaccount/namespace').trim() + TRIGGER_NAMESPACE = readFile('/run/secrets/kubernetes.io/serviceaccount/namespace').trim() PIPELINE_USERNAME = sh(returnStdout: true, script: 'id -un').trim() PAGURE_API = "${params.PAGURE_URL}/api/0" PAGURE_REPO_IS_FORK = "${params.PAGURE_REPO_IS_FORK}" @@ -93,6 +93,9 @@ pipeline { env.WAIVERDB_GIT_COMMIT = sh(returnStdout: true, script: 'git rev-parse HEAD').trim() echo "Build ${params.WAIVERDB_GIT_REF}, commit=${env.WAIVERDB_GIT_COMMIT}" + // Set GIT_COMMIT for pagure in c3i lib + env.GIT_COMMIT = env.WAIVERDB_GIT_COMMIT + // Is the current branch a pull-request? If no, env.PR_NO will be empty. env.PR_NO = getPrNo(params.WAIVERDB_GIT_REF) @@ -127,13 +130,11 @@ pipeline { // To enable HTML syntax in build description, go to `Jenkins/Global Security/Markup Formatter` and select 'Safe HTML'. def pagureLink = """${currentBuild.displayName}""" try { - def prInfo = withPagure { - it.getPR(env.PR_NO) - } + def prInfo = pagure.getPR(env.PR_NO) pagureLink = """PR#${env.PR_NO}: ${escapeHtml(prInfo.title)}""" // set PR status to Pending if (params.PAGURE_API_KEY_SECRET_NAME) - setBuildStatusOnPagurePR(null, 'Building...') + pagure.setBuildStatusOnPR(null, 'Building...') } catch (Exception e) { echo "Error using pagure API: ${e}" } @@ -143,7 +144,7 @@ pipeline { currentBuild.description = """${currentBuild.displayName}""" if (params.PAGURE_API_KEY_SECRET_NAME) { try { - flagCommit('pending', null, 'Building...') + pagure.flagCommit('pending', null, 'Building...') echo "Updated commit ${env.WAIVERDB_GIT_COMMIT} status to PENDING." } catch (e) { echo "Error updating commit ${env.WAIVERDB_GIT_COMMIT} status to PENDING: ${e}" @@ -206,7 +207,7 @@ pipeline { } } steps { - sshagent (credentials: ["${env.PIPELINE_NAMESPACE}-${params.PAGURE_DOC_SECRET}"]) { + sshagent (credentials: ["${env.TRIGGER_NAMESPACE}-${params.PAGURE_DOC_SECRET}"]) { sh ''' mkdir -p ~/.ssh/ touch ~/.ssh/known_hosts @@ -431,7 +432,7 @@ pipeline { // on pre-merge workflow success if (params.PAGURE_API_KEY_SECRET_NAME && env.PR_NO) { try { - setBuildStatusOnPagurePR(100, 'Build passed.') + pagure.setBuildStatusOnPR(100, 'Build passed.') echo "Updated PR #${env.PR_NO} status to PASS." } catch (e) { echo "Error updating PR #${env.PR_NO} status to PASS: ${e}" @@ -440,7 +441,7 @@ pipeline { // on post-merge workflow success if (params.PAGURE_API_KEY_SECRET_NAME && !env.PR_NO) { try { - flagCommit('success', 100, 'Build passed.') + pagure.flagCommit('success', 100, 'Build passed.') echo "Updated commit ${env.WAIVERDB_GIT_COMMIT} status to PASS." } catch (e) { echo "Error updating commit ${env.WAIVERDB_GIT_COMMIT} status to PASS: ${e}" @@ -454,17 +455,17 @@ pipeline { if (params.PAGURE_API_KEY_SECRET_NAME && env.PR_NO) { // updating Pagure PR flag try { - setBuildStatusOnPagurePR(0, 'Build failed.') + pagure.setBuildStatusOnPR(0, 'Build failed.') echo "Updated PR #${env.PR_NO} status to FAILURE." } catch (e) { echo "Error updating PR #${env.PR_NO} status to FAILURE: ${e}" } // making a comment try { - commentOnPR(""" + pagure.commentOnPR(""" Build ${env.WAIVERDB_GIT_COMMIT} [FAILED](${env.BUILD_URL})! Rebase or make new commits to rebuild. - """.stripIndent()) + """.stripIndent(), env.PR_NO) echo "Comment made." } catch (e) { echo "Error making a comment on PR #${env.PR_NO}: ${e}" @@ -475,7 +476,7 @@ pipeline { // updating Pagure commit flag if (params.PAGURE_API_KEY_SECRET_NAME) { try { - flagCommit('failure', 0, 'Build failed.') + pagure.flagCommit('failure', 0, 'Build failed.') echo "Updated commit ${env.WAIVERDB_GIT_COMMIT} status to FAILURE." } catch (e) { echo "Error updating commit ${env.WAIVERDB_GIT_COMMIT} status to FAILURE: ${e}" @@ -499,38 +500,7 @@ def getPrNo(branch) { def prMatch = branch =~ /^(?:.+\/)?pull\/(\d+)\/head$/ return prMatch ? prMatch[0][1] : '' } -def withPagure(args=[:], cl) { - args.apiUrl = env.PAGURE_API - args.repo = env.PAGURE_REPO_NAME - args.isFork = env.PAGURE_REPO_IS_FORK == 'true' - def pagureClient = pagure.client(args) - return cl(pagureClient) -} -def withPagureCreds(args=[:], cl) { - def pagureClient = null - withCredentials([string(credentialsId: "${env.PIPELINE_NAMESPACE}-${env.PAGURE_API_KEY_SECRET_NAME}", variable: 'TOKEN')]) { - args.token = env.TOKEN - pagureClient = withPagure(args, cl) - } - return pagureClient -} -def setBuildStatusOnPagurePR(percent, String comment) { - withPagureCreds { - it.updatePRStatus(username: 'c3i-jenkins', uid: 'ci-pre-merge', - url: env.BUILD_URL, percent: percent, comment: comment, pr: env.PR_NO) - } -} -def flagCommit(status, percent, comment) { - withPagureCreds { - it.flagCommit(username: 'c3i-jenkins', uid: "ci-post-merge-${env.WAIVERDB_GIT_COMMIT.substring(0, 7)}", status: status, - url: env.BUILD_URL, percent: percent, comment: comment, commit: env.WAIVERDB_GIT_COMMIT) - } -} -def commentOnPR(String comment) { - withPagureCreds { - it.commentOnPR(comment: comment, pr: env.PR_NO) - } -} + def sendBuildStatusEmail(String status) { def recipient = params.MAIL_ADDRESS def subject = "Jenkins job ${env.JOB_NAME} #${env.BUILD_NUMBER} ${status}." From ad1a70cb7ca60e311a08e8df89375423147240ac Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:53 +0000 Subject: [PATCH 4/11] Proceed whole execution for greenwave trigger Declarative syntax used for greenwave trigger. Merged greenwave trigger with image-promotion --- diff --git a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env index b4ec4a5..e81e1d8 100644 --- a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env +++ b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-prod.env @@ -3,4 +3,4 @@ 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 -IMAGE_PROMOTION_JOB=waiverdb-promoting-to-prod +PROMOTING_DESTINATIONS=quay.io/factory2/waiverdb diff --git a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env index 22fe0eb..1888ce9 100644 --- a/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env +++ b/openshift/pipelines/jobs/waiverdb-greenwave-promote-to-stage.env @@ -3,4 +3,4 @@ SOURCE_CONTAINER_REPO=quay.io/factory2/waiverdb TARGET_TAG=stage 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 -IMAGE_PROMOTION_JOB=waiverdb-promoting-to-stage +PROMOTING_DESTINATIONS=quay.io/factory2/waiverdb diff --git a/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env b/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env deleted file mode 100644 index a974270..0000000 --- a/openshift/pipelines/jobs/waiverdb-promoting-to-prod.env +++ /dev/null @@ -1,3 +0,0 @@ -NAME=waiverdb-promoting-to-prod -IMAGE=quay.io/factory2/waiverdb:stage -DEST_TAG=prod diff --git a/openshift/pipelines/jobs/waiverdb-promoting-to-prod.tmpl b/openshift/pipelines/jobs/waiverdb-promoting-to-prod.tmpl deleted file mode 100644 index 7cfc7da..0000000 --- a/openshift/pipelines/jobs/waiverdb-promoting-to-prod.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-image-promotion-template.yaml diff --git a/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env b/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env deleted file mode 100644 index a8227b7..0000000 --- a/openshift/pipelines/jobs/waiverdb-promoting-to-stage.env +++ /dev/null @@ -1,3 +0,0 @@ -NAME=waiverdb-promoting-to-stage -IMAGE=quay.io/factory2/waiverdb:latest -DEST_TAG=stage diff --git a/openshift/pipelines/jobs/waiverdb-promoting-to-stage.tmpl b/openshift/pipelines/jobs/waiverdb-promoting-to-stage.tmpl deleted file mode 100644 index 7cfc7da..0000000 --- a/openshift/pipelines/jobs/waiverdb-promoting-to-stage.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-image-promotion-template.yaml diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile b/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile index 0de83ec..d8a758a 100644 --- a/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.Jenkinsfile @@ -1,81 +1,123 @@ // Use scripted syntax because CIBuildTrigger currently doesn't support the declarative syntax {% include "snippets/c3i-library.groovy" %} -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: '$.msg.subject_type', expectedValue: 'container-image'], - [field: '$.msg.subject_identifier', expectedValue: params.SUBJECT_IDENTIFIER_REGEX], - [field: '$.msg.decision_context', expectedValue: params.DECISION_CONTEXT_REGEX], - [field: '$.msg.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.msg.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 build = c3i.build(script: this, objs: "bc/${promotionJob}", - '-e', "IMAGE=${image}", - '-e', "DEST_TAG=${targetTag}", +pipeline { + {% include "snippets/default-agent.groovy" %} + options { + timestamps() + timeout(time: 30, unit: 'MINUTES') + buildDiscarder(logRotator(numToKeepStr: '10')) + } + environment { + PIPELINE_NAMESPACE = readFile(file: '/run/secrets/kubernetes.io/serviceaccount/namespace').trim() + SERVICE_ACCOUNT_TOKEN = readFile(file: '/run/secrets/kubernetes.io/serviceaccount/token').trim() + } + triggers { + ciBuildTrigger( + noSquash: false, + providerList: [ + activeMQSubscriber( + name: params.MESSAGING_PROVIDER, + overrides: [topic: params.MESSAGING_TOPIC], + checks: [ + [field: '$.msg.subject_type', expectedValue: 'container-image'], + [field: '$.msg.subject_identifier', expectedValue: params.SUBJECT_IDENTIFIER_REGEX], + [field: '$.msg.decision_context', expectedValue: params.DECISION_CONTEXT_REGEX], + [field: '$.msg.policies_satisfied', expectedValue: 'true'], + ] ) - c3i.waitForBuildStart(script: this, build: build) - buildInfo = build.object() - echo "Build ${buildInfo.metadata.annotations['openshift.io/jenkins-build-uri'] ?: buildInfo.metadata.name} started." + ] + ) + } + stages { + stage("Message Check and setup") { + steps { + script { + if (!params.CI_MESSAGE) { + error("This build is not started by a CI message. Only configurations were done.") + } + 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.msg.subject_identifier =~ /@(sha256:\w+)$/)[0][1] + // Generate the pull spec of the image + // e.g. quay.io/factory2/waiverdb@sha256:35201c572fc8a137862b7a256476add8d7465fa5043d53d117f4132402f8ef6b + env.IMAGE = "${params.SOURCE_CONTAINER_REPO}@${digest}" + echo "Starting promotion of image ${env.IMAGE} to :${params.TARGET_TAG}..." + // Setting up registry credentials + dir ("${env.HOME}/.docker") { + // for the OpenShift internal registry + def dockerConfig = readJSON text: '{ "auths": {} }' + dockerConfig.auths['docker-registry.default.svc:5000'] = [ + 'email': '', + 'auth': sh(returnStdout: true, script: 'set +x; echo -n "serviceaccount:$SERVICE_ACCOUNT_TOKEN" | base64 -').trim() + ] + // merging user specified credentials + if (params.CONTAINER_REGISTRY_CREDENTIALS) { + openshift.withCluster() { + def dockerconf = openshift.selector('secret', params.CONTAINER_REGISTRY_CREDENTIALS).object().data['.dockerconfigjson'] + def dockerString = new String(dockerconf.decodeBase64()) + toBeMerged = readJSON text: dockerString + dockerConfig.auths.putAll(toBeMerged.auths) + } + } + // writing to ~/.docker/config.json + writeJSON file: 'config.json', json: dockerConfig + } + } + } + } + stage('Pull image') { + steps { + echo "Pulling container image ${env.IMAGE}..." + withEnv(["SOURCE_IMAGE_REF=${env.IMAGE}"]) { + sh ''' + set -e +x # hide the token from Jenkins console + mkdir -p _image + skopeo copy docker://"$SOURCE_IMAGE_REF" dir:_image + ''' + } + } + } + stage('Promote image') { + steps { + script { + def destinations = params.PROMOTING_DESTINATIONS ? params.PROMOTING_DESTINATIONS.split(',') : [] + openshift.withCluster() { + def pushTasks = destinations.collectEntries { + ["Pushing ${it}" : { + def dest = "${it}:${params.TARGET_TAG}" + // Only docker and atomic registries are allowed + if (!dest.startsWith('atomic:') && !dest.startsWith('docker://')) { + dest = "docker://${dest}" + } + echo "Pushing container image to ${dest}..." + withEnv(["DEST_IMAGE_REF=${dest}"]) { + retry(5) { + sh 'skopeo copy dir:_image "$DEST_IMAGE_REF"' + } + } + }] + } + parallel pushTasks + } + } + } + } + stage('Tag ImageStream') { + when { + expression { + return params.DEST_IMAGESTREAM_NAME && params.TAG_INTO_IMAGESTREAM == "true" + } + } + steps { + script { + def destRef = "${params.DEST_IMAGESTREAM_NAMESPACE ?: env.PIPELINE_NAMESPACE}/${params.DEST_IMAGESTREAM_NAME}:${params.TARGET_TAG}" + openshift.withCluster() { + echo "Tagging ${env.IMAGE} into ${destRef}..." + openshift.tag('--source=docker', env.IMAGE, destRef) + } + } } } } diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml index 9796a91..c96c4f6 100644 --- a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml @@ -32,9 +32,28 @@ parameters: - 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: CONTAINER_REGISTRY_CREDENTIALS + displayName: Secret name of container registries used for pulling and pushing images + value: factory2-pipeline-registry-credentials + required: false +- name: TAG_INTO_IMAGESTREAM + displayName: Whether to tag the image into an ImageStream + value: "false" required: true +- name: PROMOTING_DESTINATIONS + 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: "quay.io/factory2/waiverdb" +- name: DEST_IMAGESTREAM_NAME + displayName: Name of the ImageStream to be tagged + required: false + value: waiverdb +- name: DEST_IMAGESTREAM_NAMESPACE + displayName: Namespace of the ImageStream to be tagged + description: Leaving blank means using the same namespace as the pipeline build + required: false + value: waiverdb-stage - name: MESSAGING_PROVIDER displayName: Name of the JMS messaging provider value: Red Hat UMB @@ -85,6 +104,16 @@ objects: value: "${WAIVERDB_GIT_REF}" - name: OPENSHIFT_CLOUD_NAME value: "${OPENSHIFT_CLOUD_NAME}" + - name: PROMOTING_DESTINATIONS + value: "${PROMOTING_DESTINATIONS}" + - name: CONTAINER_REGISTRY_CREDENTIALS + value: "${CONTAINER_REGISTRY_CREDENTIALS}" + - name: TAG_INTO_IMAGESTREAM + value: "${TAG_INTO_IMAGESTREAM}" + - name: DEST_IMAGESTREAM_NAME + value: "${DEST_IMAGESTREAM_NAME}" + - name: DEST_IMAGESTREAM_NAMESPACE + value: "${DEST_IMAGESTREAM_NAMESPACE}" - name: JENKINS_AGENT_IMAGE value: "${JENKINS_AGENT_IMAGE}" - name: JENKINS_AGENT_SERVICE_ACCOUNT diff --git a/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml b/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml deleted file mode 100644 index 53c2447..0000000 --- a/openshift/pipelines/templates/waiverdb-image-promotion-template.yaml +++ /dev/null @@ -1,121 +0,0 @@ -# Template to produce a pipeline for promoting images between environments -# -# The pipeline pulls the image to be promoted, then pushes it to destinations with promoted tags. -# Optionally, it tags the promoted image into an image stream after pushes. ---- -apiVersion: v1 -kind: Template -metadata: - name: waiverdb-image-promotion -labels: - template: waiverdb-image-promotion -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. - required: true - value: waiverdb-promoting-to-stage-pipeline -- name: IMAGE - displayName: The container image to be promoted - 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 repositories (without tags) to which the image will be promoted - description: OpenShift registries must be prefixed with 'atomic:' - required: false - value: "quay.io/factory2/waiverdb" -- name: CONTAINER_REGISTRY_CREDENTIALS - displayName: Secret name of container registries used for pulling and pushing images - value: factory2-pipeline-registry-credentials - required: false -- name: TAG_INTO_IMAGESTREAM - displayName: Whether to tag the image into an ImageStream - value: "false" - required: true -- name: DEST_IMAGESTREAM_NAME - displayName: Name of the ImageStream to be tagged - required: false - value: waiverdb -- name: DEST_IMAGESTREAM_NAMESPACE - displayName: Namespace of the ImageStream to be tagged - description: Leaving blank means using the same namespace as the pipeline build - required: false - value: waiverdb-stage -- name: DEST_TAG - displayName: Name of the new tag - value: "stage" - required: true -- name: WAIVERDB_GIT_REPO - displayName: WaiverDB Git repo URL - description: Default WaiverDB Git repo URL in which to run functional tests against - required: true - 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 functional tests against - required: true - value: master -- name: JENKINS_AGENT_IMAGE - displayName: Container image for Jenkins slave pods - required: true - value: docker-registry.upshift.redhat.com/factory2/waiverdb-jenkins-slave:latest -- name: JENKINS_AGENT_CLOUD_NAME - displayName: Name of OpenShift cloud in Jenkins master configuration - required: true - value: openshift -{% include "snippets/c3i-library-parameters.yaml" %} -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" # FIXME: Parallel is supported, but we have limited quota in UpShift. - completionDeadlineSeconds: 1800 - strategy: - type: JenkinsPipeline - source: - type: None - jenkinsPipelineStrategy: - env: - - name: "IMAGE" - value: "${IMAGE}" - - name: "PROMOTING_DESTINATIONS" - value: "${PROMOTING_DESTINATIONS}" - - name: "CONTAINER_REGISTRY_CREDENTIALS" - value: "${CONTAINER_REGISTRY_CREDENTIALS}" - - name: "TAG_INTO_IMAGESTREAM" - value: "${TAG_INTO_IMAGESTREAM}" - - name: "DEST_IMAGESTREAM_NAME" - value: "${DEST_IMAGESTREAM_NAME}" - - name: "DEST_IMAGESTREAM_NAMESPACE" - value: "${DEST_IMAGESTREAM_NAMESPACE}" - - name: "DEST_TAG" - value: "${DEST_TAG}" - - name: JENKINS_AGENT_IMAGE - value: "${JENKINS_AGENT_IMAGE}" - - name: JENKINS_AGENT_CLOUD_NAME - value: "${JENKINS_AGENT_CLOUD_NAME}" - - name: JENKINS_AGENT_SERVICE_ACCOUNT - value: "${NAME}-jenkins-slave" - jenkinsfile: | - {% filter indent(width=10) %}{% include "waiverdb-image-promotion.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile b/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile deleted file mode 100644 index 5b7c230..0000000 --- a/openshift/pipelines/templates/waiverdb-image-promotion.Jenkinsfile +++ /dev/null @@ -1,97 +0,0 @@ -pipeline { - {% include "snippets/default-agent.groovy" %} - options { - timestamps() - timeout(time: 30, unit: 'MINUTES') - } - environment { - PIPELINE_NAMESPACE = readFile(file: '/run/secrets/kubernetes.io/serviceaccount/namespace').trim() - SERVICE_ACCOUNT_TOKEN = readFile(file: '/var/run/secrets/kubernetes.io/serviceaccount/token').trim() - } - stages { - stage ('Prepare') { - steps { - script { - // Setting up registry credentials - dir ("${env.HOME}/.docker") { - // for the OpenShift internal registry - def dockerConfig = readJSON text: '{ "auths": {} }' - dockerConfig.auths['docker-registry.default.svc:5000'] = [ - 'email': '', - 'auth': sh(returnStdout: true, script: 'set +x; echo -n "serviceaccount:$SERVICE_ACCOUNT_TOKEN" | base64 -').trim() - ] - // merging user specified credentials - if (params.CONTAINER_REGISTRY_CREDENTIALS) { - openshift.withCluster() { - def dockerconf = openshift.selector('secret', params.CONTAINER_REGISTRY_CREDENTIALS).object().data['.dockerconfigjson'] - def dockerString = new String(dockerconf.decodeBase64()) - toBeMerged = readJSON text: dockerString - dockerConfig.auths.putAll(toBeMerged.auths) - } - } - // writing to ~/.docker/config.json - writeJSON file: 'config.json', json: dockerConfig - } - } - } - } - stage('Pull Container') { - steps { - echo "Pulling container image ${params.IMAGE}..." - sh '''set -e +x # hide the token from Jenkins console - rm -rf _build/container - mkdir -p _build - skopeo copy \ - --src-cert-dir=/var/run/secrets/kubernetes.io/serviceaccount \ - docker://"$IMAGE" dir:_build/container - ''' - } - } - stage('Promote') { - steps { - script { - def destinations = params.PROMOTING_DESTINATIONS ? - params.PROMOTING_DESTINATIONS.split(',') : [] - openshift.withCluster() { - def pushTasks = destinations.collectEntries { - ["Pushing ${it}" : { - def dest = it - // Only docker and atomic registries are allowed - 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 - * with "unknown blob" due to a known issue with the registry - * storage configuration. So we retry up to 5 times. */ - retry(5) { - sh 'skopeo copy dir:_build/container "$DEST_IMAGE_REF"' - } - } - }] - } - parallel pushTasks - } - } - } - } - stage('Tag Image Stream') { - when { - expression { - return params.DEST_IMAGESTREAM_NAME && params.TAG_INTO_IMAGESTREAM == "true" - } - } - steps { - script { - 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) - } - } - } - } - } -} From 3c4fa7ff100a09eb28a5c1a1ee46eb25487244da Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:54 +0000 Subject: [PATCH 5/11] Proceed whole execution for repotracker trigger Declarative syntax used for repotracker trigger. Merged repotracker trigger with full-integration-test --- diff --git a/openshift/pipelines/jobs/waiverdb-prod-integration-test.env b/openshift/pipelines/jobs/waiverdb-prod-integration-test.env deleted file mode 100644 index da61e7b..0000000 --- a/openshift/pipelines/jobs/waiverdb-prod-integration-test.env +++ /dev/null @@ -1,3 +0,0 @@ -NAME=waiverdb-prod-integration-test -IMAGE=quay.io/factory2/waiverdb:prod -ENVIRONMENT=prod diff --git a/openshift/pipelines/jobs/waiverdb-prod-integration-test.tmpl b/openshift/pipelines/jobs/waiverdb-prod-integration-test.tmpl deleted file mode 100644 index 7061e19..0000000 --- a/openshift/pipelines/jobs/waiverdb-prod-integration-test.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-full-integration-test-template.yaml diff --git a/openshift/pipelines/jobs/waiverdb-stage-integration-test.env b/openshift/pipelines/jobs/waiverdb-stage-integration-test.env deleted file mode 100644 index 153fc8b..0000000 --- a/openshift/pipelines/jobs/waiverdb-stage-integration-test.env +++ /dev/null @@ -1,3 +0,0 @@ -NAME=waiverdb-stage-integration-test -IMAGE=quay.io/factory2/waiverdb:stage -ENVIRONMENT=stage diff --git a/openshift/pipelines/jobs/waiverdb-stage-integration-test.tmpl b/openshift/pipelines/jobs/waiverdb-stage-integration-test.tmpl deleted file mode 100644 index 7061e19..0000000 --- a/openshift/pipelines/jobs/waiverdb-stage-integration-test.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-full-integration-test-template.yaml diff --git a/openshift/pipelines/jobs/waiverdb-trigger-on-latest-tag.env b/openshift/pipelines/jobs/waiverdb-trigger-on-latest-tag.env index a390db8..65f4624 100644 --- a/openshift/pipelines/jobs/waiverdb-trigger-on-latest-tag.env +++ b/openshift/pipelines/jobs/waiverdb-trigger-on-latest-tag.env @@ -1,4 +1,4 @@ NAME=waiverdb-trigger-on-latest-tag MESSAGING_TOPIC=Consumer.rh-jenkins-ci-plugin.c3i-waiverdb-trigger-on-latest-tag.VirtualTopic.eng.repotracker.container.tag.> -TEST_JOB_NAME=waiverdb-stage-integration-test +ENVIRONMENT=stage TRACKED_TAG=latest diff --git a/openshift/pipelines/jobs/waiverdb-trigger-on-stage-tag.env b/openshift/pipelines/jobs/waiverdb-trigger-on-stage-tag.env index d026a2c..48b2d71 100644 --- a/openshift/pipelines/jobs/waiverdb-trigger-on-stage-tag.env +++ b/openshift/pipelines/jobs/waiverdb-trigger-on-stage-tag.env @@ -1,4 +1,4 @@ NAME=waiverdb-trigger-on-stage-tag MESSAGING_TOPIC=Consumer.rh-jenkins-ci-plugin.c3i-waiverdb-trigger-on-stage-tag.VirtualTopic.eng.repotracker.container.tag.> -TEST_JOB_NAME=waiverdb-prod-integration-test TRACKED_TAG=stage +ENVIRONMENT=prod diff --git a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy new file mode 100644 index 0000000..41cbedf --- /dev/null +++ b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy @@ -0,0 +1,109 @@ +stage('Run integration tests') { + stages { + stage('Request Pipeline') { + if (!env.TRIGGER_NAMESPACE) { + env.TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim() + } + if(!env.PAAS_DOMAIN) { + openshift.withCluster() { + openshift.withProject(env.TRIGGER_NAMESPACE) { + def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') + def testhost = testroute.object().spec.host + env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") + testroute.delete() + } + } + echo "Routes end with ${env.PAAS_DOMAIN}" + } + openshift.withCluster() { + openshift.withProject(env.TRIGGER_NAMESPACE) { + def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') + def testhost = testroute.object().spec.host + env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") + testroute.delete() + } + } + echo "Routes end with ${env.PAAS_DOMAIN}" + steps { + script { + env.PIPELINE_ID = 'c3i-pipeline-' + UUID.randomUUID().toString().substring(0,4) + openshift.withCluster() { + openshift.withProject(params.PIPELINEAAS_PROJECT) { + c3i.buildAndWait(script: this, objs: "bc/pipeline-as-a-service", + '-e', "DEFAULT_IMAGE_TAG=${env.ENVIRONMENT}", + '-e', "WAIVERDB_IMAGE=${env.IMAGE}", + '-e', "PIPELINE_ID=${env.PIPELINE_ID}", + '-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}" + '-e', "KOJI_HUB_IMAGE=", + '-e', "MBS_BACKEND_IMAGE=", + '-e', "MBS_FRONTEND_IMAGE=", + '-e', "KOJI_HUB_IMAGE=" + ) + } + } + } + } + } + stage('Run integration test') { + steps { + script { + c3i.clone(repo: params.BACKEND_INTEGRATION_TEST_REPO, + branch: params.BACKEND_INTEGRATION_TEST_REPO_BRANCH) + sh "${env.WORKSPACE}/${BACKEND_INTEGRATION_TEST_FILE} https://${env.PIPELINE_ID}.${env.PAAS_DOMAIN}" + } + } + } + } + post { + changed { + script { + if (params.MAIL_ADDRESS) { + emailext to: "${env.MAIL_ADDRESS}", + subject: "${env.JOB_NAME} ${env.BUILD_NUMBER} changed: ${currentBuild.result}", + body: "${env.JOB_NAME} ${env.BUILD_NUMBER} changed. Current status: ${currentBuild.result}. You can check it out: ${env.BUILD_URL}" + } + } + } + always { + script { + if (!env.MESSAGING_PROVIDER) { + // Don't send a message if messaging provider is not configured + return + } + c3i.sendResultToMessageBus( + pipeline_data = readJSON(text: controller.getVars()) + pipeline_data.WAIVERDB_IMAGE, + pipeline_data.WAIVERDB_IMAGE_DIGEST, + env.BUILD_TAG, + env.TARGET_IMAGE_IS_SCRATCH == "true", + env.MESSAGING_PROVIDER + ) + } + } + failure { + script { + openshift.withCluster() { + openshift.withProject(env.PIPELINE_ID) { + echo 'Getting logs from all pods...' + openshift.selector('pods').logs('--tail=100') + } + } + } + } + cleanup { + script { + if (env.NO_CLEANUP_AFTER_TEST == 'true') { + return + } + openshift.withCluster() { + openshift.withProject(env.PIPELINE_ID) { + /* Tear down everything we just created */ + echo 'Tearing down test resources...' + openshift.selector('all,pvc,configmap,secret', + ['c3i.redhat.com/pipeline': env.PIPELINE_ID]).delete('--ignore-not-found=true') + } + } + } + } + } +} diff --git a/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml b/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml deleted file mode 100644 index 33f7a7e..0000000 --- a/openshift/pipelines/templates/waiverdb-full-integration-test-template.yaml +++ /dev/null @@ -1,136 +0,0 @@ -# Template to produce a new OpenShift pipeline for running integration tests -# ---- -apiVersion: v1 -kind: Template -metadata: - name: waiverdb-full-integration-test -labels: - template: waiverdb-full-integration-test -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. - required: true - value: waiverdb-full-integration-test -- name: PIPELINEAAS_PROJECT - displayName: OpenShift project of pipeline-as-a-Service jobs - value: "c3i" -- name: IMAGE - displayName: The container image to be tested - description: This field must be in repo:tag or repo@sha256 format - value: quay.io/factory2/waiverdb:latest -- name: WAIVERDB_GIT_REPO - displayName: WaiverDB Git repo URL - description: Default WaiverDB Git repo URL in which to run functional tests against - required: true - 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 functional tests against - required: true - value: master -- name: JENKINS_AGENT_IMAGE - displayName: Container image for Jenkins slave pods - required: true - value: docker-registry.upshift.redhat.com/factory2/waiverdb-jenkins-slave:latest -- name: CONTAINER_REGISTRY_CREDENTIALS - displayName: Secret name of container registries used for pulling and pushing images - value: factory2-pipeline-registry-credentials - required: false -- name: JENKINS_AGENT_CLOUD_NAME - displayName: Name of OpenShift cloud in Jenkins master configuration - required: true - value: openshift -- name: ENVIRONMENT - displayName: environment name (dev/stage/prod) - required: true - value: stage -- name: MESSAGING_PROVIDER - displayName: Name of the JMS messaging provider - value: Red Hat UMB -- name: BACKEND_INTEGRATION_TEST_REPO - displayName: backend integration test repo - required: true - value: https://gitlab.cee.redhat.com/devops/factory2-segment-tests.git -- name: BACKEND_INTEGRATION_TEST_REPO_BRANCH - displayName: backend integration test repo - required: true - value: master -- name: BACKEND_INTEGRATION_TEST_FILE - displayName: backend integration test file - required: true - value: greenwave-segment-test/greenwave-segment-test-c3i.sh -- name: NO_CLEANUP_AFTER_TEST - displayName: Keep environment after test - value: "false" -- name: MAIL_ADDRESS - displayName: If set, build failure messages to this mail address. -{% include "snippets/c3i-library-parameters.yaml" %} -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: "Parallel" - completionDeadlineSeconds: 1800 - strategy: - type: JenkinsPipeline - jenkinsPipelineStrategy: - env: - - name: "WAIVERDB_GIT_REPO" - value: "${WAIVERDB_GIT_REPO}" - - name: "WAIVERDB_GIT_REF" - value: "${WAIVERDB_GIT_REF}" - - name: "IMAGE" - value: "${IMAGE}" - - name: IMAGE_IS_SCRATCH - value: "true" - - name: "CONTAINER_REGISTRY_CREDENTIALS" - value: "${CONTAINER_REGISTRY_CREDENTIALS}" - - name: "TEST_ID" - value: "" - - name: "PIPELINEAAS_PROJECT" - value: "${PIPELINEAAS_PROJECT}" - - name: JENKINS_AGENT_IMAGE - value: "${JENKINS_AGENT_IMAGE}" - - name: JENKINS_AGENT_CLOUD_NAME - value: "${JENKINS_AGENT_CLOUD_NAME}" - - name: JENKINS_AGENT_SERVICE_ACCOUNT - value: "${NAME}-jenkins-slave" - - name: "NO_CLEANUP_AFTER_TEST" - value: "${NO_CLEANUP_AFTER_TEST}" - - name: ENVIRONMENT - value: "${ENVIRONMENT}" - - name: MAIL_ADDRESS - value: "{MAIL_ADDRESS}" - - name: MESSAGING_PROVIDER - value: "${MESSAGING_PROVIDER}" - - name: BACKEND_INTEGRATION_TEST_REPO - value: "${BACKEND_INTEGRATION_TEST_REPO}" - - name: BACKEND_INTEGRATION_TEST_REPO_BRANCH - value: "${BACKEND_INTEGRATION_TEST_REPO_BRANCH}" - - name: BACKEND_INTEGRATION_TEST_FILE - value: "${BACKEND_INTEGRATION_TEST_FILE}" - jenkinsfile: | - {% filter indent(width=10) %}{% include "waiverdb-full-integration-test.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile b/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile deleted file mode 100644 index adedde9..0000000 --- a/openshift/pipelines/templates/waiverdb-full-integration-test.Jenkinsfile +++ /dev/null @@ -1,105 +0,0 @@ -{% include "snippets/c3i-library.groovy" %} -def pipeline_data -pipeline { - {% include "snippets/default-agent.groovy" %} - options { - timestamps() - timeout(time: 30, unit: 'MINUTES') - } - environment { - TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim() - } - stages { - stage('Request Pipeline') { - openshift.withCluster() { - openshift.withProject(env.TRIGGER_NAMESPACE) { - def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') - def testhost = testroute.object().spec.host - env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") - testroute.delete() - } - } - echo "Routes end with ${env.PAAS_DOMAIN}" - steps { - script { - env.PIPELINE_ID = 'c3i-pipeline-' + UUID.randomUUID().toString().substring(0,4) - openshift.withCluster() { - openshift.withProject(params.PIPELINEAAS_PROJECT) { - c3i.buildAndWait(script: this, objs: "bc/pipeline-as-a-service", - '-e', "DEFAULT_IMAGE_TAG=${env.ENVIRONMENT}", - '-e', "WAIVERDB_IMAGE=${env.IMAGE}", - '-e', "PIPELINE_ID=${env.PIPELINE_ID}", - '-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}" - '-e', "KOJI_HUB_IMAGE=", - '-e', "MBS_BACKEND_IMAGE=", - '-e', "MBS_FRONTEND_IMAGE=", - '-e', "KOJI_HUB_IMAGE=" - ) - } - } - } - } - } - stage('Run integration test') { - steps { - script { - c3i.clone(repo: params.BACKEND_INTEGRATION_TEST_REPO, - branch: params.BACKEND_INTEGRATION_TEST_REPO_BRANCH) - pipeline_data = readJSON(text: controller.getVars()) - sh "${env.WORKSPACE}/${BACKEND_INTEGRATION_TEST_FILE} https://${env.PIPELINE_ID}.${env.PAAS_DOMAIN}" - } - } - } - } - post { - changed { - script { - if (params.MAIL_ADDRESS) { - emailext to: "${env.MAIL_ADDRESS}", - subject: "${env.JOB_NAME} ${env.BUILD_NUMBER} changed: ${currentBuild.result}", - body: "${env.JOB_NAME} ${env.BUILD_NUMBER} changed. Current status: ${currentBuild.result}. You can check it out: ${env.BUILD_URL}" - } - } - } - always { - script { - if (!env.MESSAGING_PROVIDER) { - // Don't send a message if messaging provider is not configured - return - } - c3i.sendResultToMessageBus( - pipeline_data.WAIVERDB_IMAGE, - pipeline_data.WAIVERDB_IMAGE_DIGEST, - env.BUILD_TAG, - env.TARGET_IMAGE_IS_SCRATCH == "true", - env.MESSAGING_PROVIDER - ) - } - } - failure { - script { - openshift.withCluster() { - openshift.withProject(env.PIPELINE_ID) { - echo 'Getting logs from all pods...' - openshift.selector('pods').logs('--tail=100') - } - } - } - } - cleanup { - script { - if (env.NO_CLEANUP_AFTER_TEST == 'true') { - return - } - openshift.withCluster() { - openshift.withProject(env.PIPELINE_ID) { - /* Tear down everything we just created */ - echo 'Tearing down test resources...' - openshift.selector('all,pvc,configmap,secret', - ['c3i.redhat.com/pipeline': env.PIPELINE_ID]).delete('--ignore-not-found=true') - } - } - } - } - } -} diff --git a/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile b/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile index e66e89e..98b107e 100644 --- a/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile @@ -1,69 +1,39 @@ -// Use scripted syntax because CIBuildTrigger currently doesn't support the declarative syntax {% include "snippets/c3i-library.groovy" %} -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], - selector: "repo = '${params.TRACKED_CONTAINER_REPO}' AND action IN ('added', 'updated') AND tag = '${params.TRACKED_TAG}'", - ], - ], - ]), -]) - -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-repotracker-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 test') { - def message = readJSON text: params.CI_MESSAGE - echo "Tag :${message.tag} is ${message.action} in ${message.repo}. New digest: ${message.digest}" - def image = "${message.repo}@${message.digest}" - echo "Triggering a job to test if $image meets all criteria of desired tag :${message.tag}" - def buildInfo = null - openshift.withCluster() { - def build = c3i.build(script: this, objs: "bc/${params.TEST_JOB_NAME}", - '-e', "IMAGE=${image}", - '-e', 'IMAGE_IS_SCRATCH=false', +pipeline { + {% include "snippets/default-agent.groovy" %} + options { + timestamps() + timeout(time: 120, unit: 'MINUTES') + buildDiscarder(logRotator(numToKeepStr: '10')) + } + triggers { + ciBuildTrigger( + noSquash: false, + providerList: [ + activeMQSubscriber( + name: params.MESSAGING_PROVIDER, + overrides: [topic: params.MESSAGING_TOPIC], + selector: "repo = '${params.TRACKED_CONTAINER_REPO}' AND action IN ('added', 'updated') AND tag = '${params.TRACKED_TAG}'", ) - c3i.waitForBuildStart(script: this, build: build) - buildInfo = build.object() + ] + ) + } + stages { + stage("Message Check and setup") { + steps { + script { + if (!params.CI_MESSAGE) { + error("This build is not started by a CI message. Only configurations were done.") + } + def message = readJSON text: params.CI_MESSAGE + echo "Tag :${message.tag} is ${message.action} in ${message.repo}. New digest: ${message.digest}" + def env.IMAGE = "${message.repo}@${message.digest}" + echo "Triggering a job to test if ${env.IMAGE} meets all criteria of desired tag :${message.tag}" + env.IMAGE_IS_SCRATCH = false + env.PIPELINE_ID = "c3i-waiverdb-tag-${message.tag}-${message.digest[-9..-1]}" + } } - echo "Build ${buildInfo.metadata.annotations['openshift.io/jenkins-build-uri'] ?: buildInfo.metadata.name} started." } + {% include "snippets/waiverdb-full-integration-test.groovy" %} } } diff --git a/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml b/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml index d7b231c..b67dd0e 100644 --- a/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml +++ b/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml @@ -38,9 +38,10 @@ parameters: - name: MESSAGING_TOPIC displayName: Name of the topic that the trigger subscribes to value: "Consumer.rh-jenkins-ci-plugin.c3i-waiverdb-repotracker-trigger.VirtualTopic.eng.repotracker.container.tag.>" -- name: TEST_JOB_NAME - displayName: Name of integration test job to trigger +- name: ENVIRONMENT + displayName: environment name (dev/stage/prod) required: true + value: dev {% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount @@ -83,12 +84,12 @@ objects: value: "${TRACKED_CONTAINER_REPO}" - name: "TRACKED_TAG" value: "${TRACKED_TAG}" - - name: "TEST_JOB_NAME" - value: "${TEST_JOB_NAME}" - name: MESSAGING_PROVIDER value: "${MESSAGING_PROVIDER}" - name: MESSAGING_TOPIC value: "${MESSAGING_TOPIC}" + - name: ENVIRONMENT + value: "${ENVIRONMENT}" # CI_MESSAGE and MESSAGE_HEADERS are used internally by JMS messaging plugin - name: CI_MESSAGE value: From 985687596db7a64a3a096cecb0f089565f59bb26 Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:54 +0000 Subject: [PATCH 6/11] Paramaters fixes --- diff --git a/openshift/pipelines/templates/snippets/default-agent.groovy b/openshift/pipelines/templates/snippets/default-agent.groovy index c6f5180..00fa9a3 100644 --- a/openshift/pipelines/templates/snippets/default-agent.groovy +++ b/openshift/pipelines/templates/snippets/default-agent.groovy @@ -1,6 +1,6 @@ agent { kubernetes { - cloud "${params.JENKINS_AGENT_CLOUD_NAME}" + cloud "${params.OPENSHIFT_CLOUD_NAME}" label "jenkins-slave-${UUID.randomUUID().toString()}" serviceAccount "${params.JENKINS_AGENT_SERVICE_ACCOUNT}" defaultContainer 'jnlp' diff --git a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy index 41cbedf..7a57ad8 100644 --- a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy +++ b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy @@ -1,43 +1,44 @@ stage('Run integration tests') { stages { stage('Request Pipeline') { - if (!env.TRIGGER_NAMESPACE) { - env.TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim() - } - if(!env.PAAS_DOMAIN) { - openshift.withCluster() { - openshift.withProject(env.TRIGGER_NAMESPACE) { - def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') - def testhost = testroute.object().spec.host - env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") - testroute.delete() - } - } - echo "Routes end with ${env.PAAS_DOMAIN}" - } - openshift.withCluster() { - openshift.withProject(env.TRIGGER_NAMESPACE) { - def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') - def testhost = testroute.object().spec.host - env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") - testroute.delete() - } - } - echo "Routes end with ${env.PAAS_DOMAIN}" steps { script { + if (!env.TRIGGER_NAMESPACE) { + env.TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim() + } + if(!env.PAAS_DOMAIN) { + openshift.withCluster() { + openshift.withProject(env.TRIGGER_NAMESPACE) { + def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') + def testhost = testroute.object().spec.host + env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") + testroute.delete() + } + } + echo "Routes end with ${env.PAAS_DOMAIN}" + } + openshift.withCluster() { + openshift.withProject(env.TRIGGER_NAMESPACE) { + def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') + def testhost = testroute.object().spec.host + env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") + testroute.delete() + } + } + echo "Routes end with ${env.PAAS_DOMAIN}" env.PIPELINE_ID = 'c3i-pipeline-' + UUID.randomUUID().toString().substring(0,4) openshift.withCluster() { - openshift.withProject(params.PIPELINEAAS_PROJECT) { + openshift.withProject(params.PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE) { c3i.buildAndWait(script: this, objs: "bc/pipeline-as-a-service", '-e', "DEFAULT_IMAGE_TAG=${env.ENVIRONMENT}", '-e', "WAIVERDB_IMAGE=${env.IMAGE}", '-e', "PIPELINE_ID=${env.PIPELINE_ID}", - '-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}" + '-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}", '-e', "KOJI_HUB_IMAGE=", '-e', "MBS_BACKEND_IMAGE=", '-e', "MBS_FRONTEND_IMAGE=", - '-e', "KOJI_HUB_IMAGE=" + '-e', "KOJI_HUB_IMAGE=", + '-e', "TRIGGERED_BY=${env.BUILD_URL}" ) } } @@ -70,8 +71,8 @@ stage('Run integration tests') { // Don't send a message if messaging provider is not configured return } + pipeline_data = controller.getVars() c3i.sendResultToMessageBus( - pipeline_data = readJSON(text: controller.getVars()) pipeline_data.WAIVERDB_IMAGE, pipeline_data.WAIVERDB_IMAGE_DIGEST, env.BUILD_TAG, @@ -82,12 +83,7 @@ stage('Run integration tests') { } failure { script { - openshift.withCluster() { - openshift.withProject(env.PIPELINE_ID) { - echo 'Getting logs from all pods...' - openshift.selector('pods').logs('--tail=100') - } - } + c3i.archiveContainersLogs(env.PIPELINE_ID) } } cleanup { diff --git a/openshift/pipelines/templates/waiverdb-build-template.yaml b/openshift/pipelines/templates/waiverdb-build-template.yaml index ab6f6b6..ca7de7c 100644 --- a/openshift/pipelines/templates/waiverdb-build-template.yaml +++ b/openshift/pipelines/templates/waiverdb-build-template.yaml @@ -46,7 +46,7 @@ parameters: description: If WAIVERDB_MAIN_BRANCH equals WAIVERDB_GIT_REF, this is a post-merge build, otherwise it's a pre-merge build. value: master required: true -- name: JENKINS_AGENT_CLOUD_NAME +- name: OPENSHIFT_CLOUD_NAME displayName: Name of OpenShift cloud in Jenkins master configuration required: true value: openshift @@ -102,6 +102,9 @@ parameters: displayName: Whether to tag the pushed image as dev value: "true" required: true +- name: MESSAGING_PROVIDER + displayName: Name of the JMS messaging provider + value: Red Hat UMB - name: PAGURE_URL displayName: Pagure URL value: https://pagure.io @@ -188,8 +191,8 @@ objects: value: "${WAIVERDB_GIT_REPO}" - name: "WAIVERDB_GIT_REF" value: "${WAIVERDB_GIT_REF}" - - name: "JENKINS_AGENT_CLOUD_NAME" - value: "${JENKINS_AGENT_CLOUD_NAME}" + - name: "OPENSHIFT_CLOUD_NAME" + value: "${OPENSHIFT_CLOUD_NAME}" - name: "JENKINS_AGENT_IMAGE" value: "${JENKINS_AGENT_IMAGE}" - name: "JENKINS_AGENT_SERVICE_ACCOUNT" @@ -220,6 +223,8 @@ objects: value: "${WAIVERDB_INTEGRATION_TEST_BUILD_CONFIG_NAME}" - name: "WAIVERDB_INTEGRATION_TEST_BUILD_CONFIG_NAMESPACE" value: "${WAIVERDB_INTEGRATION_TEST_BUILD_CONFIG_NAMESPACE}" + - name: "MESSAGING_PROVIDER" + value: "${MESSAGING_PROVIDER}" - name: PAGURE_REPO_NAME value: "${PAGURE_REPO_NAME}" - name: PAGURE_REPO_IS_FORK diff --git a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile index 49593a8..01ad0dc 100644 --- a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile @@ -3,7 +3,7 @@ import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; pipeline { agent { kubernetes { - cloud params.JENKINS_AGENT_CLOUD_NAME + cloud params.OPENSHIFT_CLOUD_NAME label "jenkins-slave-${UUID.randomUUID().toString()}" serviceAccount params.JENKINS_AGENT_SERVICE_ACCOUNT defaultContainer 'jnlp' diff --git a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml index c96c4f6..f6d0fed 100644 --- a/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml +++ b/openshift/pipelines/templates/waiverdb-greenwave-trigger.yaml @@ -12,14 +12,6 @@ parameters: 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 @@ -98,10 +90,6 @@ objects: 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: PROMOTING_DESTINATIONS @@ -122,8 +110,6 @@ objects: 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 diff --git a/openshift/pipelines/templates/waiverdb-integration-test-template.yaml b/openshift/pipelines/templates/waiverdb-integration-test-template.yaml index c309f04..e88ac17 100644 --- a/openshift/pipelines/templates/waiverdb-integration-test-template.yaml +++ b/openshift/pipelines/templates/waiverdb-integration-test-template.yaml @@ -35,7 +35,7 @@ parameters: displayName: Secret name of container registries used for pulling and pushing images value: factory2-pipeline-registry-credentials required: false -- name: JENKINS_AGENT_CLOUD_NAME +- name: OPENSHIFT_CLOUD_NAME displayName: Name of OpenShift cloud in Jenkins master configuration required: true value: openshift @@ -92,8 +92,8 @@ objects: value: "" - name: JENKINS_AGENT_IMAGE value: "${JENKINS_AGENT_IMAGE}" - - name: JENKINS_AGENT_CLOUD_NAME - value: "${JENKINS_AGENT_CLOUD_NAME}" + - name: OPENSHIFT_CLOUD_NAME + value: "${OPENSHIFT_CLOUD_NAME}" - name: JENKINS_AGENT_SERVICE_ACCOUNT value: "${NAME}-jenkins-slave" - name: ENVIRONMENT diff --git a/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile b/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile index 1de5da9..6c7c771 100644 --- a/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile @@ -115,6 +115,10 @@ pipeline { // Don't send a message if the job fails before getting the image digest. return; } + if (!env.MESSAGING_PROVIDER) { + // Don't send a message if messaging provider is not configured + return + } // currentBuild.result == null || currentBuild.result == 'SUCCESS' indicates a successful build, // because it's possible that the pipeline engine hasn't set the value nor seen an error when reaching to this line. // See example code in https://jenkins.io/doc/book/pipeline/jenkinsfile/#deploy diff --git a/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile b/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile index 98b107e..942a57f 100644 --- a/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-repotracker-trigger.Jenkinsfile @@ -27,7 +27,7 @@ pipeline { } def message = readJSON text: params.CI_MESSAGE echo "Tag :${message.tag} is ${message.action} in ${message.repo}. New digest: ${message.digest}" - def env.IMAGE = "${message.repo}@${message.digest}" + env.IMAGE = "${message.repo}@${message.digest}" echo "Triggering a job to test if ${env.IMAGE} meets all criteria of desired tag :${message.tag}" env.IMAGE_IS_SCRATCH = false env.PIPELINE_ID = "c3i-waiverdb-tag-${message.tag}-${message.digest[-9..-1]}" diff --git a/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml b/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml index b67dd0e..307c62c 100644 --- a/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml +++ b/openshift/pipelines/templates/waiverdb-repotracker-trigger.yaml @@ -12,14 +12,6 @@ parameters: 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-repotracker-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: TRACKED_CONTAINER_REPO displayName: Container repo to be tracked value: "quay.io/factory2/waiverdb" @@ -28,10 +20,14 @@ parameters: required: true - name: JENKINS_AGENT_IMAGE displayName: Container image for Jenkins slave pods - value: docker-registry.upshift.redhat.com/factory2/waiverdb-jenkins-slave:latest + value: docker-registry.upshift.redhat.com/factory2/factory2-integration-test-jenkins-slave:latest - name: OPENSHIFT_CLOUD_NAME displayName: Name of OpenShift cloud in Jenkins master configuration value: openshift +- name: PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE + displayName: The namespace where the Pipeline-as-a-Service project request BuildConfig has been defined + required: false + value: c3i - name: MESSAGING_PROVIDER displayName: Name of the JMS messaging provider value: Red Hat UMB @@ -42,6 +38,22 @@ parameters: displayName: environment name (dev/stage/prod) required: true value: dev +- name: BACKEND_INTEGRATION_TEST_REPO + displayName: backend integration test repo + value: https://gitlab.cee.redhat.com/devops/factory2-segment-tests.git +- name: BACKEND_INTEGRATION_TEST_REPO_BRANCH + displayName: backend integration test repo + required: true + value: master +- name: BACKEND_INTEGRATION_TEST_FILE + displayName: backend integration test file + required: true + value: greenwave-segment-test/greenwave-segment-test-c3i.sh +- name: NO_CLEANUP_AFTER_TEST + displayName: Keep environment after test + value: "false" +- name: MAIL_ADDRESS + displayName: If set, build failure messages to this mail address. {% include "snippets/c3i-library-parameters.yaml" %} objects: - kind: ServiceAccount @@ -90,6 +102,18 @@ objects: value: "${MESSAGING_TOPIC}" - name: ENVIRONMENT value: "${ENVIRONMENT}" + - name: PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE + value: "${PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE}" + - name: "NO_CLEANUP_AFTER_TEST" + value: "${NO_CLEANUP_AFTER_TEST}" + - name: MAIL_ADDRESS + value: "${MAIL_ADDRESS}" + - name: BACKEND_INTEGRATION_TEST_REPO + value: "${BACKEND_INTEGRATION_TEST_REPO}" + - name: BACKEND_INTEGRATION_TEST_REPO_BRANCH + value: "${BACKEND_INTEGRATION_TEST_REPO_BRANCH}" + - name: BACKEND_INTEGRATION_TEST_FILE + value: "${BACKEND_INTEGRATION_TEST_FILE}" # CI_MESSAGE and MESSAGE_HEADERS are used internally by JMS messaging plugin - name: CI_MESSAGE value: From d9fc75c12304f4cd0755e74b1df5b0e40d58ac18 Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:54 +0000 Subject: [PATCH 7/11] Put functional tests directly to pre/post merge jobs --- diff --git a/openshift/pipelines/jobs/waiverdb-dev-integration-test.env b/openshift/pipelines/jobs/waiverdb-dev-integration-test.env deleted file mode 100644 index cc605f7..0000000 --- a/openshift/pipelines/jobs/waiverdb-dev-integration-test.env +++ /dev/null @@ -1,2 +0,0 @@ -NAME=waiverdb-dev-integration-test -IMAGE=quay.io/factory2/waiverdb:latest diff --git a/openshift/pipelines/jobs/waiverdb-dev-integration-test.tmpl b/openshift/pipelines/jobs/waiverdb-dev-integration-test.tmpl deleted file mode 100644 index f02d245..0000000 --- a/openshift/pipelines/jobs/waiverdb-dev-integration-test.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-integration-test-template.yaml diff --git a/openshift/pipelines/jobs/waiverdb-integration-test.env b/openshift/pipelines/jobs/waiverdb-integration-test.env deleted file mode 100644 index 723e655..0000000 --- a/openshift/pipelines/jobs/waiverdb-integration-test.env +++ /dev/null @@ -1,2 +0,0 @@ -NAME=waiverdb-integration-test -IMAGE=quay.io/factory2/waiverdb:latest diff --git a/openshift/pipelines/jobs/waiverdb-integration-test.tmpl b/openshift/pipelines/jobs/waiverdb-integration-test.tmpl deleted file mode 100644 index f02d245..0000000 --- a/openshift/pipelines/jobs/waiverdb-integration-test.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-integration-test-template.yaml diff --git a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy index 7a57ad8..7d59ae0 100644 --- a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy +++ b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy @@ -83,6 +83,7 @@ stage('Run integration tests') { } failure { script { + env.TESTCASE_CATEGORY = env.ENVIRONMENT c3i.archiveContainersLogs(env.PIPELINE_ID) } } diff --git a/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy new file mode 100644 index 0000000..2e9faa0 --- /dev/null +++ b/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy @@ -0,0 +1,175 @@ +stage("Functional tests phase") { + stages { + stage('Prepare') { + steps { + checkout([$class: 'GitSCM', + branches: [[name: env.PR_NO ? env.WAIVERDB_GIT_REF : env.WAIVERDB_GIT_COMMIT]], + userRemoteConfigs: [[url: params.WAIVERDB_GIT_REPO, refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head']], + ]) + env.IMAGE = "${env.RESULTING_IMAGE_REPO}:${env.RESULTING_TAG}" + } + } + stage('Cleanup') { + // Cleanup all test environments that were created 1 hour ago in case of failures of previous cleanups. + steps { + script { + openshift.withCluster() { + def df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + df.setTimeZone(TimeZone.getTimeZone('UTC')) + // Get all OpenShift objects of previous test environments + def oldObjs = openshift.selector('dc,deploy,configmap,secret,svc,route', + ['template': 'waiverdb-test', 'app':'waiverdb']) + def now = new Date() + // Delete all objects that are older than 1 hour + for (objName in oldObjs.names()) { + def obj = openshift.selector(objName) + def objData = obj.object() + if (!objData.metadata.creationTimestamp) + continue + def creationTime = df.parse(objData.metadata.creationTimestamp) + // 1 hour = 1000 * 60 * 60 ms + if (now.getTime() - creationTime.getTime() < 1000 * 60 * 60) + continue + echo "Deleting ${objName}..." + try { + obj.delete() + echo "Deleted ${objName}" + } catch (e) { + echo "Error deleting ${objName}: ${e.message}" + } + } + } + } + } + } + stage('Run functional tests') { + environment { + // Jenkins BUILD_TAG could be too long (> 63 characters) for OpenShift to consume + TEST_ID = "${params.TEST_ID ?: 'jenkins-' + currentBuild.id + '-' + UUID.randomUUID().toString().substring(0,7)}" + } + steps { + echo "Container image ${env.IMAGE} will be tested." + script { + openshift.withCluster() { + // Don't set ENVIRONMENT_LABEL in the environment block! Otherwise you will get 2 different UUIDs. + env.ENVIRONMENT_LABEL = "test-${env.TEST_ID}" + def template = readYaml file: 'openshift/waiverdb-test-template.yaml' + def webPodReplicas = 1 // The current quota in UpShift is agressively limited + echo "Creating testing environment with TEST_ID=${env.TEST_ID}..." + def models = openshift.process(template, + '-p', "TEST_ID=${env.TEST_ID}", + '-p', "WAIVERDB_APP_IMAGE=${env.IMAGE}", + '-p', "WAIVERDB_REPLICAS=${webPodReplicas}", + ) + c3i.deployAndWait(script: this, objs: models, timeout: 15) + def appPod = openshift.selector('pods', ['environment': env.ENVIRONMENT_LABEL, 'service': 'web']).object() + env.IMAGE_DIGEST = appPod.status.containerStatuses[0].imageID.split('@')[1] + // Run functional tests + def route_hostname = openshift.selector('routes', ['environment': env.ENVIRONMENT_LABEL]).object().spec.host + echo "Running tests against https://${route_hostname}/" + withEnv(["WAIVERDB_TEST_URL=https://${route_hostname}/"]) { + sh 'py.test-3 -v --junitxml=junit-functional-tests.xml functional-tests/' + } + } + } + } + post { + always { + script { + junit 'junit-functional-tests.xml' + archiveArtifacts artifacts: 'junit-functional-tests.xml' + openshift.withCluster() { + /* Extract logs for debugging purposes */ + openshift.selector('deploy,pods', ['environment': env.ENVIRONMENT_LABEL]).logs() + } + } + } + cleanup { + script { + openshift.withCluster() { + /* Tear down everything we just created */ + echo "Tearing down test resources..." + try { + openshift.selector('dc,deploy,rc,configmap,secret,svc,route', + ['environment': env.ENVIRONMENT_LABEL]).delete() + } catch (e) { + echo "Failed to tear down test resources: ${e.message}" + } + } + } + } + } + } + } + post { + always { + script { + if (!env.IMAGE_DIGEST) { + // Don't send a message if the job fails before getting the image digest. + return; + } + if (!env.MESSAGING_PROVIDER) { + // Don't send a message if messaging provider is not configured + return + } + // currentBuild.result == null || currentBuild.result == 'SUCCESS' indicates a successful build, + // because it's possible that the pipeline engine hasn't set the value nor seen an error when reaching to this line. + // See example code in https://jenkins.io/doc/book/pipeline/jenkinsfile/#deploy + def sendResult = sendCIMessage \ + providerName: params.MESSAGING_PROVIDER, \ + overrides: [topic: 'VirtualTopic.eng.ci.container-image.test.complete'], \ + messageType: 'Custom', \ + messageProperties: '', \ + messageContent: """ + { + "ci": { + "name": "C3I Jenkins", + "team": "DevOps", + "url": "${env.JENKINS_URL}", + "docs": "https://pagure.io/waiverdb/blob/master/f/openshift", + "irc": "#pnt-devops-dev", + "email": "pnt-factory2-devel@redhat.com", + "environment": "stage" + }, + "run": { + "url": "${env.BUILD_URL}", + "log": "${env.BUILD_URL}/console", + "debug": "", + "rebuild": "${env.BUILD_URL}/rebuild/parametrized" + }, + "artifact": { + "type": "container-image", + "repository": "factory2/waiverdb", + "digest": "${env.IMAGE_DIGEST}", + "nvr": "${env.IMAGE}", + "issuer": "c3i-jenkins", + "scratch": ${params.WAIVERDB_GIT_REF != params.WAIVERDB_MAIN_BRANCH}, + "id": "waiverdb@${env.IMAGE_DIGEST}" + }, + "system": + [{ + "os": "${params.JENKINS_AGENT_IMAGE}", + "provider": "openshift", + "architecture": "x86_64" + }], + "type": "integration", + "category": "${params.ENVIRONMENT}", + "status": "${currentBuild.result == null || currentBuild.result == 'SUCCESS' ? 'passed':'failed'}", + "xunit": "${env.BUILD_URL}/artifacts/junit-functional-tests.xml", + "generated_at": "${new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone('UTC'))}", + "namespace": "c3i", + "version": "0.1.0" + } + """ + if (sendResult.getMessageId()) { + // echo sent message id and content + echo 'Successfully sent the test result to ResultsDB.' + echo "Message ID: ${sendResult.getMessageId()}" + echo "Message content: ${sendResult.getMessageContent()}" + } else { + echo 'Failed to sent the test result to ResultsDB.' + } + } + } + } +} diff --git a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile index 01ad0dc..6005d5a 100644 --- a/openshift/pipelines/templates/waiverdb-build.Jenkinsfile +++ b/openshift/pipelines/templates/waiverdb-build.Jenkinsfile @@ -314,29 +314,7 @@ pipeline { } } } - stage('Run functional tests') { - steps { - script { - openshift.withCluster() { - openshift.withProject(params.WAIVERDB_INTEGRATION_TEST_BUILD_CONFIG_NAMESPACE) { - echo 'Starting a functional test for the built container image...' - c3i.buildAndWait(script: this, objs: "bc/${params.WAIVERDB_INTEGRATION_TEST_BUILD_CONFIG_NAME}", - '-e', "WAIVERDB_GIT_REPO=${params.WAIVERDB_GIT_REPO}", - '-e', "IMAGE=${env.RESULTING_IMAGE_REPO}:${env.RESULTING_TAG}", - '-e', "WAIVERDB_GIT_REF=${env.PR_NO ? env.WAIVERDB_GIT_REF : env.WAIVERDB_GIT_COMMIT}", - '-e', "IMAGE_IS_SCRATCH=${params.WAIVERDB_GIT_REF != params.WAIVERDB_MAIN_BRANCH}" - ) - echo "Functional test passed." - } - } - } - } - post { - failure { - echo "Functional test failed." - } - } - } + {% include "snippets/waiverdb-integration-test.groovy" %} stage('Push container') { when { expression { diff --git a/openshift/pipelines/templates/waiverdb-integration-test-template.yaml b/openshift/pipelines/templates/waiverdb-integration-test-template.yaml deleted file mode 100644 index e88ac17..0000000 --- a/openshift/pipelines/templates/waiverdb-integration-test-template.yaml +++ /dev/null @@ -1,104 +0,0 @@ -# Template to produce a new OpenShift pipeline for running integration tests -# ---- -apiVersion: v1 -kind: Template -metadata: - name: waiverdb-integration-test -labels: - template: waiverdb-integration-test -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. - required: true - value: waiverdb-integration-test -- name: IMAGE - displayName: The container image to be tested - description: This field must be in repo:tag or repo@sha256 format - value: quay.io/factory2/waiverdb:latest -- name: WAIVERDB_GIT_REPO - displayName: WaiverDB Git repo URL - description: Default WaiverDB Git repo URL in which to run functional tests against - required: true - 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 functional tests against - required: true - value: master -- name: JENKINS_AGENT_IMAGE - displayName: Container image for Jenkins slave pods - required: true - value: docker-registry.upshift.redhat.com/factory2/waiverdb-jenkins-slave:latest -- name: CONTAINER_REGISTRY_CREDENTIALS - displayName: Secret name of container registries used for pulling and pushing images - value: factory2-pipeline-registry-credentials - required: false -- name: OPENSHIFT_CLOUD_NAME - displayName: Name of OpenShift cloud in Jenkins master configuration - required: true - value: openshift -- name: ENVIRONMENT - displayName: environment name (dev/stage/prod) - required: true - value: dev -- name: MESSAGING_PROVIDER - displayName: Name of the JMS messaging provider - value: Red Hat UMB -{% include "snippets/c3i-library-parameters.yaml" %} -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" # FIXME: Parallel is supported, but we have limited quota in UpShift. - completionDeadlineSeconds: 1800 - strategy: - type: JenkinsPipeline - jenkinsPipelineStrategy: - env: - - name: "WAIVERDB_GIT_REPO" - value: "${WAIVERDB_GIT_REPO}" - - name: "WAIVERDB_GIT_REF" - value: "${WAIVERDB_GIT_REF}" - - name: "IMAGE" - value: "${IMAGE}" - - name: IMAGE_IS_SCRATCH - value: "true" - - name: "CONTAINER_REGISTRY_CREDENTIALS" - value: "${CONTAINER_REGISTRY_CREDENTIALS}" - - name: "TEST_ID" - value: "" - - name: JENKINS_AGENT_IMAGE - value: "${JENKINS_AGENT_IMAGE}" - - name: OPENSHIFT_CLOUD_NAME - value: "${OPENSHIFT_CLOUD_NAME}" - - name: JENKINS_AGENT_SERVICE_ACCOUNT - value: "${NAME}-jenkins-slave" - - name: ENVIRONMENT - value: "${ENVIRONMENT}" - - name: MESSAGING_PROVIDER - value: "${MESSAGING_PROVIDER}" - jenkinsfile: | - {% filter indent(width=10) %}{% include "waiverdb-integration-test.Jenkinsfile" %}{% endfilter %} diff --git a/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile b/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile deleted file mode 100644 index 6c7c771..0000000 --- a/openshift/pipelines/templates/waiverdb-integration-test.Jenkinsfile +++ /dev/null @@ -1,182 +0,0 @@ -import java.text.* - -{% include "snippets/c3i-library.groovy" %} -pipeline { - {% include "snippets/default-agent.groovy" %} - options { - timestamps() - timeout(time: 30, unit: 'MINUTES') - } - stages { - stage('Prepare') { - steps { - checkout([$class: 'GitSCM', - 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']], - ]) - } - } - stage('Cleanup') { - // Cleanup all test environments that were created 1 hour ago in case of failures of previous cleanups. - steps { - script { - openshift.withCluster() { - def df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") - df.setTimeZone(TimeZone.getTimeZone('UTC')) - // Get all OpenShift objects of previous test environments - def oldObjs = openshift.selector('dc,deploy,configmap,secret,svc,route', - ['template': 'waiverdb-test', 'app':'waiverdb']) - def now = new Date() - // Delete all objects that are older than 1 hour - for (objName in oldObjs.names()) { - def obj = openshift.selector(objName) - def objData = obj.object() - if (!objData.metadata.creationTimestamp) - continue - def creationTime = df.parse(objData.metadata.creationTimestamp) - // 1 hour = 1000 * 60 * 60 ms - if (now.getTime() - creationTime.getTime() < 1000 * 60 * 60) - continue - echo "Deleting ${objName}..." - try { - obj.delete() - echo "Deleted ${objName}" - } catch (e) { - echo "Error deleting ${objName}: ${e.message}" - } - } - } - } - } - } - stage('Run functional tests') { - environment { - // Jenkins BUILD_TAG could be too long (> 63 characters) for OpenShift to consume - TEST_ID = "${params.TEST_ID ?: 'jenkins-' + currentBuild.id + '-' + UUID.randomUUID().toString().substring(0,7)}" - } - steps { - echo "Container image ${params.IMAGE} will be tested." - script { - openshift.withCluster() { - // Don't set ENVIRONMENT_LABEL in the environment block! Otherwise you will get 2 different UUIDs. - env.ENVIRONMENT_LABEL = "test-${env.TEST_ID}" - def template = readYaml file: 'openshift/waiverdb-test-template.yaml' - def webPodReplicas = 1 // The current quota in UpShift is agressively limited - echo "Creating testing environment with TEST_ID=${env.TEST_ID}..." - def models = openshift.process(template, - '-p', "TEST_ID=${env.TEST_ID}", - '-p', "WAIVERDB_APP_IMAGE=${params.IMAGE}", - '-p', "WAIVERDB_REPLICAS=${webPodReplicas}", - ) - c3i.deployAndWait(script: this, objs: models, timeout: 15) - def appPod = openshift.selector('pods', ['environment': env.ENVIRONMENT_LABEL, 'service': 'web']).object() - env.IMAGE_DIGEST = appPod.status.containerStatuses[0].imageID.split('@')[1] - // Run functional tests - def route_hostname = openshift.selector('routes', ['environment': env.ENVIRONMENT_LABEL]).object().spec.host - echo "Running tests against https://${route_hostname}/" - withEnv(["WAIVERDB_TEST_URL=https://${route_hostname}/"]) { - sh 'py.test-3 -v --junitxml=junit-functional-tests.xml functional-tests/' - } - } - } - } - post { - always { - script { - junit 'junit-functional-tests.xml' - archiveArtifacts artifacts: 'junit-functional-tests.xml' - openshift.withCluster() { - /* Extract logs for debugging purposes */ - openshift.selector('deploy,pods', ['environment': env.ENVIRONMENT_LABEL]).logs() - } - } - } - cleanup { - script { - openshift.withCluster() { - /* Tear down everything we just created */ - echo "Tearing down test resources..." - try { - openshift.selector('dc,deploy,rc,configmap,secret,svc,route', - ['environment': env.ENVIRONMENT_LABEL]).delete() - } catch (e) { - echo "Failed to tear down test resources: ${e.message}" - } - } - } - } - } - } - } - post { - always { - script { - if (!env.IMAGE_DIGEST) { - // Don't send a message if the job fails before getting the image digest. - return; - } - if (!env.MESSAGING_PROVIDER) { - // Don't send a message if messaging provider is not configured - return - } - // currentBuild.result == null || currentBuild.result == 'SUCCESS' indicates a successful build, - // because it's possible that the pipeline engine hasn't set the value nor seen an error when reaching to this line. - // See example code in https://jenkins.io/doc/book/pipeline/jenkinsfile/#deploy - def sendResult = sendCIMessage \ - providerName: params.MESSAGING_PROVIDER, \ - overrides: [topic: 'VirtualTopic.eng.ci.container-image.test.complete'], \ - messageType: 'Custom', \ - messageProperties: '', \ - messageContent: """ - { - "ci": { - "name": "C3I Jenkins", - "team": "DevOps", - "url": "${env.JENKINS_URL}", - "docs": "https://pagure.io/waiverdb/blob/master/f/openshift", - "irc": "#pnt-devops-dev", - "email": "pnt-factory2-devel@redhat.com", - "environment": "stage" - }, - "run": { - "url": "${env.BUILD_URL}", - "log": "${env.BUILD_URL}/console", - "debug": "", - "rebuild": "${env.BUILD_URL}/rebuild/parametrized" - }, - "artifact": { - "type": "container-image", - "repository": "factory2/waiverdb", - "digest": "${env.IMAGE_DIGEST}", - "nvr": "${params.IMAGE}", - "issuer": "c3i-jenkins", - "scratch": ${params.IMAGE_IS_SCRATCH}, - "id": "waiverdb@${env.IMAGE_DIGEST}" - }, - "system": - [{ - "os": "${params.JENKINS_AGENT_IMAGE}", - "provider": "openshift", - "architecture": "x86_64" - }], - "type": "integration", - "category": "${params.ENVIRONMENT}", - "status": "${currentBuild.result == null || currentBuild.result == 'SUCCESS' ? 'passed':'failed'}", - "xunit": "${env.BUILD_URL}/artifacts/junit-functional-tests.xml", - "generated_at": "${new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone('UTC'))}", - "namespace": "c3i", - "version": "0.1.0" - } - """ - if (sendResult.getMessageId()) { - // echo sent message id and content - echo 'Successfully sent the test result to ResultsDB.' - echo "Message ID: ${sendResult.getMessageId()}" - echo "Message content: ${sendResult.getMessageContent()}" - } else { - echo 'Failed to sent the test result to ResultsDB.' - } - } - } - } -} From f090f20d9786da82a1d068ccdefbe41fcc33efbe Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:54 +0000 Subject: [PATCH 8/11] Use c3i lib for cleanup and clone --- diff --git a/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy index 2e9faa0..46c9326 100644 --- a/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy +++ b/openshift/pipelines/templates/snippets/waiverdb-integration-test.groovy @@ -2,11 +2,9 @@ stage("Functional tests phase") { stages { stage('Prepare') { steps { - checkout([$class: 'GitSCM', - branches: [[name: env.PR_NO ? env.WAIVERDB_GIT_REF : env.WAIVERDB_GIT_COMMIT]], - userRemoteConfigs: [[url: params.WAIVERDB_GIT_REPO, refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull/*/head:refs/remotes/origin/pull/*/head']], - ]) - env.IMAGE = "${env.RESULTING_IMAGE_REPO}:${env.RESULTING_TAG}" + script { + env.IMAGE = "${env.RESULTING_IMAGE_REPO}:${env.RESULTING_TAG}" + } } } stage('Cleanup') { @@ -14,29 +12,8 @@ stage("Functional tests phase") { steps { script { openshift.withCluster() { - def df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") - df.setTimeZone(TimeZone.getTimeZone('UTC')) - // Get all OpenShift objects of previous test environments - def oldObjs = openshift.selector('dc,deploy,configmap,secret,svc,route', - ['template': 'waiverdb-test', 'app':'waiverdb']) - def now = new Date() - // Delete all objects that are older than 1 hour - for (objName in oldObjs.names()) { - def obj = openshift.selector(objName) - def objData = obj.object() - if (!objData.metadata.creationTimestamp) - continue - def creationTime = df.parse(objData.metadata.creationTimestamp) - // 1 hour = 1000 * 60 * 60 ms - if (now.getTime() - creationTime.getTime() < 1000 * 60 * 60) - continue - echo "Deleting ${objName}..." - try { - obj.delete() - echo "Deleted ${objName}" - } catch (e) { - echo "Error deleting ${objName}: ${e.message}" - } + openshift.withProject(env.PIPELINE_ID) { + c3i.cleanup(script: this, age: 60, 'waiverdb') } } } From 4d8dd0eeff30f5a4e4a5616dbee1542902e2287a Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:54 +0000 Subject: [PATCH 9/11] Remove unused job waiverdb-dev waiverdb-dev is replaced by premerge and postmerge --- diff --git a/openshift/pipelines/jobs/waiverdb-dev.env b/openshift/pipelines/jobs/waiverdb-dev.env deleted file mode 100644 index ceb9e64..0000000 --- a/openshift/pipelines/jobs/waiverdb-dev.env +++ /dev/null @@ -1,3 +0,0 @@ -# This job is deprecated. New jobs are waiverdb-premerge and waiverdb-postmerge -NAME=waiverdb-dev -PAGURE_DOC_REPO_NAME= # Temporarily disable doc push to workaround https://pagure.io/pagure/issue/3919. Remove this line when it is fixed. diff --git a/openshift/pipelines/jobs/waiverdb-dev.tmpl b/openshift/pipelines/jobs/waiverdb-dev.tmpl deleted file mode 100644 index 316b89d..0000000 --- a/openshift/pipelines/jobs/waiverdb-dev.tmpl +++ /dev/null @@ -1 +0,0 @@ -waiverdb-build-template.yaml From 8dbf37329a1735907712286fa411531f8b05c270 Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 13:34:54 +0000 Subject: [PATCH 10/11] Use new SERVICES_TO_DEPLOY parameter Allows to whitelist services to be installed. --- diff --git a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy index 7d59ae0..97c1130 100644 --- a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy +++ b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy @@ -34,10 +34,7 @@ stage('Run integration tests') { '-e', "WAIVERDB_IMAGE=${env.IMAGE}", '-e', "PIPELINE_ID=${env.PIPELINE_ID}", '-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}", - '-e', "KOJI_HUB_IMAGE=", - '-e', "MBS_BACKEND_IMAGE=", - '-e', "MBS_FRONTEND_IMAGE=", - '-e', "KOJI_HUB_IMAGE=", + '-e', "SERVICES_TO_DEPLOY='resultsdb-updater datanommer greenwave resultsdb umb waiverdb datagrepper'", '-e', "TRIGGERED_BY=${env.BUILD_URL}" ) } From 0928af1af2288b7508bacbe07f01144d85286345 Mon Sep 17 00:00:00 2001 From: Michal Kovarik Date: Jan 22 2020 14:01:52 +0000 Subject: [PATCH 11/11] Removed duplicated function --- diff --git a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy index 97c1130..7e18656 100644 --- a/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy +++ b/openshift/pipelines/templates/snippets/waiverdb-full-integration-test.groovy @@ -6,7 +6,7 @@ stage('Run integration tests') { if (!env.TRIGGER_NAMESPACE) { env.TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim() } - if(!env.PAAS_DOMAIN) { + if (!env.PAAS_DOMAIN) { openshift.withCluster() { openshift.withProject(env.TRIGGER_NAMESPACE) { def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') @@ -17,15 +17,6 @@ stage('Run integration tests') { } echo "Routes end with ${env.PAAS_DOMAIN}" } - openshift.withCluster() { - openshift.withProject(env.TRIGGER_NAMESPACE) { - def testroute = openshift.create('route', 'edge', "test-${env.BUILD_NUMBER}", '--service=test', '--port=8080') - def testhost = testroute.object().spec.host - env.PAAS_DOMAIN = testhost.minus("test-${env.BUILD_NUMBER}-${env.TRIGGER_NAMESPACE}.") - testroute.delete() - } - } - echo "Routes end with ${env.PAAS_DOMAIN}" env.PIPELINE_ID = 'c3i-pipeline-' + UUID.randomUUID().toString().substring(0,4) openshift.withCluster() { openshift.withProject(params.PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE) {