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
142 changes: 142 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Documentation

# The keyword documentation is generated from the library itself and published to the
# gh-pages branch, one directory per released version plus /dev for the current main.
#
# It is not committed to the repository. A rendered libdoc page carries the generation
# time, the absolute path of the machine that produced it and the Robot Framework and
# Python versions used, so a committed copy cannot be compared against a fresh one
# without normalising all of that away. Generating on publish means there is nothing
# that can drift.

on:
push:
branches: [main]
tags: ["v*"]
workflow_dispatch:
inputs:
ref:
# workflow_dispatch can only run a workflow that exists on the chosen ref, so the
# tags released before this workflow did cannot be dispatched directly. Naming one
# here publishes it: run the workflow from main with ref set to v0.1.0.
description: "Tag to publish instead of the current main, for example v0.1.0"
required: false
default: ""

permissions:
contents: read

concurrency:
# Publishing rewrites a shared branch, so two runs must not do it at once.
group: docs
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
permissions:
# Only this job writes, and only to the gh-pages branch.
contents: write
steps:
- name: Work out what is being published
id: target
run: |
requested="${{ inputs.ref }}"
if [ -n "$requested" ]; then
# A backfill of an older tag. Its version is the tag without the v.
case "$requested" in
v*) ;;
*) echo "The ref input has to be a version tag, for example v0.1.0." >&2; exit 1 ;;
esac
echo "ref=$requested" >> "$GITHUB_OUTPUT"
echo "path=${requested#v}" >> "$GITHUB_OUTPUT"
echo "release=true" >> "$GITHUB_OUTPUT"
elif [ "${GITHUB_REF_TYPE}" = "tag" ]; then
echo "ref=${GITHUB_SHA}" >> "$GITHUB_OUTPUT"
echo "path=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
echo "release=true" >> "$GITHUB_OUTPUT"
else
echo "ref=${GITHUB_SHA}" >> "$GITHUB_OUTPUT"
echo "path=dev" >> "$GITHUB_OUTPUT"
echo "release=false" >> "$GITHUB_OUTPUT"
fi

- uses: actions/checkout@v7
with:
# Tags are needed so a backfilled ref can be checked out at all.
fetch-depth: 0
ref: ${{ steps.target.outputs.ref }}

- uses: actions/setup-python@v7
with:
python-version: "3.12"

- name: Install Poetry
run: pipx install poetry

- name: Install
run: poetry install

- name: Generate the keyword documentation
run: poetry run python -m robot.libdoc GraphQLLibrary GraphQLLibraryKeywords.html

- name: Take the index builder from main
# An older tag has no tools/ of its own, and the page it renders is the same page
# regardless of which version's keywords are being documented.
if: ${{ inputs.ref != '' }}
run: |
git fetch origin main --depth 1
git checkout FETCH_HEAD -- tools/build_docs_index.py

- name: Check out the published site
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if git ls-remote --exit-code --heads origin gh-pages; then
git fetch origin gh-pages --depth 1
git worktree add site FETCH_HEAD
else
# First publish: start the branch with no history of its own.
git worktree add --detach site
git -C site checkout --orphan gh-pages
git -C site rm -rf . --quiet || true
fi

- name: Add this version to the site
run: |
set -eu
path="${{ steps.target.outputs.path }}"
mkdir -p "site/${path}"
cp GraphQLLibraryKeywords.html "site/${path}/GraphQLLibraryKeywords.html"

# GitHub Pages otherwise runs the site through Jekyll, which drops directories
# whose names begin with an underscore and needs no help here regardless.
touch site/.nojekyll

if [ "${{ steps.target.outputs.release }}" = "true" ]; then
poetry run python tools/build_docs_index.py \
site/versions.json site/index.html --add "$path" --release
else
poetry run python tools/build_docs_index.py \
site/versions.json site/index.html --add "$path"
fi

