Skip to content
Draft
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
59 changes: 59 additions & 0 deletions .github/workflows/deploy-redirects.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Deploy docs.rapids.ai compatibility site

on:
schedule:
- cron: "0 9 * * *"
workflow_dispatch:
push:
branches:
- main

concurrency:
group: deploy-docs-rapids-ai-redirects
cancel-in-progress: false

defaults:
run:
shell: bash

permissions:
contents: read
id-token: write

jobs:
deploy:
name: Assemble and deploy compatibility site
runs-on: ubuntu-latest
env:
RAPIDS_DOCS_BASE_URL: https://docs.rapids.ai/
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
- name: Install dependencies
run: uv sync --locked
- name: Build and validate portal
run: make check
- name: Configure source AWS credentials
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}
role-duration-seconds: 7200
- name: Assemble and validate API documentation
run: make assemble
- name: Generate compatibility redirects
run: |
uv run python scripts/generate_redirect_site.py \
--output _site/_redirects
- name: Deploy compatibility site to docs.rapids.ai
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_API_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DOCS_SITE_ID }}
run: | # zizmor: ignore[adhoc-packages]
npm install --global --force @aschmidt8/netlify-cli
netlify deploy --prod --debug --dir=_site
95 changes: 72 additions & 23 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ defaults:
run:
shell: bash
permissions:
id-token: write
contents: read
jobs:
build:
name: Build (and deploy)
name: Build and publish NVIDIA docs portal
runs-on: ubuntu-latest
env:
RAPIDS_DOCS_BASE_URL: https://docs.nvidia.com/datascience/
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand All @@ -32,26 +33,74 @@ jobs:
run: uv sync --locked
- name: Build and validate portal
run: make check
- uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 #v5.1.1
- name: Configure NVIDIA docs AWS credentials
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}
role-duration-seconds: 7200 # 2h
- name: Assemble complete documentation site
run: make assemble
- name: Deploy site
aws-access-key-id: ${{ secrets.NVIDIA_DOCS_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.NVIDIA_DOCS_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.NVIDIA_DOCS_AWS_REGION }}
unset-current-credentials: true
- name: Publish portal to NVIDIA docs S3
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_API_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DOCS_SITE_ID }}
# TODO: use official netlify-cli pkg after https://github.com/netlify/cli/issues/1809
# is resolved and deployed.
run: | # zizmor: ignore[adhoc-packages]
npm install --global --force @aschmidt8/netlify-cli

