Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions .github/workflows/js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ jobs:
- name: Build augurs-js
run: just build-augurs-js

- name: Upload JS packages
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: js-packages
path: js/augurs

- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version-file: js/.node-version
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
- name: Install Rust toolchain
uses: moonrepo/setup-rust@ede6de059f8046a5e236c94046823e2af11ca670 # v1.2.2
with:
bins: cargo-nextest,just,mdbook
bins: cargo-nextest,just,mdbook,mdbook-langtabs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
192 changes: 192 additions & 0 deletions .github/workflows/test-book-examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
name: Test Book Examples

on:
# Run after Python and JS workflows complete on main
workflow_run:
workflows: ["Python", "augurs-js"]
types:
- completed
branches: [main]
# Also run on PRs that modify book content or JS/Python APIs
pull_request:
paths:
- "book/src/**/*.md"
- "book/scripts/**"
- ".github/workflows/test-book-examples.yml"
# JavaScript API changes
- "js/**/*.rs"
- "js/**/Cargo.toml"
# Python API changes
- "crates/pyaugurs/**/*.rs"
- "crates/pyaugurs/Cargo.toml"
- "crates/pyaugurs/augurs.pyi"
# Allow manual triggering
workflow_dispatch:
Comment thread Fixed

env:
CARGO_TERM_COLOR: always

permissions: {}

jobs:
test-examples:
name: Test Documentation Examples
runs-on: ubuntu-latest
# Only run if the triggering workflow succeeded (for workflow_run)
# or if manually triggered or on PR
if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || github.event.workflow_run.conclusion == 'success' }}

steps:
- name: Checkout repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
# For workflow_run, check out the correct ref
ref: ${{ github.event.workflow_run.head_branch || github.ref }}

# Set up Rust
- name: Install Rust toolchain
uses: moonrepo/setup-rust@ede6de059f8046a5e236c94046823e2af11ca670 # v1.2.2
with:
bins: just
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Set up Node.js
- name: Install Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: "20"

# Set up Python
- name: Install Python
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
with:
python-version: "3.11"

# Download artifacts from Python and JS workflows if available
# Note: artifacts are only available from workflow_run events on the same repo
- name: Download JS packages artifact
if: github.event_name == 'workflow_run'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: js-packages
path: js/augurs
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Download Python wheels
if: github.event_name == 'workflow_run'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: wheels-linux-x86_64
path: python-wheels
merge-multiple: true
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true

# For PRs and manual runs, build the packages
- name: Install wasm-pack (for PRs)
if: github.event_name != 'workflow_run'
uses: taiki-e/install-action@1ee706eb04986370fc60419ba172594c51067f29 # v2.62.58
with:
tool: wasm-pack

- name: Build JS packages (for PRs)
if: github.event_name != 'workflow_run'
run: just build-augurs-js
continue-on-error: true

- name: Install Python package
run: |
cd crates/pyaugurs
python -m venv .venv
.venv/bin/pip install numpy

