Skip to content

Commit 8e1ec12

Browse files
committed
jbook2
1 parent 4eb8ec9 commit 8e1ec12

File tree

12 files changed

+157
-131
lines changed

12 files changed

+157
-131
lines changed

.github/.kodiak.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# https://kodiakhq.com/docs/recipes
2-
version = 1
3-
4-
[merge]
5-
method = "squash"
6-
block_on_neutral_required_check_runs = true
7-
[merge.message]
8-
title = "pull_request_title"
9-
body = "pull_request_body"
1+
# https://kodiakhq.com/docs/recipes
2+
version = 1
3+
4+
[merge]
5+
method = "squash"
6+
block_on_neutral_required_check_runs = true
7+
[merge.message]
8+
title = "pull_request_title"
9+
body = "pull_request_body"

.github/ci.jl

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
1-
using IJulia
21
using JSON
3-
using Pkg
2+
using Literate
3+
44
ENV["GKSwstype"] = "100"
55

6-
function main(;
7-
basedir=get(ENV, "DOCDIR", "docs"),
8-
cachedir=get(ENV, "NBCACHE", ".cache"),
9-
rmsvg=true)
10-
nb = get(ENV, "NB", "test.ipynb")
11-
IJulia.installkernel("Julia", "--project=@.")
12-
# nbconvert command options
13-
kernelname = "--ExecutePreprocessor.kernel_name=julia-1.$(VERSION.minor)"
14-
execute = ifelse(get(ENV, "ALLOWERRORS", "false") == "true", "--execute --allow-errors", "--execute")
15-
timeout = "--ExecutePreprocessor.timeout=" * get(ENV, "TIMEOUT", "-1")
16-
nbout = joinpath(abspath(pwd()), cachedir, nb)
17-
mkpath(dirname(nbout))
18-
cmd = `jupyter nbconvert --to notebook $(execute) $(timeout) $(kernelname) --output $(nbout) $(nb)`
19-
run(cmd)
20-
rmsvg && strip_svg(nbout)
6+
function main(; rmsvg=true)
7+
file = get(ENV, "NB", "test.ipynb")
8+
cachedir = get(ENV, "NBCACHE", ".cache")
9+
nb = if endswith(file, ".jl")
10+
run_literate(file; cachedir)
11+
elseif endswith(file, ".ipynb")
12+
lit = to_literate(file)
13+
run_literate(lit; cachedir)
14+
else
15+
error("$(file) is not a valid notebook file!")
16+
end
17+
rmsvg && strip_svg(nb)
2118
return nothing
2219
end
2320

@@ -42,4 +39,35 @@ function strip_svg(ipynb)
4239
return ipynb
4340
end
4441

42+
# Convert a Jupyter notebook into a Literate notebook. Adapted from https://github.com/JuliaInterop/NBInclude.jl.
43+
function to_literate(nbpath; shell_or_help = r"^\s*[;?]")
44+
nb = open(JSON.parse, nbpath, "r")
45+
jlpath = splitext(nbpath)[1] * ".jl"
46+
open(jlpath, "w") do io
47+
separator = ""
48+
for cell in nb["cells"]
49+
if cell["cell_type"] == "code"
50+
s = join(cell["source"])
51+
isempty(strip(s)) && continue # Jupyter doesn't number empty cells
52+
occursin(shell_or_help, s) && continue # Skip cells with shell and help commands
53+
print(io, separator, "#---\n", s) # Literate code block mark
54+
separator = "\n\n"
55+
elseif cell["cell_type"] == "markdown"
56+
txt = join(cell["source"])
57+
print(io, separator, "#===\n", txt, "\n===#")
58+
separator = "\n\n"
59+
end
60+
end
61+
end
62+
return jlpath
63+
end
64+
65+
function run_literate(file; cachedir = ".cache")
66+
outpath = joinpath(abspath(pwd()), cachedir, dirname(file))
67+
mkpath(outpath)
68+
ipynb = Literate.notebook(file, dirname(file); mdstrings=true, execute=true)
69+
cp(ipynb, joinpath(outpath, basename(ipynb)); force=true)
70+
return ipynb
71+
end
72+
4573
main()

.github/workflows/automerge.yml

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
# A variant of https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions
2-
name: Dependabot auto-merge
3-
on: pull_request
4-
5-
permissions:
6-
contents: write
7-
pull-requests: write
8-
9-
jobs:
10-
dependabot:
11-
runs-on: ubuntu-slim
12-
if: github.event.pull_request.user.login == 'dependabot[bot]'
13-
steps:
14-
- name: Dependabot metadata
15-
id: metadata
16-
uses: dependabot/fetch-metadata@v2
17-
with:
18-
github-token: "${{ secrets.GITHUB_TOKEN }}"
19-
- name: Enable auto-merge for Dependabot PRs
20-
run: gh pr edit "$PR_URL" --add-label "automerge"
21-
env:
22-
PR_URL: ${{ github.event.pull_request.html_url }}
23-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1+
# A variant of https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions
2+
name: Dependabot auto-merge
3+
on: pull_request
4+
5+
permissions:
6+
contents: write
7+
pull-requests: write
8+
9+
jobs:
10+
dependabot:
11+
runs-on: ubuntu-slim
12+
if: github.event.pull_request.user.login == 'dependabot[bot]'
13+
steps:
14+
- name: Dependabot metadata
15+
id: metadata
16+
uses: dependabot/fetch-metadata@v2
17+
with:
18+
github-token: "${{ secrets.GITHUB_TOKEN }}"
19+
- name: Enable auto-merge for Dependabot PRs
20+
run: gh pr edit "$PR_URL" --add-label "automerge"
21+
env:
22+
PR_URL: ${{ github.event.pull_request.html_url }}
23+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/ci.yml

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ concurrency:
1212
cancel-in-progress: true
1313

1414
env:
15-
NBCACHE: ".cache"
15+
JULIA_CI: 'true'
1616
JULIA_CONDAPKG_BACKEND: 'Null'
1717
JULIA_CONDAPKG_OFFLINE: 'true'
1818
JULIA_CPU_TARGET: 'generic;icelake-server,clone_all;znver3,clone_all'
19-
JULIA_CI: 'true'
2019
JULIA_NUM_THREADS: 'auto'
21-
TIMEOUT: '600'
22-
ALLOWERRORS: 'false'
23-
PY_VER: '3.13'
20+
NBCACHE: '.cache'
21+
PY_VER: '3.14'
2422

2523
jobs:
2624
setup:
@@ -65,19 +63,17 @@ jobs:
6563
arch: ${{ runner.arch }}
6664
- name: Install Julia packages
6765
if: ${{ steps.cache-julia.outputs.cache-hit != 'true' }}
68-
shell: julia --color=yes {0}
66+
shell: julia --color=yes --project=@. {0}
6967
run: |
7068
using Pkg, Dates
71-
Pkg.add(["IJulia", "JSON"])
72-
Pkg.activate(".")
7369
Pkg.instantiate()
7470
Pkg.precompile()
7571
if ENV["RUNNER_ENVIRONMENT"] == "github-hosted"
7672
Pkg.gc(;collect_delay=Day(0))
7773
end
7874
- name: List notebooks as a JSON array
7975
id: set-matrix
80-
run: echo "matrix=$(python -c 'import glob, json; print(json.dumps(glob.glob("**/*.ipynb", root_dir="docs", recursive=True)))')" >> "$GITHUB_OUTPUT"
76+
run: echo "matrix=$(python -c 'import glob, json; print(json.dumps(glob.glob("**/*.ipynb", root_dir="docs", recursive=True) + glob.glob("**/*.jl", root_dir="docs", recursive=True)))')" >> "$GITHUB_OUTPUT"
8177

8278
execute:
8379
needs: setup
@@ -116,6 +112,7 @@ jobs:
116112
with:
117113
version: ${{ needs.setup.outputs.ver }}
118114
arch: ${{ runner.arch }}
115+
show-versioninfo: 'true'
119116
- name: Restore Julia packages
120117
uses: actions/cache/restore@v5
121118
if: ${{ steps.nb-cache.outputs.cache-hit != 'true' }}
@@ -150,15 +147,24 @@ jobs:
150147
merge-multiple: true
151148
- name: Copy back built notebooks
152149
run: cp --verbose -rf ${{ env.NBCACHE }}/docs/* docs/
153-
- name: Setup Quarto
154-
uses: quarto-dev/quarto-actions/setup@v2
155-
- name: Render Quarto Project
156-
run: quarto render docs --to html
157-
- name: Upload artifact for GH pages
158-
uses: actions/upload-pages-artifact@v4
150+
- name: Setup Python
151+
uses: actions/setup-python@v6
152+
id: setup-python
153+
with:
154+
python-version: ${{ env.PY_VER }}
155+
- name: Install the latest version of uv
156+
uses: astral-sh/setup-uv@v7
157+
- name: Install Python dependencies
158+
run: uv pip install --system -r requirements.txt
159+
- name: Build website
160+
env:
161+
BASE_URL: /${{ github.event.repository.name }}
162+
run: jupyter-book build --html
163+
- name: Upload pages artifact
159164
if: ${{ github.ref == 'refs/heads/main' }}
165+
uses: actions/upload-pages-artifact@v4
160166
with:
161-
path: docs/_site/
167+
path: './_build/html'
162168

163169
# CI conclusion for GitHub status check
164170
# Adaped from https://brunoscheufler.com/blog/2022-04-09-the-required-github-status-check-that-wasnt
@@ -178,7 +184,7 @@ jobs:
178184
179185
# Deployment job
180186
deploy:
181-
name: Deploy to GitHub pages
187+
name: Deploy to GitHub pages and Notebook branch
182188
needs: render
183189
if: ${{ github.ref == 'refs/heads/main' }}
184190
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment

.github/workflows/linkcheck.yml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,27 @@ concurrency:
1616
group: ${{ github.workflow }}-${{ github.ref }}
1717
cancel-in-progress: true
1818

19+
env:
20+
PY_VER: '3.14'
21+
1922
jobs:
2023
linkcheck:
21-
env:
22-
DIR: 'docs'
2324
runs-on: ubuntu-latest
25+
permissions:
26+
issues: write # required for peter-evans/create-issue-from-file
2427
steps:
2528
- name: Checkout
2629
uses: actions/checkout@v6
27-
- name: Set up Python
30+
- name: Setup Python
2831
uses: actions/setup-python@v6
32+
id: setup-python
2933
with:
30-
python-version: '3.x'
31-
- name: Install requirements
34+
python-version: ${{ env.PY_VER }}
35+
- name: Install nbconvert
3236
run: pip install nbconvert
3337
- name: Convert ipynb files to markdown
3438
run: >
35-
find ${{ env.DIR }} -type f -name '*.ipynb' |
39+
find docs/ -type f -name '*.ipynb' |
3640
parallel jupyter nbconvert --to markdown {}
3741
- name: Restore lychee cache
3842
id: restore-cache
@@ -41,13 +45,13 @@ jobs:
4145
path: .lycheecache
4246
key: cache-lychee-${{ github.sha }}
4347
restore-keys: cache-lychee-
44-
- name: Lychee link check
45-
uses: lycheeverse/lychee-action@v2.7.0
48+
- name: Lychee Checker
49+
uses: lycheeverse/lychee-action@v2
4650
id: lychee
4751
with:
4852
fail: false
4953
failIfEmpty: false
50-
args: --accept 200,204,429 --verbose --no-progress --cache --max-cache-age 1d "${{ env.DIR }}/**/*.md" "${{ env.DIR }}/**/*.qmd" "${{ env.DIR }}/**/*.jl"
54+
args: '--accept 200,204,429 --verbose --no-progress --cache --max-cache-age 1d "docs/**/*.md" "docs/**/*.jl"'
5155
env:
5256
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5357
- name: Create Issue From File

