From 7b5fa5f103dc481d9e0c9994eca58a4946ee9d71 Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Sat, 3 Jan 2026 14:02:46 +0000 Subject: [PATCH] Add documentation generation with PR preview workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Doxyfile for generating API documentation with Doxygen - Add GitHub Actions workflow for documentation: - Builds docs on every push to main and PR - Deploys main branch docs to root of GitHub Pages - Deploys PR previews to /pr-NUM/ subdirectory - Posts comment on PR with link to preview - Cleans up PR preview when PR is closed - Update .gitignore to exclude generated docs and build_* directories 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/docs.yml | 164 +++++++++++++++++++++++++++++++++++++ .gitignore | 2 + docs/Doxyfile | 106 ++++++++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/Doxyfile diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..6780008 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,164 @@ +name: Documentation + +on: + push: + branches: [main] + pull_request: + branches: [main] + +# Allow only one concurrent deployment per ref, cancelling in-progress runs +concurrency: + group: "pages-${{ github.ref }}" + cancel-in-progress: true + +permissions: + contents: write + pull-requests: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Doxygen + run: | + sudo apt-get update + sudo apt-get install -y doxygen graphviz + + - name: Build Documentation + run: | + cd docs + doxygen Doxyfile + + - name: Upload docs artifact + uses: actions/upload-artifact@v4 + with: + name: docs-html + path: docs/html + retention-days: 7 + + # Deploy to main site (root of gh-pages) + deploy-main: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: build + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Download docs artifact + uses: actions/download-artifact@v4 + with: + name: docs-html + path: docs-output + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs-output + keep_files: true # Preserve PR preview directories + + # Deploy PR preview to /pr-NUM/ + deploy-pr: + if: github.event_name == 'pull_request' + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download docs artifact + uses: actions/download-artifact@v4 + with: + name: docs-html + path: docs-output + + - name: Get PR number + id: pr + run: echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" + + - name: Deploy PR preview + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs-output + destination_dir: pr-${{ steps.pr.outputs.number }} + keep_files: true + + - name: Get Pages URL + id: pages-url + run: | + REPO="${{ github.repository }}" + echo "url=https://${{ github.repository_owner }}.github.io/${REPO#*/}/pr-${{ steps.pr.outputs.number }}/" >> "$GITHUB_OUTPUT" + + - name: Comment on PR + uses: actions/github-script@v7 + with: + script: | + const prNumber = ${{ steps.pr.outputs.number }}; + const docsUrl = '${{ steps.pages-url.outputs.url }}'; + + // Find existing bot comment + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + + const botComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('Documentation Preview') + ); + + const body = `## Documentation Preview + + Documentation for this PR is available at: + ${docsUrl} + + This preview will be updated on each push to this PR. + + --- + *Last updated: ${new Date().toISOString()}*`; + + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: body, + }); + } + + # Cleanup PR preview when PR is closed + cleanup-pr: + if: github.event_name == 'pull_request' && github.event.action == 'closed' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: gh-pages + fetch-depth: 0 + continue-on-error: true + + - name: Remove PR preview + if: success() + run: | + PR_NUM="${{ github.event.pull_request.number }}" + + if [ -d "pr-${PR_NUM}" ]; then + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + rm -rf "pr-${PR_NUM}" + git add -A + git commit -m "Remove PR #${PR_NUM} documentation preview" || echo "No changes to commit" + git push origin gh-pages + fi diff --git a/.gitignore b/.gitignore index fac7831..b6c930c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *~ build +build_* .vscode Testing +docs/html diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 0000000..3a0bca9 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,106 @@ +# Doxyfile for BaSpaCho documentation + +#--------------------------------------------------------------------------- +# Project related configuration +#--------------------------------------------------------------------------- + +PROJECT_NAME = "BaSpaCho" +PROJECT_BRIEF = "Batched Sparse Cholesky Decomposition" +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO + +#--------------------------------------------------------------------------- +# Build related configuration +#--------------------------------------------------------------------------- + +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES + +#--------------------------------------------------------------------------- +# Input configuration +#--------------------------------------------------------------------------- + +INPUT = ../baspacho/baspacho \ + ../README.md \ + ../CLAUDE.md +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.h *.hpp *.cpp *.md +RECURSIVE = NO +EXCLUDE = +EXCLUDE_PATTERNS = *Test* *test* + +USE_MDFILE_AS_MAINPAGE = ../README.md + +#--------------------------------------------------------------------------- +# Source browsing +#--------------------------------------------------------------------------- + +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# Output configuration +#--------------------------------------------------------------------------- + +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_COLORSTYLE = LIGHT +HTML_DYNAMIC_SECTIONS = YES +HTML_INDEX_NUM_ENTRIES = 100 + +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 + +GENERATE_LATEX = NO +GENERATE_RTF = NO +GENERATE_MAN = NO +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Preprocessor +#--------------------------------------------------------------------------- + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = ../baspacho/baspacho + +#--------------------------------------------------------------------------- +# Diagrams +#--------------------------------------------------------------------------- + +HAVE_DOT = NO +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES + +#--------------------------------------------------------------------------- +# Warnings +#--------------------------------------------------------------------------- + +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" + +#--------------------------------------------------------------------------- +# Alphabetical index +#--------------------------------------------------------------------------- + +ALPHABETICAL_INDEX = YES + +#--------------------------------------------------------------------------- +# Search engine +#--------------------------------------------------------------------------- + +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO