2022-05-17 14:34:21 +02:00
|
|
|
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
|
|
|
|
|
2022-10-10 11:56:55 +02:00
|
|
|
def call(String baseImage = 'ubuntu:22.04', Map options = [:]) {
|
|
|
|
Map hooks = options.get('hooks', [:])
|
|
|
|
String jobHistory = options.get('jobHistory', '10')
|
|
|
|
|
2022-05-17 14:34:21 +02:00
|
|
|
node {
|
2022-10-10 11:56:55 +02:00
|
|
|
properties([
|
|
|
|
buildDiscarder(logRotator(daysToKeepStr: jobHistory, numToKeepStr: jobHistory)),
|
|
|
|
])
|
2022-10-03 14:34:17 +02:00
|
|
|
stage('Cancel older jobs') {
|
|
|
|
def buildNumber = env.BUILD_NUMBER as int
|
|
|
|
if (buildNumber > 1) milestone(buildNumber - 1)
|
|
|
|
milestone(buildNumber)
|
|
|
|
}
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Checkout project') {
|
2022-05-17 14:34:21 +02:00
|
|
|
checkout(scm)
|
|
|
|
}
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Run pre hooks') {
|
2022-10-10 11:56:55 +02:00
|
|
|
runHook(hooks, 'preSymfonyAppPipeline')
|
2022-09-20 16:24:05 +02:00
|
|
|
}
|
2022-05-17 14:34:21 +02:00
|
|
|
stage('Run in Symfony image') {
|
2022-10-10 11:56:55 +02:00
|
|
|
def symfonyImage = buildDockerImage(baseImage, hooks)
|
2022-05-17 14:34:21 +02:00
|
|
|
symfonyImage.inside() {
|
|
|
|
def repo = env.JOB_NAME
|
|
|
|
if (env.BRANCH_NAME ==~ /^PR-.*$/) {
|
|
|
|
repo = env.JOB_NAME - "/${env.JOB_BASE_NAME}"
|
|
|
|
}
|
|
|
|
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Install composer dependencies') {
|
2022-05-17 14:34:21 +02:00
|
|
|
sh '''
|
2022-09-27 14:35:56 +02:00
|
|
|
symfony composer install
|
2022-05-17 14:34:21 +02:00
|
|
|
'''
|
|
|
|
}
|
|
|
|
|
|
|
|
parallel([
|
|
|
|
'php-security-check': {
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Check PHP security issues') {
|
2022-05-17 14:34:21 +02:00
|
|
|
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
|
2022-09-20 16:24:05 +02:00
|
|
|
def auditReport = sh(script: 'local-php-security-checker --format=markdown || true', returnStdout: true)
|
|
|
|
if (auditReport.trim() != '') {
|
2022-05-17 14:34:21 +02:00
|
|
|
if (env.CHANGE_ID) {
|
2022-10-10 11:56:55 +02:00
|
|
|
gitea.commentPullRequest(repo, env.CHANGE_ID, auditReport)
|
2022-05-17 14:34:21 +02:00
|
|
|
} else {
|
|
|
|
print auditReport
|
|
|
|
}
|
|
|
|
}
|
2022-09-20 16:24:05 +02:00
|
|
|
if (!auditReport.contains('No packages have known vulnerabilities.')) {
|
|
|
|
throw new Exception('Dependencies check failed !')
|
2022-05-17 14:34:21 +02:00
|
|
|
}
|
2022-09-20 16:24:05 +02:00
|
|
|
}
|
2022-05-17 14:34:21 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
'php-cs-fixer': {
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Run PHP-CS-Fixer on modified code') {
|
2022-05-17 14:34:21 +02:00
|
|
|
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
|
|
|
if ( !fileExists('.php-cs-fixer.dist.php') ) {
|
|
|
|
def phpCsFixerConfig = libraryResource 'com/cadoles/symfony/.php-cs-fixer.dist.php'
|
|
|
|
writeFile file:'.php-cs-fixer.dist.php', text:phpCsFixerConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
sh '''
|
|
|
|
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "HEAD~..HEAD" | fgrep ".php" | tr "\n" " ")
|
|
|
|
if ! echo "${CHANGED_FILES}" | grep -qE "^(\\.php-cs-fixer(\\.dist)\\.php?|composer\\.lock)$"; then EXTRA_ARGS=$(printf -- '--path-mode=intersection -- %s' "${CHANGED_FILES}"); else EXTRA_ARGS=''; fi
|
2022-09-27 14:35:56 +02:00
|
|
|
symfony php $(which php-cs-fixer) fix --config=.php-cs-fixer.dist.php -v --dry-run --using-cache=no --format junit ${EXTRA_ARGS} > php-cs-fixer.xml || true
|
2022-05-17 14:34:21 +02:00
|
|
|
'''
|
2022-09-20 16:24:05 +02:00
|
|
|
def report = sh(script: 'junit2md php-cs-fixer.xml', returnStdout: true)
|
2022-05-17 14:34:21 +02:00
|
|
|
if (env.CHANGE_ID) {
|
2022-10-10 11:56:55 +02:00
|
|
|
gitea.commentPullRequest(repo, env.CHANGE_ID, report)
|
2022-05-17 14:34:21 +02:00
|
|
|
} else {
|
|
|
|
print report
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'phpstan': {
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Run phpstan') {
|
2022-05-17 14:34:21 +02:00
|
|
|
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
|
|
|
|
if ( !fileExists('phpstan.neon') ) {
|
|
|
|
def phpStanConfig = libraryResource 'com/cadoles/symfony/phpstan.neon'
|
|
|
|
writeFile file:'phpstan.neon', text:phpStanConfig
|
|
|
|
}
|
|
|
|
sh '''
|
2022-09-27 14:35:56 +02:00
|
|
|
symfony php $(which phpstan) analyze -l 1 --error-format=table src > phpstan.txt || true
|
2022-05-17 14:34:21 +02:00
|
|
|
'''
|
2022-09-20 16:24:05 +02:00
|
|
|
def report = sh(script: 'cat phpstan.txt', returnStdout: true)
|
|
|
|
report = '## Rapport PHPStan\n\n```\n' + report
|
|
|
|
report = report + '\n```\n'
|
2022-05-17 14:34:21 +02:00
|
|
|
if (env.CHANGE_ID) {
|
2022-10-10 11:56:55 +02:00
|
|
|
gitea.commentPullRequest(repo, env.CHANGE_ID, report)
|
2022-05-17 14:34:21 +02:00
|
|
|
} else {
|
|
|
|
print report
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
2022-09-20 16:24:05 +02:00
|
|
|
stage('Run post hooks') {
|
2022-10-10 11:56:55 +02:00
|
|
|
runHook(hooks, 'postSymfonyAppPipeline')
|
2022-09-20 16:24:05 +02:00
|
|
|
}
|
2022-05-17 14:34:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 11:56:55 +02:00
|
|
|
void buildDockerImage(String baseImage, Map hooks) {
|
2022-09-20 16:24:05 +02:00
|
|
|
def imageName = 'cadoles-symfony-ci'
|
|
|
|
dir(".${imageName}") {
|
2022-05-17 14:34:21 +02:00
|
|
|
def dockerfile = libraryResource 'com/cadoles/symfony/Dockerfile'
|
|
|
|
writeFile file:'Dockerfile', text: "FROM ${baseImage}\n\n" + dockerfile
|
|
|
|
|
|
|
|
def addLetsEncryptCA = libraryResource 'com/cadoles/common/add-letsencrypt-ca.sh'
|
|
|
|
writeFile file:'add-letsencrypt-ca.sh', text:addLetsEncryptCA
|
2022-09-20 16:24:05 +02:00
|
|
|
|
2022-10-10 11:56:55 +02:00
|
|
|
runHook(hooks, 'buildSymfonyImage')
|
2022-09-20 16:26:44 +02:00
|
|
|
|
2022-05-17 14:34:21 +02:00
|
|
|
def safeJobName = URLDecoder.decode(env.JOB_NAME).toLowerCase().replace('/', '-').replace(' ', '-')
|
|
|
|
def imageTag = "${safeJobName}-${env.BUILD_ID}"
|
2022-09-20 16:24:05 +02:00
|
|
|
return docker.build("${imageName}:${imageTag}", '.')
|
2022-05-17 14:34:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 11:56:55 +02:00
|
|
|
void runHook(Map hooks, String name) {
|
|
|
|
if (!hooks[name]) {
|
|
|
|
println("No hook '${name}' defined. Skipping.")
|
|
|
|
return
|
|
|
|
}
|
2022-05-17 14:34:21 +02:00
|
|
|
|
2022-10-10 11:56:55 +02:00
|
|
|
if (hooks[name] instanceof Closure) {
|
|
|
|
hooks[name]()
|
|
|
|
} else {
|
|
|
|
error("Hook '${name}' seems to be defined but is not a closure !")
|
2022-09-20 16:24:05 +02:00
|
|
|
}
|
|
|
|
}
|