.github/workflows/update-manifest.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
uses: julia-actions/setup-julia@v2
3131
with:
3232
version: '1'
33+
arch: ${{ runner.arch }}
3334
- name: Update Julia dependencies
3435
env:
3536
JULIA_PKG_PRECOMPILE_AUTO: '0'

Manifest.toml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
julia_version = "1.12.3"
44
manifest_format = "2.0"
5-
project_hash = "dd841a67f83de9192b83c10324ed0dda966dd0dd"
5+
project_hash = "fef8182752b68577debb0fe3f26aacaa85f7dbfb"
66

77
[[deps.ADTypes]]
88
git-tree-sha1 = "8b2b045b22740e4be20654175cc38291d48539db"
@@ -868,6 +868,12 @@ git-tree-sha1 = "68c173f4f449de5b438ee67ed0c9c748dc31a2ec"
868868
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
869869
version = "0.3.28"
870870

871+
[[deps.IOCapture]]
872+
deps = ["Logging", "Random"]
873+
git-tree-sha1 = "0ee181ec08df7d7c911901ea38baf16f755114dc"
874+
uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
875+
version = "1.0.0"
876+
871877
[[deps.IfElse]]
872878
git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1"
873879
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
@@ -1220,6 +1226,12 @@ version = "3.54.0"
12201226
Sparspak = "e56a9233-b9d6-4f03-8d0f-1825330902ac"
12211227
blis_jll = "6136c539-28a5-5bf0-87cc-b183200dce32"
12221228

1229+
[[deps.Literate]]
1230+
deps = ["Base64", "IOCapture", "JSON", "REPL"]
1231+
git-tree-sha1 = "bb26d8b8ed0fa451ce3511e99c950653a2f31fe1"
1232+
uuid = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
1233+
version = "2.21.0"
1234+
12231235
[[deps.LogExpFunctions]]
12241236
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
12251237
git-tree-sha1 = "13ca9e2586b89836fd20cccf56e57e2b9ae7f38f"

Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ authors = ["Wen-Wei Tseng <sosiristseng@gmail.com>"]
77
DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def"
88
DisplayAs = "0b91fe84-8a4c-11e9-3e1d-67c38462b6d6"
99
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
10+
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
1011
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
1112
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
13+
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
1214
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
1315
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
1416
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
@@ -20,5 +22,7 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
2022

2123
[compat]
2224
ForwardDiff = "1"
25+
JSON = "1.3.0"
2326
Latexify = "0.16"
27+
Literate = "2.21.0"
2428
ModelingToolkit = "10"

docs/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs/_quarto.yml

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)