Skip to content
Open
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
123 changes: 123 additions & 0 deletions .github/actions/publish-api-docs/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Create API Docs PR
description: Generates API docs for all packages and creates a pull request in SAP/ai-sdk.

inputs:
token:
description: 'GitHub App token with write access to SAP/ai-sdk.'
required: true
bot-email:
description: 'Email for the bot git config.'
required: true
bot-name:
description: 'Name for the bot git config.'
required: true

runs:
using: composite
steps:
- name: Get versions from pyproject.toml
id: versions
shell: bash
run: |
get_major() {
grep -m1 '^version' "packages/$1/pyproject.toml" \
| sed 's/version = "\(.*\)"/\1/' \
| cut -d. -f1
}
echo "base-major=$(get_major base)" >> "$GITHUB_OUTPUT"
echo "core-major=$(get_major core)" >> "$GITHUB_OUTPUT"
echo "gen-major=$(get_major gen)" >> "$GITHUB_OUTPUT"

- name: Generate pydoc docs for base and core
shell: bash
run: |
generate_docs() {
(
cd "packages/$1/docs"
uv run make
)
}
generate_docs base
generate_docs core

- name: Build Sphinx docs for gen
shell: bash
working-directory: packages/gen/docs
run: uv run make

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: SAP/ai-sdk
path: ai-sdk
token: ${{ inputs.token }}
persist-credentials: true

- name: Copy API docs
shell: bash
env:
BASE_MAJOR: ${{ steps.versions.outputs.base-major }}
CORE_MAJOR: ${{ steps.versions.outputs.core-major }}
GEN_MAJOR: ${{ steps.versions.outputs.gen-major }}
run: |
rsync -avz --delete packages/base/docs/build/html/ "ai-sdk/static/api/python/base/v${BASE_MAJOR}/"
rsync -avz --delete packages/core/docs/build/html/ "ai-sdk/static/api/python/core/v${CORE_MAJOR}/"
rsync -avz --delete packages/gen/docs/build/html/ "ai-sdk/static/api/python/gen/v${GEN_MAJOR}/"

- name: Check for changes
id: check-changes
shell: bash
working-directory: ai-sdk
run: |
if test -z "$(git status --porcelain)"; then
echo "docs=false" >> "$GITHUB_OUTPUT"
else
echo "docs=true" >> "$GITHUB_OUTPUT"
fi

- name: Commit and push changes
if: steps.check-changes.outputs.docs == 'true'
shell: bash
env:
GH_TOKEN: ${{ inputs.token }}
BOT_EMAIL: ${{ inputs.bot-email }}
BOT_NAME: ${{ inputs.bot-name }}
BASE_MAJOR: ${{ steps.versions.outputs.base-major }}
CORE_MAJOR: ${{ steps.versions.outputs.core-major }}
GEN_MAJOR: ${{ steps.versions.outputs.gen-major }}
BRANCH_NAME: docs/api-update-python-${{ github.run_id }}
run: |
gh auth setup-git

cd ai-sdk
git config user.email "$BOT_EMAIL"
git config user.name "$BOT_NAME"
git checkout -b "$BRANCH_NAME"
git add -A
git commit -m "Update SAP AI SDK for Python API documentation (base v${BASE_MAJOR}, core v${CORE_MAJOR}, gen v${GEN_MAJOR})"
git push -u origin "$BRANCH_NAME"

- name: Create pull request
if: steps.check-changes.outputs.docs == 'true'
shell: bash
env:
GH_TOKEN: ${{ inputs.token }}
BASE_MAJOR: ${{ steps.versions.outputs.base-major }}
CORE_MAJOR: ${{ steps.versions.outputs.core-major }}
GEN_MAJOR: ${{ steps.versions.outputs.gen-major }}
BRANCH_NAME: docs/api-update-python-${{ github.run_id }}
WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
gh pr create \
--repo SAP/ai-sdk \
--base main \
--head "$BRANCH_NAME" \
--title "chore: Update API documentation (Python)" \
--body "Update the API documentation for SAP Cloud SDK for AI, Python.

