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
4 changes: 2 additions & 2 deletions .docker/sphinx-latex/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ RUN apt-get update \
&& mktexlsr \
&& rm -rf /var/lib/apt/lists/*

# Allow pip to install packages system-wide inside the container (used by
# actions/setup-python and plain pip invocations running as root)
# Allow pip to install packages system-wide inside the container when running
# as root (avoids PEP 668 "externally managed environment" error)
RUN printf '[global]\nbreak-system-packages = true\n' > /etc/pip.conf
6 changes: 3 additions & 3 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ permissions:
packages: write

jobs:
build-and-push:
name: Build and push sphinx-latex image
build-and-publish:
name: Build and publish sphinx-latex Docker image
runs-on: ubuntu-latest

steps:
Expand All @@ -44,7 +44,7 @@ jobs:
type=raw,value=latest,enable={{is_default_branch}}
type=sha,prefix=sha-

- name: Build and push Docker image
- name: Build and publish Docker image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .docker/sphinx-latex
Expand Down
212 changes: 66 additions & 146 deletions .github/workflows/sphinxbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,15 @@ concurrency:
cancel-in-progress: true

jobs:
setup-latex-cache:
name: Cache LaTeX packages
runs-on: ubuntu-latest

steps:
- name: Configure apt cache
run: |
mkdir -p ${{ runner.temp }}/.cache/archives
mkdir -p ${{ runner.temp }}/.cache/lists
echo 'Dir::Cache::archives "${{ runner.temp }}/.cache/archives";' | sudo tee /etc/apt/apt.conf.d/apt-cache-tmp

- name: Cache LaTeX apt packages
id: cache-latex-apt
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: |
${{ runner.temp }}/.cache/archives
${{ runner.temp }}/.cache/lists
key: latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-texlive-2023-v2
restore-keys: |
latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-
latex-apt-${{ runner.os }}-${{ runner.arch }}-
lookup-only: true

- name: Download LaTeX packages (cache miss only)
if: steps.cache-latex-apt.outputs.cache-hit != 'true'
run: |
for i in 1 2 3; do
sudo DEBIAN_FRONTEND=noninteractive apt-get update \
-o Dir::State::lists="${{ runner.temp }}/.cache/lists" \
-o Acquire::Retries=3 && break
echo "apt-get update failed (attempt $i), retrying in 15s..."
sleep 15
done
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
--download-only \
-o Dir::State::lists="${{ runner.temp }}/.cache/lists" \
python3-pil python3-pip texlive-fonts-recommended latexmk \
texlive-latex-extra texlive-latex-recommended texlive-xetex \
texlive-fonts-extra-links texlive-fonts-extra xindy tex-gyre
# Ensure downloaded packages are owned by the current user so they can be cached
sudo chown -R $(id -u):$(id -g) ${{ runner.temp }}/.cache/

- name: Save LaTeX apt cache (cache miss only)
if: steps.cache-latex-apt.outputs.cache-hit != 'true'
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: |
${{ runner.temp }}/.cache/archives
${{ runner.temp }}/.cache/lists
key: latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-texlive-2023-v2

build:
name: Build ${{ matrix.manual.name }}
# ============================================================================
# BUILD HTML
# ============================================================================
# Builds the HTML documentation for all manuals. No LaTeX required.
# Starts immediately without waiting for any setup job.
# ============================================================================
build-html:
name: Building ${{ matrix.manual.name }} HTML
runs-on: ubuntu-latest
needs: setup-latex-cache

strategy:
fail-fast: false
Expand All @@ -80,7 +33,6 @@ jobs:
directory: "user_manual"
make_target: "html"
build_path: "_build/html"
build_pdf_path: "_build/latex"
publish: true

- name: "user_manual-en"
Expand All @@ -99,68 +51,73 @@ jobs:
directory: "admin_manual"
make_target: "html"
build_path: "_build/html/com"
build_pdf_path: "_build/latex"
publish: true

steps:
- name: Cache git metadata
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
cache: "pip"

- name: Install pip dependencies
run: pip install -r requirements.txt
run: python -m pip install -r requirements.txt

- name: Configure apt cache
if: ${{ matrix.manual.build_pdf_path }}
run: |
mkdir -p ${{ runner.temp }}/.cache/archives
mkdir -p ${{ runner.temp }}/.cache/lists
echo 'Dir::Cache::archives "${{ runner.temp }}/.cache/archives";' | sudo tee /etc/apt/apt.conf.d/apt-cache-tmp
- name: Build html documentation
run: cd ${{ matrix.manual.directory }} && make ${{ matrix.manual.make_target }}

- name: Restore LaTeX apt cache
if: ${{ matrix.manual.build_pdf_path }}
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
- name: Upload static documentation
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ matrix.manual.publish }}
with:
# Use relative path https://github.com/actions/cache/issues/1127
path: |
${{ runner.temp }}/.cache/archives
${{ runner.temp }}/.cache/lists
key: latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-texlive-2023-v2
restore-keys: |
latex-apt-${{ runner.os }}-${{ runner.arch }}-ubuntu-24.04-
latex-apt-${{ runner.os }}-${{ runner.arch }}-

- name: Install LaTeX from cache
if: ${{ matrix.manual.build_pdf_path }}
timeout-minutes: 5
run: |
debs=(${{ runner.temp }}/.cache/archives/*.deb)
if [ ! -e "${debs[0]}" ]; then
echo "No .deb files found in cache archives — cache may be empty or missing." >&2
exit 1
fi
sudo dpkg -i --force-depends "${debs[@]}"
sudo DEBIAN_FRONTEND=noninteractive apt-get install -f -y --no-install-recommends \
-o Dir::State::lists="${{ runner.temp }}/.cache/lists"
name: ${{ matrix.manual.name }}
path: ${{ matrix.manual.directory }}/${{ matrix.manual.build_path }}

- name: Build html documentation
run: cd ${{ matrix.manual.directory }} && make ${{ matrix.manual.make_target }}
# ============================================================================
# BUILD PDF
# ============================================================================
# Builds the PDF documentation using the pre-built sphinx-latex Docker image.
# The image already contains all LaTeX packages, so no apt install is needed.
# Starts immediately without waiting for any setup job.
# ============================================================================
build-pdf:
name: Building ${{ matrix.manual.name }} PDF
runs-on: ubuntu-latest
# Use the pre-built sphinx-latex image which has all LaTeX packages pre-installed.
# The image is built from .docker/sphinx-latex/Dockerfile by the docker-build.yml workflow
# and published to GHCR. Using latest ensures we always use the current image for this repo.
container: ghcr.io/nextcloud/documentation/sphinx-latex:latest

strategy:
fail-fast: false
matrix:
manual:
- name: "user_manual"
directory: "user_manual"
build_pdf_path: "_build/latex/Nextcloud_User_Manual.pdf"

- name: "admin_manual"
directory: "admin_manual"
build_pdf_path: "_build/latex/Nextcloud_Server_Administration_Manual.pdf"

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
# pip cache is not compatible with the Docker container
# cache: "pip"

- name: Install pip dependencies
run: python -m pip install -r requirements.txt

- name: Compute PDF release version
if: ${{ matrix.manual.build_pdf_path }}
id: pdf_version
run: |
branch="${GITHUB_REF#refs/heads/}"
Expand All @@ -171,22 +128,19 @@ jobs:
fi

- name: Build pdf documentation
if: ${{ matrix.manual.build_pdf_path }}
env:
DOCS_RELEASE: ${{ steps.pdf_version.outputs.release }}
run: |
set -e
cd ${{ matrix.manual.directory }}
make latexpdf
ls -la ${{ matrix.manual.build_pdf_path }}
cp ${{ matrix.manual.build_pdf_path }}/*.pdf ${{ matrix.manual.build_path }}/

- name: Upload static documentation
- name: Upload PDF documentation
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ matrix.manual.publish }}
with:
name: ${{ matrix.manual.name }}
path: ${{ matrix.manual.directory }}/${{ matrix.manual.build_path }}
name: ${{ matrix.manual.name }}-pdf
path: ${{ matrix.manual.directory }}/${{ matrix.manual.build_pdf_path }}

# ============================================================================
# STAGE AND VALIDATE
Expand All @@ -203,7 +157,7 @@ jobs:
# ============================================================================
stage-and-check:
name: Stage and check documentation
needs: build
needs: [build-html, build-pdf]
runs-on: ubuntu-latest

outputs:
Expand All @@ -223,15 +177,6 @@ jobs:
additional_deployment: ${{ steps.branch.outputs.additional_deployment }}

steps:
- name: Cache git metadata
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Expand All @@ -249,22 +194,6 @@ jobs:
# 2. Merge in the new artifacts (what we're about to deploy)
# 3. Run link checks only on the NEW content, but with full context
# ========================================================================
# ========================================================================
# FETCH GH-PAGES FOR LINK VALIDATION CONTEXT
# ========================================================================
# We need the existing gh-pages content (old versions) so that link
# validation can resolve cross-version references. We use git cache
# to make this fast.
# ========================================================================
- name: Cache git metadata for gh-pages
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata

- name: Checkout gh-pages branch for validation context
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand Down Expand Up @@ -402,15 +331,6 @@ jobs:
pull-requests: write

steps:
- name: Cache git metadata
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: .git
key: git-metadata-${{ github.sha }}
restore-keys: |
git-metadata-${{ github.sha }}
git-metadata

- name: Checkout gh-pages branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand Down Expand Up @@ -526,7 +446,7 @@ jobs:
GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}

summary:
needs: [build, stage-and-check, deploy]
needs: [build-html, build-pdf, stage-and-check, deploy]
runs-on: ubuntu-latest-low
if: always()

Expand All @@ -540,10 +460,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
echo "This workflow ran for a pull request. We need build-html, build-pdf and stage-and-check to succeed, but deploy will be skipped"
if ${{ needs.build-html.result != 'success' || needs.build-pdf.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.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.build-html.result != 'success' || needs.build-pdf.result != 'success' || needs.stage-and-check.result != 'success' || needs.deploy.result != 'success' }}; then exit 1; fi
fi

Loading