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
60 changes: 45 additions & 15 deletions automation/source-repo-templates/api-docs.dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
- name: Write top-level index
# DefaultDocumentation emits one tree per assembly. Assemble
# a small README.mdx at the top of the api/ folder listing
# the available packages.
# the available packages with their pinned versions.
#
# Emit .mdx (not .md) because Mintlify's docs.json nav
# resolver only matches .mdx for page ids; without this,
Expand All @@ -171,21 +171,51 @@ jobs:
# parents fails broken-links validation when the parent is
# .mdx). Users navigate to per-package pages via the URL bar
# or future programmatic _pages.json nav splice.
#
# Version next to each project is read from <Version> /
# <VersionPrefix> in the .csproj. Falls back to "unknown" so
# missing tags don't break the doc build.
run: |
{
echo "# ResQ .NET SDK"
echo ""
echo "Auto-generated reference for the public packages in"
echo "[resq-software/dotnet-sdk](https://github.com/resq-software/dotnet-sdk)."
echo ""
echo "## Packages"
echo ""
for proj in $PUBLIC_PROJECTS; do
if [ -d "$OUTPUT_DIR/$proj" ]; then
echo "- \`$proj\`"
fi
done
} > "$OUTPUT_DIR/README.mdx"
python3 - <<'PY' > "$OUTPUT_DIR/README.mdx"
import os
import pathlib
import re

ref_name = os.environ.get("DOCS_REF_NAME", "main")
repo = os.environ.get("GITHUB_REPOSITORY", "")
output_dir = pathlib.Path(os.environ["OUTPUT_DIR"])
projects = (os.environ.get("PUBLIC_PROJECTS") or "").split()

def read_version(proj: str) -> str:
# .csproj files are usually <ProjectName>/<ProjectName>.csproj
# but DefaultDocumentation expects the assembly name as the
# output dir, so search for a .csproj matching the project.
candidates = list(pathlib.Path(".").rglob(f"{proj}.csproj"))
if not candidates:
return "unknown"
text = candidates[0].read_text(encoding="utf-8")
for tag in ("Version", "VersionPrefix"):
m = re.search(rf"<{tag}>([^<]+)</{tag}>", text)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regex for parsing .csproj tags is a bit fragile as it doesn't account for potential XML attributes on the tag (e.g., ). Using a more robust pattern would ensure the version is captured even in more complex project files.

m = re.search(rf"<{tag}\\b[^>]*>([^<]+)</{tag}>", text)

if m:
return m.group(1).strip()
return "unknown"

print("# ResQ .NET SDK")
print()
print(
f"Auto-generated reference for "
f"[`{repo}`](https://github.com/{repo}) "
f"at ref `{ref_name}`."
)
print()
print("## Packages")
print()
for proj in projects:
if not (output_dir / proj).is_dir():
continue
version = read_version(proj)
print(f"- `{proj}` — `v{version}`")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When the version cannot be determined, the current implementation outputs vunknown. It would be cleaner to omit the v prefix in the fallback case.

v_str = f"v{version}" if version != "unknown" else version
print(f"- {proj} — {v_str}")

PY

- name: Drop hash from constructor filenames + references
# DefaultDocumentation names constructor pages after the IL
Expand Down
61 changes: 43 additions & 18 deletions automation/source-repo-templates/api-docs.python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ jobs:
- name: Write top-level index
# pydoc-markdown emits an overview.md per package. Stitch
# a small README.mdx at the top of the api/ folder listing
# the available packages.
# the available packages with their pinned versions.
#
# Emit .mdx (not .md) because Mintlify's docs.json nav
# resolver only matches .mdx for page ids; without this,
Expand All @@ -242,24 +242,49 @@ jobs:
#
# Package list is sorted alphabetically by directory name
# so it stays in sync with `_pages.json` (which
# `find ... | sort` produces below).
# `find ... | sort` produces below). The version next to
# each package is read from its pyproject.toml so the
# rendered docs can be cross-referenced against a specific
# PyPI release; the workflow ref (`DOCS_REF_NAME`) is shown
# at the top so tag-triggered runs are clearly identified.
run: |
{
echo "# ResQ Python SDK"
echo ""
echo "You can use this auto-generated reference for the public packages in"
echo "[\`${{ github.repository }}\`](https://github.com/${{ github.repository }})."
echo ""
echo "## Packages"
echo ""
for entry in $PUBLIC_PACKAGES; do
echo "${entry%%:*}"
done | sort | while read -r pkg_dir; do
if [ -d "$OUTPUT_DIR/$pkg_dir" ]; then
echo "- \`$pkg_dir\`"
fi
done
} > "$OUTPUT_DIR/README.mdx"
python3 - <<'PY' > "$OUTPUT_DIR/README.mdx"
import os
import pathlib
import re

