Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-pick #22076 to 7.x: Cherry-pick to 7.10: packaging backports #23142

Merged
merged 4 commits into from
Jan 7, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 144 additions & 35 deletions .ci/packaging.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@

@Library('apm@current') _

import groovy.transform.Field

/**
This is required to store the test suites we will use to trigger the E2E tests.
*/
@Field def e2eTestSuites = []

pipeline {
agent none
environment {
BASE_DIR = 'src/github.com/elastic/beats'
REPO = 'beats'
BASE_DIR = "src/github.com/elastic/${env.REPO}"
JOB_GCS_BUCKET = 'beats-ci-artifacts'
JOB_GCS_BUCKET_STASH = 'beats-ci-temp'
JOB_GCS_CREDENTIALS = 'beats-ci-gcs-plugin'
DOCKERELASTIC_SECRET = 'secret/observability-team/ci/docker-registry/prod'
DOCKER_REGISTRY = 'docker.elastic.co'
GITHUB_CHECK_E2E_TESTS_NAME = 'E2E Tests'
SNAPSHOT = "true"
PIPELINE_LOG_LEVEL = "INFO"
}
Expand All @@ -34,7 +43,7 @@ pipeline {
}
stages {
stage('Filter build') {
agent { label 'ubuntu && immutable' }
agent { label 'ubuntu-18 && immutable' }
when {
beforeAgent true
anyOf {
Expand Down Expand Up @@ -103,14 +112,14 @@ pipeline {
'x-pack/heartbeat',
// 'x-pack/journalbeat',
'x-pack/metricbeat',
'x-pack/packetbeat',
// 'x-pack/packetbeat',
'x-pack/winlogbeat'
)
}
}
stages {
stage('Package Linux'){
agent { label 'ubuntu && immutable' }
agent { label 'ubuntu-18 && immutable' }
options { skipDefaultCheckout() }
when {
beforeAgent true
Expand Down Expand Up @@ -142,6 +151,7 @@ pipeline {
release()
pushCIDockerImages()
}
prepareE2ETestForPackage("${BEATS_FOLDER}")
}
}
stage('Package Mac OS'){
Expand Down Expand Up @@ -172,6 +182,13 @@ pipeline {
}
}
}
stage('Run E2E Tests for Packages'){
agent { label 'ubuntu-18 && immutable' }
options { skipDefaultCheckout() }
steps {
runE2ETests()
}
}
}
post {
success {
Expand All @@ -190,68 +207,160 @@ pipeline {

def pushCIDockerImages(){
catchError(buildResult: 'UNSTABLE', message: 'Unable to push Docker images', stageResult: 'FAILURE') {
if ("${env.BEATS_FOLDER}" == "auditbeat"){
tagAndPush('auditbeat-oss')
} else if ("${env.BEATS_FOLDER}" == "filebeat") {
tagAndPush('filebeat-oss')
} else if ("${env.BEATS_FOLDER}" == "heartbeat"){
tagAndPush('heartbeat-oss')
if (env?.BEATS_FOLDER?.endsWith('auditbeat')) {
tagAndPush('auditbeat')
} else if (env?.BEATS_FOLDER?.endsWith('filebeat')) {
tagAndPush('filebeat')
} else if (env?.BEATS_FOLDER?.endsWith('heartbeat')) {
tagAndPush('heartbeat')
} else if ("${env.BEATS_FOLDER}" == "journalbeat"){
tagAndPush('journalbeat')
tagAndPush('journalbeat-oss')
} else if ("${env.BEATS_FOLDER}" == "metricbeat"){
tagAndPush('metricbeat-oss')
} else if (env?.BEATS_FOLDER?.endsWith('metricbeat')) {
tagAndPush('metricbeat')
} else if ("${env.BEATS_FOLDER}" == "packetbeat"){
tagAndPush('packetbeat')
tagAndPush('packetbeat-oss')
} else if ("${env.BEATS_FOLDER}" == "x-pack/auditbeat"){
tagAndPush('auditbeat')
} else if ("${env.BEATS_FOLDER}" == "x-pack/elastic-agent") {
tagAndPush('elastic-agent')
} else if ("${env.BEATS_FOLDER}" == "x-pack/filebeat"){
tagAndPush('filebeat')
} else if ("${env.BEATS_FOLDER}" == "x-pack/heartbeat"){
tagAndPush('heartbeat')
} else if ("${env.BEATS_FOLDER}" == "x-pack/metricbeat"){
tagAndPush('metricbeat')
}
}
}

def tagAndPush(name){
def tagAndPush(beatName){
def libbetaVer = env.BEAT_VERSION
def aliasVersion = ""
if("${env.SNAPSHOT}" == "true"){
aliasVersion = libbetaVer.substring(0, libbetaVer.lastIndexOf(".")) // remove third number in version

libbetaVer += "-SNAPSHOT"
aliasVersion += "-SNAPSHOT"
}

def tagName = "${libbetaVer}"
if (isPR()) {
tagName = "pr-${env.CHANGE_ID}"
}

def oldName = "${DOCKER_REGISTRY}/beats/${name}:${libbetaVer}"
def newName = "${DOCKER_REGISTRY}/observability-ci/${name}:${tagName}"
def commitName = "${DOCKER_REGISTRY}/observability-ci/${name}:${env.GIT_BASE_COMMIT}"
dockerLogin(secret: "${DOCKERELASTIC_SECRET}", registry: "${DOCKER_REGISTRY}")
retry(3){
sh(label:'Change tag and push', script: """
docker tag ${oldName} ${newName}
docker push ${newName}
docker tag ${oldName} ${commitName}
docker push ${commitName}
""")

// supported image flavours
def variants = ["", "-oss", "-ubi8"]
variants.each { variant ->
doTagAndPush(beatName, variant, libbetaVer, tagName)
doTagAndPush(beatName, variant, libbetaVer, "${env.GIT_BASE_COMMIT}")

if (!isPR() && aliasVersion != "") {
doTagAndPush(beatName, variant, libbetaVer, aliasVersion)
}
}
}

/**
* @param beatName name of the Beat
* @param variant name of the variant used to build the docker image name
* @param sourceTag tag to be used as source for the docker tag command, usually under the 'beats' namespace
* @param targetTag tag to be used as target for the docker tag command, usually under the 'observability-ci' namespace
*/
def doTagAndPush(beatName, variant, sourceTag, targetTag) {
def sourceName = "${DOCKER_REGISTRY}/beats/${beatName}${variant}:${sourceTag}"
def targetName = "${DOCKER_REGISTRY}/observability-ci/${beatName}${variant}:${targetTag}"

def iterations = 0
retryWithSleep(retries: 3, seconds: 5, backoff: true) {
iterations++
def status = sh(label: "Change tag and push ${targetName}", script: """
docker tag ${sourceName} ${targetName}
docker push ${targetName}
""", returnStatus: true)

if ( status > 0 && iterations < 3) {
error("tag and push failed for ${beatName}, retry")
} else if ( status > 0 ) {
log(level: 'WARN', text: "${beatName} doesn't have ${variant} docker images. See https://github.com/elastic/beats/pull/21621")
}
}
}

def prepareE2ETestForPackage(String beat){
if ("${beat}" == "filebeat" || "${beat}" == "x-pack/filebeat") {
e2eTestSuites.push('fleet')
e2eTestSuites.push('helm')
} else if ("${beat}" == "metricbeat" || "${beat}" == "x-pack/metricbeat") {
e2eTestSuites.push('ALL')
echo("${beat} adds all test suites to the E2E tests job.")
} else if ("${beat}" == "x-pack/elastic-agent") {
e2eTestSuites.push('fleet')
} else {
echo("${beat} does not add any test suite to the E2E tests job.")
return
}
}

def release(){
withBeatsEnv(){
dir("${env.BEATS_FOLDER}") {
sh(label: "Release ${env.BEATS_FOLDER} ${env.PLATFORMS}", script: 'mage package')
withEnv([
"DEV=true"
]) {
dir("${env.BEATS_FOLDER}") {
sh(label: "Release ${env.BEATS_FOLDER} ${env.PLATFORMS}", script: 'mage package')
}
}
publishPackages("${env.BEATS_FOLDER}")
}
}

def runE2ETests(){
if (e2eTestSuites.size() == 0) {
echo("Not triggering E2E tests for PR-${env.CHANGE_ID} because the changes does not affect the E2E.")
return
}

def suites = '' // empty value represents all suites in the E2E tests

catchError(buildResult: 'UNSTABLE', message: 'Unable to run e2e tests', stageResult: 'FAILURE') {
def suitesSet = e2eTestSuites.toSet()

if (!suitesSet.contains('ALL')) {
suitesSet.each { suite ->
suites += "${suite},"
};
}

triggerE2ETests(suites)
}
}

def triggerE2ETests(String suite) {
echo("Triggering E2E tests for PR-${env.CHANGE_ID}. Test suites: ${suite}.")

def branchName = isPR() ? "${env.CHANGE_TARGET}" : "${env.JOB_BASE_NAME}.x"
def e2eTestsPipeline = "e2e-tests/e2e-testing-mbp/${branchName}"

def parameters = [
booleanParam(name: 'forceSkipGitChecks', value: true),
booleanParam(name: 'forceSkipPresubmit', value: true),
booleanParam(name: 'notifyOnGreenBuilds', value: !isPR()),
string(name: 'runTestsSuites', value: suite),
string(name: 'GITHUB_CHECK_NAME', value: env.GITHUB_CHECK_E2E_TESTS_NAME),
string(name: 'GITHUB_CHECK_REPO', value: env.REPO),
string(name: 'GITHUB_CHECK_SHA1', value: env.GIT_BASE_COMMIT),
]
if (isPR()) {
def version = "pr-${env.CHANGE_ID}"
parameters.push(booleanParam(name: 'ELASTIC_AGENT_USE_CI_SNAPSHOTS', value: true))
parameters.push(string(name: 'ELASTIC_AGENT_VERSION', value: "${version}"))
parameters.push(string(name: 'METRICBEAT_VERSION', value: "${version}"))
}

build(job: "${e2eTestsPipeline}",
parameters: parameters,
propagate: false,
wait: false
)

def notifyContext = "${env.GITHUB_CHECK_E2E_TESTS_NAME}"
githubNotify(context: "${notifyContext}", description: "${notifyContext} ...", status: 'PENDING', targetUrl: "${env.JENKINS_URL}search/?q=${e2eTestsPipeline.replaceAll('/','+')}")
}

def withMacOSEnv(Closure body){
withEnvMask( vars: [
[var: "KEYCHAIN_PASS", password: getVaultSecret(secret: "secret/jenkins-ci/macos-codesign-keychain").data.password],
Expand Down