Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 193 additions & 5 deletions .github/workflows/sphinxbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ jobs:
args: |
--root-dir "$(pwd)/stage"
--offline --no-progress
--remap "https://docs.nextcloud.com/server/latest/ file://$(pwd)/stage/${{ needs.stage-and-check.outputs.branch_name }}/"
--remap "https://docs.nextcloud.com/server/ file://$(pwd)/stage/"
--exclude 'go\.php' --exclude 'mailto:' --exclude-path '.*/404\.html' --exclude-path '.*/_static/.*'
--exclude "/user_manual/" --include "/user_manual/en/"
Expand Down Expand Up @@ -554,8 +555,195 @@ jobs:
env:
GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}

# ============================================================================
# NETLIFY PREVIEW
# ============================================================================
# Runs only on pull requests, in parallel with link-check.
# Downloads the staged-docs artifact (already produced by stage-and-check)
# and deploys a preview to Netlify under a stable per-PR alias.
#
# Required repository secrets:
# NETLIFY_AUTH_TOKEN – personal-access token for the Netlify account
# NETLIFY_SITE_ID – the target Netlify site ID
#
# Failure is non-fatal: the step uses continue-on-error so a missing secret
# or a Netlify outage does not block the pull request.
# ============================================================================
netlify-preview:
name: Deploy Netlify preview
needs: stage-and-check
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest

permissions:
contents: read
pull-requests: write

steps:
- name: Download staged artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: staged-docs
path: stage/

- name: Assemble Netlify deploy directory
run: |
branch="${{ needs.stage-and-check.outputs.branch_name }}"
mkdir -p netlify-deploy

# Copy each manual directory into the deploy directory
for manual in admin_manual developer_manual user_manual; do
if [ -d "stage/${branch}/${manual}" ]; then
cp -r "stage/${branch}/${manual}" "netlify-deploy/${manual}"
fi
done

# PDF files (kept at root of deploy dir)
find "stage/${branch}" -maxdepth 1 -name "*.pdf" -exec cp {} netlify-deploy/ \;

# Minimal root index linking to the deployed content
cat > netlify-deploy/index.html <<'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nextcloud Documentation Preview</title>
<style>body{font-family:sans-serif;max-width:600px;margin:2rem auto}ul{line-height:2}</style>
</head>
<body>
<h1>Nextcloud Documentation Preview</h1>
<ul>
<li><a href="admin_manual/">Administration Manual</a></li>
<li><a href="developer_manual/">Developer Manual</a></li>
<li><a href="user_manual/en/">User Manual (English)</a></li>
<li><a href="Nextcloud_User_Manual.pdf">User Manual PDF</a></li>
<li><a href="Nextcloud_Server_Administration_Manual.pdf">Administration Manual PDF</a></li>
</ul>
</body>
</html>
EOF

- name: List deploy directory tree
run: find netlify-deploy -print | sort

- name: Install Netlify CLI
run: npm install -g netlify-cli

- name: Deploy to Netlify
id: netlify
continue-on-error: true
run: |
set +e
output=$(netlify deploy \
--dir=netlify-deploy \
--site="${{ secrets.NETLIFY_SITE_ID }}" \
--auth="${{ secrets.NETLIFY_AUTH_TOKEN }}" \
--alias="pr-${{ github.event.pull_request.number }}" \
--message="Preview for PR #${{ github.event.pull_request.number }}" 2>&1)
exit_code=$?
echo "$output"
# Strip ANSI codes, then extract the URL from "Draft URL: <https://...>"
preview_url=$(printf '%s\n' "$output" \
| sed 's/\x1b\[[0-9;]*[mGKHFJABCDsuKl]//g' \
| grep -oP '(?:Draft URL|Website Draft URL|Website URL):\s+<?\Khttps://[^>\s]+' \
| head -1)
echo "url=${preview_url}" >> "$GITHUB_OUTPUT"
exit $exit_code

- name: Post PR preview comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
PREVIEW_URL: ${{ steps.netlify.outputs.url }}
with:
script: |
const previewUrl = process.env.PREVIEW_URL || '';
const prNumber = context.payload.pull_request.number;
const MAX_LINKS = 20;
const COMMENT_MARKER = '<!-- netlify-preview-comment -->';
const updatedAt = new Date().toUTCString();

// Fetch all changed files in the PR (auto-paginated)
const allFiles = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
per_page: 100,
});

// Keep only RST files that live inside a built manual
const manuals = ['admin_manual/', 'developer_manual/', 'user_manual/'];
const rstFiles = allFiles
.map(f => f.filename)
.filter(f => manuals.some(m => f.startsWith(m)) && f.endsWith('.rst'));

// Build the changed-pages section
let changedSection = '';
if (previewUrl && rstFiles.length > 0) {
const links = rstFiles.map(f => {
// user_manual HTML is deployed under user_manual/en/; other manuals deploy as-is
const htmlPath = f.startsWith('user_manual/')
? f.replace(/^user_manual\//, 'user_manual/en/').replace(/\.rst$/, '.html')
: f.replace(/\.rst$/, '.html');
return `- [${f}](${previewUrl}/${htmlPath})`;
});
const shown = links.slice(0, MAX_LINKS);
const extra = links.length - shown.length;
const extraLine = extra > 0
? `\n_…and ${extra} more. [View all changed files](https://github.com/${context.repo.owner}/${context.repo.repo}/pull/${prNumber}/files)_`
: '';
changedSection = [
'',
`<details>`,
`<summary>πŸ“„ ${rstFiles.length} changed documentation ${rstFiles.length === 1 ? 'page' : 'pages'}</summary>`,
'',
shown.join('\n') + extraLine,
'</details>',
].join('\n');
} else if (rstFiles.length === 0) {
changedSection = '\n_No RST documentation pages changed in this PR._';
}

// Compose the full comment body
const previewLine = previewUrl
? `πŸ” **[Open preview β†’](${previewUrl})**`
: '⚠️ Preview deployment failed or was skipped.';
const body = [
COMMENT_MARKER,
'## πŸ“– Documentation Preview',
'',
previewLine,
changedSection,
'',
`_Last updated: ${updatedAt}_`,
].join('\n');

// Update existing bot comment or create a new one
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
per_page: 100,
});
const existing = comments.find(c => c.body && c.body.includes(COMMENT_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: prNumber,
body,
});
}

summary:
needs: [stage-and-check, link-check, deploy]
needs: [stage-and-check, link-check, deploy, netlify-preview]
runs-on: ubuntu-latest-low
if: always()

