From 1b996aeef2cb2ea702c93973fd16cbb300296932 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 08:12:33 +0000 Subject: [PATCH 1/8] feat: add netlify-preview job to sphinxbuild workflow Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/12ab3238-1214-4ff1-b0cf-67836a1abc12 Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 84 ++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index 150e989d9d0..f4669252341 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -503,8 +503,86 @@ jobs: env: GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }} + # ============================================================================ + # NETLIFY PREVIEW + # ============================================================================ + # This job deploys a per-PR documentation preview to Netlify. + # It only runs on pull_request events (never on push/merge). + # + # The stable preview URL for PR #N is: + # https://pr---.netlify.app/ + # + # Required repository secrets: + # NETLIFY_AUTH_TOKEN – Netlify personal access token + # NETLIFY_SITE_ID – ID of the target Netlify site + # ============================================================================ + netlify-preview: + name: Deploy preview to Netlify + needs: stage-and-check + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + + permissions: + contents: read + pull-requests: write + + steps: + - name: Restore staged artifacts from cache + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + with: + path: stage/ + key: staged-docs-${{ github.sha }} + fail-on-cache-miss: true + + - name: Assemble Netlify deploy directory + run: | + branch="${{ needs.stage-and-check.outputs.branch_name }}" + mkdir -p netlify-deploy + + # Flatten stage/// into netlify-deploy// + for manual_dir in "stage/${branch}/"/*/; do + if [ -d "$manual_dir" ]; then + manual_name="$(basename "$manual_dir")" + cp -r "$manual_dir" "netlify-deploy/${manual_name}" + fi + done + + # Create a root index linking to each manual + cat > netlify-deploy/index.html << 'ENDHTML' + + + + + + Nextcloud Documentation Preview + + +

Nextcloud Documentation Preview

+ + + + ENDHTML + + - name: Deploy to Netlify + uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0 + with: + publish-dir: './netlify-deploy' + production-deploy: false + github-token: ${{ secrets.GITHUB_TOKEN }} + deploy-message: "Preview for PR #${{ github.event.number }}" + alias: pr-${{ github.event.number }} + enable-pull-request-comment: true + enable-commit-comment: false + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + summary: - needs: [build, stage-and-check, deploy] + needs: [build, stage-and-check, deploy, netlify-preview] runs-on: ubuntu-latest-low if: always() @@ -520,8 +598,10 @@ jobs: then echo "This workflow ran for a pull request. We need build and stage-and-check to succeed, but deploy will be skipped" if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'skipped' }}; then exit 1; fi + if ${{ needs.netlify-preview.result != 'success' && needs.netlify-preview.result != 'skipped' }}; then exit 1; fi else echo "This workflow ran for a push. We need all jobs to succeed, including deploy" if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi + if ${{ needs.netlify-preview.result != 'skipped' }}; then exit 1; fi fi - + From 1d35c340acdc2d5e89983698889f1bedd1df800d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 08:27:31 +0000 Subject: [PATCH 2/8] feat: deploy full merged documentation to Netlify preview Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/131cd607-27ec-4bd2-abed-7ede744acad9 Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 99 +++++++++++++++++++------------ 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index f4669252341..c787d9dd42a 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -380,6 +380,64 @@ jobs: path: stage/ key: staged-docs-${{ github.sha }} + # ======================================================================== + # ASSEMBLE FULL NETLIFY PREVIEW CONTENT + # ======================================================================== + # Combine the existing gh-pages content (all versions) with the newly + # built artifacts so the Netlify preview shows the complete site. + # + # Structure of the merged output (netlify-full/): + # netlify-full/ + # ├── index.html ← generated version listing + # ├── latest/ ← from gh-pages or newly built + # ├── stable/ ← from gh-pages or newly built + # └── / ← older versions from gh-pages + # ======================================================================== + - name: Assemble full documentation for Netlify preview + run: | + branch="${{ steps.branch.outputs.branch_name }}" + additional="${{ steps.branch.outputs.additional_deployment }}" + + mkdir -p netlify-full + + # Start with the full existing gh-pages content as the base + if [ -d "validation-context/server" ]; then + cp -r validation-context/server/. netlify-full/ + fi + + # Override the current branch's folder with the freshly built content + rm -rf "netlify-full/${branch}" + cp -r "stage/${branch}" "netlify-full/${branch}" + + # For the highest stable branch, also override its versioned folder + if [ -n "${additional}" ]; then + rm -rf "netlify-full/${additional}" + cp -r "stage/${branch}" "netlify-full/${additional}" + fi + + # Generate a root index.html listing all version folders + echo '' > netlify-full/index.html + echo '' >> netlify-full/index.html + echo '' >> netlify-full/index.html + echo '' >> netlify-full/index.html + echo 'Nextcloud Documentation Preview' >> netlify-full/index.html + echo '' >> netlify-full/index.html + echo '

