Skip to content

Commit 72a3de4

Browse files
committed
Add Jenkins CI
Signed-off-by: Thomas Keller <[email protected]>
1 parent aee20b1 commit 72a3de4

File tree

3 files changed

+421
-0
lines changed

3 files changed

+421
-0
lines changed

Jenkinsfile

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
pipeline {
2+
agent {
3+
/*docker {
4+
image 'mcr.microsoft.com/devcontainers/python:1-3.12-bookworm'
5+
}*/
6+
dockerfile {
7+
filename '.devcontainer/Dockerfile'
8+
dir '.'
9+
args '--net="jenkins_default"' // required for accessing the Gitea server
10+
}
11+
}
12+
options {
13+
disableConcurrentBuilds()
14+
//skipDefaultCheckout() // default checkout is required for .devcontainer/Dockerfile
15+
//newContainerPerStage()
16+
}
17+
parameters {
18+
booleanParam(
19+
name: 'RUN_TESTS',
20+
defaultValue: true,
21+
description: 'Flag indicating if tests should be executed'
22+
)
23+
}
24+
stages {
25+
stage('Cleanup') {
26+
steps {
27+
sh 'rm -rf build'
28+
}
29+
}
30+
stage('Checkout') {
31+
steps {
32+
//sh 'git submodule update --init --recursive'
33+
checkout(
34+
scmGit(
35+
branches: scm.branches,
36+
extensions: [submodule(recursiveSubmodules: true, reference: '')],
37+
userRemoteConfigs: scm.userRemoteConfigs
38+
)
39+
)
40+
}
41+
}
42+
stage('Build documentation') {
43+
steps {
44+
sh './tools/build-docs.sh'
45+
archiveArtifacts(
46+
artifacts: 'build/html/**',
47+
onlyIfSuccessful: true
48+
)
49+
publishHTML([
50+
allowMissing: false,
51+
alwaysLinkToLastBuild: false,
52+
keepAll: false,
53+
reportDir: 'build/html/',
54+
reportFiles: 'index.html',
55+
reportName: 'Documentation',
56+
reportTitles: '',
57+
useWrapperFileDirectly: true
58+
])
59+
}
60+
}
61+
stage('Static code analysis') {
62+
steps {
63+
warnError('clang-format issues found') {
64+
sh './tools/clang-format.sh'
65+
}
66+
sh 'cppcheck src/ --xml --xml-version=2 2> cppcheck.xml'
67+
recordIssues(
68+
sourceCodeRetention: 'LAST_BUILD',
69+
tools: [
70+
taskScanner(
71+
highTags: 'FIXME',
72+
includePattern: 'src/**/*.hpp,src/**/*.cpp',
73+
lowTags: 'HACK',
74+
normalTags: 'TODO'
75+
),
76+
cppCheck(pattern: 'cppcheck.xml')
77+
]
78+
)
79+
}
80+
}
81+
stage('Parallel build') {
82+
matrix {
83+
axes {
84+
axis {
85+
name 'COMPILER'
86+
values 'gcc', 'clang'
87+
}
88+
}
89+
stages {
90+
stage('Build project') {
91+
steps {
92+
sh "./tools/build-cmake-target.sh ${COMPILER}-release cplusplus_training_project"
93+
archiveArtifacts(
94+
artifacts: "build/${COMPILER}-release/bin/cplusplus_training_project",
95+
onlyIfSuccessful: true
96+
)
97+
recordIssues(
98+
sourceCodeRetention: 'LAST_BUILD',
99+
tools: [
100+
gcc(
101+
id: "gcc-${COMPILER}",
102+
name: "GCC [${COMPILER}]"
103+
),
104+
clang(
105+
id: "clang-${COMPILER}",
106+
name: "Clang [${COMPILER}]"
107+
)
108+
]
109+
)
110+
}
111+
}
112+
stage('Build tests') {
113+
steps {
114+
sh "./tools/build-cmake-target.sh ${COMPILER}-coverage calculate_test"
115+
archiveArtifacts(
116+
artifacts: "build/${COMPILER}-coverage/bin/calculate_test",
117+
onlyIfSuccessful: true
118+
)
119+
}
120+
}
121+
}
122+
}
123+
}
124+
stage('Parallel test execution') {
125+
when {
126+
expression {
127+
params.RUN_TESTS == true
128+
}
129+
}
130+
131+
parallel {
132+
stage('Run tests [gcc]') {
133+
steps {
134+
sh './tools/run-test.sh build/gcc-coverage/bin/calculate_test build/gcc'
135+
junit(
136+
testResults: 'build/gcc/test-report.xml'
137+
)
138+
recordCoverage(
139+
name: 'GCC Coverage',
140+
id: 'gcc-coverage',
141+
tools: [
142+
[parser: 'JUNIT', pattern: 'build/gcc/test-report.xml'],
143+
[parser: 'COBERTURA', pattern: 'build/gcc/test-coverage.xml']
144+
]
145+
)
146+
publishHTML([
147+
allowMissing: false,
148+
alwaysLinkToLastBuild: false,
149+
keepAll: false,
150+
reportDir: 'build/gcc/html',
151+
reportFiles: 'index.html',
152+
reportName: 'GCC Coverage HTML',
153+
reportTitles: '',
154+
useWrapperFileDirectly: true
155+
])
156+
}
157+
}
158+
stage('Run tests [clang]') {
159+
steps {
160+
sh './tools/run-test.sh build/clang-coverage/bin/calculate_test build/clang'
161+
junit(
162+
testResults: 'build/clang/test-report.xml'
163+
)
164+
recordCoverage(
165+
name: 'Clang Coverage',
166+
id: 'clang-coverage',
167+
tools: [
168+
[parser: 'JUNIT', pattern: 'build/clang/test-report.xml'],
169+
[parser: 'COBERTURA', pattern: 'build/clang/test-coverage.xml']
170+
]
171+
)
172+
publishHTML([
173+
allowMissing: false,
174+
alwaysLinkToLastBuild: false,
175+
keepAll: false,
176+
reportDir: 'build/clang/html',
177+
reportFiles: 'index.html',
178+
reportName: 'Clang Coverage HTML',
179+
reportTitles: '',
180+
useWrapperFileDirectly: true
181+
])
182+
}
183+
}
184+
}
185+
}
186+
}
187+
}

