Repository: twisted/incremental (language: python)

Issue:
apidocs build is failing to publish
The apidocs build is [failing to publish](https://github.com/twisted/incremental/actions/runs/10100878412/job/27933238014) to GitHub pages and has been for [at least 6 months](https://github.com/twisted/incremental/actions/runs/7729103510/job/21071501327).


Discussion / hints:
(The API hasn't changed so this is not urgent.)
The issue is due to GitHub Actions workflow permissions.

The token on has

```
GITHUB_TOKEN Permissions
  Contents: read
  Metadata: read
```

For the publish job we also need to add `content: write`

Fix patch:
diff --git a/.github/actions/publish-docs/action.yml b/.github/actions/publish-docs/action.yml
new file mode 100644
index 0000000..39416a5
--- /dev/null
+++ b/.github/actions/publish-docs/action.yml
@@ -0,0 +1,29 @@
+name: Publish API docs
+
+outputs:
+  docs_url:
+    description: "Deployed URL"
+    value: ${{ steps.deployment.outputs.page_url }}/docs/
+
+runs:
+  using: "composite"
+
+  steps:
+
+  - name: Prepare GitHub Pages
+    run: |
+      mkdir website
+      cat >website/index.html <<!
+        <DOCTYPE html>
+        <meta http-equiv="refresh" content="0;URL=./docs/">
+        <a href="./docs/">Click here if not redirected</a>
+      !
+      mv apidocs website/docs
+    shell: bash
+
+  - uses: actions/upload-pages-artifact@v3
+    with:
+      path: website
+
+  - uses: actions/deploy-pages@v4
+    id: deployment


Test patch:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index b83c179..1a3e21b 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -17,6 +17,9 @@ on:
 
 permissions:
   contents: read
+  # Required to publish to Pages:
+  pages: write
+  id-token: write
 
 
 defaults:
@@ -82,22 +85,9 @@ jobs:
         # GitHub Actions VM have 2 CPUs.
         tox --parallel 2 --installpkg dist/*.whl
 
-    - name: Prepare GitHub Pages
-      if: contains(matrix['tox-env'], 'apidocs')
-      run: |
-        mkdir website
-        touch website/index.html
-        mv apidocs website/docs
-
-    - name: Publish documentation for push on trunk
-      # Since we don't have a separate job for apidocs gh-pages updating
-      # hijack the normal apidoc test and publish the resulting files.
-      if: contains(matrix['tox-env'], 'apidocs') && github.event_name == 'push'
-      uses: peaceiris/actions-gh-pages@v3
-      with:
-        github_token: ${{ secrets.GITHUB_TOKEN }}
-        commit_message: Publish docs for ${{ github.sha }}
-        publish_dir: ./website
+    - name: Publish API docs
+      if: contains(matrix['tox-env'], 'apidocs') && github.ref == 'refs/heads/trunk'
+      uses: ./.github/actions/publish-docs
 
     - name: Prepare coverage results
       if: ${{ !cancelled() && !matrix.skip-coverage }}