Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7a890f9
.tool-versions(uv) uv 0.12.9 -> 0.12.11
tony Sep 12, 2026
70bb770
.nvmrc(nodejs) 24.20.0 -> 24.21.0
tony Sep 12, 2026
a9150de
py(deps[dev]) ruff 0.16.5 -> 0.16.6
tony Sep 12, 2026
4087791
py(deps[dev]) pytest-rerunfailures 16.6 -> 16.6.1
tony Sep 12, 2026
76c50c5
py(deps[dev]) Bump dev packages
tony Sep 12, 2026
6f2e5dd
py(deps) Refresh eligible dependencies
tony Sep 20, 2026
9fdd083
.tool-versions(uv) uv 0.12.11 -> 0.12.15
tony Sep 20, 2026
f5c9ade
docs: redirect Sphinx search page to the shell's Pagefind search
tony Sep 5, 2026
3a604ac
docs(css): add libtmux-org.css design-token adapter for Furo
tony Sep 5, 2026
8195f20
docs(css): fall back to Furo's stock values when tokens.css is unreac…
tony Sep 5, 2026
ce92238
docs: add lang attribute to the search-page redirect stub
tony Sep 5, 2026
02adc28
Load the shared shell from a root-relative path
tony Sep 5, 2026
1671e1d
docs(fix[css]): Drop a local path from the token adapter
tony Sep 6, 2026
652da1b
docs(fix[search]): Keep a working search on the standalone build
tony Sep 6, 2026
4ed4122
docs(test[conf]): Pin the shell integration's two deploy shapes
tony Sep 6, 2026
4c1ffb3
docs(ci[deploy]) Say when the standalone flag comes back out
tony Sep 6, 2026
3e66e2a
docs(CHANGES) libtmux.org chrome, search, and the 0.1.0a38 toolchain
tony Sep 6, 2026
28a754a
docs(ci[deploy]): Publish to libtmux.org under this port's prefix
tony Sep 6, 2026
f917a4f
docs(ci[deploy]) Pin the deploy workflow to v1
tony Sep 6, 2026
b96002e
docs(ci[deploy]): Publish to libtmux.org alongside git-pull.com
tony Sep 6, 2026
024aa81
docs(ci[deploy]): Pin the deploy workflow to a commit
tony Sep 6, 2026
cd09c09
docs(ci[deploy]) Move the deploy pin to v0.1.0-alpha.1
tony Sep 6, 2026
43f3c38
DO NOT MERGE: publish from docs-site-deploy, and repin
Sep 6, 2026
02b5769
fix(ci) Publish the shell tree to libtmux.org, not the Sphinx site
Sep 6, 2026
6468ff8
docs(CHANGES) A second docs publish, to libtmux.org
tony Sep 6, 2026
e9fa85b
docs(query_list): Document the two exceptions QueryList raises
tony Sep 6, 2026
e8c4b33
docs(constants): Say what the default-scope sentinel means
tony Sep 6, 2026
22cba98
Docs(ci[deploy]): Pin the current docs shell
tony Sep 20, 2026
f70faac
Docs(ci[deploy]): Pin the refreshed docs shell
tony Sep 20, 2026
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
179 changes: 157 additions & 22 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,38 @@ on:
push:
branches:
- master
# DO NOT MERGE: publishes /en/py/latest/ before anything merges — that
# tree 403s on libtmux.org today. Drop this line when merging to master.
- docs-site-deploy

permissions:
contents: read
id-token: write

# Required of every caller of reusable-deploy.yml, and not something that
# workflow can do for itself: concurrency groups do not cross repository
# boundaries, so each port serialises its own publishes here. `queue: max`
# runs the newest queued publish after the running one instead of cancelling
# it, and cannot be combined with cancel-in-progress. See libtmux/docs
# docs/ci.md.
concurrency:
group: docs-deploy-${{ github.repository }}
queue: max

jobs:
build:
# Its own job because the answer has to reach the deploy job, and a step's
# $GITHUB_ENV does not leave the job that wrote it. Every job below is
# gated on this one output rather than repeating the condition per step.
changes:
runs-on: ubuntu-latest
environment: docs
strategy:
matrix:
python-version: ['3.14']
outputs:
publish: ${{ steps.gate.outputs.publish }}
steps:
- uses: actions/checkout@v7

- name: Filter changed file paths to outputs
uses: dorny/paths-filter@v4
id: changes
id: filter
with:
filters: |
root_docs:
Expand All @@ -36,35 +50,57 @@ jobs:
- pyproject.toml