# /latest and the bare path are only moved when the version just published is
# actually the newest release, so backfilling an old tag cannot demote them. The
# bare path is what the released package metadata points at, so it stays served.
if poetry run python tools/build_docs_index.py --is-latest "$path" site/versions.json; then
mkdir -p site/latest
cp GraphQLLibraryKeywords.html site/latest/GraphQLLibraryKeywords.html
cp GraphQLLibraryKeywords.html site/GraphQLLibraryKeywords.html
fi

- name: Publish
run: |
cd site
git add -A
if git diff --cached --quiet; then
echo "The published documentation is already up to date."
exit 0
fi
git commit -m "docs: publish ${{ steps.target.outputs.path }} from ${GITHUB_SHA}"
git push origin HEAD:gh-pages
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ build/

atest-results/
libdoc-check.html
# The keyword documentation is generated and published by the docs workflow, per version,
# and never committed: a rendered libdoc page carries the generation time, the path of the
# machine that made it and the Robot Framework and Python versions used.
GraphQLLibraryKeywords.html
log.html
report.html
output.xml
Expand Down
Empty file removed .nojekyll
Empty file.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- The keyword documentation is now generated on publish and served per version, at
`/<version>/GraphQLLibraryKeywords.html`, with `/latest` and `/dev` alongside them and a
landing page listing everything. Reading the documentation for the version you have installed
no longer means reading the documentation for whatever is newest. The rendered page is no
longer committed to the repository: it records its own generation time, the path of the
machine that produced it and the Robot Framework and Python versions used, none of which
belongs in version control and all of which made a committed copy impossible to verify.

## [0.2.0] - 2026-08-17

### Added
Expand Down
387 changes: 0 additions & 387 deletions GraphQLLibraryKeywords.html

This file was deleted.

9 changes: 6 additions & 3 deletions HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,12 @@ surface rather than protocol work.
asked for it. That is the honest state.
2. First commit and a GitHub repository under `MobyNl`. Conventional commits, matching the
MongoDB library.
3. Publish keyword documentation via GitHub Pages: `GraphQLLibraryKeywords.html` and
`index.html` are committed, and `.nojekyll` is present because Jekyll would otherwise eat
libdoc's `{{ }}` sequences.
3. Keyword documentation is published by `.github/workflows/docs.yml` to the `gh-pages`
branch, one directory per release plus `/dev` for main, with `tools/build_docs_index.py`
rendering the landing page. Nothing is committed to `main`, so the pages cannot drift from
the code. GitHub Pages has to be set to serve from `gh-pages`, and the two tags released
before the workflow existed are published by dispatching it with `ref` set to `v0.1.0` and
`v0.2.0`.
4. Set up PyPI trusted publishing for the `pypi` environment, then tag `v0.1.0`.
`release.yml` checks the tag against `poetry version --short` before building.
5. Try it against a real API before 1.0 — a public one such as countries.trevorblades.com,
Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

GraphQL test library for Robot Framework.

[Keyword documentation](https://mobynl.github.io/robotframework-graphqllibrary/)
[Keyword documentation](https://mobynl.github.io/robotframework-graphqllibrary/), published per version.

## Why not just RequestsLibrary

Expand Down Expand Up @@ -143,6 +143,19 @@ reported. Drift detection compares types and fields, not the built-in directives
`Execute Raw Request` sends an operation with no checking at all, for cases this library does
not model.

## Documentation

The [keyword documentation](https://mobynl.github.io/robotframework-graphqllibrary/) describes
every keyword, its arguments and examples. It is published per version, so you can read the
documentation for the version you actually have installed rather than for whatever is newest:

- [all versions](https://mobynl.github.io/robotframework-graphqllibrary/) — start here
- [latest release](https://mobynl.github.io/robotframework-graphqllibrary/latest/GraphQLLibraryKeywords.html)
- [current main, unreleased](https://mobynl.github.io/robotframework-graphqllibrary/dev/GraphQLLibraryKeywords.html)

The pages are generated from the library itself when a tag or a push to main is published, so
they cannot drift from the code they document.

## Development

```
Expand Down
5 changes: 0 additions & 5 deletions index.html

This file was deleted.

Loading