Skip to content

Commit 318ad60

Browse files
committed
Migrate to bzlmod + rules_latex; modernize toolchain & CI
- Replace WORKSPACE with MODULE.bazel (bzlmod-only; Bazel 8.7.0). - Bump rules_python to 2.0.2 and the Python toolchain to 3.13. - Swap Prodrive bazel_latex for rules_latex 0.6.1 (Tectonic); the document entry points move to the repo root so main-rooted staging and Overleaf both resolve the existing root-relative include paths. - Add CI-run tests: pytest unit tests for insert_sha plus proposal/thesis latex_test compile checks, across a Linux (x86_64 + arm64) and macOS arm64 matrix. - Modernize the Nix dev shell (bazelisk, Python 3.13, drop TeX Live) and refresh the README.
1 parent 050879e commit 318ad60

20 files changed

Lines changed: 1255 additions & 277 deletions

.bazelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Bzlmod-only: rules_latex and the modern rules_python setup both require it,
2+
# and we deliberately do not keep a WORKSPACE file.
3+
common --enable_bzlmod
4+
common --noenable_workspace
5+
6+
# Surface the underlying command (tectonic/biber) on a failed action.
7+
build --verbose_failures

.bazelversion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8.7.0

.github/workflows/ci.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master, main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: ci-${{ github.ref }}-${{ github.workflow }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
test:
18+
name: bazel test //... (${{ matrix.runner }})
19+
# Linux (x86_64 + arm64) and macOS arm64 — the platforms rules_latex ships a
20+
# Tectonic + biber toolchain for that also have reliable GitHub runners.
21+
# (Windows: no rules_latex Tectonic toolchain. Intel macOS / macos-13:
22+
# GitHub-hosted runners are being deprecated and queue unreliably.)
23+
strategy:
24+
fail-fast: false
25+
matrix:
26+
runner:
27+
- ubuntu-24.04 # linux x86_64
28+
- ubuntu-24.04-arm # linux aarch64
29+
- macos-14 # macos arm64
30+
runs-on: ${{ matrix.runner }}
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v4
34+
35+
- name: Set up Bazel
36+
uses: bazel-contrib/setup-bazel@0.19.0
37+
with:
38+
# Honour .bazelversion deterministically and persist ~/.cache/bazel
39+
# across runs, so the one-time Tectonic prime (the document compile
40+
# tests) becomes an action-cache hit on later runs. Keyed per runner
41+
# so platforms don't share an incompatible cache.
42+
bazelisk-cache: true
43+
disk-cache: ${{ matrix.runner }}
44+
repository-cache: true
45+
46+
- name: bazel test //...
47+
# Runs the pure-Python insert_sha_test plus the proposal/thesis
48+
# latex_test compile checks. The compile tests fetch from the network
49+
# on a cold cache (Tectonic bundle + biber); a couple of retries keep a
50+
# transient CDN blip from failing the run.
51+
run: |
52+
for attempt in 1 2 3; do
53+
bazel test //... --test_output=errors --keep_going && exit 0
54+
echo "::warning::bazel test attempt ${attempt} failed; retrying"
55+
sleep $((5 * attempt))
56+
done
57+
exit 1

.github/workflows/publish_proposal.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@ on:
66
paths:
77
- 'common/**'
88
- 'proposal/**'
9+
- 'proposal.tex'
910
jobs:
1011
build:
1112
name: "Build Proposal PDF"
12-
runs-on: ubuntu-22.04
13+
runs-on: ubuntu-24.04
1314
steps:
1415
- name: Checkout Repo
15-
uses: actions/checkout@v3
16+
uses: actions/checkout@v4
17+
- name: Set up Bazel
18+
uses: bazel-contrib/setup-bazel@0.19.0
19+
with:
20+
bazelisk-cache: true
21+
disk-cache: rules-latex
22+
repository-cache: true
1623
- name: Build Target
1724
id: build
1825
run: |
@@ -23,7 +30,7 @@ jobs:
2330
cp "$file" "$sha_file"
2431
echo "artifact_path=${sha_file}" >> $GITHUB_OUTPUT
2532
- name: Upload Artifact
26-
uses: actions/upload-artifact@v3
33+
uses: actions/upload-artifact@v4
2734
with:
2835
name: ${{ steps.build.outputs.artifact_name }}
2936
path: ${{ steps.build.outputs.artifact_path }}

.github/workflows/publish_thesis.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@ on:
66
paths:
77
- 'common/**'
88
- 'thesis/**'
9+
- 'thesis.tex'
910
jobs:
1011
build:
1112
name: "Build Thesis v2 PDF"
12-
runs-on: ubuntu-22.04
13+
runs-on: ubuntu-24.04
1314
steps:
1415
- name: Checkout Repo
15-
uses: actions/checkout@v3
16+
uses: actions/checkout@v4
17+
- name: Set up Bazel
18+
uses: bazel-contrib/setup-bazel@0.19.0
19+
with:
20+
bazelisk-cache: true
21+
disk-cache: rules-latex
22+
repository-cache: true
1623
- name: Build Target
1724
id: build
1825
run: |
@@ -23,7 +30,7 @@ jobs:
2330
cp "$file" "$sha_file"
2431
echo "artifact_path=${sha_file}" >> $GITHUB_OUTPUT
2532
- name: Upload Artifact
26-
uses: actions/upload-artifact@v3
33+
uses: actions/upload-artifact@v4
2734
with:
2835
name: ${{ steps.build.outputs.artifact_name }}
29-
path: ${{ steps.build.outputs.artifact_path }}
36+
path: ${{ steps.build.outputs.artifact_path }}

BUILD.bazel

Lines changed: 44 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,62 @@
11
load("@pypi//:requirements.bzl", "requirement")
2-
load("@bazel_latex//:latex.bzl", "latex_document")
3-
4-
PY_DEPS = [
5-
requirement("loguru"),
6-
requirement("mypy"),
7-
requirement("pytest"),
8-
]
9-
2+
load("@rules_latex//latex:defs.bzl", "latex_document", "latex_test")
3+
load("@rules_python//python:defs.bzl", "py_binary")
104

115
py_binary(
126
name = "main",
137
srcs = glob(["src/**/*.py"]),
14-
deps = PY_DEPS,
8+
deps = [requirement("loguru")],
159
)
1610

11+
# Shared preamble, references and images used by both documents. allow_empty
12+
# keeps the optional image patterns (e.g. *.jpeg) from failing the build when a
13+
# given format isn't present under common/.
14+
_COMMON = glob(
15+
[
16+
"common/**/*.tex",
17+
"common/**/*.png",
18+
"common/**/*.jpeg",
19+
"common/**/*.bib",
20+
],
21+
allow_empty = True,
22+
)
1723

18-
TEX_DEPS = [
19-
"@bazel_latex//packages:amsmath",
20-
"@bazel_latex//packages:babel_english",
21-
"@bazel_latex//packages:biblatex",
22-
"@bazel_latex//packages:calc",
23-
"@bazel_latex//packages:csquotes",
24-
"@bazel_latex//packages:enumitem",
25-
"@bazel_latex//packages:float",
26-
"@bazel_latex//packages:geometry",
27-
"@bazel_latex//packages:grfext",
28-
"@bazel_latex//packages:hyperref",
29-
"@bazel_latex//packages:l3keys2e",
30-
"@bazel_latex//packages:listings",
31-
"@bazel_latex//packages:longtable",
32-
"@bazel_latex//packages:tikz",
33-
"@bazel_latex//packages:titling",
34-
"@bazel_latex//packages:upquote",
35-
"@bazel_latex//packages:xcolor",
36-
"@bazel_latex//packages:xkeyval",
37-
"@texlive_texmf__texmf-dist__tex__generic__hyph-utf8__loadhyph", #lipsum
38-
"@texlive_texmf__texmf-dist__tex__generic__hyph-utf8__patterns__tex", #lipsum
39-
"@texlive_texmf__texmf-dist__tex__latex__appendix",
40-
"@texlive_texmf__texmf-dist__tex__latex__biblatex-ieee",
41-
"@texlive_texmf__texmf-dist__tex__latex__braket",
42-
"@texlive_texmf__texmf-dist__tex__latex__lipsum",
43-
"@texlive_texmf__texmf-dist__tex__latex__lstaddons", # lstautogobble
44-
"@texlive_texmf__texmf-dist__tex__latex__mathtools",
45-
"@texlive_texmf__texmf-dist__tex__latex__multirow",
46-
"@texlive_texmf__texmf-dist__tex__latex__pdflscape",
47-
"@texlive_texmf__texmf-dist__tex__latex__tocbibind",
48-
"@texlive_texmf__texmf-dist__tex__latex__todonotes",
49-
]
24+
# The document entry points live at the repository root (proposal.tex,
25+
# thesis.tex) so rules_latex's main-rooted staging mirrors the workspace
26+
# layout: every `\input`/`\include` path is written relative to the repo root,
27+
# which is also what keeps the template buildable on Overleaf unchanged.
28+
_PROPOSAL_SRCS = ["proposal.tex"] + glob(["proposal/**/*.tex"]) + _COMMON
5029

30+
_THESIS_SRCS = ["thesis.tex"] + glob(["thesis/**/*.tex"]) + _COMMON
5131

5232
latex_document(
5333
name = "proposal",
54-
srcs = glob(
55-
[
56-
"proposal/**/*.tex",
57-
"common/**/*.tex",
58-
"common/**/*.png",
59-
"common/**/*.jpeg",
60-
"common/**/*.bib",
61-
],
62-
) + TEX_DEPS,
63-
format = "pdf",
64-
cmd_flags = ["--bibtex-cmd=biber"],
65-
main = "proposal/main.tex",
34+
srcs = _PROPOSAL_SRCS,
35+
biber = True,
36+
main = "proposal.tex",
6637
)
6738

39+
# timeout = "long": the first compile primes Tectonic's cache online (~2 min);
40+
# subsequent runs are action-cache hits.
41+
latex_test(
42+
name = "proposal_compiles",
43+
timeout = "long",
44+
srcs = _PROPOSAL_SRCS,
45+
biber = True,
46+
main = "proposal.tex",
47+
)
6848

6949
latex_document(
7050
name = "thesis",
71-
srcs = glob(
72-
[
73-
"thesis/**/*.tex",
74-
"common/**/*.tex",
75-
"common/**/*.png",
76-
"common/**/*.jpeg",
77-
"common/**/*.bib",
78-
],
79-
) + TEX_DEPS,
80-
format = "pdf",
81-
cmd_flags = ["--bibtex-cmd=biber"],
82-
main = "thesis/main.tex",
51+
srcs = _THESIS_SRCS,
52+
biber = True,
53+
main = "thesis.tex",
54+
)
55+
56+
latex_test(
57+
name = "thesis_compiles",
58+
timeout = "long",
59+
srcs = _THESIS_SRCS,
60+
biber = True,
61+
main = "thesis.tex",
8362
)

MODULE.bazel

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Bzlmod module for the (unofficial) UQ EECS thesis/proposal template.
2+
3+
Builds two LaTeX documents (`//:proposal`, `//:thesis`) with rules_latex +
4+
Tectonic, plus a small Python toolchain via rules_python. Bzlmod-only: there
5+
is deliberately no WORKSPACE file.
6+
"""
7+
8+
module(
9+
name = "thesis",
10+
version = "0.0.0",
11+
)
12+
13+
bazel_dep(name = "rules_python", version = "2.0.2")
14+
bazel_dep(name = "rules_latex", version = "0.6.1")
15+
16+
# rules_latex is not on the Bazel Central Registry yet, so pin it to the
17+
# v0.6.1 release commit. To adopt a newer release, bump both this commit and
18+
# the bazel_dep version above.
19+
git_override(
20+
module_name = "rules_latex",
21+
commit = "05b25f37003d262239e6115a9adf7b690553fe80", # v0.6.1
22+
remote = "https://github.com/nicklambourne/rules_latex.git",
23+
)
24+
25+
# Hermetic Python toolchain + pip-resolved dependencies.
26+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
27+
python.defaults(python_version = "3.13")
28+
python.toolchain(python_version = "3.13")
29+
use_repo(python, "python_3_13")
30+
31+
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
32+
pip.parse(
33+
hub_name = "pypi",
34+
python_version = "3.13",
35+
requirements_lock = "//tools/build/python:requirements.txt",
36+
)
37+
use_repo(pip, "pypi")
38+
39+
# Tectonic-based LaTeX toolchain. The pinned TeX Live 2026 bundle ships
40+
# biblatex 3.21 + biber 2.21 natively, so the IEEE citation style the
41+
# documents use (see common/tex/packages.tex) works with no extra setup.
42+
tectonic = use_extension("@rules_latex//latex/toolchain:extensions.bzl", "tectonic")
43+
tectonic.toolchain()
44+
use_repo(tectonic, "rules_latex_tectonic_toolchains")
45+
46+
register_toolchains("@rules_latex_tectonic_toolchains//:all")

0 commit comments

Comments
 (0)