Skip to content

Commit aa6ad14

Browse files
committed
add support for jenkins-ci
Signed-off-by: NucleonGodX <[email protected]>
1 parent e46d127 commit aa6ad14

File tree

2 files changed

+244
-0
lines changed

2 files changed

+244
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@Library('scancode-pipeline@main') _
2+
3+
pipeline {
4+
agent any
5+
stages {
6+
stage('Checkout') {
7+
steps {
8+
checkout scm
9+
}
10+
}
11+
stage('ScanCode Analysis') {
12+
steps {
13+
scanCodePipeline([
14+
projectName: "${env.JOB_NAME}",
15+
inputsPath: '.',
16+
pipelines: 'scan_codebase'
17+
])
18+
}
19+
}
20+
}
21+
}
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
def call(Map config = [:]) {
2+
def defaults = [
3+
pipelines: 'scan_codebase',
4+
outputFormats: 'json xlsx spdx cyclonedx',
5+
inputsPath: 'scancode-inputs',
6+
inputUrls: '',
7+
projectName: 'scancode-jenkins',
8+
outputsArchiveName: 'scancode-outputs',
9+
checkCompliance: false,
10+
complianceFailLevel: 'ERROR',
11+
complianceFailOnVulnerabilities: false,
12+
pythonVersion: '3.12',
13+
scancodeioBranch: ''
14+
]
15+
16+
def settings = defaults + config
17+
18+
def scanCodeEnv = [
19+
"SECRET_KEY=${generateSecretKey()}",
20+
"SCANCODEIO_DB_NAME=scancodeio",
21+
"SCANCODEIO_DB_USER=scancodeio",
22+
"SCANCODEIO_DB_PASSWORD=scancodeio"
23+
]
24+
25+
try {
26+
stage('Setup Environment') {
27+
setupPython(settings.pythonVersion)
28+
setupPostgreSQL(scanCodeEnv)
29+
installScanCodeIO(settings.scancodeioBranch)
30+
}
31+
32+
stage('Prepare Database') {
33+
withEnv(scanCodeEnv) {
34+
sh 'scanpipe migrate --verbosity 0'
35+
}
36+
}
37+
38+
stage('Create Project') {
39+
withEnv(scanCodeEnv) {
40+
def pipelineCLIArgs = generatePipelineArgs(settings.pipelines)
41+
def inputUrlCLIArgs = generateInputUrlArgs(settings.inputUrls)
42+
43+
sh """
44+
scanpipe create-project ${settings.projectName} \\
45+
${pipelineCLIArgs} \\
46+
${inputUrlCLIArgs}
47+
"""
48+
49+
def projectStatus = sh(
50+
script: "scanpipe status --project ${settings.projectName}",
51+
returnStdout: true
52+
).trim()
53+
54+
def workDirectory = extractWorkDirectory(projectStatus)
55+
env.PROJECT_WORK_DIRECTORY = workDirectory
56+
}
57+
}
58+
59+
stage('Copy Input Files') {
60+
copyInputFiles(settings.inputsPath, env.PROJECT_WORK_DIRECTORY)
61+
}
62+
63+
stage('Run ScanCode Pipelines') {
64+
withEnv(scanCodeEnv) {
65+
sh "scanpipe execute --project ${settings.projectName} --no-color"
66+
}
67+
}
68+
69+
stage('Generate Outputs') {
70+
withEnv(scanCodeEnv) {
71+
sh """
72+
scanpipe output \\
73+
--project ${settings.projectName} \\
74+
--format ${settings.outputFormats}
75+
"""
76+
}
77+
}
78+
79+
stage('Archive Outputs') {
80+
archiveArtifacts(
81+
artifacts: "${env.PROJECT_WORK_DIRECTORY}/output/*",
82+
allowEmptyArchive: false,
83+
fingerprint: true
84+
)
85+
}
86+
87+
if (settings.checkCompliance) {
88+
stage('Check Compliance') {
89+
checkCompliance(
90+
settings.projectName,
91+
settings.complianceFailLevel,
92+
settings.complianceFailOnVulnerabilities,
93+
scanCodeEnv
94+
)
95+
}
96+
}
97+
98+
echo "ScanCode.io pipeline completed successfully"
99+
100+
} catch (Exception e) {
101+
error "ScanCode.io pipeline failed: ${e.getMessage()}"
102+
}
103+
}
104+
105+
def setupPython(pythonVersion) {
106+
echo "Setting up Python ${pythonVersion}"
107+
108+
sh """
109+
sudo apt-get update
110+
111+
sudo apt-get install -y python${pythonVersion} python${pythonVersion}-pip python${pythonVersion}-venv
112+
113+
sudo ln -sf /usr/bin/python${pythonVersion} /usr/bin/python3
114+
sudo ln -sf /usr/bin/pip${pythonVersion} /usr/bin/pip3
115+
116+
python3 --version
117+
pip3 --version
118+
"""
119+
}
120+
121+
def setupPostgreSQL(scanCodeEnv) {
122+
echo "Setting up PostgreSQL"
123+
124+
withEnv(scanCodeEnv) {
125+
sh """
126+
127+
sudo apt-get install -y postgresql postgresql-contrib
128+
sudo systemctl start postgresql
129+
sudo systemctl enable postgresql
130+
131+
sudo -u postgres createuser --no-createrole --no-superuser --login --inherit --createdb \$SCANCODEIO_DB_USER || true
132+
sudo -u postgres psql -c "ALTER USER \$SCANCODEIO_DB_USER WITH encrypted password '\$SCANCODEIO_DB_PASSWORD'"
133+
sudo -u postgres createdb --owner=\$SCANCODEIO_DB_USER --encoding=UTF-8 \$SCANCODEIO_DB_NAME || true
134+
"""
135+
}
136+
}
137+
138+
def installScanCodeIO(branch) {
139+
echo "Installing ScanCode.io"
140+
141+
if (branch) {
142+
echo "Installing ScanCode.io from branch: ${branch}"
143+
sh "pip3 install git+https://github.com/aboutcode-org/scancode.io.git@${branch}"
144+
} else {
145+
echo "Installing latest ScanCode.io release from PyPI"
146+
sh "pip3 install --upgrade scancodeio"
147+
}
148+
}
149+
150+
def generatePipelineArgs(pipelines) {
151+
def pipelineList = pipelines.split(',')
152+
def args = ""
153+
154+
pipelineList.each { pipeline ->
155+
args += " --pipeline ${pipeline.trim()}"
156+
}
157+
158+
return args
159+
}
160+
161+
def generateInputUrlArgs(inputUrls) {
162+
if (!inputUrls || inputUrls.trim().isEmpty()) {
163+
return ""
164+
}
165+
166+
def urlList = inputUrls.split(/\s+/)
167+
def args = ""
168+
169+
urlList.each { url ->
170+
if (url.trim()) {
171+
args += " --input-url ${url.trim()}"
172+
}
173+
}
174+
175+
return args
176+
}
177+
178+
def extractWorkDirectory(projectStatus) {
179+
def matcher = projectStatus =~ /Work directory:\s*([^\n]+)/
180+
if (matcher) {
181+
return matcher[0][1].trim()
182+
}
183+
error "Could not extract work directory from project status"
184+
}
185+
186+
def copyInputFiles(inputsPath, workDirectory) {
187+
echo "Copying input files"
188+
189+
if (fileExists(inputsPath)) {
190+
sh """
191+
mkdir -p ${workDirectory}/input/
192+
cp -r ${inputsPath}/* ${workDirectory}/input/ || true
193+
"""
194+
} else {
195+
echo "Input path ${inputsPath} does not exist, skipping file copy"
196+
}
197+
}
198+
199+
def checkCompliance(projectName, failLevel, failOnVulnerabilities, scanCodeEnv) {
200+
echo "Checking compliance"
201+
202+
withEnv(scanCodeEnv) {
203+
def cmd = "scanpipe check-compliance --project ${projectName} --fail-level ${failLevel}"
204+
205+
if (failOnVulnerabilities) {
206+
cmd += " --fail-on-vulnerabilities"
207+
}
208+
209+
try {
210+
sh cmd
211+
echo "Compliance check passed"
212+
} catch (Exception e) {
213+
error "Compliance check failed: ${e.getMessage()}"
214+
}
215+
}
216+
}
217+
218+
def generateSecretKey() {
219+
return sh(
220+
script: 'openssl rand -base64 32',
221+
returnStdout: true
222+
).trim()
223+
}

0 commit comments

Comments
 (0)