Skip to content

Commit

Permalink
[CI] sign artifacts for the release (partially implemented) (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
v1v authored Sep 29, 2020
1 parent 9926756 commit a0ca5c1
Showing 1 changed file with 84 additions and 19 deletions.
103 changes: 84 additions & 19 deletions .ci/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
@Library('apm@current') _

pipeline {
agent { label 'linux && immutable' }
agent { label 'linux && docker && ubuntu-18.04 && immutable' }
environment {
REPO = 'apm-agent-php'
BASE_DIR = "src/go.elastic.co/apm/${env.REPO}"
NOTIFY_TO = credentials('notify-to')
JOB_GCS_BUCKET = credentials('gcs-bucket')
SLACK_CHANNEL = '#apm-agent-php'
NOTIFY_TO = 'build-apm+apm-agent-php@elastic.co'
ONLY_DOCS = "false"
}
options {
Expand Down Expand Up @@ -51,7 +51,7 @@ pipeline {
}
failFast false
matrix {
agent { label 'linux && immutable' }
agent { label 'linux && docker && ubuntu-18.04 && immutable' }
options { skipDefaultCheckout() }
axes {
axis {
Expand Down Expand Up @@ -140,7 +140,8 @@ pipeline {
unstash 'generate-for-package-7.4-Dockerfile.alpine'
sh script: "make -C packaging package", label: 'package'
sh script: "make -C packaging info", label: 'package info'
stash includes: 'build/packages/*', name: 'package'
// checksum files are regenerated by the signing component in the internal-ci instance.
stash(includes: 'build/packages/*', name: 'package', excludes: 'build/packages/**/*.sha512')
}
}
}
Expand All @@ -159,7 +160,7 @@ pipeline {
}
failFast false
matrix {
agent { label 'linux && immutable' }
agent { label 'linux && docker && ubuntu-18.04 && immutable' }
options { skipDefaultCheckout() }
axes {
axis {
Expand Down Expand Up @@ -197,7 +198,7 @@ pipeline {
}
matrix {
// TODO: This should be uncommented out when the implementation is in place
// agent { label 'linux && immutable' }
// agent { label 'linux && docker && ubuntu-18.04 && immutable' }
options { skipDefaultCheckout() }
axes {
axis {
Expand Down Expand Up @@ -245,27 +246,64 @@ pipeline {
}
}
}
// This meta-stage happens in the internal-ci instance to be able to sign the artifacts correctly.
stage('Release') {
options {
skipDefaultCheckout()
timeout(time: 12, unit: 'HOURS')
}
when {
beforeAgent true
tag pattern: 'v\\d+.*', comparator: 'REGEXP'
allOf {
tag pattern: 'v\\d+.*', comparator: 'REGEXP'
expression { isInternalCI() }
}
}
agent { label 'linux && docker && ubuntu-18.04 && immutable' }
environment {
BUCKET_NAME = 'internal-ci-artifacts'
BUCKET_SUBFOLDER = "${env.REPO}/${env.TAG_NAME}"
BUCKET_PATH = "gs://${env.BUCKET_NAME}/${env.BUCKET_SUBFOLDER}"
BUCKET_CREDENTIALS = 'internal-ci-gcs-plugin'
SIGNED_ARTIFACTS = 'signed-artifacts'
BUCKET_SUBFOLDER_SIGNED_ARTIFACTS = "${env.BUCKET_SUBFOLDER}/${env.SIGNED_ARTIFACTS}"
BUCKET_SIGNED_ARTIFACTS_PATH = "gs://${env.BUCKET_NAME}/${env.BUCKET_SUBFOLDER_SIGNED_ARTIFACTS}"
}
stages {
stage('Notify') {
options { skipDefaultCheckout() }
steps {
emailext subject: "[${env.REPO}] Release ready to be pushed", to: "${NOTIFY_TO}",
body: "Please go to ${env.BUILD_URL}input to approve or reject within 12 hours.\n Changes: ${env.TAG_NAME}"
script {
def should_continue = input(message: "You are about to release version ${env.TAG_NAME}",
parameters: [ [$class: 'ChoiceParameterDefinition',
name: 'Do you wish to release it?',
choices: ['Yes', 'No']] ])
env.RELEASE = should_continue.equals('Yes')
notifyStatus(slackStatus: 'warning', subject: "[${env.REPO}] Release ready to be pushed",
body: "Please (<${env.BUILD_URL}input|approve>) it or reject within 12 hours.\n Changes: ${env.TAG_NAME}")
setEnvVar('RELEASE', askAndWait("You are about to release version ${env.TAG_NAME}. Do you wish to release it?"))
}
}
stage('Signing CI') {
when {
beforeAgent true
expression { return env.RELEASE == 'true' }
}
options { skipDefaultCheckout() }
steps {
deleteDir()
unstash 'source'
dir("${BASE_DIR}") {
unstash 'package'
googleStorageUpload(bucket: env.BUCKET_PATH,
credentialsId: env.BUCKET_CREDENTIALS,
pathPrefix: 'build/packages/',
pattern: 'build/packages/**/*',
sharedPublicly: false,
showInline: true)
build(wait: true, propagate: true, job: 'elastic+unified-release+master+sign-artifacts-with-gpg', parameters: [string(name: 'gcs_input_path', value: "${env.BUCKET_PATH}")])
dir("${SIGNED_ARTIFACTS}") {
googleStorageDownload(bucketUri: "${env.BUCKET_SIGNED_ARTIFACTS_PATH}/*",
credentialsId: env.BUCKET_CREDENTIALS,
localDirectory: 'build/packages/',
pathPrefix: "${env.BUCKET_SUBFOLDER_SIGNED_ARTIFACTS}")
stash allowEmpty: false, name: env.SIGNED_ARTIFACTS, useDefaultExcludes: false
}
archiveArtifacts(allowEmptyArchive: true, artifacts: "${SIGNED_ARTIFACTS}/**/*")
}
}
}
Expand All @@ -279,15 +317,15 @@ pipeline {
deleteDir()
unstash 'source'
dir("${BASE_DIR}") {
unstash 'package'
unstash "${env.SIGNED_ARTIFACTS}"
withCredentials([string(credentialsId: '2a9602aa-ab9f-4e52-baf3-b71ca88469c7', variable: 'GITHUB_TOKEN')]) {
sh script: 'make -f .ci/Makefile release', label: 'release'
}
}
}
post {
success {
emailext subject: "[${env.REPO}] Release published", to: "${env.NOTIFY_TO}", body: "Great news, the release has been done successfully."
notifyStatus(slackStatus: 'good', subject: "[${env.REPO}] Release *${env.TAG_NAME}* published", body: "(<${env.RUN_DISPLAY_URL}|Open>)")
}
always {
script {
Expand All @@ -297,11 +335,38 @@ pipeline {
}
}
}
post {
failure {
notifyStatus(slackStatus: 'danger', subject: "[${env.REPO}] Release *${env.TAG_NAME}* failed", body: "(<${env.RUN_DISPLAY_URL}|Open>)")
}
}
}
}
post {
cleanup {
notifyBuildResult()
// Reporting disables in the `internal-ci` since credentials are not in place
// OTOH it avoids duplicated notifications
whenFalse(isInternalCI()){
notifyBuildResult()
}
}
}
}

// TODO: create an input step to avoid this try/catch and return true/false
def askAndWait(message) {
try {
input(message: message, ok: 'Yes')
return true
} catch(err) {
return false
}
}

def notifyStatus(def args = [:]) {
slackSend(channel: env.SLACK_CHANNEL, color: args.slackStatus, message: "${args.subject}. ${args.body}",
tokenCredentialId: 'jenkins-slack-integration-token')
// transform slack URL format '(<URL|description>)' to 'URL'.
def bodyEmail = args.body.replaceAll('\\(<', '').replaceAll('\\|.*>\\)', '')
emailext(subject: args.subject, to: "${env.NOTIFY_TO}", body: bodyEmail)
}

0 comments on commit a0ca5c1

Please sign in to comment.