Skip to content

Commit 0ff4475

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

File tree

2 files changed

+300
-0
lines changed

2 files changed

+300
-0
lines changed

jenkins/pipelines/JenkinsFile

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
pipeline {
2+
agent { label 'ubuntu-latest' }
3+
4+
parameters {
5+
string(
6+
name: 'PROJECT_NAME',
7+
defaultValue: 'scancode-jenkins',
8+
description: 'Name for the ScanCode.io project'
9+
)
10+
choice(
11+
name: 'PIPELINES',
12+
choices: ['scan_codebase', 'scan_package', 'inspect_packages'],
13+
description: 'ScanCode.io pipeline to run'
14+
)
15+
booleanParam(
16+
name: 'CHECK_COMPLIANCE',
17+
defaultValue: true,
18+
description: 'Check for compliance issues'
19+
)
20+
choice(
21+
name: 'COMPLIANCE_FAIL_LEVEL',
22+
choices: ['WARNING', 'ERROR', 'MISSING'],
23+
description: 'Compliance failure level'
24+
)
25+
}
26+
27+
environment {
28+
SCANCODE_INPUTS = "${WORKSPACE}/scancode-inputs"
29+
PYTHON_VERSION = '3.12'
30+
}
31+
32+
stages {
33+
stage('Checkout') {
34+
steps {
35+
echo 'Checking out source code...'
36+
checkout scm
37+
38+
sh '''
39+
mkdir -p "${SCANCODE_INPUTS}"
40+
rsync -av --exclude='.git' --exclude='node_modules' --exclude='*.log' . "${SCANCODE_INPUTS}/"
41+
'''
42+
}
43+
}
44+
45+
stage('Run ScanCode Analysis') {
46+
steps {
47+
echo 'Running ScanCode.io analysis with compliance check...'
48+
49+
scanCodePipeline([
50+
pipelines: params.PIPELINES,
51+
projectName: params.PROJECT_NAME,
52+
inputsPath: env.SCANCODE_INPUTS,
53+
outputFormats: 'json xlsx spdx cyclonedx',
54+
checkCompliance: params.CHECK_COMPLIANCE,
55+
complianceFailLevel: params.COMPLIANCE_FAIL_LEVEL,
56+
pythonVersion: env.PYTHON_VERSION
57+
])
58+
}
59+
}
60+
}
61+
62+
post {
63+
always {
64+
echo 'Cleaning up...'
65+
sh '''
66+
rm -rf /tmp/scancode-* || true
67+
rm -rf "${SCANCODE_INPUTS}" || true
68+
'''
69+
}
70+
success {
71+
echo 'ScanCode.io pipeline with compliance check completed successfully!'
72+
}
73+
failure {
74+
echo 'ScanCode.io pipeline failed or compliance issues detected!'
75+
}
76+
}
77+
}
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)