Nextcloud Documentation Preview

    ' >> netlify-full/index.html + for version_dir in netlify-full/*/; do + version="$(basename "$version_dir")" + echo "
  • ${version}
  • " >> netlify-full/index.html + done + echo '
' >> netlify-full/index.html + + echo "Full Netlify deploy structure:" + find netlify-full -maxdepth 2 -type d + + - name: Cache full documentation for Netlify preview + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + with: + path: netlify-full/ + key: netlify-full-docs-${{ github.sha }} + # ============================================================================ # DEPLOY # ============================================================================ @@ -527,50 +585,17 @@ jobs: pull-requests: write steps: - - name: Restore staged artifacts from cache + - name: Restore full documentation from cache uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: - path: stage/ - key: staged-docs-${{ github.sha }} + path: netlify-full/ + key: netlify-full-docs-${{ github.sha }} fail-on-cache-miss: true - - name: Assemble Netlify deploy directory - run: | - branch="${{ needs.stage-and-check.outputs.branch_name }}" - mkdir -p netlify-deploy - - # Flatten stage/// into netlify-deploy// - for manual_dir in "stage/${branch}/"/*/; do - if [ -d "$manual_dir" ]; then - manual_name="$(basename "$manual_dir")" - cp -r "$manual_dir" "netlify-deploy/${manual_name}" - fi - done - - # Create a root index linking to each manual - cat > netlify-deploy/index.html << 'ENDHTML' - - - - - - Nextcloud Documentation Preview - - -

Nextcloud Documentation Preview

- - - - ENDHTML - - name: Deploy to Netlify uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0 with: - publish-dir: './netlify-deploy' + publish-dir: './netlify-full' production-deploy: false github-token: ${{ secrets.GITHUB_TOKEN }} deploy-message: "Preview for PR #${{ github.event.number }}" From aec4ec00c55768a7465bc21fbcb39e23cad71473 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:31:19 +0000 Subject: [PATCH 3/8] Initial plan From 0bdd6b8017ac9733b17be1501adf269afa1b658c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:35:37 +0000 Subject: [PATCH 4/8] refactor: move Netlify preview into deploy job, avoiding 2GB cache round-trip Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/1f6603ff-c52e-4e41-bf59-d23447600bfb Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 125 +++++------------------------- 1 file changed, 20 insertions(+), 105 deletions(-) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index c787d9dd42a..fa6f2516058 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -380,79 +380,25 @@ jobs: path: stage/ key: staged-docs-${{ github.sha }} - # ======================================================================== - # ASSEMBLE FULL NETLIFY PREVIEW CONTENT - # ======================================================================== - # Combine the existing gh-pages content (all versions) with the newly - # built artifacts so the Netlify preview shows the complete site. - # - # Structure of the merged output (netlify-full/): - # netlify-full/ - # ├── index.html ← generated version listing - # ├── latest/ ← from gh-pages or newly built - # ├── stable/ ← from gh-pages or newly built - # └── / ← older versions from gh-pages - # ======================================================================== - - name: Assemble full documentation for Netlify preview - run: | - branch="${{ steps.branch.outputs.branch_name }}" - additional="${{ steps.branch.outputs.additional_deployment }}" - - mkdir -p netlify-full - - # Start with the full existing gh-pages content as the base - if [ -d "validation-context/server" ]; then - cp -r validation-context/server/. netlify-full/ - fi - - # Override the current branch's folder with the freshly built content - rm -rf "netlify-full/${branch}" - cp -r "stage/${branch}" "netlify-full/${branch}" - - # For the highest stable branch, also override its versioned folder - if [ -n "${additional}" ]; then - rm -rf "netlify-full/${additional}" - cp -r "stage/${branch}" "netlify-full/${additional}" - fi - - # Generate a root index.html listing all version folders - echo '' > netlify-full/index.html - echo '' >> netlify-full/index.html - echo '' >> netlify-full/index.html - echo '' >> netlify-full/index.html - echo 'Nextcloud Documentation Preview' >> netlify-full/index.html - echo '' >> netlify-full/index.html - echo '

