diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml new file mode 100644 index 00000000000..a92092409d1 --- /dev/null +++ b/.github/workflows/build-and-deploy.yml @@ -0,0 +1,91 @@ +name: Build and Deploy Documentation + +on: + push: + branches: + - master + - optimize-build-simplify + pull_request: + branches: + - master + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 120 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Cache migrated files + uses: actions/cache@v4 + id: cache-migrated + with: + path: _migrated + key: migrated-${{ hashFiles('**/*.rst', 'conf.py', 'migrate.py') }} + + - name: Cache Sphinx doctrees + uses: actions/cache@v4 + with: + path: _sphinx/.doctrees + key: doctrees-${{ github.ref }}-${{ github.run_id }} + restore-keys: | + doctrees-${{ github.ref }}- + doctrees- + + - name: Build documentation + run: | + export FULL_RUN=1 + bash build.sh + env: + FULL_RUN: 1 + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: redot-docs-build + path: output/ + retention-days: 1 + + deploy: + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/optimize-build-simplify') + + steps: + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: redot-docs-build + path: output/ + + - name: Determine deploy directory + run: | + if [ "${{ github.ref_name }}" = "master" ]; then + echo "DEPLOY_DIR=output/html/en/latest" >> $GITHUB_ENV + else + echo "DEPLOY_DIR=output/html/en/${{ github.ref_name }}" >> $GITHUB_ENV + fi + + - name: Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy ${{ env.DEPLOY_DIR }} --project-name=redot-docs --branch=${{ github.ref_name }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml.disabled similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/ci.yml.disabled diff --git a/.gitignore b/.gitignore index 710a4e2301d..5f14e2756f1 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,5 @@ _build/ _migrated/ _sphinx/ _repo/ +output/ *.log diff --git a/README.md b/README.md index a65537bafe2..144221319d9 100644 --- a/README.md +++ b/README.md @@ -16,20 +16,75 @@ For mobile devices or e-readers, you can also download an ePub copy (updated eve [latest](https://download.redotengine.org/docs/redot-docs-epub-master.zip). Extract the ZIP archive then open the `RedotEngine.epub` file in an e-book reader application. -## Migrating +## Building Documentation -We are transitioning from Godot to Redot. In this period, a temporary solution is available. +### Quick Build (Local Development) +For local development, use the optimized build script: + +```bash +# Full build (includes migration + Sphinx) +FULL_RUN=1 ./build.sh + +# The output will be in output/html/en/latest/ (for master branch) +# or output/html/en// (for other branches) ``` -python migrate.py . _migrated True + +**Build optimizations:** +- `--exclude-classes`: Skips class reference migration (faster, these are auto-generated) +- `-j auto`: Uses all available CPU cores for parallel builds +- Branch mapping: `master` → `latest/`, other branches → `/` + +### Manual Build + +If you prefer manual control: + +```bash +# 1. Migrate (optional - skip for faster builds, use --exclude-classes) +python migrate.py --exclude-classes . _migrated + +# 2. Build with Sphinx (auto-detect CPU cores) +sphinx-build -b html -j auto ./_migrated/ _build/html ``` -After the docs are converted, you can build with +### Architecture + +**GitHub Actions + Cloudflare Pages (Current):** +- Source: This repository (`Redot-Engine/redot-docs`) +- Build: GitHub Actions runs `build.sh` (2-hour timeout vs Cloudflare's 20 minutes) +- Deploy: Built output pushed to Cloudflare Pages +- Output: `/output/html/en//` +- Serve: Cloudflare Pages serves the built documentation + +**Previous architectures (deprecated):** +1. ~Two repos: `redot-docs` (source) → builds → pushes to `redot-docs-live` (deployment)~ +2. ~Direct Cloudflare Pages build (hit 20-minute timeout limit)~ + +### GitHub Actions Workflow + +The repository includes an automated workflow (`.github/workflows/build-and-deploy.yml`) that: +1. **Builds on every push** to `master` or `optimize-build-simplify` +2. **Runs on GitHub Actions** with a 2-hour timeout (vs Cloudflare's 20-minute limit) +3. **Deploys automatically** to Cloudflare Pages using the official Cloudflare action + +**Setup required:** + +Add these secrets to your GitHub repository (Settings → Secrets and variables → Actions): +- `CLOUDFLARE_ACCOUNT_ID` - Your Cloudflare account ID +- `CLOUDFLARE_API_TOKEN` - API token with Cloudflare Pages:Edit permission + +**How it works:** ``` -sphinx-build -b html ./_migrated/ _build/html +Push to branch → GitHub Actions builds (30 min) → Deploys to Cloudflare Pages ``` +**Benefits:** +- No 20-minute timeout limit +- Python dependencies cached between builds +- Automatic deployment on every push +- Works for both production (master) and preview branches + ## Theming The Redot documentation uses the default `sphinx_rtd_theme` with many @@ -58,24 +113,31 @@ Here are some quick links to the areas you might be interested in: ### How to build with anaconda/miniconda -``` -# 1) create env with Python 3.11 +**Recommended: Use the build script** +```bash +# Setup environment (one-time) conda create -n redot-docs python=3.11 -y - -# 2) activate it conda activate redot-docs +pip install -r requirements.txt + +# Build documentation +FULL_RUN=1 ./build.sh -# 3) ensure pip is available (usually is) -conda install pip -y +# Output: output/html/en/latest/ +``` -# 4) from the repo root, install requirements via pip -python -m pip install -r requirements.txt +**Manual build (if you need fine control):** +```bash +# 1) Setup environment +conda create -n redot-docs python=3.11 -y +conda activate redot-docs +pip install -r requirements.txt -# 5) Migration -python migrate.py . _migrated True +# 2) Migrate (use --exclude-classes for faster builds) +python migrate.py --exclude-classes . _migrated -# 6) build the docs -sphinx-build -b html ./_migrated/ _build/html +# 3) Build with Sphinx (auto-detect CPU cores) +sphinx-build -b html -j auto ./_migrated/ _build/html ``` ## License diff --git a/build.sh b/build.sh index b72b80f40c1..69cfe83574f 100755 --- a/build.sh +++ b/build.sh @@ -1,117 +1,107 @@ #!/bin/bash - -# Init env vars -date=`date` -workDir=`pwd` -sshCommand="ssh -v" # Add -v, -vv, or -vvv for verbose debugging - -gitBranch=`git rev-parse --abbrev-ref HEAD` -if [ -n "$CF_PAGES" ] -then - echo "We are on Cloudflare Pages. Retrieve branch from env." - gitBranch=$CF_PAGES_BRANCH -fi - -liveDir=$gitBranch -if [ $gitBranch == "master" ] -then - liveDir="latest" -fi -gitCommitMessage="branch $gitBranch on $date, will deploy to $liveDir" -redotDocsLiveBranch=${1:-develop} - +# +# Redot Documentation Build Script +# Builds documentation and outputs to /output for Cloudflare Pages +# +# Usage: +# FULL_RUN=1 ./build.sh # Full build +# ./build.sh # Skip build (for testing) +# +# Environment Variables: +# FULL_RUN - Set to enable full documentation build +# CF_PAGES - Automatically set by Cloudflare Pages +# CF_PAGES_BRANCH - Branch being built (set by Cloudflare Pages) + +set -e # Exit on error + +# Configuration inputDir="." migrateDir="_migrated" sphinxDir="_sphinx" -repoDir="_repo" -liveRoot="redot-docs-live" -liveRepo="git@github.com:Redot-Engine/$liveRoot.git" -buildDir="html/en/$liveDir" # TODO: implement i18n support - -# Report vars and intention -echo "Building $gitCommitMessage" -echo "Live branch: $redotDocsLiveBranch" -echo "Live root: $liveRoot, live repo: $liveRepo, build dir: $buildDir, report dir: $reportDir" -echo "Temp dirs: $migrateDir, $sphinxDir, $repoDir" - -echo "Delete temp dirs" -rm -rf $migrateDir -rm -rf $sphinxDir -rm -rf $repoDir - -mkdir -p $migrateDir -mkdir -p $sphinxDir -if [ -n "$FULL_RUN" ] -then - echo "Migrate Godot to Redot" - python migrate.py $inputDir $migrateDir - - echo "Translate to html" - sphinx-build -b html -j 4 $migrateDir $sphinxDir +# Determine output directory based on branch +gitBranch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "master") +if [ -n "$CF_PAGES" ]; then + echo "Building on Cloudflare Pages" + gitBranch="${CF_PAGES_BRANCH:-master}" fi -echo "DUMMY FILE FOR TESTING: $date" > $sphinxDir/test.html - -echo "Cloning $liveRepo $repoDir" -git clone $liveRepo $repoDir - -cd $repoDir -echo "Checking out $redotDocsLiveBranch" -git checkout $redotDocsLiveBranch - -git config core.sshCommand "$sshCommand" -echo "Using ssh command: $sshCommand" - -if [ -n "$CF_PAGES" ] -then - echo "We are on Cloudflare Pages. Setting custom ssh key and method" - # HACK: Remove annoying https redirect. I presume this was used by Cloudflare - echo "Remove Cloudflare redirect." - insteadof=`git config --list | grep insteadof` - remove=`echo $insteadof | cut -d "=" -f 1` - git config --global --unset $remove - - mkdir ~/.ssh - echo "$BUILD_SSH_KEY" > ~/.ssh/id_ed25519 - echo "$BUILD_SSH_KEY_PUB" > ~/.ssh/id_ed25519.pub - echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts +# Map branches to output directories +# master -> latest, everything else -> branch name +buildDir="$gitBranch" +if [ "$gitBranch" = "master" ]; then + buildDir="latest" +fi - chmod 0600 ~/.ssh/id_ed25519 - chmod 0600 ~/.ssh/id_ed25519.pub - chmod 0644 ~/.ssh/known_hosts - chmod 0755 ~/.ssh +echo "========================================" +echo "Redot Documentation Build" +echo "========================================" +echo "Branch: $gitBranch" +echo "Output: html/en/$buildDir" +echo "Date: $(date)" +echo "========================================" + +# Clean and prepare directories +# Skip migration if _migrated exists (for faster rebuilds) +echo "" +echo "[1/4] Preparing build directories..." +rm -rf "$sphinxDir" +mkdir -p "$sphinxDir" + +# Full build (only if FULL_RUN is set) +if [ -n "$FULL_RUN" ]; then + # Check if migration is needed + if [ -d "$migrateDir" ] && [ -f "$migrateDir/index.rst" ]; then + echo "" + echo "[2/4] Using existing migrated files (skipping migration)..." + else + echo "" + echo "[2/4] Migrating Godot to Redot (with --exclude-classes)..." + rm -rf "$migrateDir" + mkdir -p "$migrateDir" + python migrate.py --exclude-classes "$inputDir" "$migrateDir" + fi - # Init git - git remote set-url origin git@github.com:Redot-Engine/redot-docs-live.git - - echo "Setting credentials" - git config user.email "noreply_pages_bot@cloudflare.com" - git config user.name "Redot Docs Build Worker" + echo "" + echo "[3/4] Building HTML documentation with Sphinx..." + # Use -j 4 for consistent performance + # Use -d for doctree caching (enables incremental builds) + mkdir -p "$sphinxDir/.doctrees" + sphinx-build -b html \ + -j 4 \ + -d "$sphinxDir/.doctrees" \ + --color \ + "$migrateDir" \ + "$sphinxDir" + + echo "" + echo "[4/4] Copying build output..." + # Cloudflare Pages serves from /output + # Build triggered: $(date) + outputDir="output/html/en/$buildDir" + mkdir -p "$outputDir" + cp -r "$sphinxDir"/* "$outputDir/" + + echo "" + echo "========================================" + echo "Build Complete!" + echo "Output: $outputDir" + echo "========================================" +else + echo "" + echo "[2/4] Skipping migration and build (FULL_RUN not set)" + echo "" + echo "[3/4] Creating placeholder output..." + mkdir -p "output/html/en/$buildDir" + echo "Build skipped. Set FULL_RUN=1 to build documentation." > "output/html/en/$buildDir/index.html" + echo "" + echo "[4/4] Done (placeholder only)" + echo "" + echo "========================================" + echo "Build Skipped (FULL_RUN not set)" + echo "========================================" fi -echo "### SSH CONFIG VALUES ###" -ls -la ~/.ssh -cat ~/.ssh/known_hosts -echo "### SSH TEST ###" -ssh -T -vv git@ssh.github.com -echo "### GIT CONFIG VALUES ###" -git config core.pager cat -git config --list - -echo "Copying generated content to repository" -echo "mkdir -p $buildDir" -mkdir -p $buildDir -echo "cp -r ../$sphinxDir/* $buildDir" -cp -r ../$sphinxDir/* $buildDir - -echo "Commit and push to $redotDocsLiveBranch, with message $gitCommitMessage" -git add . -git commit --message "$gitCommitMessage" -git push --force - -# Create some output so Cloudflare is happy -cd .. -mkdir -p ./output -echo "Build finished. Commit message: $gitCommitMessage" > ./output/index.html -echo "Done. Made by @Craptain" +echo "" +echo "Build script finished successfully" +echo "Build completed at $(date)" diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 00000000000..82f0eeeda38 --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,17 @@ +name = "redot-docs" +compatibility_date = "2024-01-01" + +# Build settings +[build] +command = "FULL_RUN=1 bash build.sh" + +# The directory containing your static files +[site] +bucket = "output" + +# Environment variables +[env.production] +name = "redot-docs" + +[env.preview] +name = "redot-docs-preview"