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

CLOUD-869 Enhance Jenkinsfile to skip builds for specified non-trigger files #1901

Merged
merged 65 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
617c344
Enhance Jenkinsfile to skip builds for specified non-trigger files
ptankov Dec 5, 2024
9528209
Add logic to determine non-trigger files in Jenkins pipeline
ptankov Dec 5, 2024
e072a10
Fix logic to determine non-trigger files in Jenkins pipeline
ptankov Dec 5, 2024
461414f
Refactor Jenkinsfile to comment out non-trigger files determination l…
ptankov Dec 5, 2024
5243196
Add non-trigger-files.txt to changeset in Jenkinsfile
ptankov Dec 5, 2024
c80e42f
Refactor Jenkinsfile to restore non-trigger files determination logic…
ptankov Dec 6, 2024
89e3e9d
Enhance non-trigger files logic in Jenkinsfile to use regex for exclu…
ptankov Dec 6, 2024
cac0946
Implement non-trigger files determination logic in Jenkinsfile with r…
ptankov Dec 6, 2024
2c46d1f
Replace non-trigger-files.txt with .e2eignore for file exclusion in J…
ptankov Dec 6, 2024
0087f39
Add checkE2EIgnoreFiles function to validate changed files against .e…
ptankov Dec 6, 2024
5f6f92c
Remove .e2eignore and Jenkinsfile from exclusion list in .e2eignore
ptankov Dec 6, 2024
ff4ec1a
improved readability and consistency
ptankov Dec 6, 2024
85a3187
Refactor Jenkinsfile to improve handling of e2eignore files and strea…
ptankov Dec 6, 2024
3498d98
Add onlyIgnoredFiles flag to Jenkinsfile for enhanced e2eignore handling
ptankov Dec 6, 2024
60c267b
Fix variable declaration for onlyIgnoredFiles in checkE2EIgnoreFiles …
ptankov Dec 6, 2024
34bcf49
testing the new behavior of skipping builds for non-trigger files
ptankov Dec 6, 2024
db9abe9
Refactor Jenkinsfile to enhance build logic and streamline post-build…
ptankov Dec 6, 2024
34de7f5
Merge branch 'main' into CLOUD-869
ptankov Dec 6, 2024
7ec7d31
Merge branch 'main' into CLOUD-869
ptankov Dec 6, 2024
926b461
Merge branch 'main' into CLOUD-869
ptankov Dec 6, 2024
ded65b4
Update .e2eignore to include additional documentation files
ptankov Dec 6, 2024
1619503
debug
ptankov Dec 6, 2024
0804924
avoiding unnecessary test executions for subsequent commits
ptankov Dec 6, 2024
47cd5e5
debug
ptankov Dec 6, 2024
344ce42
Refactor Jenkinsfile to improve variable usage and enhance readability
ptankov Dec 7, 2024
fff22a7
Remove unnecessary debug echo statements from Jenkinsfile to streamli…
ptankov Dec 7, 2024
12cc48f
Remove unused variable 'changedFiles' from Jenkinsfile to clean up code
ptankov Dec 7, 2024
c23fb58
debug
ptankov Dec 7, 2024
78f5373
Refactor Jenkinsfile to enhance previous build handling and streamlin…
ptankov Dec 7, 2024
11532fe
Remove redundant echo statements for 'onlyIgnoredFiles' in Jenkinsfil…
ptankov Dec 7, 2024
fa716b1
Remove 'Jenkinsfile' from .e2eignore to ensure it is included in end-…
ptankov Dec 7, 2024
b648d4c
Format code in Jenkinsfile for improved readability in checkE2EIgnore…
ptankov Dec 7, 2024
82d566e
Refactor checkE2EIgnoreFiles function in Jenkinsfile to improve varia…
ptankov Dec 7, 2024
0992924
debug to see if the job will run the tests
ptankov Dec 7, 2024
71534d6
remove unnecessary if-else statement.
ptankov Dec 7, 2024
cc9921e
Refactor checkE2EIgnoreFiles function in Jenkinsfile to improve varia…
ptankov Dec 7, 2024
8c737c2
Refactor logic in checkE2EIgnoreFiles function to simplify test execu…
ptankov Dec 7, 2024
8be2a98
Merge branch 'main' into CLOUD-869
ptankov Dec 9, 2024
9d0f1fd
Merge branch 'main' into CLOUD-869
ptankov Dec 9, 2024
cafffe8
resolving conflicts by accepting the target branch
ptankov Dec 9, 2024
132fa4b
resolving conflicts by accepting the target branch
ptankov Dec 9, 2024
26691dd
Merge branch 'main' into CLOUD-869
ptankov Dec 9, 2024
ffa45dd
refactor: update Jenkinsfile for improved readability and consistency
ptankov Dec 10, 2024
f4bb946
Merge branch 'main' into CLOUD-869
ptankov Dec 10, 2024
6646808
Merge branch 'main' into CLOUD-869
ptankov Dec 12, 2024
b168e9b
Merge branch 'main' into CLOUD-869
ptankov Dec 12, 2024
ca18e0b
Merge branch 'main' into CLOUD-869
ptankov Dec 12, 2024
be5cda2
Merge branch 'main' into CLOUD-869
ptankov Dec 13, 2024
c44fb15
Merge branch 'main' into CLOUD-869
ptankov Dec 19, 2024
1db6ca4
Merge branch 'main' into CLOUD-869
ptankov Dec 19, 2024
2176451
Merge branch 'main' into CLOUD-869
ptankov Dec 27, 2024
adc5049
Merge branch 'main' into CLOUD-869
ptankov Dec 28, 2024
b28b5e6
Merge branch 'main' into CLOUD-869
ptankov Dec 30, 2024
68d030a
Merge branch 'main' into CLOUD-869
ptankov Dec 31, 2024
52823a3
Enhance Jenkins pipeline to support manual builds and improve logging…
ptankov Jan 1, 2025
c77b605
Merge branch 'main' into CLOUD-869
ptankov Jan 6, 2025
c99f533
Extract node preparation steps into a function.
ptankov Jan 7, 2025
643f307
Update .e2eignore
ptankov Jan 10, 2025
1b27819
Refactor Jenkinsfile to improve e2eignore file handling and streamlin…
ptankov Jan 11, 2025
940f31f
Remove unnecessary blank line.
ptankov Jan 11, 2025
d0dba5e
Fix paths in Jenkinsfile for docker tag file and golicense command
ptankov Jan 11, 2025
dc5a8c8
Merge branch 'main' into CLOUD-869
ptankov Jan 13, 2025
f702ccb
Merge branch 'main' into CLOUD-869
ptankov Jan 13, 2025
ce3a25a
Merge branch 'main' into CLOUD-869
ptankov Jan 14, 2025
6c055b7
remove unnecessary debug flag
ptankov Jan 14, 2025
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
12 changes: 12 additions & 0 deletions .e2eignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.github/**
docs/**
code-of-conduct.md
CONTRIBUTING.md
README.md
.gitattributes
.gitignore
LICENSE
operator.png
kubernetes.svg
.e2eignore
release_versions
207 changes: 145 additions & 62 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
region='us-central1-a'
region="us-central1-a"
testUrlPrefix="https://percona-jenkins-artifactory-public.s3.amazonaws.com/cloud-pxc-operator"
tests=[]

Expand All @@ -14,7 +14,7 @@ void createCluster(String CLUSTER_SUFFIX) {
gcloud config set project $GCP_PROJECT
gcloud container clusters list --filter $CLUSTER_NAME-${CLUSTER_SUFFIX} --zone $region --format='csv[no-heading](name)' | xargs gcloud container clusters delete --zone $region --quiet || true

gcloud container clusters create --zone $region $CLUSTER_NAME-${CLUSTER_SUFFIX} --cluster-version=1.28 --machine-type=n1-standard-4 --preemptible --disk-size 30 --num-nodes=\$NODES_NUM --network=jenkins-vpc --subnetwork=jenkins-${CLUSTER_SUFFIX} --no-enable-autoupgrade --cluster-ipv4-cidr=/21 --labels delete-cluster-after-hours=6 && \
gcloud container clusters create --zone $region $CLUSTER_NAME-${CLUSTER_SUFFIX} --cluster-version=1.28 --machine-type=n1-standard-4 --preemptible --disk-size 30 --num-nodes=\$NODES_NUM --network=jenkins-vpc --subnetwork=jenkins-${CLUSTER_SUFFIX} --no-enable-autoupgrade --cluster-ipv4-cidr=/21 --labels delete-cluster-after-hours=6 --enable-ip-alias && \
kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user jenkins@"$GCP_PROJECT".iam.gserviceaccount.com || ret_val=\$?
if [ \${ret_val} -eq 0 ]; then break; fi
ret_num=\$((ret_num + 1))
Expand Down Expand Up @@ -145,22 +145,22 @@ void printKubernetesStatus(String LOCATION, String CLUSTER_SUFFIX) {
echo
kubectl top pod --all-namespaces
echo
kubectl get events --field-selector type!=Normal --all-namespaces
kubectl get events --field-selector type!=Normal --all-namespaces --sort-by=".lastTimestamp"
echo "======================================================"
"""
}

TestsReport = '| Test name | Status |\r\n| ------------- | ------------- |'
TestsReport = '| Test name | Status |\r\n| ------------- | ------------- |'
TestsReportXML = '<testsuite name=\\"PXC\\">\n'

void makeReport() {
def wholeTestAmount=tests.size()
def startedTestAmount = 0

for (int i=0; i<tests.size(); i++) {
def testNameWithMysqlVersion = tests[i]["name"] +"-"+ tests[i]["mysql_ver"].replace(".", "-")
def testResult = tests[i]["result"]
def testTime = tests[i]["time"]
def testNameWithMysqlVersion = tests[i]["name"] +"-"+ tests[i]["mysql_ver"].replace(".", "-")
def testUrl = "${testUrlPrefix}/${env.GIT_BRANCH}/${env.GIT_SHORT_COMMIT}/${testNameWithMysqlVersion}.log"

if (tests[i]["result"] != "skipped") {
Expand All @@ -171,6 +171,10 @@ void makeReport() {
}
TestsReport = TestsReport + "\r\n| We run $startedTestAmount out of $wholeTestAmount|"
TestsReportXML = TestsReportXML + '</testsuite>\n'

sh """
echo "${TestsReportXML}" > TestsReport.xml
"""
}

void clusterRunner(String cluster) {
Expand Down Expand Up @@ -224,6 +228,7 @@ void runTest(Integer TEST_ID) {
}
catch (exc) {
printKubernetesStatus("AFTER","$clusterSuffix")
echo "Test $testName has failed!"
if (retryCount >= 1 || currentBuild.nextBuild != null) {
currentBuild.result = 'FAILURE'
return true
Expand All @@ -241,9 +246,105 @@ void runTest(Integer TEST_ID) {
}
}

def skipBranchBuilds = true
void prepareNode() {
sh """
sudo curl -s -L -o /usr/local/bin/kubectl https://dl.k8s.io/release/\$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl && sudo chmod +x /usr/local/bin/kubectl
kubectl version --client --output=yaml

curl -fsSL https://get.helm.sh/helm-v3.12.3-linux-amd64.tar.gz | sudo tar -C /usr/local/bin --strip-components 1 -xzf - linux-amd64/helm

sudo curl -fsSL https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -o /usr/local/bin/yq && sudo chmod +x /usr/local/bin/yq
sudo curl -fsSL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux64 -o /usr/local/bin/jq && sudo chmod +x /usr/local/bin/jq

sudo tee /etc/yum.repos.d/google-cloud-sdk.repo << EOF
[google-cloud-cli]
name=Google Cloud CLI
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
sudo yum install -y google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin

curl -sL https://github.com/mitchellh/golicense/releases/latest/download/golicense_0.2.0_linux_x86_64.tar.gz | sudo tar -C /usr/local/bin -xzf - golicense

sudo yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm || true
sudo percona-release enable-only tools
sudo yum install -y percona-xtrabackup-80 | true
"""
}

boolean isManualBuild() {
def causes = currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause')
return !causes.isEmpty()
}

needToRunTests = true
void checkE2EIgnoreFiles() {
if (isManualBuild()) {
echo "This is a manual rebuild. Forcing pipeline execution."
return
}

def e2eignoreFile = ".e2eignore"
if (fileExists(e2eignoreFile)) {
def excludedFiles = readFile(e2eignoreFile).split('\n').collect{it.trim()}
def lastProcessedCommitFile="last-processed-commit.txt"
def lastProcessedCommitHash = ""
ptankov marked this conversation as resolved.
Show resolved Hide resolved

def build = currentBuild.previousBuild
while (build != null) {
try {
echo "Checking previous build: #$build.number"
copyArtifacts(projectName: env.JOB_NAME, selector: specific("$build.number"), filter: lastProcessedCommitFile)
lastProcessedCommitHash = readFile(lastProcessedCommitFile).trim()
echo "Last processed commit hash: $lastProcessedCommitHash"
break
} catch (Exception e) {
echo "No $lastProcessedCommitFile found in build $build.number. Checking earlier builds."
}
build = build.previousBuild
}

if (lastProcessedCommitHash == "") {
echo "This is the first run. Using merge base as the starting point for the diff."
changedFiles = sh(script: "git diff --name-only \$(git merge-base HEAD origin/$CHANGE_TARGET)", returnStdout: true).trim().split('\n').findAll{it}
} else {
echo "Processing changes since last processed commit: $lastProcessedCommitHash"
changedFiles = sh(script: "git diff --name-only $lastProcessedCommitHash HEAD", returnStdout: true).trim().split('\n').findAll{it}
}

echo "Excluded files: $excludedFiles"
echo "Changed files: $changedFiles"

def excludedFilesRegex = excludedFiles.collect{it.replace("**", ".*").replace("*", "[^/]*")}
needToRunTests = !changedFiles.every{changed -> excludedFilesRegex.any{regex -> changed ==~ regex}}

if (needToRunTests) {
echo "Some changed files are outside of the e2eignore list. Proceeding with execution."
} else {
if (currentBuild.previousBuild?.result in ['FAILURE', 'ABORTED', 'UNSTABLE']) {
echo "All changed files are e2eignore files, and previous build was unsuccessful. Propagating previous state."
currentBuild.result = currentBuild.previousBuild?.result
error "Skipping execution as non-significant changes detected and previous build was unsuccessful."
} else {
echo "All changed files are e2eignore files. Aborting pipeline execution."
}
}

sh """
echo \$(git rev-parse HEAD) > $lastProcessedCommitFile
"""
archiveArtifacts "$lastProcessedCommitFile"
} else {
echo "No $e2eignoreFile file found. Proceeding with execution."
}
}
ptankov marked this conversation as resolved.
Show resolved Hide resolved

def isPRJob = false
if (env.CHANGE_URL) {
skipBranchBuilds = false
isPRJob = true
}

pipeline {
Expand All @@ -262,16 +363,28 @@ pipeline {
}
options {
disableConcurrentBuilds(abortPrevious: true)
copyArtifactPermission("$JOB_NAME/PR-*")
}
stages {
stage('Check Ignore Files') {
when {
expression {
isPRJob
}
}
steps {
checkE2EIgnoreFiles()
}
}
stage('Prepare') {
when {
expression {
!skipBranchBuilds
isPRJob && needToRunTests
}
}
steps {
initTests()
prepareNode()
script {
if (AUTHOR_NAME == 'null') {
AUTHOR_NAME = sh(script: "git show -s --pretty=%ae | awk -F'@' '{print \$1}'", , returnStdout: true).trim()
Expand All @@ -284,33 +397,6 @@ pipeline {
}
}
}
sh """
sudo curl -s -L -o /usr/local/bin/kubectl https://dl.k8s.io/release/\$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl && sudo chmod +x /usr/local/bin/kubectl
kubectl version --client --output=yaml

curl -fsSL https://get.helm.sh/helm-v3.12.3-linux-amd64.tar.gz | sudo tar -C /usr/local/bin --strip-components 1 -xzf - linux-amd64/helm

sudo curl -fsSL https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -o /usr/local/bin/yq && sudo chmod +x /usr/local/bin/yq
sudo curl -fsSL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux64 -o /usr/local/bin/jq && sudo chmod +x /usr/local/bin/jq

sudo tee /etc/yum.repos.d/google-cloud-sdk.repo << EOF
[google-cloud-cli]
name=Google Cloud CLI
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
sudo yum install -y google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin

curl -sL https://github.com/mitchellh/golicense/releases/latest/download/golicense_0.2.0_linux_x86_64.tar.gz | sudo tar -C /usr/local/bin -xzf - golicense

sudo yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm || true
sudo percona-release enable-only tools
sudo yum install -y percona-xtrabackup-80 | true
"""

withCredentials([file(credentialsId: 'cloud-secret-file', variable: 'CLOUD_SECRET_FILE')]) {
sh '''
cp $CLOUD_SECRET_FILE e2e-tests/conf/cloud-secret.yml
Expand All @@ -322,7 +408,7 @@ EOF
stage('Build docker image') {
when {
expression {
!skipBranchBuilds
isPRJob && needToRunTests
}
}
steps {
Expand All @@ -339,7 +425,7 @@ EOF
./e2e-tests/build
docker logout
"
sudo rm -rf ./build
sudo rm -rf build
'''
}
stash includes: 'results/docker/TAG', name: 'IMAGE'
Expand All @@ -349,7 +435,7 @@ EOF
stage('GoLicenseDetector test') {
when {
expression {
!skipBranchBuilds
isPRJob && needToRunTests
}
}
steps {
Expand All @@ -376,7 +462,7 @@ EOF
stage('GoLicense test') {
when {
expression {
!skipBranchBuilds
isPRJob && needToRunTests
}
}
steps {
Expand Down Expand Up @@ -410,7 +496,7 @@ EOF
stage('Run tests for operator') {
when {
expression {
!skipBranchBuilds
isPRJob && needToRunTests
}
}
options {
Expand Down Expand Up @@ -478,34 +564,31 @@ EOF
slackSend channel: '#cloud-dev-ci', color: '#FF0000', message: "[${JOB_NAME}]: build ${currentBuild.result}, ${BUILD_URL} owner: @${AUTHOR_NAME}"
}
}

if (env.CHANGE_URL && currentBuild.nextBuild == null) {
for (comment in pullRequest.comments) {
println("Author: ${comment.user}, Comment: ${comment.body}")
if (comment.user.equals('JNKPercona')) {
println("delete comment")
comment.delete()
if (needToRunTests) {
if (isPRJob && currentBuild.nextBuild == null) {
for (comment in pullRequest.comments) {
println("Author: ${comment.user}, Comment: ${comment.body}")
if (comment.user.equals('JNKPercona')) {
println("delete comment")
comment.delete()
}
}
makeReport()
step([$class: 'JUnitResultArchiver', testResults: '*.xml', healthScaleFactor: 1.0])
archiveArtifacts '*.xml'

unstash 'IMAGE'
def IMAGE = sh(returnStdout: true, script: "cat results/docker/TAG").trim()
TestsReport = TestsReport + "\r\n\r\ncommit: ${env.CHANGE_URL}/commits/${env.GIT_COMMIT}\r\nimage: `${IMAGE}`\r\n"
pullRequest.comment(TestsReport)
}
makeReport()
deleteOldClusters("$CLUSTER_NAME")
sh """
echo "${TestsReportXML}" > TestsReport.xml
sudo docker system prune --volumes -af
"""
step([$class: 'JUnitResultArchiver', testResults: '*.xml', healthScaleFactor: 1.0])
archiveArtifacts '*.xml'

unstash 'IMAGE'
def IMAGE = sh(returnStdout: true, script: "cat results/docker/TAG").trim()
TestsReport = TestsReport + "\r\n\r\ncommit: ${env.CHANGE_URL}/commits/${env.GIT_COMMIT}\r\nimage: `${IMAGE}`\r\n"
pullRequest.comment(TestsReport)
}
deleteDir()
}
deleteOldClusters("$CLUSTER_NAME")
sh """
sudo docker system prune --volumes -af
sudo rm -rf *
"""
deleteDir()
}
}
}
1 change: 1 addition & 0 deletions e2e-tests/build
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/bash

set -o errexit
set -o xtrace
ptankov marked this conversation as resolved.
Show resolved Hide resolved

test_dir="$(dirname $0)"
. $(dirname $0)/functions
Expand Down
Loading