diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 82a079c7..89ea9b93 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -5,6 +5,7 @@ jobs: build: name: generate-html runs-on: ubuntu-22.04 + if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' permissions: contents: read steps: @@ -17,3 +18,16 @@ jobs: with: name: generated-html path: _build/docs/nvidia_network_operator + - name: 'Create PR metadata' + if: github.event_name == 'pull_request' + run: | + mkdir -p pr + echo "${{ github.event.pull_request.number }}" > pr/pr.txt + echo "${{ github.event.pull_request.merged }}" > pr/merged.txt + echo "${{ github.event.action }}" > pr/action.txt + - name: 'Upload PR metadata artifact' + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: pr + path: pr diff --git a/.github/workflows/docs-preview-pr.yaml b/.github/workflows/docs-preview-pr.yaml new file mode 100644 index 00000000..e1d3caec --- /dev/null +++ b/.github/workflows/docs-preview-pr.yaml @@ -0,0 +1,138 @@ +name: docs-preview-pr + +on: + workflow_run: + workflows: ["Build"] + types: + - completed + +env: + WF_ID: ${{ github.event.workflow_run.id }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + # Always determine if GitHub Pages are configured for this repo. + get-gh-pages-url: + if: + (github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'push') && + github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + outputs: + url: ${{ steps.api-resp.outputs.html_url || '' }} + branch: ${{ steps.api-resp.outputs.branch || '' }} + steps: + - name: Check for GitHub Pages + id: api-resp + run: | + has_pages=$(gh api "repos/${GITHUB_REPOSITORY}" -q '.has_pages') + if [ "true" != "${has_pages}" ]; then + echo "GitHub pages is not active for the repository. Quitting." + return + fi + + url=$(gh api "repos/${GITHUB_REPOSITORY}/pages" -q '.html_url') + branch=$(gh api "repos/${GITHUB_REPOSITORY}/pages" -q '.source.branch') + + echo "html_url=${url}" >> $GITHUB_OUTPUT + echo "branch=${branch}" >> $GITHUB_OUTPUT + + # Identify the dir for the HTML. + store-html: + runs-on: ubuntu-latest + needs: [get-gh-pages-url] + if: needs.get-gh-pages-url.outputs.url != '' + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.get-gh-pages-url.outputs.branch }} + - name: Initialize Git configuration + run: | + git config user.name docs-preview + git config user.email do-not-send-@github.com + - name: Download artifacts + run: | + gh run view "${WF_ID}" + gh run download "${WF_ID}" -n pr -n generated-html + + # Check if pr artifact exists (for merged PRs, it won't exist) + if [ -f "./pr/pr.txt" ]; then + PR=$(cat ./pr/pr.txt) + MERGED=$(cat ./pr/merged.txt) + ACTION=$(cat ./pr/action.txt) + else + # For merged PRs, we can't determine which PR was merged + # so we'll skip this run since we can't clean up the specific preview + echo "PR artifact not found - this is likely a merged PR" + echo "Cannot determine PR number for cleanup - skipping" + exit 0 + fi + + echo "PR_NO=${PR}" >> $GITHUB_ENV + echo "MERGE_STATUS=${MERGED}" >> $GITHUB_ENV + echo "PR_ACTION=${ACTION}" >> $GITHUB_ENV + echo "REVIEW_DIR=review/" >> $GITHUB_ENV + echo "PR_REVIEW_DIR=review/pr-${PR}" >> $GITHUB_ENV + + # Remove the pr artifact directory so that it does not + # appear in listings or confuse git with untracked files. + rm -rf ./pr + + # Permutations: + # - REMOVED: PR was merged, update `main` directory; PR_ACTION is closed, need to delete review directory. + # - PR was updated, PR_ACTION is !closed, need to delete review directory and update it. + # - PR was closed (regardless of merge), PR_ACTION is closed, need to delete review directory. + + # If this PR is still open, store HTML in a review directory. + - name: Handle HTML review directory for open PRs and updates to PRs + if: env.MERGE_STATUS == 'false' && env.PR_ACTION != 'closed' + run: | + rm -rf "${{ env.PR_REVIEW_DIR }}" 2>/dev/null || true + if [ ! -d "${{ env.REVIEW_DIR }}" ]; then + mkdir "${{ env.REVIEW_DIR }}" + fi + mkdir -p "${{ env.PR_REVIEW_DIR }}" + cp -r ./generated-html/latest/. "${{ env.PR_REVIEW_DIR }}/" + git add "${{ env.PR_REVIEW_DIR }}" + # If the PR was closed, merged or not, delete review directory. + - name: Delete HTML review directory for closed PRs + if: env.PR_ACTION == 'closed' + run: | + if [ -d ./generated-html/ ]; then + rm -rf ./generated-html/ 2>/dev/null + fi + if [ -d "${{ env.PR_REVIEW_DIR }}" ]; then + git rm -rf "${{ env.PR_REVIEW_DIR }}" + fi + - name: Commit changes to the GitHub Pages branch + run: | + git status + if git commit -m 'Pushing changes to GitHub Pages.'; then + git push -f + else + echo "Nothing changed." + fi + - name: Check for existing documentation review comment + run: | + # Get PR number from environment, if not set, skip this step + if [ -z "${{ env.PR_NO }}" ]; then + echo "No PR number available, skipping comment check" + echo "COMMENT_EXISTS=false" >> $GITHUB_ENV + exit 0 + fi + + result=$(gh pr view ${{ env.PR_NO }} --json comments -q 'any(.comments[].body; contains("Documentation preview"))') + echo "COMMENT_EXISTS=${result}" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Add HTML review URL comment to a newly opened PR + if: env.MERGE_STATUS == 'false' && env.COMMENT_EXISTS == 'false' && env.PR_NO != '' + env: + URL: ${{ needs.get-gh-pages-url.outputs.url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + echo -e "## Documentation preview" > body + echo -e "" >> body + echo -e "<${{ env.URL }}${{ env.PR_REVIEW_DIR }}>" >> body + cat body + gh pr comment ${{ env.PR_NO }} --body-file body \ No newline at end of file diff --git a/.github/workflows/docs-publish.yaml b/.github/workflows/docs-publish.yaml index 11de40d0..ad40ff7d 100644 --- a/.github/workflows/docs-publish.yaml +++ b/.github/workflows/docs-publish.yaml @@ -11,13 +11,77 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Build HTML run: make gen-docs - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 + - name: Upload HTML + uses: actions/upload-artifact@v4 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: _build/docs/nvidia_network_operator/latest + name: html-build-artifact + path: _build/docs/nvidia_network_operator/latest + if-no-files-found: error + retention-days: 1 + + # Deploy to GitHub Pages + deploy: + needs: [build-and-deploy] + runs-on: ubuntu-latest + steps: + - name: Checkout gh-pages branch + uses: actions/checkout@v4 + with: + ref: gh-pages + + - name: Initialize Git configuration + run: | + git config user.name docs-publish + git config user.email do-not-send-@github.com + + - name: Download artifacts to temp directory + uses: actions/download-artifact@v4 + with: + name: html-build-artifact + path: /tmp/new-docs + + - name: Copy HTML files (preserving review directories) + run: | + # Remove current files except review directories + find . -maxdepth 1 -not -name '.' -not -name '..' -not -name 'review' -not -name '.git' -not -name '.nojekyll' -exec rm -rf {} \; 2>/dev/null || true + + # Copy new documentation files from temp directory + cp -r /tmp/new-docs/* . 2>/dev/null || true + + # Clean up temp directory + rm -rf /tmp/new-docs + + # List what we have now + echo "Files after deployment:" + ls -la + + # Add all files to git + git add . + + - name: Check or create dot-no-jekyll file + run: | + if [ -f ".nojekyll" ]; then + echo "The .nojekyll file already exists." + else + touch .nojekyll + git add .nojekyll + fi + + - name: Commit and push changes + run: | + git status + if git commit -m 'Deploy documentation to GitHub Pages.'; then + git push + else + echo "Nothing changed." + fi + + # Clean up stale PR reviews + cleanup-stale-reviews: + needs: [deploy] + uses: ./.github/workflows/docs-remove-stale-reviews.yaml diff --git a/.github/workflows/docs-remove-stale-reviews.yaml b/.github/workflows/docs-remove-stale-reviews.yaml new file mode 100644 index 00000000..7f207658 --- /dev/null +++ b/.github/workflows/docs-remove-stale-reviews.yaml @@ -0,0 +1,47 @@ +name: docs-remove-stale-reviews + +on: + workflow_call: + workflow_dispatch: + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + remove: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: "gh-pages" + - name: Initialize Git configuration + run: | + git config user.name docs-remove-stale-reviews + git config user.email do-not-send-@github.com + - name: List up to 200 open PRs + run: | + gh pr list -L 200 -s open + - name: Remove stale reviews + shell: bash + run: | + if [ ! -d "review" ]; then + echo "No reviews exist." + exit 0 + fi + open=$(gh pr list -L 200 -s open --json 'number' -q '.[]|.pr = "pr-\(.number)"|.pr') + reviews=$(ls review/) + for i in ${reviews}; do + echo "Checking if ${i} is still open" + if ! [[ ${open[*]} =~ "${i}" ]]; then + echo "Removing review/${i}" + git rm -rf "review/${i}" + fi + done + - name: Commit changes + run: | + if git commit -m 'Removing stale reviews from GitHub Pages.'; then + git push -f + else + echo "Nothing changed." + fi