ARGS=""
if [ "$GITHUB_REF_NAME" = "main" ]; then
ARGS="--prod"
fi
netlify deploy "$ARGS" \
--debug \
--dir=_site
TARGET_BUCKET: ${{ secrets.NVIDIA_DOCS_S3_BUCKET }}
run: |
# The deployment repository owns this subtree. Excluded objects are also
# protected from --delete by the AWS CLI.
aws s3 sync --delete \
--exclude 'deployment/*' \
_site "s3://${TARGET_BUCKET}/developer/docs/datascience"
- name: Check out Akamai request template
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: rapidsai/shared-actions
ref: main
path: shared-actions
persist-credentials: false
sparse-checkout: publish-docs
- name: Install Akamai request dependencies
run: |
sudo apt-get update
sudo apt-get install --yes --no-install-recommends xsltproc
- name: Prepare Akamai cache flush request
env:
AKAMAI_ACCESS_TOKEN: ${{ secrets.NVIDIA_DOCS_AKAMAI_ACCESS_TOKEN }}
AKAMAI_CLIENT_SECRET: ${{ secrets.NVIDIA_DOCS_AKAMAI_CLIENT_SECRET }}
AKAMAI_CLIENT_TOKEN: ${{ secrets.NVIDIA_DOCS_AKAMAI_CLIENT_TOKEN }}
AKAMAI_EMAILS_TO_NOTIFY: ${{ secrets.NVIDIA_DOCS_AKAMAI_EMAILS_TO_NOTIFY }}
AKAMAI_HOST: ${{ secrets.NVIDIA_DOCS_AKAMAI_HOST }}
run: |
umask 077
{
echo '[default]'
echo "client_secret = ${AKAMAI_CLIENT_SECRET}"
echo "host = ${AKAMAI_HOST}"
echo "access_token = ${AKAMAI_ACCESS_TOKEN}"
echo "client_token = ${AKAMAI_CLIENT_TOKEN}"
} > ~/.edgerc
xsltproc \
--stringparam target-path datascience \
shared-actions/publish-docs/akamai-eccu-flush.xslt \
shared-actions/publish-docs/akamai-eccu-flush.xslt \
| sed 's/xmlns:match="x" //' > /tmp/flush.xml
jq -Rnc \
--arg emails "${AKAMAI_EMAILS_TO_NOTIFY}" \
'$emails | split(",") | map(select(length > 0))' \
> /tmp/email-addresses.json
- name: Submit Akamai cache flush request
env:
REQUEST_NAME: rapidsai-docs-${{ github.run_id }}
run: |
uv tool run --from httpie-edgegrid http \
--ignore-stdin \
--auth-type edgegrid \
-a default: \
:/eccu-api/v1/requests \
metadata=@/tmp/flush.xml \
propertyName=docs.nvidia.com \
propertyNameExactMatch=true \
propertyType=HOST_HEADER \
requestName="${REQUEST_NAME}" \
statusUpdateEmails:=@/tmp/email-addresses.json
- name: Delete Akamai credentials
if: always()
run: rm -f ~/.edgerc
10 changes: 8 additions & 2 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ jobs:
permissions:
contents: read
id-token: write
env:
RAPIDS_DOCS_BASE_URL: https://docs.rapids.ai/
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -55,11 +57,15 @@ jobs:
run: uv sync --locked
- name: Build and validate portal
run: make check
- name: Configure AWS credentials
- name: Configure source AWS credentials
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}
role-duration-seconds: 7200
- name: Assemble and validate complete documentation site
- name: Assemble and validate API documentation
run: make assemble
- name: Generate compatibility redirects
run: |
uv run python scripts/generate_redirect_site.py \
--output _site/_redirects
5 changes: 3 additions & 2 deletions 404.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ orphan: true
We could not find the page you were looking for.

