Skip to content

Add workflow for generating C++ docs with Doxygen on GitHub Pages #2

Add workflow for generating C++ docs with Doxygen on GitHub Pages

Add workflow for generating C++ docs with Doxygen on GitHub Pages #2

Workflow file for this run

name: Build and Deploy C++ Documentation
on:
# workflow only triggers when C++ file, the doxygen config, or css are changed
pull_request:
paths:
- '**/*.cpp'
- '**/*.h'
- 'doc/fulldoc.conf.in'
- 'doc/htmldoc/static/css/doxygen-awesome.css'
push:
paths:
- '.github/workflows/docs.yml'
- '**/*.cpp'
- '**/*.h'
- 'doc/fulldoc.conf.in'
- 'doc/htmldoc/static/css/doxygen-awesome.css'
env:
DOXYGEN_VERSION: 1.9.8
jobs:
determine-versions:
if: github.event_name == 'push'
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Compute versions matrix (master + latest two releases)
id: set-matrix
uses: actions/github-script@v7
with:
script: |
try {
const owner = context.repo.owner;
const repo = context.repo.repo;
core.startGroup('Compute versions matrix debug');
core.info(`Repository: ${owner}/${repo}`);
const versions = [{ version: 'master', branch: 'master' }];
core.info( 'Fetching tags (per_page=20) ...');
const tagResp = await github.rest.repos.listTags({ owner, repo, per_page: 20 });
const allTagNames = tagResp.data.map(x => x.name);
core.info(`Total tags returned: ${tagResp.data.length}`);
core.info('All tag names: ' + JSON.stringify(allTagNames));
const mmPattern = /^v(\d+)\.(\d+)$/;
core.info(`Filter regex: ${mmPattern}`);
const mmTags = allTagNames.filter(name => mmPattern.test(name));
core.info('Filtered major.minor tags: ' + JSON.stringify(mmTags));
const semverSort = (a, b) => {
const [, amaj, amin] = a.match(/^v(\d+)\.(\d+)$/);
const [, bmaj, bmin] = b.match(/^v(\d+)\.(\d+)$/);
const ai = parseInt(amaj, 10);
const aj = parseInt(amin, 10);
const bi = parseInt(bmaj, 10);
const bj = parseInt(bmin, 10);
if (ai !== bi) return bi - ai; // major desc
return bj - aj; // minor desc
};
const sorted = [...mmTags].sort(semverSort);
core.info('Sorted matching tags (desc): ' + JSON.stringify(sorted));
const picked = sorted.slice(0, 2);
core.info('Picked latest two: ' + JSON.stringify(picked));
if (picked.length === 0) {
core.warning('No tags matched the pattern vX.Y. Is your repo using tags like vX.Y.Z?');
}
for (const name of picked) {
versions.push({ version: name, branch: name });
}
const matrix = { include: versions };
core.setOutput('matrix', JSON.stringify(matrix));
core.info( 'Final matrix: ' + JSON.stringify(matrix, null, 2));
core.endGroup();
} catch (err) {
core.error( 'Error while computing versions matrix: ' + (err && err.stack ? err.stack : err));
throw err;
}
# Separate job for push events that builds all versions
build-docs-push:
if: github.event_name == 'push'
needs: determine-versions
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJson(needs.determine-versions.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}
- name: Get master config files
if: matrix.version != 'master'
run: |
git fetch $GITHUB_SERVER_URL/$GITHUB_REPOSITORY master --depth=1
# get the version of files from master to ensure consistent output of docs on all versions
git show FETCH_HEAD:doc/fulldoc.conf.in > doc/fulldoc.conf.in.master
git show FETCH_HEAD:doc/htmldoc/static/css/doxygen-awesome.css > doc/htmldoc/static/css/doxygen-awesome.css.master
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y doxygen graphviz cmake build-essential
- name: Configure with CMake
run: |
mkdir -p build-${{ matrix.version }}
cd build-${{ matrix.version }}
if [ "${{ matrix.version }}" != "master" ]; then
# Use master config files for non-master versions before CMake
cp ../doc/fulldoc.conf.in.master ../doc/fulldoc.conf.in
cp ../doc/htmldoc/static/css/doxygen-awesome.css.master ../doc/htmldoc/static/css/doxygen-awesome.css
fi
cmake -Dwith-devdoc=ON -Dwith-python=OFF ..
- name: Generate Doxygen documentation
run: |
cd build-${{ matrix.version }}
doxygen doc/fulldoc.conf
- name: Upload docs artifact ${{ matrix.version }}
uses: actions/upload-artifact@v4
with:
name: docs-${{ matrix.version }}
path: build-${{ matrix.version }}/doc/doxygen/html/
prepare-pages:
needs: build-docs-push
runs-on: ubuntu-latest
steps:
- name: Download all docs artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: docs-*
# Combine all versions' artifacts into 1 because GitHub pages requires a single deployment
- name: Prepare combined site directory
run: |
set -euo pipefail
mkdir -p _site
shopt -s nullglob
for d in artifacts/docs-*; do
version=${d#artifacts/docs-}
mkdir -p "_site/${version}"
cp -r "${d}"/* "_site/${version}/"
done
# Dynamic index listing built versions
cat > _site/index.html << 'HTML_HEAD'
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>NEST Simulator C++ Doxygen</title>
<style>
body { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 40px; }
a { display:inline-block; margin: 8px 12px; padding: 10px 14px; background:#ff6633; color:#fff; border-radius:6px; text-decoration:none; }
a:hover { background:#072f42; }
</style>
</head>
<body>
<h1>NEST Simulator C++ Doxygen</h1>
<p>Select a version:</p>
<div>
HTML_HEAD
for d in $(ls -1 _site | sort -Vr); do
if [ -d "_site/$d" ]; then
echo " <a href=\"$d/\">$d</a>" >> _site/index.html
fi
done
cat >> _site/index.html << 'HTML_TAIL'
</div>
</body>
</html>
HTML_TAIL
- name: Upload Pages artifact (combined)
uses: actions/upload-pages-artifact@v3
with:
path: _site
deploy:
needs: prepare-pages
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
# url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Configure Pages
id: pages
uses: actions/configure-pages@v5
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
# build the documentation for pull requests
build-docs-pull:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get master config files
run: |
git fetch $GITHUB_SERVER_URL/$GITHUB_REPOSITORY master --depth=1
# Get master config files for consistent output of documentation
git show FETCH_HEAD:doc/fulldoc.conf.in > $RUNNER_TEMP/fulldoc.conf.in.master
git show FETCH_HEAD:doc/htmldoc/static/css/doxygen-awesome.css > $RUNNER_TEMP/doxygen-awesome.css.master
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y doxygen graphviz cmake build-essential
- name: Configure with CMake
run: |
mkdir -p build-${{ github.run_id }}
cd build-${{ github.run_id }}
# Use master config files for non-master versions before CMake
cp $RUNNER_TEMP/fulldoc.conf.in.master ../doc/fulldoc.conf.in
cp $RUNNER_TEMP/doxygen-awesome.css.master ../doc/htmldoc/static/css/doxygen-awesome.css
cmake -Dwith-devdoc=ON -Dwith-python=OFF ..
- name: Generate Doxygen documentation
run: |
cd build-${{ github.run_id }}
doxygen doc/fulldoc.conf
- name: Upload docs artifact
uses: actions/upload-artifact@v4
with:
name: docs-${{ github.run_id }}
path: build-${{ github.run_id }}/doc/doxygen/html/