From dab049ceb61b4cd1cd36094b77e4eb96a8157f32 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Mon, 18 May 2026 13:42:09 +0200 Subject: [PATCH 01/10] [ci][docs] Move doxygen job to alma10. - Base the doxygen job on the alma10 container. - This allows for using a preinstalled doxygen in the container (currently 1.13.2), replacing the manual install of 1.10 - Also use preinstalled XRootD and qhelpgenerator --- .github/workflows/root-docs-ci.yml | 36 ++++-------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index b41d0eae316d7..2ae4b08d3a719 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -33,7 +33,7 @@ jobs: - x64 env: - PLATFORM: alma9 + PLATFORM: alma10 DOC_DIR: master DOC_LOCATION: /github/home BASE_REF: master @@ -44,7 +44,7 @@ jobs: contents: read container: - image: registry.cern.ch/root-ci/alma9:buildready + image: registry.cern.ch/root-ci/alma10:buildready options: '--security-opt label=disable --rm' env: OS_APPLICATION_CREDENTIAL_ID: '7f5b64a265244623a3a933308569bdba' @@ -74,32 +74,10 @@ jobs: echo TAR_NAME=html${BASE_REF}.tar >> $GITHUB_ENV echo DOCDIR_NAME=${BASE_REF} >> $GITHUB_ENV - # TODO: install latest versions in image on root-ci-images - - name: Install Doxygen 1.10.0 - run : | - mkdir -p ${{ github.workspace }}/doxygen - curl -L https://github.com/doxygen/doxygen/releases/download/Release_1_10_0/doxygen-1.10.0.linux.bin.tar.gz | tar -xz -C ${{ github.workspace }}/doxygen/ --strip-components=1 - echo PATH=$PATH:${{ github.workspace }}/doxygen/bin >> $GITHUB_ENV -# git clone --branch Release_1_12_0 https://github.com/doxygen/doxygen.git -# cd doxygen -# mkdir build -# cd build -# cmake .. -# make -j$(nproc) -# echo PATH=$PATH:${{ github.workspace }}/doxygen/build/bin >> $GITHUB_ENV -# cd ${{ github.workspace }} -# doxygen --version - - - name: Install qhelpgenerator-qt5 - run: | - dnf upgrade -y - dnf install -y qt5-doctools - which qhelpgenerator-qt5 - - name: Apply option overrides env: OVERRIDES: "testing=Off roottest=Off" - CONFIGFILE: '.github/workflows/root-ci-config/buildconfig/alma9.txt' + CONFIGFILE: '.github/workflows/root-ci-config/buildconfig/alma10.txt' shell: bash run: | set -x @@ -170,12 +148,6 @@ jobs: path: ${{env.DOC_LOCATION}}/${{env.TAR_NAME}}.gz if-no-files-found: error - - name: Install Kerberos utilities - run: dnf -y install krb5-workstation - - - name: Install XRootD client - run: dnf -y install xrootd-client - - name: Sync documentation to EOS env: RWEBEOS_KT: ${{ secrets.RWEBEOS_KT }} @@ -207,4 +179,4 @@ jobs: rm -r html xrdcp --parallel 64 -rf ./ ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} cd .. - xrdcp -rf ${TAR_NAME}.gz ${EOS_ENDPOINT}/${EOS_BASE_PATH}/download \ No newline at end of file + xrdcp -rf ${TAR_NAME}.gz ${EOS_ENDPOINT}/${EOS_BASE_PATH}/download From 6b1ba43685e5624a660e141034e0406c80bde580 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 19 May 2026 13:17:51 +0200 Subject: [PATCH 02/10] [ci][docs] Mount the alma10 ccache volume for the doxygen job. --- .github/workflows/root-docs-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index 2ae4b08d3a719..29a80d4d7c83c 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -46,6 +46,8 @@ jobs: container: image: registry.cern.ch/root-ci/alma10:buildready options: '--security-opt label=disable --rm' + volumes: + - alma10_ccache_volume:/github/home/.cache/ccache env: OS_APPLICATION_CREDENTIAL_ID: '7f5b64a265244623a3a933308569bdba' OS_APPLICATION_CREDENTIAL_SECRET: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }} From cd39f08478ba08a75cc4755c6f5a8bb4906bab8a Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Mon, 18 May 2026 13:52:08 +0200 Subject: [PATCH 03/10] [ci][docs] Simplify the doxygen job. - Remove the override step from the doxygen job. Overrides can be specified as command-line arguments, which significantly shortens the job file. - Remove duplicated build step. There is no difference between the jobs, so we don't need build job based on the workflow trigger. - Create & compress the tar archive in one go. --- .github/workflows/root-docs-ci.yml | 56 +++++------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index 29a80d4d7c83c..53a368103cebf 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -38,7 +38,7 @@ jobs: DOC_LOCATION: /github/home BASE_REF: master WEB_DIR_NAME: master - TAR_NAME: htmlmaster.tar + TAR_FILE: htmlmaster.tar.gz permissions: contents: read @@ -71,45 +71,7 @@ jobs: # code of the `if`. run: 'if [ -d /py-venv/ROOT-CI/bin/ ]; then . /py-venv/ROOT-CI/bin/activate && echo PATH=$PATH >> $GITHUB_ENV; fi' - - name: Set up directory name and tar filenames - run: | - echo TAR_NAME=html${BASE_REF}.tar >> $GITHUB_ENV - echo DOCDIR_NAME=${BASE_REF} >> $GITHUB_ENV - - - name: Apply option overrides - env: - OVERRIDES: "testing=Off roottest=Off" - CONFIGFILE: '.github/workflows/root-ci-config/buildconfig/alma10.txt' - shell: bash - run: | - set -x - echo '' >> "$CONFIGFILE" - for ENTRY in $OVERRIDES; do - KEY=$( echo "$ENTRY" | cut -d '=' -f 1 ) - # Add entry to file if not exists, otherwise replace - if grep -q "$KEY=" "$CONFIGFILE"; then - sed -i "s/$KEY=.*\$/$ENTRY/" "$CONFIGFILE" - else - echo "$ENTRY" >> "$CONFIGFILE" - fi - done - cat "$CONFIGFILE" || true - - - name: Build ROOT - Workflow Dispatch - if: github.event_name == 'workflow_dispatch' - env: - INCREMENTAL: ${{ inputs.incremental == 'true' }} - run: ".github/workflows/root-ci-config/build_root.py - --buildtype Release - --platform ${{ env.PLATFORM }} - --incremental ${{ env.INCREMENTAL }} - --base_ref ${BASE_REF} - --head_ref ${BASE_REF} - --binaries false - --repository ${{ github.server_url }}/${{ github.repository }}" - - - name: Build ROOT - Schedule - if: github.event_name == 'schedule' + - name: Build ROOT run: ".github/workflows/root-ci-config/build_root.py --buildtype Release --platform ${{ env.PLATFORM }} @@ -117,7 +79,8 @@ jobs: --base_ref ${BASE_REF} --head_ref ${BASE_REF} --binaries false - --repository ${{ github.server_url }}/${{ github.repository }}" + --repository ${{ github.server_url }}/${{ github.repository }} + --overrides testing=Off roottest=Off" - name: Run Doxygen working-directory: ${{ env.DOC_LOCATION }} @@ -134,11 +97,8 @@ jobs: run: | pwd ls -l - echo ${DOC_DIR} - echo ${TAR_NAME} ls -l ${DOC_DIR} - tar cf ${TAR_NAME} ${DOC_DIR} - gzip ${TAR_NAME} + tar -caf ${TAR_FILE} ${DOC_DIR} ls -l #Upload to GitHub as an artifact @@ -146,8 +106,8 @@ jobs: if: ${{ !cancelled() }} uses: actions/upload-artifact@v6 with: - name: ${{env.TAR_NAME}}.gz - path: ${{env.DOC_LOCATION}}/${{env.TAR_NAME}}.gz + name: ${{env.TAR_FILE}} + path: ${{env.DOC_LOCATION}}/${{env.TAR_FILE}} if-no-files-found: error - name: Sync documentation to EOS @@ -181,4 +141,4 @@ jobs: rm -r html xrdcp --parallel 64 -rf ./ ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} cd .. - xrdcp -rf ${TAR_NAME}.gz ${EOS_ENDPOINT}/${EOS_BASE_PATH}/download + xrdcp -rf ${TAR_FILE} ${EOS_ENDPOINT}/${EOS_BASE_PATH}/download From a10b950b1ec8a744fe30cb4937514e71d6a1a263 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Mon, 18 May 2026 14:16:25 +0200 Subject: [PATCH 04/10] [ci][docs] Add job inputs for manually triggered workflows. - Add two job inputs for the workflow trigger. These should allow for choosing a ROOT version to build docs for, and for choosing a directory where the generated page should be served. Omitting the page means no upload to eos. - Remove the input "incremental". Since the documentation jobs don't upload or download anything, it never had an effect. --- .github/workflows/root-docs-ci.yml | 37 ++++++++++++++++++------------ 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index 53a368103cebf..6d765dbe2d225 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -6,22 +6,28 @@ on: # providing the relevant branch as "default" value here: workflow_call: inputs: - incremental: - type: boolean - default: true + input_branch: + description: 'Which branch to build documentation for' + type: string + required: true + eos_upload_directory: + description: 'Make documentation available at /doc/. Leave empty for skipping the upload to eos.' + type: string + required: false + default: '' workflow_dispatch: inputs: - incremental: - description: 'Do full build' - type: boolean + input_branch: + description: 'Which branch to build documentation for' + type: string + required: false + default: 'master' + eos_upload_directory: + description: 'Make documentation available at /doc/. Leave empty for skipping the upload to eos.' + type: string required: false - default: false - # docu_input: # opportunity: overwrite makeinput.sh with these args - # description: Folders to build documentation for. All folders are built if empty. - # type: string - # default: "" - # required: false + default: 'master' jobs: build-docs: @@ -36,8 +42,8 @@ jobs: PLATFORM: alma10 DOC_DIR: master DOC_LOCATION: /github/home - BASE_REF: master - WEB_DIR_NAME: master + BASE_REF: ${{ inputs.input_branch == null && 'master' || inputs.input_branch }} + WEB_DIR_NAME: ${{ inputs.eos_upload_directory == null && '' || inputs.eos_upload_directory }} TAR_FILE: htmlmaster.tar.gz permissions: @@ -75,7 +81,7 @@ jobs: run: ".github/workflows/root-ci-config/build_root.py --buildtype Release --platform ${{ env.PLATFORM }} - --incremental ${{ inputs.incremental }} + --incremental false --base_ref ${BASE_REF} --head_ref ${BASE_REF} --binaries false @@ -111,6 +117,7 @@ jobs: if-no-files-found: error - name: Sync documentation to EOS + if: ${{ env.WEB_DIR_NAME != null && env.WEB_DIR_NAME != '' }} env: RWEBEOS_KT: ${{ secrets.RWEBEOS_KT }} KRB5USER: ${{ secrets.KRB5USER }} From b81b0f94af446fcf15f702b05a231d44be19fa53 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Mon, 18 May 2026 14:19:02 +0200 Subject: [PATCH 05/10] [ci][docs] Make actionlint and shellcheck happier with the workflow. - Quote many variables to prevent word splitting or unwanted globbing --- .github/workflows/root-docs-ci.yml | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index 6d765dbe2d225..fccc7798168d1 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -93,9 +93,9 @@ jobs: shell: bash run: | source ROOT-CI/build/bin/thisroot.sh - export DOXYGEN_OUTPUT_DIRECTORY=/github/home/${DOC_DIR} + export DOXYGEN_OUTPUT_DIRECTORY="/github/home/${DOC_DIR}" cd ROOT-CI/src/documentation/doxygen - make -j `nproc --all` + make -j "$(nproc --all)" - name: Create documentation archives working-directory: ${{ env.DOC_LOCATION }} @@ -132,20 +132,20 @@ jobs: # them by extension. Once that is fixed in XRootD, a single command can be used # instead. run: | - echo ${RWEBEOS_KT} | base64 -d > ${KT_FILE_NAME} - kinit -p ${{ secrets.KRB5USER }}@${{ secrets.KRB5REALM }} -kt ${KT_FILE_NAME} - cd ${DOC_DIR}/html/ - xrdcp --parallel 64 -rf ./*.html ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} - rm -rf *.html - xrdcp --parallel 64 -rf ./*.svg ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} - rm -rf *.svg - xrdcp --parallel 64 -rf ./*.map ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} - rm -rf *.map - xrdcp --parallel 64 -rf ./*.md5 ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} - rm -rf *.md5 - xrdcp --parallel 64 -rf ./ ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} + echo "${RWEBEOS_KT}" | base64 -d > "${KT_FILE_NAME}" + kinit -p "${{ secrets.KRB5USER }}@${{ secrets.KRB5REALM }}" -kt "${KT_FILE_NAME}" + cd "${DOC_DIR}/html/" + xrdcp --parallel 64 -rf ./*.html "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + rm -rf ./*.html + xrdcp --parallel 64 -rf ./*.svg "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + rm -rf ./*.svg + xrdcp --parallel 64 -rf ./*.map "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + rm -rf ./*.map + xrdcp --parallel 64 -rf ./*.md5 "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + rm -rf ./*.md5 + xrdcp --parallel 64 -rf ./ "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" cd .. rm -r html - xrdcp --parallel 64 -rf ./ ${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME} + xrdcp --parallel 64 -rf ./ "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" cd .. - xrdcp -rf ${TAR_FILE} ${EOS_ENDPOINT}/${EOS_BASE_PATH}/download + xrdcp -rf "${TAR_FILE}" "${EOS_ENDPOINT}/${EOS_BASE_PATH}/download" From ce40ef95205bce85eece82aaadf864d3b0cafcf7 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 19 May 2026 13:18:32 +0200 Subject: [PATCH 06/10] [ci][docs] Add a pull request trigger for the doxygen job. When the workflow file or the doxygen folder are touched, the CI will also run the doxygen build. --- .github/workflows/root-docs-ci.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index fccc7798168d1..a1f39ea7d1b52 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -1,9 +1,13 @@ name: 'ROOT Docs CI' on: + pull_request: + paths: + - '.github/workflows/root-docs-ci.yml' + - 'documentation/doxygen/**' + branches: + - 'master' - # Allows nightly builds to trigger one run for each branch easily, by - # providing the relevant branch as "default" value here: workflow_call: inputs: input_branch: @@ -84,9 +88,10 @@ jobs: --incremental false --base_ref ${BASE_REF} --head_ref ${BASE_REF} - --binaries false --repository ${{ github.server_url }}/${{ github.repository }} - --overrides testing=Off roottest=Off" + --overrides testing=Off roottest=Off + --upload_artifacts false + --binaries false" - name: Run Doxygen working-directory: ${{ env.DOC_LOCATION }} From da842070df948f8a754328219f73c59f2d150e00 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 19 May 2026 16:56:16 +0200 Subject: [PATCH 07/10] [ci][docs] Fix escaping of regexes in converttonotebook. Strings such as "\s" are not correct, any more. --- documentation/doxygen/converttonotebook.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/doxygen/converttonotebook.py b/documentation/doxygen/converttonotebook.py index bb13fb99d0625..f4cb4f6bc701d 100755 --- a/documentation/doxygen/converttonotebook.py +++ b/documentation/doxygen/converttonotebook.py @@ -423,7 +423,7 @@ def findBracedBlock(text, startpos, openingBraceChar): def findStuffBeforeFunc(text, searchStart, searchEnd): - beforeFunctionRe = re.compile("(;|}|//[^\n]*)\s*$", flags = re.MULTILINE) + beforeFunctionRe = re.compile("(;|}|//[^\n]*)\\s*$", flags = re.MULTILINE) try: # Find the last '}' or comment line etc before function definition: lastMatchBeforeFunc = [thisMatch for thisMatch in beforeFunctionRe.finditer(text, searchStart, searchEnd)][-1] @@ -622,7 +622,7 @@ def changeString(matchObject): matchString = matchString.replace("THISISASPACE" , " ") return matchString - newcode = re.sub("#\s\s?\w\s[\w-]\s\w.*", changeString , code) + newcode = re.sub(r"#\s\s?\w\s[\w-]\s\w.*", changeString , code) return newcode def declareNamespace(code): From 10e8afe8a068fc71fac96f2dcb5057a06f2be426 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 19 May 2026 17:49:23 +0200 Subject: [PATCH 08/10] [ci][docs] Add a step to clean temporary files. The md5 and map files are used only when doxygen is run on an existing folder. They therefore should not be uploaded or put in the tar archive. --- .github/workflows/root-docs-ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index a1f39ea7d1b52..64d3cb9f921c0 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -102,6 +102,14 @@ jobs: cd ROOT-CI/src/documentation/doxygen make -j "$(nproc --all)" + - name: Clean temporary files + # These files are used when doxygen runs incrementally + shell: bash + run: | + cd "/github/home/${DOC_DIR}" + rm html/*.md5 + rm html/*.map + - name: Create documentation archives working-directory: ${{ env.DOC_LOCATION }} shell: bash From 694a481aafb194a697edf343d2a9596e11aab62d Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Wed, 20 May 2026 08:36:17 +0200 Subject: [PATCH 09/10] [ci][docs] Don't compress that tar archive twice; shorter retention. By default, the upload action puts the archive into an archive and tries to compress it. This is unnecessary. Furthermore, reduce the retention period to a week. The default of 90 days is excessive for a nightly job. --- .github/workflows/root-docs-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index 64d3cb9f921c0..d4396a0da441c 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -128,6 +128,8 @@ jobs: name: ${{env.TAR_FILE}} path: ${{env.DOC_LOCATION}}/${{env.TAR_FILE}} if-no-files-found: error + archive: false + retention-days: 8 - name: Sync documentation to EOS if: ${{ env.WEB_DIR_NAME != null && env.WEB_DIR_NAME != '' }} From 870bfd8b2768c01bb7ef8c68e3e46f45547e5949 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Mon, 25 May 2026 06:59:46 +0200 Subject: [PATCH 10/10] [docs][ci] Don't abort sync to eos on failure. --- .github/workflows/root-docs-ci.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/root-docs-ci.yml b/.github/workflows/root-docs-ci.yml index d4396a0da441c..9117dc284a253 100644 --- a/.github/workflows/root-docs-ci.yml +++ b/.github/workflows/root-docs-ci.yml @@ -148,19 +148,20 @@ jobs: # instead. run: | echo "${RWEBEOS_KT}" | base64 -d > "${KT_FILE_NAME}" - kinit -p "${{ secrets.KRB5USER }}@${{ secrets.KRB5REALM }}" -kt "${KT_FILE_NAME}" + kinit -p "${{ secrets.KRB5USER }}@${{ secrets.KRB5REALM }}" -kt "${KT_FILE_NAME}" || failure=1 cd "${DOC_DIR}/html/" - xrdcp --parallel 64 -rf ./*.html "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + xrdcp --parallel 64 -rf ./*.html "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" || failure=1 rm -rf ./*.html - xrdcp --parallel 64 -rf ./*.svg "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + xrdcp --parallel 64 -rf ./*.svg "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" || failure=1 rm -rf ./*.svg - xrdcp --parallel 64 -rf ./*.map "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + xrdcp --parallel 64 -rf ./*.map "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" || failure=1 rm -rf ./*.map - xrdcp --parallel 64 -rf ./*.md5 "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + xrdcp --parallel 64 -rf ./*.md5 "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" || failure=1 rm -rf ./*.md5 - xrdcp --parallel 64 -rf ./ "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + xrdcp --parallel 64 -rf ./ "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" || failure=1 cd .. rm -r html - xrdcp --parallel 64 -rf ./ "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" + xrdcp --parallel 64 -rf ./ "${EOS_ENDPOINT}/${EOS_BASE_PATH}/doc/${WEB_DIR_NAME}" || failure=1 cd .. - xrdcp -rf "${TAR_FILE}" "${EOS_ENDPOINT}/${EOS_BASE_PATH}/download" + xrdcp -rf "${TAR_FILE}" "${EOS_ENDPOINT}/${EOS_BASE_PATH}/download" || failure=1 + exit "$failure"