ref_name = os.environ.get("DOCS_REF_NAME", "main")
repo = os.environ.get("GITHUB_REPOSITORY", "")
output_dir = pathlib.Path(os.environ["OUTPUT_DIR"])
public = (os.environ.get("PUBLIC_PACKAGES") or "").split()

def read_version(pkg_dir: str) -> str:
# Best-effort version lookup so a parse failure doesn't
# break the whole doc build — fall back to "unknown".
pyproject = pathlib.Path("packages") / pkg_dir / "pyproject.toml"
if not pyproject.exists():
return "unknown"
text = pyproject.read_text(encoding="utf-8")
m = re.search(r'^\s*version\s*=\s*"([^"]+)"', text, re.M)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regex for pyproject.toml only matches double-quoted version strings. TOML allows single quotes as well. Updating the regex to handle both will make the version extraction more reliable.

m = re.search(r'^\\s*version\\s*=\\s*["\']([^"\']+)["\']', text, re.M)

return m.group(1) if m else "unknown"

print("# ResQ Python SDK")
print()
print(
f"Auto-generated API reference for "
f"[`{repo}`](https://github.com/{repo}) "
f"at ref `{ref_name}`."
)
print()
print("## Packages")
print()
entries = sorted(e.split(":", 1)[0] for e in public)
for pkg_dir in entries:
if not (output_dir / pkg_dir).is_dir():
continue
version = read_version(pkg_dir)
print(f"- `{pkg_dir}` — `v{version}`")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the .NET template, this will output vunknown if the version lookup fails. It's better to avoid the prefix for the fallback value.

v_str = f"v{version}" if version != "unknown" else version
print(f"- {pkg_dir} — {v_str}")

PY

- name: Prefix bare-filename intra-page links with ./
# Mintlify rejects bare-filename .md links as broken;
Expand Down
36 changes: 35 additions & 1 deletion automation/source-repo-templates/api-docs.typescript.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,52 @@ jobs:
# `[components/X](X/README.md)` module list down to plain
# backticked text. Users navigate to specific pages via
# the URL bar.
#
# Prepend a version banner so users browsing the rendered
# docs can identify which release the reference describes.
# Version is read from package.json at the package root;
# ref is the workflow's input ref (tag for tag-triggered
# runs).
working-directory: ${{ env.PKG_DIR }}/generated-docs
env:
PKG_REF: ${{ inputs.ref || github.ref_name }}
GH_REPO: ${{ github.repository }}
run: |
if [ -f README.md ]; then
python3 - <<'PY'
import pathlib, re
import json, os, pathlib, re

INTERNAL_LINK = re.compile(r'\[([^\]]+)\]\((?!https?://|mailto:|#)[^)]+\)')
p = pathlib.Path("README.md")
text = p.read_text(encoding="utf-8")
text = INTERNAL_LINK.sub(r'`\1`', text)
# Collapse accidental double-backticks from already-
# backticked link text.
text = text.replace("``", "`")

ref_name = os.environ.get("PKG_REF", "main")
repo = os.environ.get("GH_REPO", "")
# package.json is one level up from generated-docs.
pkg_json = pathlib.Path("..") / "package.json"
version = "unknown"
if pkg_json.exists():
try:
version = json.loads(pkg_json.read_text(encoding="utf-8")).get("version", "unknown")
except json.JSONDecodeError:
pass

banner = (
f"> **Version:** `v{version}` · **Ref:** `{ref_name}` · "
f"**Source:** [`{repo}`](https://github.com/{repo})\n\n"
)
# Insert banner after the first H1 (typedoc emits `# ui`
# or similar). If there's no leading H1, prepend.
h1_match = re.match(r'(# [^\n]+\n+)', text)
if h1_match:
text = text[:h1_match.end()] + banner + text[h1_match.end():]
else:
text = banner + text
Comment on lines +167 to +177
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are three improvements possible here:

  1. Avoid the vunknown string when the version is missing.
  2. Use re.search with the MULTILINE flag instead of re.match for robustness against frontmatter.
  3. Ensure the Source link includes the relative path to the package directory to correctly resolve file locations in this monorepo.
v_display = f"v{version}" if version != "unknown" else version
banner = (
    f"**Version:** {v_display} · **Ref:** {ref_name} · "
    f"**Source:** [{repo}](https://github.com/{repo}/tree/{ref_name}/{pkg_dir})\\n\\n"
)
h1_match = re.search(r"(^# [^\\n]+\\n+)", text, re.M)
if h1_match:
    text = text[:h1_match.end()] + banner + text[h1_match.end():]
else:
    text = banner + text
References
  1. When configuring source code links in documentation generators for monorepos, the base URL must include the relative path to the package directory to ensure 'View source' links resolve correctly to the file locations.


pathlib.Path("README.mdx").write_text(text, encoding="utf-8")
p.unlink()
PY
Expand Down
Loading