diff --git a/build/jenkins/dockerfiles/lint.Dockerfile b/build/jenkins/dockerfiles/lint.Dockerfile new file mode 100644 index 0000000000..663faa3b65 --- /dev/null +++ b/build/jenkins/dockerfiles/lint.Dockerfile @@ -0,0 +1,23 @@ +FROM debian:bookworm-slim +ARG DEBIAN_FRONTEND=noninteractive +ARG DEBCONF_NOWARNINGS="yes" +RUN useradd -ms /bin/bash --uid 1006 builder +RUN apt-get -qq update && apt-get install -qqy --no-install-recommends \ + python3-dev \ + cppcheck \ + git \ + subversion \ + libphutil \ + php-cli \ + php-curl \ + curl \ +&& apt-get clean +ENV SHELL /bin/bash +WORKDIR "/home/builder" +RUN curl -fsSLk https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh +RUN chmod +x nodesource_setup.sh && ./nodesource_setup.sh && rm nodesource_setup.sh +RUN apt install nodejs -qqy +RUN npm install -g eslint@8.57.0 eslint-plugin-brace-rules +USER builder +RUN git clone https://github.com/phacility/arcanist.git ~/arcanist +ENV PATH="${PATH}:~/arcanist/bin/" diff --git a/build/jenkins/pipelines/docker-differential.Jenkinsfile b/build/jenkins/pipelines/docker-differential.Jenkinsfile index a73e82d79a..6a7ac9f89e 100644 --- a/build/jenkins/pipelines/docker-differential.Jenkinsfile +++ b/build/jenkins/pipelines/docker-differential.Jenkinsfile @@ -1,27 +1,28 @@ -/* Copyright (C) 2022 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with 0 A.D. If not, see . - */ +/* Copyright (C) 2024 Wildfire Games. +* This file is part of 0 A.D. +* +* 0 A.D. is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 of the License, or +* (at your option) any later version. +* +* 0 A.D. is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with 0 A.D. If not, see . +*/ // This pipeline is used to build patches on various compilers. -def compilers = ["gcc7", "clang7"] +def compilers = ["gcc7", "clang8"] def patchesMap = compilers.collectEntries { ["${it}": patch(it)] } + def patch(compiler) { return { stage("Patch: ${compiler}") { @@ -30,16 +31,31 @@ def patch(compiler) { sh "arc patch --diff ${params.DIFF_ID} --force" } } catch(e) { - sh "sudo zfs rollback zpool0/${compiler}@latest" + reset("${compiler}").call() throw e } } } } +def resetMap = compilers.collectEntries { + ["${it}": reset(it)] +} + +def reset(compiler) +{ + return { + stage("Reset: ${compiler}") { + sleep 30 + sh "sudo zfs rollback zpool0/${compiler}@latest" + } + } +} + def buildsMap = compilers.collectEntries { ["${it}": build(it)] } + def build(compiler) { return { stage("Build: ${compiler}") { @@ -101,7 +117,7 @@ def build(compiler) { } catch (e) { throw e } finally { - sh "sudo zfs rollback zpool0/${compiler}@latest" + reset("${compiler}").call() } } } @@ -123,13 +139,31 @@ pipeline { stage("Patch") { when { expression { return !!params.DIFF_ID } } steps { - sh "arc patch --diff ${params.DIFF_ID} --force" - script { parallel patchesMap } + script { + try { + sh "arc patch --diff ${params.DIFF_ID} --force" + script { parallel patchesMap } + } catch(e) { + // In case of failure, reset both, since they were patched together. + parallel resetMap + throw e + } + } } } stage("Build") { steps { - script { parallel buildsMap } + script { + try { + buildsMap.each { key, value -> + value.call() + } + } catch(e) { + // In case of failure, reset both, since they were patched together. + parallel resetMap + throw e + } + } } post { always { @@ -144,10 +178,10 @@ pipeline { catchError { sh ''' for file in builderr-*.txt ; do - if [ -s "$file" ]; then - echo "$file" >> build-errors.txt - cat "$file" >> build-errors.txt - fi + if [ -s "$file" ]; then + echo "$file" >> build-errors.txt + cat "$file" >> build-errors.txt + fi done ''' } @@ -159,21 +193,38 @@ pipeline { steps { script { try { - // arc lint outputs an empty file on success - unless there is nothing to lint. - // On failure, it'll output the file and a failure error code. - // Explicitly checking for the file presence is thus best to detect the linter did run - sh 'arc lint --never-apply-patches --output jenkins --outfile .phabricator-lint && touch .phabricator-lint' - } catch (e) { - if (!fileExists(".phabricator-lint")) { - sh '''echo '{"General":[{"line": 0, "char": 0, "code": "Jenkins", "severity": "error", "name": "ci-error", "description": "Error running lint", "original": null, "replacement": null, "granularity": 1, "locations": [], "bypassChangedLineFiltering": true, "context": null}]}' > .phabricator-lint ''' - } + docker.image("0ad-lint:latest").inside { + try { + // arc lint outputs an empty file on success - unless there is nothing to lint. + // On failure, it'll output the file and a failure error code. + // Explicitly checking for the file presence is thus best to detect the linter did run + sh '~/arcanist/bin/arc lint --never-apply-patches --output jenkins --outfile .phabricator-lint && touch .phabricator-lint' + } + catch (e) { + if (!fileExists(".phabricator-lint")) { + sh '''echo '{"General":[{"line": 0, "char": 0, "code": "Jenkins", "severity": "error", "name": "ci-error", "description": "Error running lint", "original": null, "replacement": null, "granularity": 1, "locations": [], "bypassChangedLineFiltering": true, "context": null}]}' > .phabricator-lint ''' + } + else { + sh 'echo "error(s) were found running lint"' + } + } + finally { + stash includes: ".phabricator-lint", name: "Lint File" + } + } + } + finally { + unstash("Lint File") + if (fileExists(".phabricator-lint")) { + sh '''cat .phabricator-lint ''' + } } } } } stage("Data checks") { steps { - warnError('CheckRefs.pl script failed!') { + warnError('CheckRefs.py script failed!') { sh "cd source/tools/entity/ && python3 checkrefs.py -tax 2> data-errors.txt" } } @@ -187,8 +238,8 @@ pipeline { sh "if [ -s build-errors.txt ]; then cat build-errors.txt >> .phabricator-comment ; fi" sh ''' if [ -s data-errors.txt ]; then - echo "Data checks errors:" >> .phabricator-comment - cat data-errors.txt >> .phabricator-comment + echo "Data checks errors:" >> .phabricator-comment + cat data-errors.txt >> .phabricator-comment fi ''' } diff --git a/build/jenkins/pipelines/docker-reset.Jenkinsfile b/build/jenkins/pipelines/docker-reset.Jenkinsfile index ae691e71f1..35e1cd4034 100644 --- a/build/jenkins/pipelines/docker-reset.Jenkinsfile +++ b/build/jenkins/pipelines/docker-reset.Jenkinsfile @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -42,16 +42,34 @@ pipeline { steps { sh 'docker build --no-cache -t build-base ~/dockerfiles/build-base' sh 'docker build --no-cache -t 0ad-gcc7 ~/dockerfiles/gcc7' - sh 'docker build --no-cache -t 0ad-coala ~/dockerfiles/coala' + sh 'docker build --no-cache -t 0ad-gcc7-docs ~/dockerfiles/gcc7-docs' + sh 'docker build --no-cache -t 0ad-clang8 ~/dockerfiles/clang8' sh 'docker build --no-cache -t 0ad-translations ~/dockerfiles/translations' + sh 'docker build --no-cache -t 0ad-lint ~/dockerfiles/lint' } } stage("Build") { + when { + environment name: 'no-cache', value: 'true' + } steps { sh 'docker build -t build-base ~/dockerfiles/build-base' sh 'docker build -t 0ad-gcc7 ~/dockerfiles/gcc7' - sh 'docker build -t 0ad-coala ~/dockerfiles/coala' + sh 'docker build -t 0ad-gcc7-docs ~/dockerfiles/gcc7-docs' + sh 'docker build -t 0ad-clang8 ~/dockerfiles/clang8' sh 'docker build -t 0ad-translations ~/dockerfiles/translations' + sh 'docker build -t 0ad-lint ~/dockerfiles/lint' + sh """ + docker rmi debian:buster + DANGLING_IMAGES="\$(docker images --filter \"\"\"dangling=true\"\"\" -q --no-trunc)" + if [ -n "\$DANGLING_IMAGES" ]; then + echo "Removing dangling images: \$DANGLING_IMAGES" + docker rmi \$(docker images --filter \"\"\"dangling=true\"\"\" -q --no-trunc) + echo "Done." + else + echo "No dangling images found." + fi + """ } } stage("Update") { @@ -72,8 +90,10 @@ pipeline { sh "sudo zfs snapshot zpool0/trunk@base" sh "sudo zfs clone zpool0/trunk@base zpool0/gcc7" - + sh "sudo zfs clone zpool0/trunk@base zpool0/clang8" sh "sudo zfs snapshot zpool0/trunk@latest" + sh "sudo zfs snapshot zpool0/clang8@latest" + sh "sudo zfs snapshot zpool0/gcc7@latest" } } }