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 1/3] 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 2/3] 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 - - 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 3/3] 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