| Package | Version |
|---------|---------|
| base | v${BASE_MAJOR} |
| core | v${CORE_MAJOR} |
| gen | v${GEN_MAJOR} |

Automatically generated by the [api-docs workflow run]($WORKFLOW_URL)."
6 changes: 4 additions & 2 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ runs:

- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 #v8.2.0
with:
uv-version: "0.11.16"
- name: Install dependencies
shell: bash
env:
Expand All @@ -51,10 +53,10 @@ runs:
if [[ "$IS_FORK" == "true" ]]; then
echo "Fork detected — syncing from PyPI without lockfile"
UV_INDEX_URL="https://pypi.org/simple/" \
uv sync --all-packages --all-extras
uv sync --all-packages --all-extras --no-group docs
else
echo "Syncing from Artifactory with lockfile"
UV_INDEX_ARTIFACTORY_USERNAME="${INDEX_USERNAME}" \
UV_INDEX_ARTIFACTORY_PASSWORD="${INDEX_TOKEN}" \
uv sync --all-packages --all-extras --locked
uv sync --all-packages --all-extras --locked --no-group docs
fi
5 changes: 2 additions & 3 deletions .github/workflows/auto-doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ jobs:
generate_docs() {
(
cd packages/$1/docs
rm -f *.html
uv run python -m pydoc -w ../ || true
uv run make
)
}

Expand All @@ -59,6 +58,6 @@ jobs:
if git diff --cached --quiet; then
echo "No documentation changes to commit"
else
git commit -m "docs: update pydoc3 documentation [skip ci]"
git commit -m "docs: update sphinx documentation [skip ci]"
git push origin HEAD:"$HEAD_REF"
fi
18 changes: 18 additions & 0 deletions packages/base/docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
SHELL := /bin/bash

.PHONY: all api_doc build comment_out_lines

all: api_doc build comment_out_lines

api_doc:
python -m sphinx.ext.apidoc -o source/_api_doc ../ai_api_client_sdk -d 1 -T -f -M

build:
python -m sphinx -b html ./source ./build/html

comment_out_lines:
@if [ "$$(uname)" = "Darwin" ]; then \
sed -i '' '/window\.location/s/^/\/\/ /' ./build/html/_static/doctools.js; \
else \
sed -i '/window\.location/s/^/\/\/ /' ./build/html/_static/doctools.js; \
fi
115 changes: 115 additions & 0 deletions packages/base/docs/source/_static/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* Light theme */
:root {
--mystnb-source-bg-color: #f8fafc;
--mystnb-source-color: #334155;
--mystnb-stdout-bg-color: #f0f7ff;
--mystnb-output-border-color: #bfdbfe;
--mystnb-border-color: #e2e8f0;
}

/* Dark theme */
.dark {
--mystnb-source-bg-color: #1e1e2e;
--mystnb-source-color: #cdd6f4;
--mystnb-stdout-bg-color: #171731;
--mystnb-output-border-color: #2e2e72;
--mystnb-border-color: #313244;
}

.cell_input {
border: 1px solid var(--mystnb-border-color) !important;
border-radius: 8px;
margin: 1.5rem 0;
padding: 1px;
}

