Fix fork PR docs workflow (check PR comment from the fork) #10397
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Sphinx | |
| on: | |
| push: | |
| branches: | |
| - master | |
| pull_request: | |
| types: [opened, synchronize, reopened, closed] | |
| permissions: read-all | |
| env: | |
| GH_BOT_NAME: 'github-actions[bot]' | |
| GH_BOT_EMAIL: 'github-actions[bot]@users.noreply.github.com' | |
| GH_EVENT_PUSH_UPSTREAM: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' && | |
| github.event.ref == 'refs/heads/master' && github.event.repository && !github.event.repository.fork }} | |
| PUBLISH_DIR: doc/_build/html/ | |
| defaults: | |
| run: | |
| shell: bash -el {0} | |
| jobs: | |
| build-and-deploy: | |
| name: Build and Deploy Docs | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 90 | |
| permissions: | |
| # Needed to cancel any previous runs that are not completed for a given workflow | |
| actions: write | |
| # Needed to deploy static files to GitHub Pages | |
| contents: write | |
| # Needed to add a comment to a pull request's issue | |
| pull-requests: write | |
| env: | |
| environment-file: 'environments/environment.yml' | |
| build-with-oneapi-env: 'environments/build_with_oneapi.yml' | |
| building-docs-env: 'environments/building_docs.yml' | |
| oneapi-pkgs-env: '' | |
| # Enable env when it's required to use only conda packages without OneAPI installation | |
| # oneapi-pkgs-env: '${{ github.workspace }}/environments/oneapi_pkgs.yml' | |
| dpctl-pkg-txt: 'environments/dpctl_pkg.txt' | |
| steps: | |
| - name: Cancel Previous Runs | |
| uses: styfle/cancel-workflow-action@d07a454dad7609a92316b57b23c9ccfd4f59af66 # 0.13.1 | |
| with: | |
| access_token: ${{ github.token }} | |
| - name: Dump GitHub context | |
| env: | |
| GITHUB_CONTEXT: ${{ toJson(github) }} | |
| run: | | |
| echo "$GITHUB_CONTEXT" | |
| - name: Free Disk Space (Ubuntu) | |
| uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 | |
| with: | |
| docker-images: false | |
| - name: Add Intel repository | |
| if: env.oneapi-pkgs-env == '' | |
| run: | | |
| wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | |
| < GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null | |
| rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | |
| echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list | |
| sudo apt update | |
| - name: Update libstdc++-dev | |
| run: | | |
| sudo apt remove -y gcc-7 g++-7 gcc-8 g++-8 gcc-10 g++-10 | |
| sudo apt remove -y libstdc++-10-dev | |
| sudo apt autoremove | |
| sudo apt install --reinstall -y gcc-9 g++-9 libstdc++-9-dev | |
| - name: Install Intel OneAPI | |
| if: env.oneapi-pkgs-env == '' | |
| run: | | |
| sudo apt install hwloc \ | |
| intel-oneapi-mkl \ | |
| intel-oneapi-umf \ | |
| intel-oneapi-mkl-devel \ | |
| intel-oneapi-tbb-devel \ | |
| intel-oneapi-libdpstd-devel \ | |
| intel-oneapi-compiler-dpcpp-cpp | |
| # required by sphinxcontrib-spelling extension | |
| - name: Install enchant package | |
| run: | | |
| sudo apt-get install enchant-2 | |
| - name: Install nvidia-cuda support drivers | |
| run: | | |
| sudo add-apt-repository ppa:graphics-drivers/ppa | |
| sudo apt-get update | |
| sudo apt-get install -y libnvidia-gl-450 | |
| sudo apt-get install -y nvidia-cuda-toolkit clinfo | |
| - name: Checkout repo | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install conda-merge tool | |
| uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318 # v1 | |
| with: | |
| packages: conda-merge | |
| - name: Merge conda env files | |
| run: | | |
| conda-merge ${{ env.build-with-oneapi-env }} ${{ env.building-docs-env }} ${{ env.oneapi-pkgs-env }} > ${{ env.environment-file }} | |
| cat ${{ env.environment-file }} | |
| - name: Setup miniconda | |
| id: setup_miniconda | |
| continue-on-error: true | |
| uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 | |
| with: | |
| miniforge-version: latest | |
| use-mamba: 'true' | |
| conda-remove-defaults: 'true' | |
| environment-file: ${{ env.environment-file }} | |
| activate-environment: 'docs' | |
| - name: ReSetup miniconda | |
| if: steps.setup_miniconda.outcome == 'failure' | |
| uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 | |
| with: | |
| miniforge-version: latest | |
| use-mamba: 'true' | |
| conda-remove-defaults: 'true' | |
| environment-file: ${{ env.environment-file }} | |
| activate-environment: 'docs' | |
| # We can't install dpctl as a conda package when the environment is created through | |
| # installing of Intel OneAPI packages because the dpctl conda package has a runtime | |
| # dependency on DPC++ RT one. Whereas the DPC++ RT package has been already installed | |
| # by the apt command above and its version has been matched with the DPC++ compiler. | |
| # In case where we install the DPC++ compiler with the apt (including DPC++ RT) and | |
| # install the DPC++ RT conda package while resolving dependencies, this can lead | |
| # to a versioning error, i.e. compatibility issue as the DPC++ compiler only guarantees | |
| # backwards compatibility, not forward compatibility (DPC++ RT may not run a binary built | |
| # with a newer version of the DPC++ compiler). | |
| # Installing dpctl via the pip manager has no such limitation, as the package has no | |
| # run dependency on the DPC++ RT pip package, so this is why the step is necessary here. | |
| - name: Install dpctl | |
| if: env.oneapi-pkgs-env == '' | |
| run: | | |
| pip install -r ${{ env.dpctl-pkg-txt }} | |
| - name: Conda info | |
| run: | | |
| mamba info | |
| mamba list | |
| - name: Build library | |
| run: | | |
| [ -f /opt/intel/oneapi/setvars.sh ] && source /opt/intel/oneapi/setvars.sh | |
| python scripts/build_locally.py | |
| - name: Run a spelling checker for docs | |
| run: | | |
| [ -f /opt/intel/oneapi/setvars.sh ] && source /opt/intel/oneapi/setvars.sh | |
| make spelling | |
| working-directory: doc | |
| - name: Build docs | |
| run: | | |
| [ -f /opt/intel/oneapi/setvars.sh ] && source /opt/intel/oneapi/setvars.sh | |
| make html | |
| working-directory: doc | |
| - name: Set a project number to current release | |
| run: | | |
| PROJECT_NUMBER=$(git describe --tags --abbrev=0) | |
| export PROJECT_NUMBER | |
| echo "PROJECT_NUMBER=${PROJECT_NUMBER}" | |
| echo "PROJECT_NUMBER=$PROJECT_NUMBER" >> "$GITHUB_ENV" | |
| - name: Build backend docs | |
| uses: mattnotmitt/doxygen-action@b84fe17600245bb5db3d6c247cc274ea98c15a3b # v1.12 | |
| with: | |
| working-directory: 'dpnp/backend/doc' | |
| - name: Copy backend docs | |
| run: cp -r dpnp/backend/doc/html ${{ env.PUBLISH_DIR }}/backend_doc | |
| # Detect if this is a fork PR | |
| - name: Check if fork PR | |
| id: check_fork | |
| run: | | |
| IS_FORK="false" | |
| if [ "${{ github.event_name }}" == "pull_request" ] && [ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]; then | |
| IS_FORK="true" | |
| fi | |
| echo "is_fork=$IS_FORK" >> "$GITHUB_OUTPUT" | |
| echo "Is fork PR: $IS_FORK" | |
| # Upload artifact for fork PRs | |
| - name: Upload docs artifact (Fork PRs) | |
| if: steps.check_fork.outputs.is_fork == 'true' && github.event.action != 'closed' | |
| uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 | |
| with: | |
| name: pr-${{ github.event.number }}-docs | |
| path: ${{ env.PUBLISH_DIR }} | |
| retention-days: 30 | |
| # The step is only used to build docs while pushing a PR to "master" | |
| - name: Deploy docs | |
| if: env.GH_EVENT_PUSH_UPSTREAM == 'true' | |
| uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ${{ env.PUBLISH_DIR }} | |
| keep_files: true | |
| commit_message: ${{ github.event.head_commit.message }} | |
| publish_branch: gh-pages | |
| user_name: ${{ env.GH_BOT_NAME }} | |
| user_email: ${{ env.GH_BOT_EMAIL }} | |
| # The step is only used to build docs while pushing to PR branch | |
| - name: Publish pull-request docs | |
| if: github.event_name == 'pull_request' && github.event.action != 'closed' && steps.check_fork.outputs.is_fork == 'false' | |
| uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ${{ env.PUBLISH_DIR }} | |
| destination_dir: ./pull/${{ github.event.number }} | |
| allow_empty_commit : true | |
| keep_files: true | |
| commit_message: ${{ github.event.pull_request.title }} | |
| publish_branch: gh-pages | |
| user_name: ${{ env.GH_BOT_NAME }} | |
| user_email: ${{ env.GH_BOT_EMAIL }} | |
| # Prepare documentation preview comment based on PR type | |
| - name: Prepare docs preview comment | |
| if: github.event_name == 'pull_request' && github.event.action != 'closed' | |
| id: docs_comment | |
| env: | |
| PR_NUM: ${{ github.event.number }} | |
| IS_FORK: ${{ steps.check_fork.outputs.is_fork }} | |
| run: | | |
| if [ "$IS_FORK" == "true" ]; then | |
| # Fork PR - provide artifact download instructions | |
| cat << 'EOF' >> "$GITHUB_OUTPUT" | |
| message<<COMMENT_EOF | |
| 📚 **Documentation Preview (Fork PR)** | |
| Your docs have been built successfully! For security reasons, fork PRs cannot automatically publish to GitHub Pages. | |
| **To view your docs:** | |
| ```bash | |
| gh run download ${{ github.run_id }} -R ${{ github.repository }} -n pr-${{ env.PR_NUM }}-docs | |
| cd pr-${{ env.PR_NUM }}-docs | |
| python -m http.server 8000 | |
| # Open http://localhost:8000 in your browser | |
| ``` | |
| **Alternative: Manual download** | |
| 1. Download artifact `pr-${{ env.PR_NUM }}-docs` from [this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) (scroll to "Artifacts" section) | |
| 2. Extract the ZIP file and open `index.html` in your browser | |
| <details> | |
| <summary>Why can't fork PRs publish automatically?</summary> | |
| Fork PRs run with restricted permissions to prevent malicious code from modifying the repository or accessing secrets. This is a GitHub security feature to protect open source projects. | |
| </details> | |
| COMMENT_EOF | |
| EOF | |
| else | |
| # Upstream PR - provide direct URL | |
| cat << 'EOF' >> "$GITHUB_OUTPUT" | |
| message<<COMMENT_EOF | |
| View rendered docs @ https://intelpython.github.io/dpnp/pull/${{ env.PR_NUM }}/index.html | |
| COMMENT_EOF | |
| EOF | |
| fi | |
| # Comment on PR with docs preview | |
| - name: Comment with docs preview | |
| if: github.event_name == 'pull_request' && github.event.action != 'closed' | |
| uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0.8.3.11.0 | |
| with: | |
| message-id: docs_preview | |
| message: ${{ steps.docs_comment.outputs.message }} | |
| allow-repeats: false | |
| # The job is only used to build docs when PR is closed (action from PR branch) | |
| clean: | |
| if: | | |
| github.event_name == 'pull_request' && github.event.action == 'closed' && | |
| github.event.pull_request.head.repo && !github.event.pull_request.head.repo.fork | |
| needs: build-and-deploy | |
| permissions: | |
| # Needed to remove docs for closed pull request from the repo | |
| contents: write | |
| # Needed to modify a comment in the pull request's issue | |
| pull-requests: write | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Remove docs [PR closed] | |
| env: | |
| PR_NUM: ${{ github.event.number }} | |
| run: | | |
| git remote add tokened_docs https://IntelPython:${{ secrets.GITHUB_TOKEN }}@github.com/IntelPython/dpnp.git | |
| git fetch tokened_docs | |
| git checkout --track tokened_docs/gh-pages | |
| pwd | |
| [ -d pull/"${PR_NUM}" ] && git rm -rf pull/"${PR_NUM}" | |
| git config --global user.name ${{ env.GH_BOT_NAME }} | |
| git config --global user.email ${{ env.GH_BOT_EMAIL }} | |
| git commit -m "Removing docs for closed pull request ${PR_NUM}" | |
| git push tokened_docs gh-pages | |
| - name: Modify the comment with URL to official documentation | |
| uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0.8.3.11.0 | |
| with: | |
| message-id: url_to_docs | |
| find: | | |
| View rendered docs @.+ | |
| replace: | | |
| View rendered docs @ https://intelpython.github.io/dpnp/index.html |