Nextcloud Documentation Preview

    ' >> netlify-full/index.html - for version_dir in netlify-full/*/; do - version="$(basename "$version_dir")" - echo "
  • ${version}
  • " >> netlify-full/index.html - done - echo '
' >> netlify-full/index.html - - echo "Full Netlify deploy structure:" - find netlify-full -maxdepth 2 -type d - - - name: Cache full documentation for Netlify preview - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - path: netlify-full/ - key: netlify-full-docs-${{ github.sha }} - # ============================================================================ # DEPLOY # ============================================================================ - # This job is responsible for: - # 1. Downloading the staged artifacts from stage-and-check - # 2. Applying them to the gh-pages branch - # 3. Creating a pull request for the deployment + # This job handles two scenarios: + # + # Push to master/stable: + # Applies the staged artifacts to the gh-pages branch and creates a PR. + # + # Pull request: + # Applies the staged artifacts on top of gh-pages content and deploys the + # result to a Netlify preview (no gh-pages PR is created). # - # This job ONLY runs on pushes (not on pull requests), since we only want - # to deploy when code is merged to master or a stable branch. + # Required repository secrets for Netlify previews: + # NETLIFY_AUTH_TOKEN – Netlify personal access token + # NETLIFY_SITE_ID – ID of the target Netlify site # ============================================================================ deploy: - name: Deploy documentation for gh-pages + name: Deploy documentation needs: stage-and-check - if: github.event_name == 'push' runs-on: ubuntu-latest permissions: @@ -533,12 +479,13 @@ jobs: # Remove the stage/ directory BEFORE creating the PR so it doesn't get committed - name: Clean up staging cache before commit + if: github.event_name == 'push' run: rm -rf stage/ - name: Create Pull Request for documentation deployment uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 id: cpr - if: steps.apply.outputs.has_changes == 'true' + if: github.event_name == 'push' && steps.apply.outputs.has_changes == 'true' with: token: ${{ secrets.COMMAND_BOT_PAT }} commit-message: "chore: update documentation for `${{ needs.stage-and-check.outputs.branch_name }}`" @@ -557,45 +504,15 @@ jobs: - name: Enable Pull Request Automerge run: gh pr merge --merge --auto "${{ steps.cpr.outputs.pull-request-number }}" - if: steps.cpr.outputs.pull-request-number != '' + if: github.event_name == 'push' && steps.cpr.outputs.pull-request-number != '' env: GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }} - # ============================================================================ - # NETLIFY PREVIEW - # ============================================================================ - # This job deploys a per-PR documentation preview to Netlify. - # It only runs on pull_request events (never on push/merge). - # - # The stable preview URL for PR #N is: - # https://pr---.netlify.app/ - # - # Required repository secrets: - # NETLIFY_AUTH_TOKEN – Netlify personal access token - # NETLIFY_SITE_ID – ID of the target Netlify site - # ============================================================================ - netlify-preview: - name: Deploy preview to Netlify - needs: stage-and-check - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - - permissions: - contents: read - pull-requests: write - - steps: - - name: Restore full documentation from cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - path: netlify-full/ - key: netlify-full-docs-${{ github.sha }} - fail-on-cache-miss: true - - name: Deploy to Netlify uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0 + if: github.event_name == 'pull_request' with: - publish-dir: './netlify-full' + publish-dir: './server' production-deploy: false github-token: ${{ secrets.GITHUB_TOKEN }} deploy-message: "Preview for PR #${{ github.event.number }}" @@ -607,7 +524,7 @@ jobs: NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} summary: - needs: [build, stage-and-check, deploy, netlify-preview] + needs: [build, stage-and-check, deploy] runs-on: ubuntu-latest-low if: always() @@ -621,12 +538,10 @@ jobs: run: | if ${{ github.event_name == 'pull_request' }} then - echo "This workflow ran for a pull request. We need build and stage-and-check to succeed, but deploy will be skipped" - if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'skipped' }}; then exit 1; fi - if ${{ needs.netlify-preview.result != 'success' && needs.netlify-preview.result != 'skipped' }}; then exit 1; fi + echo "This workflow ran for a pull request. We need build, stage-and-check, and deploy (Netlify preview) to succeed" + if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi else echo "This workflow ran for a push. We need all jobs to succeed, including deploy" if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi - if ${{ needs.netlify-preview.result != 'skipped' }}; then exit 1; fi fi From b3fa78823c433d5a9a5835f8d334be9f58c8c1dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:29:36 +0000 Subject: [PATCH 5/8] refactor: use netlify-cli directly, preview current branch only with simple index.html Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/af4f573e-5b1e-4d54-bae0-dbfec917b30c Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 159 ++++++++++++++++++++++++------ 1 file changed, 129 insertions(+), 30 deletions(-) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index fa6f2516058..29ab9fef660 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -383,22 +383,18 @@ jobs: # ============================================================================ # DEPLOY # ============================================================================ - # This job handles two scenarios: - # - # Push to master/stable: - # Applies the staged artifacts to the gh-pages branch and creates a PR. - # - # Pull request: - # Applies the staged artifacts on top of gh-pages content and deploys the - # result to a Netlify preview (no gh-pages PR is created). + # This job is responsible for: + # 1. Downloading the staged artifacts from stage-and-check + # 2. Applying them to the gh-pages branch + # 3. Creating a pull request for the deployment # - # Required repository secrets for Netlify previews: - # NETLIFY_AUTH_TOKEN – Netlify personal access token - # NETLIFY_SITE_ID – ID of the target Netlify site + # This job ONLY runs on pushes (not on pull requests), since we only want + # to deploy when code is merged to master or a stable branch. # ============================================================================ deploy: - name: Deploy documentation + name: Deploy documentation for gh-pages needs: stage-and-check + if: github.event_name == 'push' runs-on: ubuntu-latest permissions: @@ -479,13 +475,12 @@ jobs: # Remove the stage/ directory BEFORE creating the PR so it doesn't get committed - name: Clean up staging cache before commit - if: github.event_name == 'push' run: rm -rf stage/ - name: Create Pull Request for documentation deployment uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 id: cpr - if: github.event_name == 'push' && steps.apply.outputs.has_changes == 'true' + if: steps.apply.outputs.has_changes == 'true' with: token: ${{ secrets.COMMAND_BOT_PAT }} commit-message: "chore: update documentation for `${{ needs.stage-and-check.outputs.branch_name }}`" @@ -504,27 +499,129 @@ jobs: - name: Enable Pull Request Automerge run: gh pr merge --merge --auto "${{ steps.cpr.outputs.pull-request-number }}" - if: github.event_name == 'push' && steps.cpr.outputs.pull-request-number != '' + if: steps.cpr.outputs.pull-request-number != '' env: GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }} + # ============================================================================ + # NETLIFY PREVIEW + # ============================================================================ + # This job deploys a per-PR documentation preview to Netlify. + # It only runs on pull_request events (never on push/merge). + # + # Only the artifacts built for the current branch are deployed, with a simple + # index.html listing the available manuals. + # + # The stable preview URL for PR #N is: + # https://pr---.netlify.app/ + # + # Required repository secrets: + # NETLIFY_AUTH_TOKEN – Netlify personal access token + # NETLIFY_SITE_ID – ID of the target Netlify site + # ============================================================================ + netlify-preview: + name: Deploy preview to Netlify + needs: stage-and-check + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + + permissions: + contents: read + pull-requests: write + + steps: + - name: Restore staged artifacts from cache + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + with: + path: stage/ + key: staged-docs-${{ github.sha }} + fail-on-cache-miss: true + + - name: Generate index.html for preview + run: | + branch="${{ needs.stage-and-check.outputs.branch_name }}" + preview_dir="stage/${branch}" + + cat > "${preview_dir}/index.html" <<'EOF' + + + + + + Nextcloud Documentation Preview + + +