- name: Should publish
if: steps.changes.outputs.docs == 'true' || steps.changes.outputs.root_docs == 'true' || steps.changes.outputs.python_files == 'true'
run: echo "PUBLISH=$(echo true)" >> $GITHUB_ENV
id: gate
env:
MATCHED: ${{ steps.filter.outputs.docs == 'true' || steps.filter.outputs.root_docs == 'true' || steps.filter.outputs.python_files == 'true' }}
run: echo "publish=$MATCHED" >> "$GITHUB_OUTPUT"

# The two sites need different bytes, not the same tree published twice.
# libtmux.git-pull.com serves this build at a root, where /_shell/ is
# nothing and /search/ is the build's own search page — so it is built
# standalone, keeping Furo's search and loading no chrome. libtmux.org
# nests it at en/py/latest/, where both are reachable and belong on.
# Publishing one artifact to both gives an unskinned nested site or a
# root site whose search redirects to itself, depending which way the
# flag is set. tests/test_docs_conf.py pins both shapes.
build:
needs: changes
if: needs.changes.outputs.publish == 'true'
runs-on: ubuntu-latest
environment: docs
strategy:
# Neither destination should lose its publish because the other
# failed to build.
fail-fast: false
matrix:
include:
- site: git-pull-com
standalone: '1'
- site: libtmux-org
standalone: ''
steps:
- uses: actions/checkout@v7

- name: Install uv
if: env.PUBLISH == 'true'
uses: astral-sh/setup-uv@v10.0.1
with:
enable-cache: true

- name: Set up Python ${{ matrix.python-version }}
if: env.PUBLISH == 'true'
run: uv python install ${{ matrix.python-version }}
- name: Set up Python
run: uv python install 3.14

- name: Install dependencies [w/ docs]
if: env.PUBLISH == 'true'
run: uv sync --all-extras --dev

- name: Install just
if: env.PUBLISH == 'true'
uses: extractions/setup-just@v4

- name: Print python versions
if: env.PUBLISH == 'true'
run: |
python -V
uv run python -V

- name: Cache sphinx fonts
if: env.PUBLISH == 'true'
uses: actions/cache@v6
with:
path: ~/.cache/sphinx-fonts
Expand All @@ -73,33 +109,132 @@ jobs:
sphinx-fonts-

- name: Build documentation
if: env.PUBLISH == 'true'
if: matrix.site == 'git-pull-com'
env:
LIBTMUX_DOCS_STANDALONE: ${{ matrix.standalone }}
run: |
cd docs && just html

- name: Configure AWS Credentials
if: env.PUBLISH == 'true'
# libtmux.org's tree is not this Sphinx build. en/py/latest/ is the
# shared shell rendered with Python's code fences, with this port's
# gp-sphinx output nested at api/ — build-site.sh produces both, running
# sphinx itself from this checkout. Publishing the Sphinx site directly
# replaced the whole tree with it: /en/py/latest/ served Furo and
# /en/py/latest/concepts/ 403'd.
- uses: actions/checkout@v7
if: matrix.site == 'libtmux-org'
with:
repository: libtmux/docs
ref: b1e3bb25b1b5aaad9381365f4566019586cd00ff
path: libtmux-docs

- uses: pnpm/action-setup@v6
if: matrix.site == 'libtmux-org'
with:
package_json_file: libtmux-docs/package.json
- uses: actions/setup-node@v7
if: matrix.site == 'libtmux-org'
with:
node-version: '26'
cache: pnpm
cache-dependency-path: libtmux-docs/pnpm-lock.yaml
- run: pnpm install --frozen-lockfile
if: matrix.site == 'libtmux-org'
working-directory: libtmux-docs

# No --skip-refs: for every other port api/ is a redirect to
# /reference/<slug>/, but Python's is the real gp-sphinx render that
# check-style-parity.mjs measures against, so it has to be built.
- name: Build the libtmux.org tree
if: matrix.site == 'libtmux-org'
working-directory: libtmux-docs
env:
LIBTMUX_DOCS_CHECKOUT_PY: ${{ github.workspace }}
run: ./scripts/build-site.sh --ports py --skip-pagefind

# libtmux.git-pull.com publishes from inside this job, as it always
# has. Kept in place rather than moved behind an artifact: this is a
# live site, and an artifact round trip does not preserve the symlinks
# the sync below is told to follow.
- name: Configure AWS credentials for libtmux.git-pull.com
if: matrix.site == 'git-pull-com'
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ secrets.LIBTMUX_DOCS_ROLE_ARN }}
aws-region: us-east-1

- name: Push documentation to S3
if: env.PUBLISH == 'true'
if: matrix.site == 'git-pull-com'
run: |
aws s3 sync docs/_build/html "s3://${{ secrets.LIBTMUX_DOCS_BUCKET }}" \
--delete --follow-symlinks

