name: Build Documentation on: workflow_dispatch: inputs: pr_number: description: 'Pull request number for which the documentation should be built' type: number required: true doc_version: description: 'Version number of the documentation build' type: string required: true force_build: description: 'Force the build of the documentation' type: boolean required: false default: false issue_comment: types: [created] env: author_association: ${{ github.event.comment.author_association }} comment_body: ${{ github.event.comment.body }} permissions: contents: read # to fetch code (actions/checkout) jobs: pre_build_checks: if: ${{ inputs.pr_number || startsWith(github.event.comment.body, '/build:') || startsWith(github.event.comment.body, '/force-build:') }} runs-on: ubuntu-latest name: Trigger the build? outputs: trigger_build: ${{ steps.get_doc_version.outputs.result && steps.get_doc_version.outputs.result != '' }} force_build: ${{ steps.check_comment_body.outputs.force_build }} pr_number: ${{ steps.get_pr_number.outputs.pr_number }} doc_version: ${{ steps.get_doc_version.outputs.result }} steps: - name: Display inputs run: | echo "pr_number=${{ inputs.pr_number || github.event.issue.number }}" echo "doc_version=${{ inputs.doc_version }}" echo "force_build=${{ inputs.force_build || startsWith(env.comment_body, '/force-build:') }}" - name: Check comment body id: check_comment_body env: trigger_build: ${{ inputs && inputs.pr_number || startsWith(env.comment_body, '/build:') || startsWith(env.comment_body, '/force-build:') }} force_build: ${{ inputs && inputs.force_build || startsWith(env.comment_body, '/force-build:') }} if: inputs.pr_number || startsWith(env.comment_body, '/build:') || startsWith(env.comment_body, '/force-build:') run: | if [ "${trigger_build}" = "false" ]; then echo "No build requested" exit 1 fi echo "force_build=${force_build}" >> $GITHUB_OUTPUT echo "trigger_build=${trigger_build}" >> $GITHUB_OUTPUT - name: Check permissions if: ( steps.check_comment_body.outputs.trigger_build || false ) && (inputs.pr_number || env.author_association == 'OWNER' || env.author_association == 'MEMBER') run: echo "Authorized" - name: No permissions if: ( steps.check_comment_body.outputs.trigger_build || false ) && (! inputs.pr_number && env.author_association != 'OWNER' && env.author_association != 'MEMBER' ) run: | echo 'ERROR: User ${{ github.actor }} is not allowed to trigger the build of the documentation with /build:* or /force-build:*' exit 1 - name: Get PR number if: ( steps.check_comment_body.outputs.trigger_build || false ) id: get_pr_number env: pr_number: ${{ inputs.pr_number || github.event.issue.number }} run: echo "pr_number=$pr_number" >> $GITHUB_OUTPUT - name: Get doc version if: ( steps.check_comment_body.outputs.trigger_build || false ) uses: actions/github-script@v7 id: get_doc_version with: result-encoding: string script: | if ( context.payload.input && context.payload.inputs.doc_version ) { return context.payload.inputs.doc_version } const body = context.payload.comment.body const re = /\/(force-)?build:(\w+)\s*/; if(re.test(body)) { const res = re.exec(body) return res[2] } throw new Error('No version found') build_doc: name: | ${{ format('{0}: Build Documentation version "{1}"', github.actor, needs.pre_build_checks.outputs.doc_version) }} needs: pre_build_checks permissions: contents: read # to fetch code (actions/checkout) pull-requests: write # to create comment runs-on: ubuntu-latest env: force_build: ${{ needs.pre_build_checks.outputs.force_build }} pr_number: ${{ needs.pre_build_checks.outputs.pr_number }} doc_version: ${{ needs.pre_build_checks.outputs.doc_version }} if: ${{ fromJSON(needs.pre_build_checks.outputs.trigger_build || false) }} steps: - name: Emoji-comment if: github.event_name == 'issue_comment' continue-on-error: true uses: actions/github-script@v7 with: script: | github.rest.reactions.createForIssueComment({ comment_id: ${{ github.event.comment.id }}, owner: context.repo.owner, repo: context.repo.repo, content: 'rocket' }) - uses: actions/checkout@v4 name: "checkout branch" with: repository: ${{ github.repository }} ref: refs/pull/${{ env.pr_number }}/head fetch-depth: 0 - name: Install dependencies run: | set -x # Install Github CLI `gh` (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) sudo mkdir -p -m 755 /etc/apt/keyrings wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null sudo apt-get update && sudo apt-get install -y gh cmake graphviz ssh bibtex2html sudo pip install lxml sudo pip install pyquery wget --no-verbose -O doxygen_exe https://cgal.geometryfactory.com/~cgaltest/doxygen_1_9_6_patched/doxygen sudo mv doxygen_exe /usr/bin/doxygen sudo chmod +x /usr/bin/doxygen git config --global user.email "cgal@geometryfactory.com" git config --global user.name "cgaltest" - name: CMake configuration of Documentation/doc run: | set -ex mkdir -p build_doc && cd build_doc && cmake ../Documentation/doc - name: Build and upload Doc id: build_and_run env: GH_TOKEN: ${{ github.token }} run: | set -ex PR_NUMBER=$pr_number ROUND=$doc_version force=$force_build wget --no-verbose cgal.github.io -O index.html if ! egrep -qF "/$PR_NUMBER/$ROUND" index.html || [ "$force" = "yes" ]; then #list impacted packages LIST_OF_PKGS=$(git diff --name-only origin/master...HEAD |cut -s -d/ -f1 |sort -u | xargs -I {} echo {} && ls -d {}/package_info 2>/dev/null |cut -d/ -f1 |egrep -v Installation||true) if [ "$LIST_OF_PKGS" = "" ]; then echo "DoxygenError=No package affected." >> $GITHUB_OUTPUT exit 1 fi for p in $LIST_OF_PKGS; do if [ -f $p/doc/$p/dependencies ]; then LIST_OF_PKGS="$LIST_OF_PKGS $(cat $p/doc/$p/dependencies)" fi done LIST_OF_PKGS=$(echo $LIST_OF_PKGS | tr ' ' '\n' | sort -u) cd build_doc && make -j$(nproc) doc make -j$(nproc) doc_with_postprocessing 2>build.log if [ -s build.log ]; then delimiter="$(openssl rand -hex 8)" echo "DoxygenError<<${delimiter}" >> "${GITHUB_OUTPUT}" cat build.log >> "${GITHUB_OUTPUT}" echo "${delimiter}" >> "${GITHUB_OUTPUT}" exit 1 fi cd .. git clone https://CGAL:${{ secrets.PUSH_TO_CGAL_GITHUB_IO_TOKEN }}@github.com/CGAL/cgal.github.io.git mkdir -p cgal.github.io/${PR_NUMBER}/$ROUND rm cgal.github.io/${PR_NUMBER}/$ROUND/* -rf for f in $LIST_OF_PKGS Manual do if [ -d ./build_doc/doc_output/$f ]; then cp -r ./build_doc/doc_output/$f ./cgal.github.io/${PR_NUMBER}/$ROUND fi done cd ./cgal.github.io echo "
  • Manual for PR ${PR_NUMBER} ($ROUND).
  • " >> ./index.html ./cleanup.bash git add ${PR_NUMBER}/$ROUND index.html && git commit -q --amend -m "sole commit" && git push -q -f -u origin master else echo "DoxygenError=This round already exists. Overwrite it with /force-build." >> $GITHUB_OUTPUT exit 1 fi - name: Post address uses: actions/github-script@v7 if: ${{ success() }} with: script: | const round = "${{ env.doc_version }}" const address = "The documentation is built. It will be available, after a few minutes, here: https://cgal.github.io/${{ env.pr_number }}/"+round+"/Manual/index.html" github.rest.issues.createComment({ owner: "CGAL", repo: "cgal", issue_number: ${{ github.event.issue.number }}, body: address }); - name: Post error env: ERRORMSG: ${{steps.build_and_run.outputs.DoxygenError}} uses: actions/github-script@v7 if: ${{ failure() }} with: script: | const error = process.env.ERRORMSG const job_url = `${context.serverUrl}/CGAL/cgal/actions/runs/${context.runId}` const msg = "There was an error while building the doc: \n```\n"+error + "\n```\n" + job_url github.rest.issues.createComment({ owner: "CGAL", repo: "cgal", issue_number: ${{ github.event.issue.number }}, body: msg });