Jenkinsfile.groovy

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
node {
2+
properties([
3+
disableConcurrentBuilds()
4+
])
5+
stage('Checkout SCM') {
6+
checkout(
7+
scmGit(
8+
branches: scm.branches,
9+
extensions: [submodule(recursiveSubmodules: true, reference: '')],
10+
userRemoteConfigs: scm.userRemoteConfigs
11+
)
12+
)
13+
}
14+
stage('Agent Setup') {
15+
docker.withRegistry('http://gitea.lan:3000', 'gitea') {
16+
customImage = docker.build(
17+
"root/jenkins-cplusplus:latest",
18+
"-f .devcontainer/Dockerfile ./")
19+
customImage.push() // push custom image to the own registry
20+
}
21+
}
22+
customImage.inside('--net="jenkins_default"') { // required for accessing the Gitea server
23+
stage('Cleanup') {
24+
sh 'rm -rf build'
25+
}
26+
stage('Build documentation') {
27+
sh './tools/build-docs.sh'
28+
archiveArtifacts(
29+
artifacts: 'build/html/**',
30+
onlyIfSuccessful: true
31+
)
32+
publishHTML([
33+
allowMissing: false,
34+
alwaysLinkToLastBuild: false,
35+
keepAll: false,
36+
reportDir: 'build/html/',
37+
reportFiles: 'index.html',
38+
reportName: 'Documentation',
39+
reportTitles: '',
40+
useWrapperFileDirectly: true
41+
])
42+
}
43+
stage('Static code analysis') {
44+
warnError('clang-format issues found') {
45+
sh './tools/clang-format.sh'
46+
}
47+
sh 'cppcheck src/ --xml --xml-version=2 2> cppcheck.xml'
48+
recordIssues(
49+
sourceCodeRetention: 'LAST_BUILD',
50+
tools: [
51+
taskScanner(
52+
highTags: 'FIXME',
53+
includePattern: 'src/**/*.hpp,src/**/*.cpp',
54+
lowTags: 'HACK',
55+
normalTags: 'TODO'
56+
),
57+
cppCheck(pattern: 'cppcheck.xml')
58+
]
59+
)
60+
}
61+
def compilers = ["gcc", "clang"]
62+
stage('Parallel build') {
63+
def builds = [:]
64+
compilers.each { c ->
65+
builds[c] = {
66+
stage("Build project [${c}]") {
67+
sh "./tools/build-cmake-target.sh ${c}-release cplusplus_training_project"
68+
archiveArtifacts(
69+
artifacts: "build/${c}-release/bin/cplusplus_training_project",
70+
onlyIfSuccessful: true
71+
)
72+
recordIssues(
73+
sourceCodeRetention: 'LAST_BUILD',
74+
tools: [
75+
"${c}"() // use dynamic method invocation
76+
]
77+
)
78+
}
79+
stage("Build tests [${c}]") {
80+
sh "./tools/build-cmake-target.sh ${c}-coverage calculate_test"
81+
archiveArtifacts(
82+
artifacts: "build/${c}-coverage/bin/calculate_test",
83+
onlyIfSuccessful: true
84+
)
85+
}
86+
}
87+
}
88+
parallel builds
89+
}
90+
stage('Parallel test execution')
91+
{
92+
def tests = [:]
93+
compilers.each { c ->
94+
tests[c] = {
95+
stage("Run tests [${c}]") {
96+
sh "./tools/run-test.sh build/${c}-coverage/bin/calculate_test build/${c}"
97+
junit(
98+
testResults: "build/${c}/test-report.xml"
99+
)
100+
def coverage_name = c == 'gcc' ? 'GCC' : 'Clang'
101+
recordCoverage(
102+
name: "${coverage_name} Coverage",
103+
id: "${c}-coverage",
104+
tools: [
105+
[parser: 'JUNIT', pattern: "build/${c}/test-report.xml"],
106+
[parser: 'COBERTURA', pattern: "build/${c}/test-coverage.xml"]
107+
]
108+
)
109+
publishHTML([
110+
allowMissing: false,
111+
alwaysLinkToLastBuild: false,
112+
keepAll: false,
113+
reportDir: "build/${c}/html",
114+
reportFiles: 'index.html',
115+
reportName: "${coverage_name} Coverage HTML",
116+
reportTitles: '',
117+
useWrapperFileDirectly: true
118+
])
119+
}
120+
}
121+
}
122+
parallel tests
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)