diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..1373a27 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,54 @@ +name: Deploy API Docs +on: + push: + branches: [main] + paths: + - apollo-openapi.yaml + - redocly.yaml + - scripts/build-docs.sh + - package.json + - package-lock.json + - .github/workflows/deploy-docs.yml + tags: ['v*'] + workflow_dispatch: {} + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + # Always build from main, never from the triggering ref: on a v* tag push + # github.ref is the tag, and site/next would then be built from the tag's + # spec instead of the current main HEAD. Released versions are read out of + # git history (git show :spec), so they are unaffected by this. + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + fetch-tags: true + - uses: actions/setup-node@v4 + with: + node-version: "20" + - run: npm ci + - run: ./scripts/build-docs.sh + - uses: actions/upload-pages-artifact@v3 + with: + path: site + + deploy: + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 7146375..fe8a3f1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,9 @@ # Temporary OpenAPI Generator output build/generated/ + +# Node dependencies +node_modules/ + +# Generated docs site output +site/ diff --git a/README.md b/README.md index 1c6ffed..bb7b487 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,20 @@ # apollo-openapi ![OpenAPI](https://img.shields.io/badge/spec-OpenAPI%203.0.1-blue) +[![Docs](https://img.shields.io/badge/docs-API%20reference-blue)](https://apolloconfig.github.io/apollo-openapi/) This repository maintains the Apollo OpenAPI contract. The source of truth is [`apollo-openapi.yaml`](apollo-openapi.yaml). +## 📖 API Reference + +Browse the rendered API reference for every released version (plus `next` +for the unreleased `main` HEAD): + +**https://apolloconfig.github.io/apollo-openapi/** + +See [all versions](https://apolloconfig.github.io/apollo-openapi/versions.html). + Generated code is treated as a temporary verification artifact, not as maintained source code or an official Apollo SDK. Apollo Portal pins a released `apollo-openapi.yaml` tag and generates its Spring OpenAPI interfaces during diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9c6ba48 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "apollo-openapi-docs", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "apollo-openapi-docs", + "devDependencies": { + "@redocly/cli": "2.51.2" + } + }, + "node_modules/@redocly/cli": { + "version": "2.51.2", + "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-2.51.2.tgz", + "integrity": "sha512-pviW1gfsjCAuIVutmQcihlhlgoivfNzisBIR61EwSSREHGZ08Sbtjp/h/HPDkVavWwdzR/gs2wgHrdXLd6qU1A==", + "dev": true, + "license": "MIT", + "bin": { + "openapi": "bin/cli.js", + "redocly": "bin/cli.js" + }, + "engines": { + "node": ">=22.12.0 || >=20.19.0 <21.0.0", + "npm": ">=10" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..95db336 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "apollo-openapi-docs", + "private": true, + "description": "Build tooling for the Apollo OpenAPI reference documentation site", + "scripts": { + "docs:build": "./scripts/build-docs.sh" + }, + "devDependencies": { + "@redocly/cli": "2.51.2" + } +} diff --git a/redocly.yaml b/redocly.yaml new file mode 100644 index 0000000..68f1e48 --- /dev/null +++ b/redocly.yaml @@ -0,0 +1,5 @@ +openapi: + theme: + colors: + primary: + main: '#1a56db' diff --git a/scripts/build-docs.sh b/scripts/build-docs.sh new file mode 100755 index 0000000..50e05e1 --- /dev/null +++ b/scripts/build-docs.sh @@ -0,0 +1,114 @@ +#!/bin/bash +set -euo pipefail + +SPEC_FILE="${SPEC_FILE:-apollo-openapi.yaml}" +SITE_DIR="${SITE_DIR:-site}" +REDOCLY_VERSION="2.51.2" + +usage() { + cat <<'EOF' +Usage: ./scripts/build-docs.sh [--help] + +Builds static Redoc HTML docs for every released git tag (vX.Y.Z) plus the +current HEAD ("next") from apollo-openapi.yaml, into site/ (gitignored build +output): + + site/index.html - copy of the latest successfully-built tag's docs + site/next/index.html - built from the current working tree HEAD + site/vX.Y.Z/index.html - one per released tag + site/versions.html - generated index linking every built version + +Options: + --help Show this help. +EOF +} + +for arg in "$@"; do + case "$arg" in + --help|-h) + usage + exit 0 + ;; + *) + echo "Unknown argument: $arg" >&2 + usage >&2 + exit 2 + ;; + esac +done + +command -v npx >/dev/null 2>&1 || { echo "npx is required" >&2; exit 127; } +REDOCLY=(npx --yes "@redocly/cli@${REDOCLY_VERSION}") + +WORK_DIR="$(mktemp -d)" +trap 'rm -rf "$WORK_DIR"' EXIT + +echo "Cleaning previous site output..." +rm -rf "$SITE_DIR" +mkdir -p "$SITE_DIR" + +# build_one +build_one() { + local spec_path="$1" label="$2" subdir="$3" + mkdir -p "$SITE_DIR/$subdir" + "${REDOCLY[@]}" build-docs "$spec_path" \ + --output "$SITE_DIR/$subdir/index.html" \ + --title "Apollo OpenAPI ($label)" \ + --lint-config off +} + +echo "Building next (unreleased HEAD)..." +build_one "$SPEC_FILE" "next, unreleased" "next" + +TAGS=() +while IFS= read -r tag; do + [ -n "$tag" ] && TAGS+=("$tag") +done < <(git tag -l 'v*' --sort=v:refname) +if [ "${#TAGS[@]}" -eq 0 ]; then + echo "No vX.Y.Z tags found" >&2 + exit 1 +fi + +BUILT_TAGS=() +for tag in "${TAGS[@]}"; do + echo "Building $tag..." + if ! git show "$tag:$SPEC_FILE" > "$WORK_DIR/$tag.yaml" 2>/dev/null; then + echo "WARN: $tag does not contain $SPEC_FILE, skipping" >&2 + continue + fi + if build_one "$WORK_DIR/$tag.yaml" "$tag" "$tag"; then + BUILT_TAGS+=("$tag") + else + echo "WARN: build-docs failed for $tag, exit" >&2 + exit 1 + fi +done + +if [ "${#BUILT_TAGS[@]}" -eq 0 ]; then + echo "No tag built successfully" >&2 + exit 1 +fi + +LATEST_TAG="${BUILT_TAGS[${#BUILT_TAGS[@]}-1]}" +echo "Latest version: $LATEST_TAG" +cp "$SITE_DIR/$LATEST_TAG/index.html" "$SITE_DIR/index.html" + +echo "Generating versions.html..." +{ + echo '' + echo 'Apollo OpenAPI — Versions' + echo '

Apollo OpenAPI — Versions

' + echo '' +} > "$SITE_DIR/versions.html" + +echo "Done. Built $((${#BUILT_TAGS[@]} + 1)) versions (${#BUILT_TAGS[@]} tags + next)."