name: Generate Documentation

on:
  pull_request:
  schedule:
    - cron: '0 0 * * *'

defaults:
  run:
    shell: bash

permissions:
  contents: read

jobs:
  generate:
    permissions:
      contents: write  # for Git to git push
    if: "github.repository == 'zeek/zeek' && contains(github.event.pull_request.labels.*.name, 'CI: Skip All') == false"
    runs-on: ubuntu-24.04

    steps:
      # We only perform a push if the action was triggered via a schedule
      # event, so we only need to authenticate in that case. Use
      # unauthenticated access otherwise so this action can e.g., also run from
      # clones.
      - uses: actions/checkout@v4
        if: github.event_name == 'schedule'
        with:
          submodules: "recursive"
          token: ${{ secrets.ZEEK_BOT_TOKEN }}
      - uses: actions/checkout@v4
        if: github.event_name != 'schedule'
        with:
          submodules: "recursive"

      # Only reset the submodule pointer for scheduled builds. The reason to do
      # this is to pick up any merge commits or anything that may have been
      # missed in a merge, but not have any actual content. We don't want to do
      # it otherwise because PRs should just use the submodule they're pointing
      # at.
      - name: Switch doc submodule to master
        if: github.event_name == 'schedule'
        run: cd doc && git checkout master

      - name: Fetch Dependencies
        run: |
          sudo apt-get update
          sudo apt-get -y install \
            bison \
            bsdmainutils \
            ccache \
            cmake \
            cppzmq-dev \
            flex \
            g++ \
            gcc \
            git \
            libhiredis-dev \
            libfl-dev \
            libfl2 \
            libkrb5-dev \
            libnode-dev \
            libpcap-dev \
            libssl-dev \
            make \
            python3 \
            python3-dev \
            python3-pip \
            sqlite3 \
            swig \
            zlib1g-dev
          python3 -m venv ci-docs-venv
          source ci-docs-venv/bin/activate
          pip3 install -r doc/requirements.txt
          pip3 install pre-commit

      - name: ccache
        uses: hendrikmuhs/ccache-action@v1.2
        with:
          key: 'docs-gen-${{ github.job }}'
          max-size: '2000M'

      # Github runners have node installed on them by default in /usr/local. This
      # causes problems with configure finding the version from the apt package,
      # plus gcc using it by default if we pass the right cmake variables to
      # configure. The easiest solution is to move the directory away prior to
      # running our build. It's moved back after just in case some workflow action
      # expects it to exist.
      - name: Move default node install to backup
        run: sudo mv /usr/local/include/node /usr/local/include/node.bak

      - name: Configure
        run: ./configure --disable-broker-tests --disable-cpp-tests --ccache

      - name: Build
        run: cd build && make -j $(nproc)

      - name: Move default node install to original location
        run: sudo mv /usr/local/include/node.bak /usr/local/include/node

      - name: Check Spicy docs
        run: cd doc && make check-spicy-docs

      # Cache pre-commit environment for reuse.
      - uses: actions/cache@v4
        with:
          path: ~/.cache/pre-commit
          key: doc-pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('doc/.pre-commit-config.yaml') }}

      - name: Generate Docs
        run: |
          source ci-docs-venv/bin/activate
          git config --global user.name zeek-bot
          git config --global user.email info@zeek.org

          echo "*** Generating Zeekygen Docs ***"
          ./ci/update-zeekygen-docs.sh || exit 1

          cd doc

          echo "*** Running pre-commit ***"
          pre-commit run -a --show-diff-on-failure --color=always

          echo "*** Generating Sphinx Docs ***"
          make > make.out 2>&1
          make_status=$?
          echo "*** Sphinx Build Output ***"
          cat make.out
          test ${make_status} -ne 0 && exit 1
          echo "*** Check for Sphinx Warnings ***"
          grep -q WARNING make.out && exit 1
          rm make.out

      - name: Push zeek-docs Changes
        if: github.event_name == 'schedule'
        run: |
          cd doc
          git add scripts/ script-reference/
          git status
          # git commit errors when there's nothing to commit, so guard it
          # with a check that detects whether there's anything staged.
          git diff-index --cached --quiet HEAD || { git commit -m "Generate docs" && git push; }

      - name: Update zeek-docs Submodule
        if: github.event_name == 'schedule'
        run: |
          git config --global user.name zeek-bot
          git config --global user.email info@zeek.org
          git add doc
          git status
          # Similar logic here: proceed only if there's a change in the submodule.
          git diff-index --cached --quiet HEAD || { git commit -m 'Update doc submodule [nomail] [skip ci]' && git push; }

      - name: Send email
        # Only send notifications for scheduled runs. Runs from pull requests
        # show failures in the GitHub UI.
        if: failure() && github.event_name == 'schedule'
        uses: dawidd6/action-send-mail@v3.12.0
        with:
          server_address: ${{secrets.SMTP_HOST}}
          server_port: ${{secrets.SMTP_PORT}}
          username: ${{secrets.SMTP_USER}}
          password: ${{secrets.SMTP_PASS}}
          subject: generate-docs GitHub Action failed!
          body: generate-docs job of ${{github.repository}} Failed! See https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} for details.
          to: ${{secrets.MAIL_TO}}
          from: GitHub Actions <${{secrets.MAIL_FROM}}>