Nextcloud Documentation Preview

+
    + EOF + + for manual_dir in "${preview_dir}"/*/; do + [ -d "$manual_dir" ] || continue + manual="$(basename "$manual_dir")" + echo "
  • ${manual}
  • " >> "${preview_dir}/index.html" + done + + cat >> "${preview_dir}/index.html" <<'EOF' +
+ + + EOF + + - name: Install Netlify CLI + run: npm install -g netlify-cli + - name: Deploy to Netlify - uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0 - if: github.event_name == 'pull_request' + id: netlify + run: | + branch="${{ needs.stage-and-check.outputs.branch_name }}" + output=$(netlify deploy \ + --dir="stage/${branch}" \ + --site="${{ secrets.NETLIFY_SITE_ID }}" \ + --auth="${{ secrets.NETLIFY_AUTH_TOKEN }}" \ + --alias="pr-${{ github.event.number }}" \ + --message="Preview for PR #${{ github.event.number }}" \ + --json) + deploy_url=$(echo "$output" | jq -r '.deploy_url // .url') + if [ -z "$deploy_url" ] || [ "$deploy_url" = "null" ]; then + echo "Failed to get deploy URL from Netlify output:" >&2 + echo "$output" >&2 + exit 1 + fi + echo "deploy_url=${deploy_url}" >> $GITHUB_OUTPUT + + - name: Comment preview URL on PR + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: - publish-dir: './server' - production-deploy: false - github-token: ${{ secrets.GITHUB_TOKEN }} - deploy-message: "Preview for PR #${{ github.event.number }}" - alias: pr-${{ github.event.number }} - enable-pull-request-comment: true - enable-commit-comment: false - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + script: | + const deployUrl = '${{ steps.netlify.outputs.deploy_url }}'; + const marker = ''; + const body = `${marker}\n:rocket: **Netlify preview deployed:** ${deployUrl}`; + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const existing = comments.find(c => c.body.includes(marker)); + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + } summary: - needs: [build, stage-and-check, deploy] + needs: [build, stage-and-check, deploy, netlify-preview] runs-on: ubuntu-latest-low if: always() @@ -538,10 +635,12 @@ jobs: run: | if ${{ github.event_name == 'pull_request' }} then - echo "This workflow ran for a pull request. We need build, stage-and-check, and deploy (Netlify preview) to succeed" - if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi + echo "This workflow ran for a pull request. We need build and stage-and-check to succeed, but deploy will be skipped" + if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'skipped' }}; then exit 1; fi + if ${{ needs.netlify-preview.result != 'success' && needs.netlify-preview.result != 'skipped' }}; then exit 1; fi else echo "This workflow ran for a push. We need all jobs to succeed, including deploy" if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi + if ${{ needs.netlify-preview.result != 'skipped' }}; then exit 1; fi fi From 937510e352a55330162d0e0a294ce891ef82c132 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:57:23 +0000 Subject: [PATCH 6/8] refactor: merge netlify preview into deploy job, make it optional Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/fd9abf90-6eb8-4986-ae43-4ce3c769083e Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 109 ++++++++---------------------- 1 file changed, 30 insertions(+), 79 deletions(-) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index 29ab9fef660..1d31866e66d 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -383,18 +383,20 @@ jobs: # ============================================================================ # DEPLOY # ============================================================================ - # This job is responsible for: - # 1. Downloading the staged artifacts from stage-and-check - # 2. Applying them to the gh-pages branch - # 3. Creating a pull request for the deployment + # This job handles two cases based on the event type: + # + # push → Apply staged artifacts to gh-pages and open a PR for the update. + # + # pull_request → Check out gh-pages, overlay the new artifacts, and deploy + # the full server/ tree to Netlify as a preview (optional – + # Netlify failure does NOT block the PR). # - # This job ONLY runs on pushes (not on pull requests), since we only want - # to deploy when code is merged to master or a stable branch. + # In both cases the job checks out gh-pages first, so the full existing + # documentation is available before the new artifacts are applied. # ============================================================================ deploy: name: Deploy documentation for gh-pages needs: stage-and-check - if: github.event_name == 'push' runs-on: ubuntu-latest permissions: @@ -480,7 +482,7 @@ jobs: - name: Create Pull Request for documentation deployment uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 id: cpr - if: steps.apply.outputs.has_changes == 'true' + if: steps.apply.outputs.has_changes == 'true' && github.event_name == 'push' with: token: ${{ secrets.COMMAND_BOT_PAT }} commit-message: "chore: update documentation for `${{ needs.stage-and-check.outputs.branch_name }}`" @@ -503,79 +505,26 @@ jobs: env: GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }} - # ============================================================================ - # NETLIFY PREVIEW - # ============================================================================ - # This job deploys a per-PR documentation preview to Netlify. - # It only runs on pull_request events (never on push/merge). - # - # Only the artifacts built for the current branch are deployed, with a simple - # index.html listing the available manuals. - # - # The stable preview URL for PR #N is: - # https://pr---.netlify.app/ - # - # Required repository secrets: - # NETLIFY_AUTH_TOKEN – Netlify personal access token - # NETLIFY_SITE_ID – ID of the target Netlify site - # ============================================================================ - netlify-preview: - name: Deploy preview to Netlify - needs: stage-and-check - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - - permissions: - contents: read - pull-requests: write - - steps: - - name: Restore staged artifacts from cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - path: stage/ - key: staged-docs-${{ github.sha }} - fail-on-cache-miss: true - - - name: Generate index.html for preview - run: | - branch="${{ needs.stage-and-check.outputs.branch_name }}" - preview_dir="stage/${branch}" - - cat > "${preview_dir}/index.html" <<'EOF' - - - - - - Nextcloud Documentation Preview - - -

Nextcloud Documentation Preview

-
    - EOF - - for manual_dir in "${preview_dir}"/*/; do - [ -d "$manual_dir" ] || continue - manual="$(basename "$manual_dir")" - echo "
  • ${manual}
  • " >> "${preview_dir}/index.html" - done - - cat >> "${preview_dir}/index.html" <<'EOF' -
