From 0550e4a431cf55edb70b11ef8bdde66220933336 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:22:25 +0100 Subject: [PATCH 01/13] Update jenkinsfile.ci --- Jenkinsfile.ci | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 51612d5..7e75d8f 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -97,9 +97,75 @@ pipeline { always { script { node { + junit testResults: 'backend/pytest.xml', allowEmptyResults: true + + try { + if (env.CHANGE_ID) { + def owner = null + def repo = null + def giteaBase = null + + if (env.CHANGE_URL) { + def u = new URL(env.CHANGE_URL) + giteaBase = "${u.protocol}://${u.host}" + def path = u.path // /gitea/OpenBokeron/TallerCiCd/pulls/29 + def m = (path =~ /\/gitea\/([^\/]+)\/([^\/]+)\/pulls\/\d+/) + if (m) { + owner = m[0][1] + repo = m[0][2] + } + } + + if ((!owner || !repo) && env.GIT_URL) { + def m = (env.GIT_URL =~ /[:\/]([^\/:]+)\/([^\/]+?)(?:\.git)?$/) + if (m) { + owner = m[0][1] + repo = m[0][2] + } + + if (!giteaBase) giteaBase = 'https://openbokeron.org' // AJUSTA si hace falta + } + + if (owner && repo && giteaBase) { + def pr = env.CHANGE_ID + def result = currentBuild.currentResult + def emoji = (result == 'SUCCESS') ? '✅' : (result == 'UNSTABLE') ? '⚠️' : '❌' + + def msg = "${emoji} Jenkins: **${result}**\\n\\n" + + "- Job: `${env.JOB_NAME}`\\n" + + "- Build: #${env.BUILD_NUMBER}\\n" + + "- Commit: `${env.GIT_COMMIT?.take(7) ?: env.COMMIT_SHORT}`\\n" + + "- URL: ${env.BUILD_URL}" + + def url = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" + + withCredentials([string(credentialsId: 'gitea-jenkins-bot-token', variable: 'GITEA_TOKEN')]) { + sh """ + set -e + curl -sS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + --data @- \ + '${url}' <<'JSON' +{"body":"${msg.replace('\\', '\\\\').replace('"','\\"')}"} +JSON + """ + } + echo "Comentado en PR #${pr} (${owner}/${repo})." + } else { + echo "No pude deducir owner/repo/baseURL; no comento en la PR." + } + } else { + echo "No es build de PR (CHANGE_ID vacío); no comento." + } + } catch (err) { + echo "Fallo al comentar en PR: ${err}" + } + cleanWs() } } } } + } From f431f1c5dc5935150627a1a92984f820af749829 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:27:14 +0100 Subject: [PATCH 02/13] Actualizar Jenkinsfile.ci --- Jenkinsfile.ci | 97 ++++++++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 63 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 7e75d8f..204f6da 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -57,7 +57,7 @@ pipeline { pip install --upgrade pip pip install -r requirements-dev.txt ruff check app tests - pytest -o cache_dir="$WORKSPACE/.cache/pytest" + pytest -o cache_dir="$WORKSPACE/.cache/pytest" --junitxml=pytest.xml ''' } } @@ -93,79 +93,50 @@ pipeline { } - post { - always { - script { - node { - junit testResults: 'backend/pytest.xml', allowEmptyResults: true +post { + always { + script { + node { + junit testResults: 'backend/pytest.xml', allowEmptyResults: true - try { - if (env.CHANGE_ID) { - def owner = null - def repo = null - def giteaBase = null + if (env.CHANGE_ID) { + def giteaBase = 'https://openbokeron.org' + def owner = 'OpenBokeron' + def repo = 'TallerCiCd' + def pr = env.CHANGE_ID - if (env.CHANGE_URL) { - def u = new URL(env.CHANGE_URL) - giteaBase = "${u.protocol}://${u.host}" - def path = u.path // /gitea/OpenBokeron/TallerCiCd/pulls/29 - def m = (path =~ /\/gitea\/([^\/]+)\/([^\/]+)\/pulls\/\d+/) - if (m) { - owner = m[0][1] - repo = m[0][2] - } - } + def result = currentBuild.currentResult + def emoji = (result == 'SUCCESS') ? '✅' : (result == 'UNSTABLE') ? '⚠️' : '❌' - if ((!owner || !repo) && env.GIT_URL) { - def m = (env.GIT_URL =~ /[:\/]([^\/:]+)\/([^\/]+?)(?:\.git)?$/) - if (m) { - owner = m[0][1] - repo = m[0][2] - } + def msg = "${emoji} Jenkins: **${result}**\\n\\n" + + "- Job: `${env.JOB_NAME}`\\n" + + "- Build: #${env.BUILD_NUMBER}\\n" + + "- Commit: `${env.GIT_COMMIT?.take(7) ?: env.COMMIT_SHORT}`\\n" + + "- URL: ${env.BUILD_URL}" - if (!giteaBase) giteaBase = 'https://openbokeron.org' // AJUSTA si hace falta - } + def commentsUrl = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" - if (owner && repo && giteaBase) { - def pr = env.CHANGE_ID - def result = currentBuild.currentResult - def emoji = (result == 'SUCCESS') ? '✅' : (result == 'UNSTABLE') ? '⚠️' : '❌' - - def msg = "${emoji} Jenkins: **${result}**\\n\\n" + - "- Job: `${env.JOB_NAME}`\\n" + - "- Build: #${env.BUILD_NUMBER}\\n" + - "- Commit: `${env.GIT_COMMIT?.take(7) ?: env.COMMIT_SHORT}`\\n" + - "- URL: ${env.BUILD_URL}" - - def url = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" - - withCredentials([string(credentialsId: 'gitea-jenkins-bot-token', variable: 'GITEA_TOKEN')]) { - sh """ - set -e - curl -sS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - --data @- \ - '${url}' <<'JSON' + withCredentials([string(credentialsId: 'gitea-jenkins-bot-token', variable: 'GITEA_TOKEN')]) { + sh """ + set -e + curl -sS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + --data @- \ + '${commentsUrl}' <<'JSON' {"body":"${msg.replace('\\', '\\\\').replace('"','\\"')}"} JSON - """ - } - echo "Comentado en PR #${pr} (${owner}/${repo})." - } else { - echo "No pude deducir owner/repo/baseURL; no comento en la PR." - } - } else { - echo "No es build de PR (CHANGE_ID vacío); no comento." - } - } catch (err) { - echo "Fallo al comentar en PR: ${err}" + """ } - - cleanWs() + } else { + echo "No es build de PR (CHANGE_ID vacío); no comento." } + + cleanWs() } } } +} + } From 214aec2e73a4eb7aa935327b4ac7e63992e4a330 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:31:19 +0100 Subject: [PATCH 03/13] Actualizar Jenkinsfile.ci --- Jenkinsfile.ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 204f6da..118bed2 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -116,7 +116,7 @@ post { def commentsUrl = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" - withCredentials([string(credentialsId: 'gitea-jenkins-bot-token', variable: 'GITEA_TOKEN')]) { + withCredentials([string(credentialsId: 'jenkins-bot-api', variable: 'GITEA_TOKEN')]) { sh """ set -e curl -sS -X POST \ From 4ef74b38eb9fa375f990b73eb377d68954840b18 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:34:23 +0100 Subject: [PATCH 04/13] Actualizar Jenkinsfile.ci --- Jenkinsfile.ci | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 118bed2..74ecf7f 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -116,18 +116,21 @@ post { def commentsUrl = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" - withCredentials([string(credentialsId: 'jenkins-bot-api', variable: 'GITEA_TOKEN')]) { - sh """ - set -e - curl -sS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - --data @- \ - '${commentsUrl}' <<'JSON' -{"body":"${msg.replace('\\', '\\\\').replace('"','\\"')}"} -JSON - """ - } + withCredentials([usernamePassword(credentialsId: 'jenkins-bot-api', + usernameVariable: 'GITEA_USER', + passwordVariable: 'GITEA_TOKEN')]) { + sh """ + set -e + curl -sS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + --data @- \ + '${commentsUrl}' <<'JSON' + {"body":"${msg.replace('\\', '\\\\').replace('"','\\"')}"} + JSON + """ + } + } else { echo "No es build de PR (CHANGE_ID vacío); no comento." } From ac2174d36550d740536c42110c872b3ba5a251df Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:45:24 +0100 Subject: [PATCH 05/13] Actualizar Jenkinsfile.ci --- Jenkinsfile.ci | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 74ecf7f..b867c70 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -106,13 +106,29 @@ post { def pr = env.CHANGE_ID def result = currentBuild.currentResult - def emoji = (result == 'SUCCESS') ? '✅' : (result == 'UNSTABLE') ? '⚠️' : '❌' + def msg = "" - def msg = "${emoji} Jenkins: **${result}**\\n\\n" + - "- Job: `${env.JOB_NAME}`\\n" + - "- Build: #${env.BUILD_NUMBER}\\n" + - "- Commit: `${env.GIT_COMMIT?.take(7) ?: env.COMMIT_SHORT}`\\n" + - "- URL: ${env.BUILD_URL}" + if (result == "SUCCESS") { + msg = """✅ Todo en orden, camarada. + + Build #${env.BUILD_NUMBER} + ${env.BUILD_URL} + """ + } + else if (result == "FAILURE") { + msg = """❌ ¿Qué clase de crímenes de guerra has metido en la PR? + + Build #${env.BUILD_NUMBER} + ${env.BUILD_URL} + """ + } + else { + msg = """⚠️ Dudoso, *arquea una ceja* + + Build #${env.BUILD_NUMBER} + ${env.BUILD_URL} + """ + } def commentsUrl = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" From 22f19a2ced023a09b1aec3ddd0defbae70311da4 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:54:14 +0100 Subject: [PATCH 06/13] Update Jenkinsfile.ci --- Jenkinsfile.ci | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index b867c70..a075521 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -133,20 +133,26 @@ post { def commentsUrl = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" withCredentials([usernamePassword(credentialsId: 'jenkins-bot-api', - usernameVariable: 'GITEA_USER', - passwordVariable: 'GITEA_TOKEN')]) { - sh """ - set -e - curl -sS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - --data @- \ - '${commentsUrl}' <<'JSON' - {"body":"${msg.replace('\\', '\\\\').replace('"','\\"')}"} - JSON - """ - } + usernameVariable: 'GITEA_USER', + passwordVariable: 'GITEA_TOKEN')]) { + def body = msg.replace('\\', '\\\\').replace('"','\\"').replace('\n','\\n') + + // Avoid interpolation of secret variables (https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#string-interpolation) + withEnv(["GITEA_COMMENTS_URL=${commentsUrl}", "GITEA_BODY=${body}"]) { + sh(label: 'Comentar en PR (Gitea)', script: ''' + set -euo pipefail + + curl -sS -X POST \ + -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + --data-binary @- \ + "$GITEA_COMMENTS_URL" < Date: Fri, 6 Feb 2026 20:57:55 +0100 Subject: [PATCH 07/13] Update shell --- Jenkinsfile.ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index a075521..2ba05e9 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -140,7 +140,7 @@ post { // Avoid interpolation of secret variables (https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#string-interpolation) withEnv(["GITEA_COMMENTS_URL=${commentsUrl}", "GITEA_BODY=${body}"]) { - sh(label: 'Comentar en PR (Gitea)', script: ''' + sh(label: 'Comentar en PR (Gitea)', shell: '/bin/bash', script: ''' set -euo pipefail curl -sS -X POST \ From aafc74d876d68371c2a3ab51c85fdd4c599fd588 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 20:59:19 +0100 Subject: [PATCH 08/13] Delete illegal option --- Jenkinsfile.ci | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 2ba05e9..632c9e7 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -140,9 +140,7 @@ post { // Avoid interpolation of secret variables (https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#string-interpolation) withEnv(["GITEA_COMMENTS_URL=${commentsUrl}", "GITEA_BODY=${body}"]) { - sh(label: 'Comentar en PR (Gitea)', shell: '/bin/bash', script: ''' - set -euo pipefail - + sh(label: 'Comentar en PR (Gitea)', script: ''' curl -sS -X POST \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ From 94097073291735c3c088eb2171b234d0553fe706 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 21:08:25 +0100 Subject: [PATCH 09/13] Update ci msgs --- Jenkinsfile.ci | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 632c9e7..1bb5a45 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -109,26 +109,29 @@ post { def msg = "" if (result == "SUCCESS") { - msg = """✅ Todo en orden, camarada. - - Build #${env.BUILD_NUMBER} - ${env.BUILD_URL} - """ + msg = """ + ✅ Todo en orden, camarada. + + - Build: #${env.BUILD_NUMBER} + - URL: ${env.BUILD_URL} + """.stripIndent().trim() } else if (result == "FAILURE") { - msg = """❌ ¿Qué clase de crímenes de guerra has metido en la PR? + msg = """ + ❌ Alto ahí. ¿Qué clase de crímenes de guerra has cometido en esta PR? - Build #${env.BUILD_NUMBER} - ${env.BUILD_URL} - """ - } + - Build: #${env.BUILD_NUMBER} + - URL: ${env.BUILD_URL} + """.stripIndent().trim() + } else { - msg = """⚠️ Dudoso, *arquea una ceja* + msg = """ + ⚠️ Dudoso… - Build #${env.BUILD_NUMBER} - ${env.BUILD_URL} - """ - } + - Build: #${env.BUILD_NUMBER} + - URL: ${env.BUILD_URL} + """.stripIndent().trim() + } def commentsUrl = "${giteaBase}/gitea/api/v1/repos/${owner}/${repo}/issues/${pr}/comments" From 484412b34e1dbac6b8e22a25cbae716a20438ad8 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 21:11:28 +0100 Subject: [PATCH 10/13] Generate junit xml in frontend tests --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 830dd9a..ca8da30 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,7 +8,7 @@ "build": "vite build", "preview": "vite preview", "check": "svelte-check", - "test": "vitest" + "test": "vitest run --reporter=default --reporter=junit --outputFile=./test-results/junit.xml" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.1", From e5cd76c0bac5ab1f0a5514ece16b29fd8b0aa5be Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 21:13:24 +0100 Subject: [PATCH 11/13] Publish frontend tests --- Jenkinsfile.ci | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index 1bb5a45..cf8087f 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -84,6 +84,7 @@ pipeline { mkdir -p "$NPM_CONFIG_CACHE" npm install --no-progress --no-audit --prefer-offline npm run check + mkdir -p test-results npm test npm run build ''' @@ -98,6 +99,7 @@ post { script { node { junit testResults: 'backend/pytest.xml', allowEmptyResults: true + junit testResults: 'frontend/test-results/junit.xml', allowEmptyResults: true if (env.CHANGE_ID) { def giteaBase = 'https://openbokeron.org' From 1c572a30a0e6963ec6e96ad21fc7128faa0af660 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 21:34:34 +0100 Subject: [PATCH 12/13] Delete build from CD job --- Jenkinsfile.cd | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/Jenkinsfile.cd b/Jenkinsfile.cd index d766f1b..33446d6 100644 --- a/Jenkinsfile.cd +++ b/Jenkinsfile.cd @@ -36,32 +36,6 @@ pipeline { stages { - /* ========================= - TESTS - ========================= */ - - stage('Backend: test (main)') { - agent { - docker { - image 'python:3.11-slim' - args '-u root' - } - } - steps { - dir('backend') { - sh ''' - set -e - python -m venv .venv - . .venv/bin/activate - pip install --upgrade pip - pip install -r requirements-dev.txt - pytest - ''' - } - } - } - - /* ========================= DOCKER BUILD ========================= */ From 896a7413fea89c3c78bfcad5316bb55aed2d21ed Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 6 Feb 2026 21:35:56 +0100 Subject: [PATCH 13/13] Update Jenkinsfile.ci --- Jenkinsfile.ci | 3 --- 1 file changed, 3 deletions(-) diff --git a/Jenkinsfile.ci b/Jenkinsfile.ci index cf8087f..3db5ae0 100644 --- a/Jenkinsfile.ci +++ b/Jenkinsfile.ci @@ -114,7 +114,6 @@ post { msg = """ ✅ Todo en orden, camarada. - - Build: #${env.BUILD_NUMBER} - URL: ${env.BUILD_URL} """.stripIndent().trim() } @@ -122,7 +121,6 @@ post { msg = """ ❌ Alto ahí. ¿Qué clase de crímenes de guerra has cometido en esta PR? - - Build: #${env.BUILD_NUMBER} - URL: ${env.BUILD_URL} """.stripIndent().trim() } @@ -130,7 +128,6 @@ post { msg = """ ⚠️ Dudoso… - - Build: #${env.BUILD_NUMBER} - URL: ${env.BUILD_URL} """.stripIndent().trim() }