<script defer>
if (window.location.pathname.match(/^\/api.*/)) {
const portalBase = new URL("{{ site_baseurl }}");
if (window.location.pathname.startsWith(`${portalBase.pathname}api`)) {
var redirectEl = document.createElement("p");
redirectEl.innerHTML = "Redirecting you to the latest documentation in 5 seconds..."
(document.querySelector("article") || document.body).appendChild(redirectEl);
setTimeout(function() {
window.location.href = '/api/';
window.location.href = new URL("api/", portalBase).href;
}, 5000);
}
</script>
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# NVIDIA RAPIDS Documentation

This repository contains the source for the
[NVIDIA RAPIDS documentation site](https://docs.rapids.ai/). The site is built
[NVIDIA RAPIDS documentation site](https://docs.nvidia.com/datascience/). The site is built
with Sphinx and the NVIDIA Sphinx theme.

## Build the site
Expand All @@ -16,17 +16,28 @@ make serve
The rendered site is written to `_site`. The server uses port 8000 by default;
override it with `PORT` (for example, `make serve PORT=8080`).

## Build the full site
## Build the docs.rapids.ai compatibility site

The complete docs site imports versioned API documentation and the deployment
documentation from the private `rapidsai-docs` S3 bucket. Configure a read-only
AWS profile named `rapids-docs`, then run:
The compatibility site imports versioned API documentation and deployment
documentation from the private `rapidsai-docs` S3 bucket. It continues to serve
real API content from `docs.rapids.ai/api/<library>` until each library migrates
to `docs.nvidia.com`. Configure a read-only AWS profile named `rapids-docs`, then
run:

```shell
AWS_PROFILE=rapids-docs make full
```

This applies the RAPIDS library/version selectors to the imported documentation.
Generate the Netlify redirect file after assembly:

```shell
uv run python scripts/generate_redirect_site.py --output _site/_redirects
```

The generated rules redirect portal pages and only those library versions whose
migration metadata points at `docs.nvidia.com`. Unmatched API routes and shared
assets remain real files in the assembled site.

## Validation

Expand All @@ -37,10 +48,17 @@ make check
Run checks including linting, tests, and a local build.

Pull requests opened against `rapidsai/docs` are copied to a
`pull-request/<number>` branch by the RAPIDS copy-PR bot. That branch runs the
same validation and dry-runs assembly of the complete S3-backed documentation
tree without deploying it. Netlify's repository integration separately creates
a site preview. Merges to `main` deploy the production site.
`pull-request/<number>` branch by the RAPIDS copy-PR bot. That branch builds the
full `docs.rapids.ai` compatibility site and validates its generated redirects.
Netlify's repository integration separately creates a site preview.

Merges to `main` and the daily scheduled workflow publish the portal to
`docs.nvidia.com/datascience/`. The independently published
`docs.nvidia.com/datascience/deployment/` subtree is explicitly preserved.
The companion compatibility workflow assembles and publishes the remaining API
documentation to `docs.rapids.ai`, with redirects for migrated API versions and
portal routes. Both automated and manually triggered compatibility deployments
use permanent HTTP 301 redirects.

## Repository layout

Expand Down
17 changes: 1 addition & 16 deletions extensions/rapids_docs/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,7 @@

"""Render the API documentation listings."""


def _version_label(project: dict, version_name: str, releases: dict) -> str:
override = project.get("version-overrides", {}).get(version_name)
if override:
return str(override)
version_key = "ucxx_version" if "ucxx" in project["path"].lower() else "version"
return str(releases[version_name][version_key])


def _documentation_url(project: dict, version_name: str, version: str) -> str:
first_docs_nvidia_com_release = project["first_docs_nvidia_com_release"]
if first_docs_nvidia_com_release and tuple(map(int, version.split("."))) >= tuple(
map(int, first_docs_nvidia_com_release.split("."))
):
return f"https://docs.nvidia.com/{project['path']}/{version}/"
return f"https://docs.rapids.ai/api/{project['path']}/{version_name}/"
from .routes import _documentation_url, _version_label


def _api_docs(data: dict, section: str) -> str:
Expand Down
3 changes: 3 additions & 0 deletions extensions/rapids_docs/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def _jinja_environment(app) -> Environment:

def _context(app, docname: str = "index") -> dict:
data = app.rapids_portal_data
config = getattr(app, "config", None)
site_baseurl = getattr(config, "html_baseurl", "https://docs.nvidia.com/datascience/")
return {
**data,
"api_docs": lambda section: _api_docs(data, section),
Expand All @@ -36,6 +38,7 @@ def _context(app, docname: str = "index") -> dict:
),
"platform_support_content": lambda: _platform_support(data),
"previous_schedules": lambda: _previous_schedules(data),
"site_baseurl": site_baseurl.rstrip("/") + "/",
}


Expand Down
8 changes: 5 additions & 3 deletions extensions/rapids_docs/notices.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from bs4 import BeautifulSoup

from .dates import _date, _long_date
from .routes import _site_url

_NOTICE_STATUS_COLORS = {"blue", "green", "purple", "red", "yellow"}

Expand Down Expand Up @@ -103,11 +104,12 @@ def _build_rss(app, exception) -> None:
ElementTree.SubElement(
channel, "description"
).text = "Notices communicate and document changes in RAPIDS for contributors, developers, users, and the community."
ElementTree.SubElement(channel, "link").text = "https://docs.rapids.ai/notices/"
base_url = app.config.html_baseurl
ElementTree.SubElement(channel, "link").text = _site_url(base_url, "/notices/")
ElementTree.SubElement(
channel,
"{http://www.w3.org/2005/Atom}link",
href="https://docs.rapids.ai/notices/feed.xml",
href=_site_url(base_url, "/notices/feed.xml"),
rel="self",
type="application/rss+xml",
)
Expand All @@ -129,7 +131,7 @@ def _build_rss(app, exception) -> None:
ElementTree.SubElement(item, "description").text = html.unescape(description)
published = notice.get("notice_updated") or notice["notice_created"]
ElementTree.SubElement(item, "pubDate").text = _rss_date(published)
url = f"https://docs.rapids.ai/notices/{Path(notice['docname']).name}/"
url = _site_url(base_url, f"/notices/{Path(notice['docname']).name}/")
ElementTree.SubElement(item, "link").text = url
ElementTree.SubElement(item, "guid", isPermaLink="true").text = url
for category in [*notice.get("tags", []), *notice.get("categories", [])]:
Expand Down
Loading
Loading