- - - EOF - + # ======================================================================== + # NETLIFY PREVIEW (pull_request events only) + # ======================================================================== + # At this point the working directory is the gh-pages checkout with the + # newly staged artifacts already applied, so server/ is a complete, + # up-to-date snapshot of the full documentation site. + # Netlify failure is non-fatal – the step uses continue-on-error so it + # does not block the PR. + # ======================================================================== - name: Install Netlify CLI + if: github.event_name == 'pull_request' run: npm install -g netlify-cli - name: Deploy to Netlify id: netlify + if: github.event_name == 'pull_request' + continue-on-error: true run: | - branch="${{ needs.stage-and-check.outputs.branch_name }}" output=$(netlify deploy \ - --dir="stage/${branch}" \ + --dir=server \ --site="${{ secrets.NETLIFY_SITE_ID }}" \ --auth="${{ secrets.NETLIFY_AUTH_TOKEN }}" \ --alias="pr-${{ github.event.number }}" \ @@ -590,6 +539,7 @@ jobs: echo "deploy_url=${deploy_url}" >> $GITHUB_OUTPUT - name: Comment preview URL on PR + if: github.event_name == 'pull_request' && steps.netlify.outputs.deploy_url != '' uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | @@ -620,8 +570,11 @@ jobs: }); } + # ============================================================================ + # SUMMARY + # ============================================================================ summary: - needs: [build, stage-and-check, deploy, netlify-preview] + needs: [build, stage-and-check, deploy] runs-on: ubuntu-latest-low if: always() @@ -635,12 +588,10 @@ jobs: run: | if ${{ github.event_name == 'pull_request' }} then - echo "This workflow ran for a pull request. We need build and stage-and-check to succeed, but deploy will be skipped" - if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'skipped' }}; then exit 1; fi - if ${{ needs.netlify-preview.result != 'success' && needs.netlify-preview.result != 'skipped' }}; then exit 1; fi + echo "This workflow ran for a pull request. We need build, stage-and-check and deploy to succeed" + if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi else echo "This workflow ran for a push. We need all jobs to succeed, including deploy" if ${{ needs.build.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi - if ${{ needs.netlify-preview.result != 'skipped' }}; then exit 1; fi fi From 79c0629150c04be87fd18fb682a87f7f3f6f5550 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:19:39 +0000 Subject: [PATCH 7/8] feat: add index.html generation with user_manual/en redirect for Netlify preview Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/dc4b0ad9-feda-46fe-ab00-99b1703bcdb0 Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index 1d31866e66d..a976e91bdf9 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -518,6 +518,52 @@ jobs: if: github.event_name == 'pull_request' run: npm install -g netlify-cli + - name: Generate index.html for preview + if: github.event_name == 'pull_request' + run: | + # Build a root index listing all top-level version folders + cat > server/index.html <<'INDEXEOF' + + + + + + Nextcloud Documentation Preview + + +

