commit to main for docs deploy action #40
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: Tests | |
| on: | |
| push: | |
| branches: [main, convert-to-uv] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| deploy_docs: | |
| description: "Deploy documentation to GitHub Pages" | |
| required: false | |
| type: boolean | |
| default: false | |
| jobs: | |
| test: | |
| name: Test Python ${{ matrix.python-version }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.11", "3.12"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y findutils | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies | |
| run: uv sync | |
| - name: Run tests | |
| run: | | |
| uv run pytest tests/ --cov=nexusLIMS \ | |
| --cov-report html:tests/coverage \ | |
| --cov-report term-missing \ | |
| --cov-report=xml \ | |
| --cov-branch \ | |
| --mpl --mpl-baseline-path=tests/files/figs | |
| - name: Upload HTML coverage report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-html-${{ matrix.python-version }} | |
| path: tests/coverage | |
| - name: Upload coverage to Codecov | |
| if: matrix.python-version == '3.11' | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./coverage.xml | |
| fail_ci_if_error: false | |
| deploy-docs: | |
| # Deploy documentation to GitHub Pages after successful test run on main branch | |
| # Can also be triggered manually via workflow_dispatch with deploy_docs input | |
| if: github.ref == 'refs/heads/main' || github.event.inputs.deploy_docs == 'true' | |
| needs: test | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pages: write # Required to deploy to GitHub Pages | |
| id-token: write # Required for OIDC authentication | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: uv sync | |
| - name: Download coverage artifact | |
| # Download the HTML coverage report generated by the test job | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: coverage-html-3.11 | |
| path: tests/coverage | |
| - name: Build documentation | |
| # Build Sphinx documentation (includes API docs and coverage link) | |
| run: ./scripts/build_docs.sh | |
| - name: Generate switcher.json | |
| # Create version switcher for PyData Sphinx Theme navigation | |
| run: python scripts/generate_switcher_json.py | |
| - name: Prepare Pages artifact | |
| # Assemble final site structure with docs and coverage in _site directory | |
| run: | | |
| mkdir -p _site | |
| rsync -avr _build/ _site/ | |
| mkdir -p _site/_static | |
| cp docs/_static/switcher.json _site/_static/switcher.json | |
| mkdir -p _site/coverage | |
| if [ -d "tests/coverage" ]; then | |
| rsync -avr tests/coverage/ _site/coverage/ | |
| fi | |
| - name: Setup Pages | |
| # Configure GitHub Pages deployment settings | |
| id: pages | |
| uses: actions/configure-pages@v5 | |
| - name: Upload artifact | |
| # Upload the complete site as a Pages deployment artifact | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: _site | |
| - name: Deploy to GitHub Pages | |
| # Deploy the uploaded artifact to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 | |
| - name: Create latest redirect | |
| # Create a /latest/ redirect in gh-pages branch pointing to /stable/ | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git fetch origin gh-pages | |
| git checkout gh-pages | |
| git pull origin gh-pages | |
| rm -rf latest | |
| mkdir -p latest | |
| cat > latest/index.html << 'EOF' | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="refresh" content="0; url=../stable/"> | |
| <link rel="canonical" href="../stable/" /> | |
| <title>Redirecting to stable documentation</title> | |
| </head> | |
| <body> | |
| <p>Redirecting to <a href="../stable/">stable documentation</a>...</p> | |
| </body> | |
| </html> | |
| EOF | |
| git add latest | |
| git commit -m "Update latest redirect to stable" || echo "No changes to commit" | |
| git push origin gh-pages | |
| echo "✅ Latest redirect updated!" | |
| echo "🔗 https://datasophos.github.io/NexusLIMS/latest/ → stable" | |
| deploy-pr-docs: | |
| # Deploy documentation preview for pull requests to gh-pages branch | |
| if: github.event_name == 'pull_request' | |
| needs: test | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # Required to push to gh-pages branch | |
| pull-requests: write # Required to comment on PR | |
| steps: | |
| - name: Checkout gh-pages branch | |
| # Start from gh-pages to preserve existing PR previews | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: gh-pages | |
| - name: Checkout PR code | |
| # Checkout the PR source code into pr-source subdirectory | |
| uses: actions/checkout@v4 | |
| with: | |
| path: pr-source | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| cd pr-source | |
| uv sync | |
| - name: Download coverage artifact | |
| # Download the HTML coverage report from the test job | |
| continue-on-error: true | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: coverage-html-3.11 | |
| path: pr-source/tests/coverage | |
| - name: Generate switcher.json | |
| # Create version switcher for PyData Sphinx Theme navigation | |
| env: | |
| GITHUB_EVENT_NAME: ${{ github.event_name }} | |
| GITHUB_REF: refs/pull/${{ github.event.pull_request.number }}/merge | |
| run: | | |
| cd pr-source | |
| python scripts/generate_switcher_json.py | |
| - name: Build documentation | |
| # Build Sphinx documentation for this PR (includes switcher.json from above) | |
| env: | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| cd pr-source | |
| ./scripts/build_docs.sh | |
| - name: Deploy to PR preview directory | |
| # Create/update pr-{NUMBER} directory in gh-pages with docs and coverage | |
| run: | | |
| PR_NUMBER=${{ github.event.pull_request.number }} | |
| rm -rf "pr-${PR_NUMBER}" | |
| mkdir -p "pr-${PR_NUMBER}" | |
| rsync -avr pr-source/_build/ "pr-${PR_NUMBER}/" | |
| if [ -d "pr-source/tests/coverage" ]; then | |
| mkdir -p "pr-${PR_NUMBER}/coverage" | |
| rsync -avr pr-source/tests/coverage/ "pr-${PR_NUMBER}/coverage/" | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add "pr-${PR_NUMBER}" | |
| git commit -m "Deploy docs preview for PR #${PR_NUMBER}" || echo "No changes to commit" | |
| git pull --rebase origin gh-pages | |
| git push origin gh-pages | |
| echo "✅ Documentation preview deployed!" | |
| echo "🔗 View at: https://datasophos.github.io/NexusLIMS/pr-${PR_NUMBER}/" | |
| - name: Comment on PR | |
| # Post a comment with links to the deployed preview and coverage | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prNumber = context.payload.pull_request.number; | |
| const repo = context.repo.owner + '/' + context.repo.repo; | |
| const baseUrl = `https://${context.repo.owner}.github.io/${context.repo.repo}`; | |
| const commentBody = `## 📚 Documentation Preview | |
| The documentation for this PR has been deployed to: | |
| - **Docs**: ${baseUrl}/pr-${prNumber}/ | |
| - **Coverage**: ${baseUrl}/pr-${prNumber}/coverage/ | |
| _This preview will be updated on each push to this PR._`; | |
| // Find existing 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') | |
| ); | |
| if (botComment) { | |
| // Update existing comment | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: commentBody, | |
| }); | |
| } else { | |
| // Create new comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: commentBody, | |
| }); | |
| } |