Switch GitHub Pages deployment to Actions workflow (#1583)
This commit is contained in:
parent
1db6c0f5ba
commit
3eec8b625d
4 changed files with 22 additions and 387 deletions
5
.github/pages/_config.yml
vendored
5
.github/pages/_config.yml
vendored
|
|
@ -1,5 +0,0 @@
|
|||
title: '@modelcontextprotocol/sdk'
|
||||
|
||||
# Include generated files and directories which may start with underscores
|
||||
include:
|
||||
- '_*'
|
||||
183
.github/pages/index.html
vendored
183
.github/pages/index.html
vendored
|
|
@ -1,183 +0,0 @@
|
|||
---
|
||||
# Jekyll front matter to enable Liquid templating
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>MCP TypeScript SDK - API Documentation</title>
|
||||
<meta http-equiv="refresh" content="1; url={{ site.data.latest_version }}/" />
|
||||
<link rel="canonical" href="{{ site.data.latest_version }}/" />
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
h1 {
|
||||
color: #1a1a1a;
|
||||
border-bottom: 2px solid #eee;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
h2 {
|
||||
color: #444;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
a {
|
||||
color: #0066cc;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.redirect-notice {
|
||||
background: #f0f7ff;
|
||||
border: 1px solid #cce0ff;
|
||||
border-radius: 6px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.versions-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.versions-table th,
|
||||
.versions-table td {
|
||||
text-align: left;
|
||||
padding: 0.75rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.versions-table th {
|
||||
background: #f5f5f5;
|
||||
font-weight: 600;
|
||||
}
|
||||
.package-versions {
|
||||
display: none;
|
||||
background: #fafafa;
|
||||
border-radius: 6px;
|
||||
padding: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.package-versions.loaded {
|
||||
display: block;
|
||||
}
|
||||
.package-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.package-list li {
|
||||
padding: 0.25rem 0;
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.package-name {
|
||||
color: #666;
|
||||
}
|
||||
.package-version {
|
||||
color: #0066cc;
|
||||
font-weight: 500;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
h1 {
|
||||
color: #fff;
|
||||
border-bottom-color: #333;
|
||||
}
|
||||
h2 {
|
||||
color: #ccc;
|
||||
}
|
||||
a {
|
||||
color: #66b3ff;
|
||||
}
|
||||
.redirect-notice {
|
||||
background: #1a2a3a;
|
||||
border-color: #2a4a6a;
|
||||
}
|
||||
.versions-table th {
|
||||
background: #2a2a2a;
|
||||
}
|
||||
.versions-table td,
|
||||
.versions-table th {
|
||||
border-bottom-color: #333;
|
||||
}
|
||||
.package-versions {
|
||||
background: #2a2a2a;
|
||||
}
|
||||
.package-name {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>MCP TypeScript SDK</h1>
|
||||
|
||||
<div class="redirect-notice">
|
||||
<p>Redirecting to <a href="{{ site.data.latest_version }}/">latest documentation ({{ site.data.latest_version }})</a>...</p>
|
||||
</div>
|
||||
|
||||
<h2>Package Versions</h2>
|
||||
<div id="package-versions" class="package-versions">
|
||||
<p>Loading package versions...</p>
|
||||
</div>
|
||||
|
||||
<h2>All Documentation Versions</h2>
|
||||
<p>Select a version to view its API documentation:</p>
|
||||
<ul id="versions-list">
|
||||
<li><a href="{{ site.data.latest_version }}/">{{ site.data.latest_version }}</a> (latest)</li>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
// Redirect to latest version
|
||||
setTimeout(function () {
|
||||
window.location.href = '{{ site.data.latest_version }}/';
|
||||
}, 1000);
|
||||
|
||||
// Load and display package versions from versions.json
|
||||
fetch('{{ site.data.latest_version }}/versions.json')
|
||||
.then(function (response) {
|
||||
if (!response.ok) throw new Error('versions.json not found');
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
var container = document.getElementById('package-versions');
|
||||
var html = '<p>Packages included in the latest documentation:</p><ul class="package-list">';
|
||||
|
||||
for (var pkg in data.packages) {
|
||||
html +=
|
||||
'<li><span class="package-name">' +
|
||||
pkg +
|
||||
'</span>: <span class="package-version">' +
|
||||
data.packages[pkg] +
|
||||
'</span></li>';
|
||||
}
|
||||
|
||||
html += '</ul>';
|
||||
html +=
|
||||
'<p style="font-size: 0.85rem; color: #666; margin-top: 1rem;">Generated from tag: ' +
|
||||
data.generated_from_tag +
|
||||
'</p>';
|
||||
|
||||
container.innerHTML = html;
|
||||
container.classList.add('loaded');
|
||||
})
|
||||
.catch(function (err) {
|
||||
// versions.json may not exist for older docs
|
||||
document.getElementById('package-versions').style.display = 'none';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
35
.github/workflows/main.yml
vendored
35
.github/workflows/main.yml
vendored
|
|
@ -109,20 +109,22 @@ jobs:
|
|||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
# Generates API documentation for GitHub Pages on any release
|
||||
# Supports both simple tags (v1.2.3) and package-scoped tags (@scope/package@1.2.3)
|
||||
publish-gh-pages:
|
||||
# Generates API documentation and deploys to GitHub Pages on any release
|
||||
deploy-docs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release'
|
||||
needs: [publish]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all branches and tags
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
|
@ -137,13 +139,20 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
- name: Build packages
|
||||
run: pnpm build:all
|
||||
|
||||
- name: Generate documentation
|
||||
run: ./scripts/generate-gh-pages.sh "${{ github.ref_name }}"
|
||||
run: pnpm docs
|
||||
|
||||
- name: Push to gh-pages
|
||||
run: git push origin gh-pages
|
||||
- name: Configure Pages
|
||||
uses: actions/configure-pages@v5
|
||||
|
||||
- name: Upload Pages artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: tmp/docs
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
|
|
|||
|
|
@ -1,186 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Generates versioned API documentation and commits to gh-pages branch
|
||||
#
|
||||
# PURPOSE:
|
||||
# This script generates API documentation in the gh-pages branch for a
|
||||
# specific version tag while preserving existing versioned documentation.
|
||||
# This script is invoked by the publish-gh-pages job in the GitHub Actions
|
||||
# workflow (.github/workflows/main.yml) when a release is published.
|
||||
#
|
||||
# HOW IT WORKS:
|
||||
# - Creates isolated git worktrees for the specified tag and gh-pages branch
|
||||
# - Generates documentation into gh-pages in a directory based on the tag name (e.g., v1.2.3/)
|
||||
# - Generates _data/latest_version.yml for Jekyll template
|
||||
# - Generates versions.json manifest showing all package versions
|
||||
# - Copies static Jekyll template files from .github/pages/
|
||||
# - Commits changes to gh-pages (does not push automatically)
|
||||
#
|
||||
# WORKFLOW:
|
||||
# 1. Run this script with a tag name: `generate-gh-pages.sh v1.2.3`
|
||||
# Or with a package-scoped tag: `generate-gh-pages.sh @modelcontextprotocol/client@1.2.3`
|
||||
# 2. Script generates docs and commits to local gh-pages branch
|
||||
# 3. Push gh-pages branch to deploy: `git push origin gh-pages`
|
||||
|
||||
TAG_NAME="${1}"
|
||||
|
||||
# Parse semantic version from tag name
|
||||
# Supports both simple tags (v1.2.3) and package-scoped tags (@scope/package@1.2.3)
|
||||
if [[ "${TAG_NAME}" =~ @[^@]+@([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?)$ ]]; then
|
||||
# Package-scoped tag (e.g., @modelcontextprotocol/client@1.2.3)
|
||||
VERSION="v${BASH_REMATCH[1]}"
|
||||
elif [[ "${TAG_NAME}" =~ ([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?)$ ]]; then
|
||||
# Simple version tag (e.g., v1.2.3 or 1.2.3)
|
||||
VERSION="v${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "Error: Must specify a tag name that contains a valid semantic version"
|
||||
echo "Usage: ${0} <tag-name>"
|
||||
echo "Examples:"
|
||||
echo " ${0} 1.2.3"
|
||||
echo " ${0} v2.0.0-rc.1"
|
||||
echo " ${0} @modelcontextprotocol/client@1.2.3"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Generating documentation for tag: ${TAG_NAME}"
|
||||
echo "Documentation version directory: ${VERSION}"
|
||||
|
||||
# Generates documentation for the given source directory.
|
||||
#
|
||||
# Can modify this function to customize documentation structure.
|
||||
# For example, to add guides from ./docs/ and nest API docs under /api:
|
||||
# 1. Copy docs/ contents: `cp -r docs/* "${output_dir}/"`
|
||||
# 2. Change typedoc output: `npx typedoc --out "${output_dir}/api"`
|
||||
generate_docs() {
|
||||
local source_dir="${1}"
|
||||
local output_dir="${2}"
|
||||
|
||||
# Resolve to absolute path (because typedoc runs from source_dir)
|
||||
[[ "${output_dir}" != /* ]] && output_dir="$(pwd)/${output_dir}"
|
||||
|
||||
echo "Installing dependencies..."
|
||||
(cd "${source_dir}" && pnpm install --frozen-lockfile --ignore-scripts)
|
||||
|
||||
echo "Generating TypeDoc documentation..."
|
||||
(cd "${source_dir}" && pnpm run docs --out "${output_dir}")
|
||||
|
||||
# Verify docs were generated
|
||||
if [ -z "$(ls -A "${output_dir}")" ]; then
|
||||
echo "Error: Documentation was not generated at ${output_dir}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Gets list of public (non-private) package paths from pnpm workspace
|
||||
get_public_packages() {
|
||||
local source_dir="${1}"
|
||||
(cd "${source_dir}" && pnpm list -r --json --depth -1 | node -e '
|
||||
const data = JSON.parse(require("fs").readFileSync(0, "utf8"));
|
||||
data.filter(p => !p.private).forEach(p => console.log(p.path));
|
||||
')
|
||||
}
|
||||
|
||||
# Generates versions.json manifest showing all package versions
|
||||
# This helps users understand which versions of each package are included
|
||||
generate_versions_manifest() {
|
||||
local source_dir="${1}"
|
||||
local output_dir="${2}"
|
||||
local tag_name="${3}"
|
||||
|
||||
echo "Generating versions.json manifest..."
|
||||
|
||||
# Get list of public packages dynamically from pnpm workspace
|
||||
local packages
|
||||
packages=$(get_public_packages "${source_dir}")
|
||||
|
||||
# Start JSON object
|
||||
local json="{\n"
|
||||
json+=" \"generated_from_tag\": \"${tag_name}\",\n"
|
||||
json+=" \"generated_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\n"
|
||||
json+=" \"packages\": {\n"
|
||||
|
||||
local first=true
|
||||
while IFS= read -r pkg_path; do
|
||||
local pkg_json="${pkg_path}/package.json"
|
||||
if [ -f "${pkg_json}" ]; then
|
||||
local pkg_name=$(node -p "require('${pkg_json}').name")
|
||||
local pkg_version=$(node -p "require('${pkg_json}').version")
|
||||
|
||||
if [ "${first}" = true ]; then
|
||||
first=false
|
||||
else
|
||||
json+=",\n"
|
||||
fi
|
||||
json+=" \"${pkg_name}\": \"${pkg_version}\""
|
||||
fi
|
||||
done <<< "${packages}"
|
||||
|
||||
json+="\n }\n}"
|
||||
|
||||
# Write the manifest
|
||||
echo -e "${json}" > "${output_dir}/versions.json"
|
||||
echo "Created ${output_dir}/versions.json"
|
||||
}
|
||||
|
||||
# Create temporary directories for both worktrees
|
||||
TAG_WORKTREE_DIR=$(mktemp -d)
|
||||
GHPAGES_WORKTREE_DIR=$(mktemp -d)
|
||||
|
||||
# Set up trap to clean up both worktrees on exit
|
||||
trap 'git worktree remove --force "${TAG_WORKTREE_DIR}" 2>/dev/null || true; \
|
||||
git worktree remove --force "${GHPAGES_WORKTREE_DIR}" 2>/dev/null || true' EXIT
|
||||
|
||||
echo "Creating worktree for ${TAG_NAME}..."
|
||||
git worktree add --quiet "${TAG_WORKTREE_DIR}" "${TAG_NAME}"
|
||||
|
||||
# Fetch gh-pages from remote if available (creates local branch if missing)
|
||||
git fetch --quiet origin gh-pages:refs/heads/gh-pages 2>/dev/null || true
|
||||
|
||||
if git show-ref --verify --quiet refs/heads/gh-pages; then
|
||||
echo "Creating worktree for gh-pages branch..."
|
||||
git worktree add --quiet "${GHPAGES_WORKTREE_DIR}" gh-pages
|
||||
else
|
||||
echo "Creating worktree for new orphan gh-pages branch..."
|
||||
git worktree add --quiet --detach "${GHPAGES_WORKTREE_DIR}"
|
||||
git -C "${GHPAGES_WORKTREE_DIR}" switch --orphan gh-pages
|
||||
fi
|
||||
|
||||
# Change to gh-pages worktree for all subsequent operations
|
||||
cd "${GHPAGES_WORKTREE_DIR}"
|
||||
|
||||
# Generate TypeDoc documentation into gh-pages worktree
|
||||
mkdir -p "${VERSION}"
|
||||
generate_docs "${TAG_WORKTREE_DIR}" "${VERSION}"
|
||||
|
||||
# Generate versions manifest showing all package versions
|
||||
generate_versions_manifest "${TAG_WORKTREE_DIR}" "${VERSION}" "${TAG_NAME}"
|
||||
|
||||
# Generate version data for Jekyll
|
||||
echo "Generating _data/latest_version.yml..."
|
||||
mkdir -p _data
|
||||
LATEST_VERSION="v$(printf '%s\n' */ | grep '^v[0-9]' | sed -e 's/^v//' -e 's:/$::' | sort -Vr | head -1)"
|
||||
echo "${LATEST_VERSION}" > _data/latest_version.yml
|
||||
|
||||
if [ "${VERSION}" = "${LATEST_VERSION}" ]; then
|
||||
echo "${VERSION} is the latest version, updating static files..."
|
||||
|
||||
# Clean up old tracked files from gh-pages root (but preserve directories)
|
||||
git ls-files -z | grep -zv '/' | xargs -0 rm -f
|
||||
|
||||
# Copy static files from .github/pages/
|
||||
find "${TAG_WORKTREE_DIR}/.github/pages" -maxdepth 1 -type f -exec cp {} . \;
|
||||
else
|
||||
echo "${VERSION} is not the latest version (latest is ${LATEST_VERSION})"
|
||||
fi
|
||||
|
||||
# Commit if there are changes
|
||||
git add .
|
||||
|
||||
if git diff --staged --quiet; then
|
||||
echo "No changes to commit for tag ${TAG_NAME}"
|
||||
else
|
||||
git commit -m "Add ${VERSION} docs"
|
||||
echo "Documentation for tag ${TAG_NAME} committed to gh-pages branch!"
|
||||
echo "Push to remote to deploy to GitHub Pages"
|
||||
fi
|
||||
Loading…
Reference in a new issue