# Try to install from wheel first (if available from workflow_run)
if [ -d "../../python-wheels" ] && [ -n "$(ls -A ../../python-wheels/*.whl 2>/dev/null)" ]; then
echo "Installing from downloaded wheel..."
.venv/bin/pip install ../../python-wheels/*.whl
else
echo "Building from source..."
.venv/bin/pip install maturin
.venv/bin/maturin develop --release
fi
continue-on-error: true

# Run test script
- name: Test examples with Python script
run: |
cd book
python3 scripts/test_examples.py

# Upload artifacts on failure
- name: Upload test artifacts
if: failure()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: test-examples-output
path: book/.test-examples/
retention-days: 7

# Optional: Check that examples are present in docs
verify-coverage:
name: Verify Example Coverage
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false

- name: Check for code examples in key files
run: |
echo "Checking for code examples in documentation..."

# Files that should have code examples
FILES=(
"book/src/getting-started/installation.md"
"book/src/getting-started/quick-start.md"
)

MISSING=0

for file in "${FILES[@]}"; do
if [ ! -f "$file" ]; then
echo "⚠ File not found: $file"
continue
fi

# Check for langtabs sections
if ! grep -q "<!-- langtabs-start -->" "$file"; then
echo "✗ Missing langtabs in: $file"
MISSING=$((MISSING + 1))
else
# Count code blocks
RUST_COUNT=$(grep -c '```rust' "$file" || true)
JS_COUNT=$(grep -c '```javascript' "$file" || true)
PY_COUNT=$(grep -c '```python' "$file" || true)

echo "✓ $file has examples:"
echo " - Rust: $RUST_COUNT"
echo " - JavaScript: $JS_COUNT"
echo " - Python: $PY_COUNT"

# Warn if languages are imbalanced
if [ $RUST_COUNT -gt 0 ] && [ $JS_COUNT -eq 0 ]; then
echo " ⚠ Missing JavaScript examples"
fi
if [ $RUST_COUNT -gt 0 ] && [ $PY_COUNT -eq 0 ]; then
echo " ⚠ Missing Python examples"
fi
fi
done

if [ $MISSING -gt 0 ]; then
echo ""
echo "Some key documentation files are missing code examples."
echo "This is a warning, not a failure."
fi
7 changes: 7 additions & 0 deletions book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ title = "augurs - a time series toolkit"

[rust]
edition = "2021"

[preprocessor.langtabs]
command = "mdbook-langtabs"

[output.html]
additional-css = ["langtabs.css"]
additional-js = ["langtabs.js"]
24 changes: 24 additions & 0 deletions book/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,27 @@ build:

test:
mdbook test -L ../target/debug/deps

# Test all code examples in documentation
test-examples:
python3 scripts/test_examples.py

# Test only Rust examples
test-rust:
python3 scripts/test_examples.py --lang rust

# Test only JavaScript examples
test-javascript:
python3 scripts/test_examples.py --lang javascript

# Test only Python examples
test-python:
python3 scripts/test_examples.py --lang python

# Run all tests (mdbook + examples)
test-all: test test-examples

# Install mdbook-langtabs preprocessor
install-langtabs:
cargo install mdbook-langtabs
mdbook-langtabs install .
136 changes: 136 additions & 0 deletions book/langtabs.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
.langtabs {
margin: 0.5em 0 1.5em 0;
font-family: var(--fonts);
}

.langtabs-header {
display: flex;
overflow-x: auto;
gap: 0.25rem;
border-bottom: 1px solid var(--icons);
padding-bottom: 1px;
margin-bottom: -1px;
position: relative;
z-index: 2;
}

.langtabs-header {
-webkit-overflow-scrolling: touch;
scrollbar-width: none; /* Firefox */
}

.langtabs-header::-webkit-scrollbar {
display: none; /* Chrome, Safari, Edge */
}

.langtabs-tab {
padding: 0.6rem 1.1rem;
background: none;
border: 1px solid transparent;
border-bottom: none;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
cursor: pointer;
white-space: nowrap;
display: flex;
align-items: center;
gap: 0.7rem;
color: var(--text);
font-size: 1.2rem;
font-weight: 400;
transition: all 0.15s ease;
position: relative;
top: 1px;
}

.langtabs-tab:hover {
color: var(--links);
background-color: rgba(0, 0, 0, 0.03);
}

.langtabs-tab.active {
color: var(--links); /* Use theme link color */
border-color: var(--icons);
border-bottom: 1px solid var(--bg);
background-color: var(--bg);
font-weight: 500;
}

.langtabs-icon {
width: 1.4em;
height: 1.4em;
font-size: 1.4em;
display: inline-flex;
align-items: center;
justify-content: center;
}

/* inactive tabs use text color, active tabs use theme link color */
.langtabs-tab .langtabs-icon {
color: inherit;
opacity: 0.8;
}

.langtabs-tab.active .langtabs-icon {
color: var(--links); /* Use theme link color */
opacity: 1;
}

.langtabs-content {
position: relative;
border: 1px solid var(--icons);
border-radius: 3px;
border-top-left-radius: 0;
overflow: hidden;
}

.langtabs-code {
display: none;
}

.langtabs-code.active {
display: block;
}

/* CodeBlock styling to match mdBook */
.langtabs-code pre {
margin: 0;
padding: 0;
background-color: var(--bg);
}

.langtabs-code pre code {
display: block;
padding: 1rem;
overflow-x: auto;
font-family: var(--mono-font);
font-size: 0.85em;
line-height: 1.5;
}

@media print {
.langtabs-tab:not(.active) {
display: none;
}

.langtabs-content {
border: 1px solid #ddd;
}

.langtabs-code.active {
display: block !important;
}
}

@media (max-width: 640px) {
.langtabs-tab {
padding: 0.5rem 0.8rem;
font-size: 1.1rem;
}

.langtabs-icon {
font-size: 1.3em;
width: 1.3em;
height: 1.3em;
}
}
Loading
Loading