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
83 changes: 33 additions & 50 deletions .github/workflows/deploy-docs.yaml → .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
name: Deploy Docs
name: Docs

on:
push:
branches:
- main
- "pull-request/[0-9]+"
tags:
- "v*"
workflow_dispatch:

concurrency:
group: deploy-docs
cancel-in-progress: false
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main' }}

permissions:
contents: write

jobs:
build-and-deploy:
build:
if: github.repository == 'NVIDIA/tilus'
runs-on: ubuntu-latest
steps:
Expand All @@ -34,7 +35,30 @@ jobs:
- name: Build docs
run: |
cd docs
sphinx-build -W source build/html
make html SPHINXOPTS="-W" # -W treats warnings as errors

- name: Upload docs artifact
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-artifact@v4
with:
name: docs-html
path: docs/build/html/

deploy:
needs: build
if: github.repository == 'NVIDIA/tilus' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Download docs artifact
uses: actions/download-artifact@v4
with:
name: docs-html
path: docs/build/html/

- name: Determine version directory
id: version
Expand Down Expand Up @@ -83,51 +107,10 @@ jobs:

# Update versions.json and generate root index.html
cd "$DEPLOY_DIR"
python3 << PYEOF
import json, pathlib

versions_file = pathlib.Path("versions.json")
versions = json.loads(versions_file.read_text()) if versions_file.exists() else []
# versions.json format: [{"slug": "stable", "label": "v0.2.0 (Stable)"}, ...]
slugs = {v["slug"] for v in versions}

version = "${VERSION_DIR}"
is_tag = "${IS_TAG}" == "true"

# Add the version entry if new
if version not in slugs:
versions.append({"slug": version, "label": version})
slugs.add(version)

# For tag releases, add or update the "stable" entry
if is_tag:
# Remove old stable entry
versions = [v for v in versions if v["slug"] != "stable"]
versions.append({"slug": "stable", "label": version + " (Stable)"})

# Sort: latest first, stable second, then tags in reverse order
def sort_key(v):
s = v["slug"]
if s == "latest":
return (0, "")
if s == "stable":
return (1, "")
return (2, s)
versions.sort(key=sort_key)
versions_file.write_text(json.dumps(versions, indent=2) + "\n")

# Generate root index.html
# Redirect to stable if it exists, otherwise latest
has_stable = any(v["slug"] == "stable" for v in versions)
target = "stable" if has_stable else "latest"
pathlib.Path("index.html").write_text(
"<!DOCTYPE html>\\n"
"<html>\\n"
f'<head><meta http-equiv="refresh" content="0; url={target}/index.html"></head>\\n'
f"<body><p>Redirecting to <a href=\\"{target}/index.html\\">{target} documentation</a>...</p></body>\\n"
"</html>\\n"
)
PYEOF
TAG_FLAG=""
if [[ "$IS_TAG" == "true" ]]; then TAG_FLAG="--is-tag"; fi
python3 "$GITHUB_WORKSPACE/.github/workflows/scripts/update_gh_pages.py" \
--version-dir "$VERSION_DIR" $TAG_FLAG