Expand All @@ -569,9 +757,9 @@ jobs:
run: |
if ${{ github.event_name == 'pull_request' }}
then
echo "This workflow ran for a pull request. We need stage-and-check and link-check to succeed, but deploy will be skipped"
if ${{ needs.stage-and-check.result != 'success' || needs.link-check.result != 'success' || needs.deploy.result != 'skipped' }}; then exit 1; fi
echo "This workflow ran for a pull request. We need stage-and-check, link-check, and netlify-preview to succeed, and deploy must be skipped"
if ${{ needs.stage-and-check.result != 'success' || needs.link-check.result != 'success' || needs.deploy.result != 'skipped' || needs.netlify-preview.result != 'success' }}; then exit 1; fi
else
echo "This workflow ran for a push. We need all jobs to succeed, including deploy"
if ${{ needs.stage-and-check.result != 'success' || needs.link-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi
echo "This workflow ran for a push. We need stage-and-check, link-check, and deploy to succeed; netlify-preview must be skipped"
if ${{ needs.stage-and-check.result != 'success' || needs.link-check.result != 'success' || needs.deploy.result != 'success' || needs.netlify-preview.result != 'skipped' }}; then exit 1; fi
fi
9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
Nextcloud Documentation
=======================

|build| |netlify|

.. |build| image:: https://img.shields.io/github/actions/workflow/status/nextcloud/documentation/sphinxbuild.yml?branch=master&style=flat-square
:alt: Build Status

.. |netlify| image:: https://img.shields.io/badge/Netlify-powered-00C7B7?style=flat-square&logo=netlify
:target: https://www.netlify.com
:alt: Netlify

Documentation is published on `<https://docs.nextcloud.com>`_.
To edit it yourself, you need to tinker a bit with Git and Sphinx.
See the `Style Guide <https://github.com/nextcloud/documentation/blob/master/style_guide.rst>`_ for formatting and style conventions.
Expand Down
8 changes: 6 additions & 2 deletions admin_manual/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ Introduction

**Welcome to the Nextcloud Server Administration Guide.**

This guide explains how to perform administrative tasks in Nextcloud, a highly versatile and scalable open-source platform for file synchronization and content collaboration.
This guide explains how to perform administrative tasks in Nextcloud, a highly versatile and scalable
open-source platform for file synchronization and content collaboration.

With over 400,000 deployments, Nextcloud can run on a simple two-user Raspberry Pi or scale to support global, distributed installations serving tens of millions of users. It can be deployed on-premises, in private or public clouds, or in hybrid environments. Supported by a large and growing community, Nextcloud is available in more than 60 languages.
With over 400,000 deployments, Nextcloud can run on a simple two-user Raspberry Pi or scale to support
global, distributed installations serving tens of millions of users. It can be deployed on-premises,
in private or public clouds, or in hybrid environments. Supported by a large and growing community,
Nextcloud is available in more than 60 languages.

The latest editions of the Nextcloud manuals are always available online at
`docs.nextcloud.com <https://docs.nextcloud.com/>`_.
Expand Down
6 changes: 3 additions & 3 deletions user_manual/session_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ those individually if necessary:
.. figure:: images/settings_devices_add.png
:alt: Adding a new device.

.. note:: You have only access to the device password when creating it,
Nextcloud will not save the plain password, hence it's recommended to
.. note:: You only have access to the device password when creating it.
Nextcloud will not save the plain password, so it is recommended to
enter the password on the new client immediately.


.. note:: If you use :doc:`user_2fa` for your account,
device-specific passwords are the only way to configure clients. The
server will deny connections of clients using your login password then.
server will then deny connections from clients using your login password.

Device-specific passwords and password changes
----------------------------------------------
Expand Down
5 changes: 3 additions & 2 deletions user_manual/user_2fa.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ If the code was correct you will be redirected to your Nextcloud account.

Using two-factor authentication with hardware tokens
----------------------------------------------------

You can use two-factor authentication based on hardware tokens. The following devices are known to work:

* TOTP based:
Expand All @@ -92,12 +93,12 @@ Using client applications with two-factor authentication

Once you have enabled 2FA, your clients will no longer be able to connect with
just your password unless they also have support for two-factor authentication.
To solve this, you should generate device specific passwords for them. See
To solve this, you should generate device-specific passwords for them. See
:doc:`session_management` for more information on how to do this.


Considerations
--------------

If you use WebAuthn to login to your Nextcloud be sure to not use the same token for 2FA. As this
If you use WebAuthn to log in to your Nextcloud, be sure to not use the same token for 2FA, as this
would mean you are again only using a single factor.
6 changes: 3 additions & 3 deletions user_manual/userpreferences.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ include the following:
* Social sharing links
* Nextcloud version

.. note:: Available options and settings depending on your administrator's configuration.
.. note:: Available options and settings depend on your administrator's configuration.
If you are not able to change the password or the display name in your personal settings,
please contact your administrator for help.

Expand Down Expand Up @@ -73,7 +73,7 @@ Someone with a public facing role such as marketing or sales might want to share
Restrict who can see your profile data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If the profile is enabled by your administrator, then your profile data can be read by other users and guest.
If the profile is enabled by your administrator, then your profile data can be read by other users and guests.
To control who can see which information you can adjust the scopes already mentioned:

* **Private** will only allow you and users you have added to your phone book to see the data
Expand All @@ -87,7 +87,7 @@ On the personal settings you can find the button for profile visibility:
:alt: screenshot of the profile visibility button in personal settings


Which allows to configure the visibility for each profile attribute:
Which allows you to configure the visibility for each profile attribute:

.. figure:: images/userdata-visibility.png
:alt: screenshot of scope dropdown on personal information form field
6 changes: 3 additions & 3 deletions user_manual/webinterface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ you use the latest and supported version of a browser from this list:
* Apple **Safari** (Desktop and iOS)
* Microsoft **Edge**

.. note:: Not all versions are supported. Nextcloud is tested and built to work with `these versions only.
<https://browserslist.dev/?q=PjAuMjUlLCBub3Qgb3BfbWluaSBhbGwsIG5vdCBkZWFkLCBGaXJlZm94IEVTUg==>`_
.. note:: Not all versions are supported. Nextcloud is tested and built to work with
`these browser versions <https://browserslist.dev/?q=PjAuMjUlLCBub3Qgb3BfbWluaSBhbGwsIG5vdCBkZWFkLCBGaXJlZm94IEVTUg==>`_ only.

.. note:: If you want to use Nextcloud Talk you need to run Mozilla **Firefox** 52+
or Google **Chrome**/Chromium 49+ to have the full experience with video calls and
Expand Down Expand Up @@ -57,7 +57,7 @@ The Nextcloud user interface contains the following fields and functions:

* **Navigation Bar** (4): Located over the main viewing window (the Application
View), this bar provides a type of breadcrumbs navigation that enables you to
migrate to higher levels of the folder hierarchy up to the root level (home).
navigate to higher levels of the folder hierarchy up to the root level (home).

* **New** button (5): Located in the Navigation Bar, the ``New`` button
enables you to create new files, new folders, or upload files.
Expand Down
Loading