- name: Invalidate CloudFront
if: env.PUBLISH == 'true'
if: matrix.site == 'git-pull-com'
run: |
aws cloudfront create-invalidation \
--distribution-id "${{ secrets.LIBTMUX_DOCS_DISTRIBUTION }}" \
--paths "/index.html" "/objects.inv" "/searchindex.js"

- name: Purge cache on Cloudflare
if: env.PUBLISH == 'true'
if: matrix.site == 'git-pull-com'
uses: jakejarvis/cloudflare-purge-action@v0.3.0
env:
CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }}

# libtmux.org publishes through the shared workflow instead, which
# only ever writes one port's own prefix. It downloads to dist/ and
# syncs dist/, so the tree has to sit at the artifact root.
- name: Upload the built site for libtmux.org
if: matrix.site == 'libtmux-org'
uses: actions/upload-artifact@v7
with:
name: docs-html
path: libtmux-docs/_site/en/py/latest
retention-days: 1

# Additive: a failure here leaves libtmux.git-pull.com serving exactly what
# it serves today, because that publish already happened in the job above.
#
# path-prefix is unprefixed by locale — reusable-deploy prepends `<locale>/`
# itself whenever `port` is set, so this publishes to en/py/latest/, and
# passing en/py/latest here would produce en/en/py/latest.
#
# `environment` is an input rather than `environment:` on this job, which
# `uses:` does not accept — and reusable-deploy's own job is the one whose
# OIDC subject has to carry `environment:docs` to match the role's trust
# policy. The three secrets are passed explicitly, never `secrets: inherit`.
#
# LIBTMUX_ORG_* is a separate set from LIBTMUX_DOCS_*, which keeps its
# current meaning: the libtmux.git-pull.com bucket, unchanged.
publish-libtmux-org:
needs: [changes, build]
if: needs.changes.outputs.publish == 'true'
permissions:
contents: read
id-token: write
# Pinned to a commit, with the release it belongs to named beside it.
#
# Not a tag: this `uses:` runs another repository's workflow inside ours
# with `id-token: write` and a role that can write the bucket, and a tag
# can be repointed — so pinning one lets what executes here change with
# no diff in this repository and no review. A commit cannot be
# repointed. libtmux/docs asks callers for the same thing.
#
# Bumping is manual. Dependabot reads a trailing version comment, but
# only where the `github-actions` ecosystem is enabled, and this
# repository has no dependabot.yml at all.
uses: libtmux/docs/.github/workflows/reusable-deploy.yml@b1e3bb25b1b5aaad9381365f4566019586cd00ff
with:
path-prefix: py/latest
artifact: docs-html
version-kind: trunk
port: py
version: latest
is-default: true
environment: docs
secrets:
role-arn: ${{ secrets.LIBTMUX_ORG_ROLE_ARN }}
bucket: ${{ secrets.LIBTMUX_ORG_BUCKET }}
distribution: ${{ secrets.LIBTMUX_ORG_DISTRIBUTION }}
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24.20.0
24.21.0
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
just 1.58.0
uv 0.12.9
uv 0.12.15
python 3.14 3.13 3.12 3.11 3.10
22 changes: 22 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ _Notes on the upcoming release will go here._

### Documentation

#### libtmux.org chrome and site-wide search (#755)

Documentation pages carry libtmux.org's header, footer, and version switcher,
and take their colors from the site's shared design tokens. Sphinx's own
search page redirects to the site-wide search, which covers every libtmux
port. Pages render as stock Furo when the shared stylesheet is unreachable.

#### Cleaner `from_env` examples (#719)

The rendered examples for {meth}`Pane.from_env() <libtmux.Pane.from_env>` and
Expand All @@ -59,6 +66,21 @@ it.

### Development

#### Docs publish to libtmux.org (#756)

The docs build publishes to `libtmux.org` under `en/py/latest/` through the
shared deploy workflow every libtmux port calls, and keeps publishing to
libtmux.git-pull.com unchanged. Each destination takes its own build:
libtmux.org gets the site's shared shell with this port's reference nested
at `api/`, libtmux.git-pull.com the Sphinx site at a root.

#### Docs toolchain on gp-sphinx 0.1.0a38 (#755)

`gp-sphinx` and its sibling extensions move to 0.1.0a38. `sphinx-gp-llms`
resolves from a pinned upstream commit until a release carries its fix:
`genindex`, `py-modindex`, and `search` no longer link a `.md` twin that was
never written.

#### CI actions updated to current majors

Workflow actions moved to their current major releases: `actions/checkout` v7,
Expand Down
Loading
Loading