# Add .nojekyll to prevent GitHub Pages from ignoring _static
touch .nojekyll
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/scripts/update_gh_pages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""Update versions.json and root index.html for gh-pages deployment."""

import argparse
import json
import pathlib


def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--version-dir", required=True, help="Version directory name (e.g., 'latest' or 'v0.2.0')")
parser.add_argument("--is-tag", action="store_true", help="Whether this is a tag release")
args = parser.parse_args()

version = args.version_dir
is_tag = args.is_tag

# Update versions.json
versions_file = pathlib.Path("versions.json")
versions = json.loads(versions_file.read_text()) if versions_file.exists() else []
# versions.json format: [{"slug": "stable", "label": "v0.2.0 (Stable)"}, ...]
slugs = {v["slug"] for v in versions}

# Add the version entry if new
if version not in slugs:
versions.append({"slug": version, "label": version})
slugs.add(version)

# For tag releases, add or update the "stable" entry
if is_tag:
versions = [v for v in versions if v["slug"] != "stable"]
versions.append({"slug": "stable", "label": version + " (Stable)"})

# Sort: latest first, stable second, then tags in reverse order
def sort_key(v):
s = v["slug"]
if s == "latest":
return (0, "")
if s == "stable":
return (1, "")
return (2, s)

versions.sort(key=sort_key)
versions_file.write_text(json.dumps(versions, indent=2) + "\n")

# Generate root index.html — redirect to stable if it exists, otherwise latest
has_stable = any(v["slug"] == "stable" for v in versions)
target = "stable" if has_stable else "latest"
pathlib.Path("index.html").write_text(
"<!DOCTYPE html>\n"
"<html>\n"
f'<head><meta http-equiv="refresh" content="0; url={target}/index.html"></head>\n'
f'<body><p>Redirecting to <a href="{target}/index.html">{target} documentation</a>...</p></body>\n'
"</html>\n"
)


if __name__ == "__main__":
main()
78 changes: 44 additions & 34 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ jobs:
outputs:
should_run_tests: ${{ steps.changed-tests.outputs.any_changed }}
should_run_examples: ${{ steps.changed-examples.outputs.any_changed }}
should_run_docs: ${{ steps.changed-docs.outputs.any_changed }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
Expand Down Expand Up @@ -44,15 +43,47 @@ jobs:
pyproject.toml
base_sha: 'origin/main'

- name: Check for changes in docs
id: changed-docs
uses: step-security/changed-files@v46
test-python-compat:
needs: check-changes
if: github.repository == 'NVIDIA/tilus' && needs.check-changes.outputs.should_run_tests == 'true'
runs-on: linux-amd64-gpu-l4-latest-1
container:
image: nvidia/cuda:12.6.2-devel-ubuntu22.04
options: --gpus all
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
files: |
python/**
docs/**
pyproject.toml
base_sha: 'origin/main'
fetch-depth: 0

- name: Install dependencies
run: |
apt-get update && apt-get install -y git cmake nodejs software-properties-common
add-apt-repository -y ppa:deadsnakes/ppa
apt-get update && apt-get install -y python3.10 python3.10-venv python3.10-dev \
python3.11 python3.11-venv python3.11-dev \
python3.12 python3.12-venv python3.12-dev \
python3.13 python3.13-venv python3.13-dev

- name: Mark repo as safe for git
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: Run smoke tests across Python versions
run: |
for pyver in 3.10 3.11 3.12 3.13; do
echo "========================================="
echo "Testing Python $pyver"
echo "========================================="
python${pyver} -m venv /tmp/venv-${pyver}
source /tmp/venv-${pyver}/bin/activate
pip install --upgrade pip
pip install build
python -m build .
pip install dist/*.whl[dev]
pytest tests/kernels/matmul/test_matmul_v2.py -v
deactivate
rm -rf /tmp/venv-${pyver} dist/
done

test-core:
needs: check-changes
Expand Down Expand Up @@ -81,27 +112,6 @@ jobs:
- name: Run main tests
run: pytest ./tests --ignore=tests/examples/

docs:
needs: check-changes
if: github.repository == 'NVIDIA/tilus' && needs.check-changes.outputs.should_run_docs == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup and Install Tilus
id: setup-and-install
uses: ./.github/actions/setup-environment
with:
python-version: '3.10'

- name: Build docs
run: |
cd docs
sphinx-build -W source build/html

test-examples:
needs: check-changes
if: github.repository == 'NVIDIA/tilus' && needs.check-changes.outputs.should_run_examples == 'true'
Expand All @@ -127,21 +137,21 @@ jobs:

all-functional-tests:
name: All Functional Tests
needs: [test-core, docs, test-examples]
needs: [test-python-compat, test-core, test-examples]
if: always() && github.repository == 'NVIDIA/tilus'
runs-on: ubuntu-latest
steps:
- name: Check job results
run: |
echo "Python compat result: ${{ needs.test-python-compat.result }}"
echo "Core tests result: ${{ needs.test-core.result }}"
echo "Docs result: ${{ needs.docs.result }}"
echo "Example tests result: ${{ needs.test-examples.result }}"

# Check if any required job failed
if [[ "${{ needs.test-core.result }}" == "failure" ]] || [[ "${{ needs.docs.result }}" == "failure" ]] || [[ "${{ needs.test-examples.result }}" == "failure" ]]; then
if [[ "${{ needs.test-python-compat.result }}" == "failure" ]] || [[ "${{ needs.test-core.result }}" == "failure" ]] || [[ "${{ needs.test-examples.result }}" == "failure" ]]; then
echo "One or more functional tests failed"
exit 1
elif [[ "${{ needs.test-core.result }}" == "cancelled" ]] || [[ "${{ needs.docs.result }}" == "cancelled" ]] || [[ "${{ needs.test-examples.result }}" == "cancelled" ]]; then
elif [[ "${{ needs.test-python-compat.result }}" == "cancelled" ]] || [[ "${{ needs.test-core.result }}" == "cancelled" ]] || [[ "${{ needs.test-examples.result }}" == "cancelled" ]]; then
echo "One or more functional tests were cancelled"
exit 1
else
Expand Down
Loading