Nextcloud Documentation Preview

+
    + INDEXEOF + + for version_dir in server/*/; do + [ -d "$version_dir" ] || continue + version="$(basename "$version_dir")" + echo "
  • ${version}
  • " >> server/index.html + done + + cat >> server/index.html <<'INDEXEOF' +
+ + + INDEXEOF + + # For user_manual, create a redirect from user_manual/index.html → user_manual/en/ + if [ -d server/user_manual ]; then + cat > server/user_manual/index.html <<'REDIRECTEOF' + + + + + + Redirecting… + + +

Redirecting to user_manual/en/

+ + + REDIRECTEOF + fi + - name: Deploy to Netlify id: netlify if: github.event_name == 'pull_request' From c61e9a6ff68d4a2cdf57b580ad1ca36d7114e74b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:25:10 +0000 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20remove=20redundant=20user=5Fmanual/i?= =?UTF-8?q?ndex.html=20generation=20=E2=80=94=20already=20exists=20in=20gh?= =?UTF-8?q?-pages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/nextcloud/documentation/sessions/a6ca17cd-be62-49ee-91e1-82877e91b614 Co-authored-by: skjnldsv <14975046+skjnldsv@users.noreply.github.com> --- .github/workflows/sphinxbuild.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/.github/workflows/sphinxbuild.yml b/.github/workflows/sphinxbuild.yml index a976e91bdf9..dd00ff6d749 100644 --- a/.github/workflows/sphinxbuild.yml +++ b/.github/workflows/sphinxbuild.yml @@ -547,23 +547,6 @@ jobs: INDEXEOF - # For user_manual, create a redirect from user_manual/index.html → user_manual/en/ - if [ -d server/user_manual ]; then - cat > server/user_manual/index.html <<'REDIRECTEOF' - - - - - - Redirecting… - - -

Redirecting to user_manual/en/

- - - REDIRECTEOF - fi - - name: Deploy to Netlify id: netlify if: github.event_name == 'pull_request'