.cell_output {
border: 1px solid var(--mystnb-output-border-color);
border-radius: 8px;
margin: 1.5rem 0;
padding: 1px;
overflow: hidden;
background: var(--mystnb-stdout-bg-color);
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

.cell_output .output.stream {
border: none;
margin: 0;
border-radius: 8px;
}

.cell_input:focus-within {
outline: 2px solid var(--mystnb-source-color);
outline-offset: 2px;
}

.highlight {
background-color: var(--mystnb-source-bg-color);
color: var(--mystnb-source-color);
scrollbar-width: thin;
scrollbar-color: var(--mystnb-source-color) transparent;
border-radius: 6px;
margin: 0;
}

.cell_output .highlight {
background-color: var(--mystnb-stdout-bg-color);
border: none;
border-radius: 8px;
margin: -1px;
}

.highlight::-webkit-scrollbar {
height: 6px;
}

.highlight::-webkit-scrollbar-thumb {
background: var(--mystnb-source-color);
border-radius: 3px;
}

/* Dark theme syntax */
.dark .highlight .c1 { color: #7f849c; }
.dark .highlight .s1, .dark .highlight .s2 { color: #89dceb; }
.dark .highlight .k, .dark .highlight .kn { color: #f5c2e7; }
.dark .highlight .n { color: #cdd6f4; }
.dark .highlight .o { color: #89b4fa; }
.dark .highlight .p { color: #9399b2; }

/* Light theme syntax */
.highlight .c1 { color: #64748b; }
.highlight .s1, .highlight .s2 { color: #0369a1; }
.highlight .k, .highlight .kn { color: #be185d; }
.highlight .n { color: #334155; }
.highlight .o { color: #0284c7; }
.highlight .p { color: #475569; }

button.copy {
background: transparent;
border: none;
opacity: 0.25;
transition: opacity 0.2s ease;
}

button.copy:hover {
opacity: 1;
}

/* autodoc related adjustments*/

/* autodoc generation for docstring causes no wordwrap */
.sig-name, .viewcode-link, .py-attribute, .py-class, .py-function, .descclassname {
word-break: break-all;
white-space: normal !important;
}

/* break word and avoid horizontal scrollbar */
#left-sidebar {
word-break: break-word;
}

main{
word-wrap: break-word;
}

39 changes: 39 additions & 0 deletions packages/base/docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pathlib
import sys
sys.path.insert(0, pathlib.Path(__file__).parents[2].resolve().as_posix())

import tomllib

project = 'SAP Cloud SDK for AI (Python) - base'
copyright = '2026, SAP SE'
author = 'SAP SE'

def get_version():
pyproject = pathlib.Path(__file__).parents[2] / 'pyproject.toml'
with open(pyproject, 'rb') as f:
return tomllib.load(f)['project']['version']

release = get_version()

extensions = [
'sphinx.ext.duration',
'sphinx.ext.autodoc',
]

templates_path = ['_templates']
exclude_patterns = []

html_theme = 'sphinxawesome_theme'
html_static_path = ['_static']
html_css_files = ['custom.css']

smartquotes = False
html_title = "SAP Cloud SDK for AI (Python) - base v" + release
html_permalinks = False

autodoc_typehints = "description"
autodoc_class_signature = "separated"
add_module_names = False
autodoc_typehints_format = 'short'
autodoc_member_order = 'groupwise'
modindex_common_prefix = ['ai_api_client_sdk']
5 changes: 5 additions & 0 deletions packages/base/docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SAP Cloud SDK for AI (Python) - base
=====================================

.. toctree::
API Reference <./_api_doc/ai_api_client_sdk.rst>
4 changes: 4 additions & 0 deletions packages/base/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ dev = [
"pylint==4.0.5",
"pytest-dotenv>=0.5.2",
]
docs = [
"sphinx<9.0.0",
"sphinxawesome-theme",
]

[tool.pytest.ini_options]
env_files = [".env"]
Expand Down
18 changes: 18 additions & 0 deletions packages/core/docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
SHELL := /bin/bash

.PHONY: all api_doc build comment_out_lines

all: api_doc build comment_out_lines

api_doc:
python -m sphinx.ext.apidoc -o source/_api_doc ../ai_core_sdk -d 1 -T -f -M

build:
python -m sphinx -b html ./source ./build/html

comment_out_lines:
@if [ "$$(uname)" = "Darwin" ]; then \
sed -i '' '/window\.location/s/^/\/\/ /' ./build/html/_static/doctools.js; \
else \
sed -i '/window\.location/s/^/\/\/ /' ./build/html/_static/doctools.js; \
fi
Loading
Loading