pipeline: add symfony app generic integration pipeline

This commit is contained in:
2022-05-17 14:34:21 +02:00
parent f2602a8d27
commit ef76e3340e
5 changed files with 242 additions and 0 deletions

40
vars/gitea.groovy Normal file
View File

@ -0,0 +1,40 @@
def commentPullRequest(String repo, String issueId, String comment, Integer commentIndex = 0) {
comment = comment.replaceAll('"', '\\"')
withCredentials([
string(credentialsId: 'GITEA_JENKINS_PERSONAL_TOKEN', variable: 'GITEA_TOKEN'),
]) {
writeFile(file: ".prComment", text: comment)
sh """#!/bin/bash
set -xeo pipefail
# Récupération si il existe du commentaire existant
previous_comment_id=\$(curl -v --fail \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
https://forge.cadoles.com/api/v1/repos/${repo}/issues/${issueId}/comments \
| jq -c '[ .[] | select(.user.login=="jenkins") ] | .[${commentIndex}] | .id' \
)
# Génération du payload pour l'API Gitea
echo '{}' | jq -c --rawfile body .prComment '.body = \$body' > payload.json
if [[ "\$previous_comment_id" == "null" ]]; then
# Création du commentaire via l'API Gitea
curl -v --fail \
-XPOST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d @payload.json \
https://forge.cadoles.com/api/v1/repos/${repo}/issues/${issueId}/comments
else
# Modification du commentaire existant
curl -v --fail \
-XPATCH \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d @payload.json \
https://forge.cadoles.com/api/v1/repos/${repo}/issues/comments/\$previous_comment_id
fi
"""
}
}

View File

@ -0,0 +1,115 @@
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
def call(String baseImage = "ubuntu:22.04") {
node {
stage("Checkout project") {
checkout(scm)
}
stage('Run in Symfony image') {
def symfonyImage = buildDockerImage(baseImage)
symfonyImage.inside() {
def repo = env.JOB_NAME
if (env.BRANCH_NAME ==~ /^PR-.*$/) {
repo = env.JOB_NAME - "/${env.JOB_BASE_NAME}"
}
stage("Install composer dependencies") {
sh '''
composer install
'''
}
parallel([
'php-security-check': {
stage("Check PHP security issues") {
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
def auditReport = sh(script: "local-php-security-checker --format=markdown || true", returnStdout: true)
if (auditReport.trim() != "") {
if (env.CHANGE_ID) {
gitea.commentPullRequest(repo, env.CHANGE_ID, auditReport, 0)
} else {
print auditReport
}
}
if (!auditReport.contains("No packages have known vulnerabilities.")) {
throw new Exception("Dependencies check failed !")
}
}
}
},
'php-cs-fixer': {
stage("Run PHP-CS-Fixer on modified code") {
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
php-cs-fixer fix -v --dry-run --using-cache=no --format junit > php-cs-fixer.xml ${EXTRA_ARGS}
'''
def report = sh(script: "junit2md php-cs-fixer.xml", returnStdout: true)
if (env.CHANGE_ID) {
gitea.commentPullRequest(repo, env.CHANGE_ID, report, 1)
} else {
print report
}
}
}
},
'phpstan': {
stage("Run phpstan") {
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
if ( !fileExists('phpstan.neon') ) {
def phpStanConfig = libraryResource 'com/cadoles/symfony/phpstan.neon'
writeFile file:'phpstan.neon', text:phpStanConfig
}
sh '''
phpstan analyze -l 1 --error-format=table src > phpstan.txt || true
'''
def report = sh(script: "cat phpstan.txt", returnStdout: true)
report = "## Rapport PHPStan\n\n```\n" + report
report = report + "\n```\n"
if (env.CHANGE_ID) {
gitea.commentPullRequest(repo, env.CHANGE_ID, report, 2)
} else {
print report
}
}
}
}
])
}
}
}
}
def buildDockerImage(String baseImage) {
def imageName = "cadoles-symfony-ci"
dir (".${imageName}") {
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
def safeJobName = URLDecoder.decode(env.JOB_NAME).toLowerCase().replace('/', '-').replace(' ', '-')
def imageTag = "${safeJobName}-${env.BUILD_ID}"
return docker.build("${imageName}:${imageTag}", ".")
}
}
def when(boolean condition, body) {
def config = [:]
body.resolveStrategy = Closure.OWNER_FIRST
body.delegate = config
if (condition) {
body()
} else {
Utils.markStageSkippedForConditional(STAGE_NAME)
}
}