Skip to content
Draft
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
126 changes: 126 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# CI/CD Setup for Union.ai Documentation

This directory contains GitHub Actions workflows for building and deploying the Union.ai documentation site to Cloudflare Workers.

## Architecture

The site is migrated from Cloudflare Pages to a GitHub Actions + Cloudflare Workers setup:

- **Building**: Done entirely in GitHub Actions
- **Deployment**: Static assets uploaded to Cloudflare Workers
- **Routing**: Handled by a Cloudflare Worker script

## Workflows

### 1. Production Build and Deploy (`build-and-deploy.yml`)

**Trigger**: Push to `main` or `v1` branches

**Process**:
1. Builds both versions (v1 and v2) regardless of which branch was updated
2. Combines them into a single site structure:
```
final_dist/
├── index.html (redirects to /docs/byoc/)
└── docs/
├── v2/ (from main branch)
│ ├── flyte/
│ ├── serverless/
│ ├── byoc/
│ └── selfmanaged/
└── v1/ (from v1 branch)
├── flyte/
├── serverless/
├── byoc/
└── selfmanaged/
```
3. Deploys to production Cloudflare Workers

### 2. PR Preview (`pr-preview.yml`)

**Trigger**: PR opened/updated against `main` or `v1`

**Process**:
1. Builds the PR branch version
2. Builds the stable version of the other branch
3. Combines them for preview
4. Deploys to a PR-specific preview environment
5. Comments on the PR with preview links

**PR Comment Features**:
- Direct links to all variants in the changed version
- Automatic updates when PR is updated
- Includes both the modified version and stable other version

### 3. PR Cleanup (`cleanup-pr.yml`)

**Trigger**: PR closed

**Process**:
1. Removes the preview deployment
2. Adds a cleanup comment to the PR

## Build Script

The `scripts/build-combined.sh` script handles the complex build logic:

- **Production builds**: Build both v1 and v2, combine them
- **Preview builds**: Build PR branch + stable other version, combine them
- Handles branch switching and cleanup automatically
- Provides detailed logging

## Required Secrets

Set these in your GitHub repository settings:

- `CLOUDFLARE_API_TOKEN`: Token with Workers and Pages permissions
- `CLOUDFLARE_ACCOUNT_ID`: Your Cloudflare account ID

## Cloudflare Worker

The `worker.js` file contains the routing logic:

- Redirects root (`/`) to `/docs/byoc/`
- Adds version prefixes when missing (defaults to v2)
- Handles legacy domain redirects
- Serves static files

## Version Management

- **v2** (latest): `main` branch → `/docs/v2/`
- **v1** (archived): `v1` branch → `/docs/v1/`

## Directory Structure

```
.github/workflows/
├── build-and-deploy.yml # Production builds
├── pr-preview.yml # PR preview builds
└── cleanup-pr.yml # PR cleanup

scripts/
└── build-combined.sh # Build script for combining versions

worker.js # Cloudflare Worker routing logic
wrangler.toml # Cloudflare deployment config
```

## Features

- ✅ Production builds when either branch updates
- ✅ PR previews for all contributors (including forks)
- ✅ Automatic PR comments with preview links
- ✅ Combined multi-version site structure
- ✅ Support for all variants (flyte, serverless, byoc, selfmanaged)
- ✅ Proper cleanup of preview environments
- ✅ Detailed build logging and error handling

## Migration Notes

This setup replaces the previous Cloudflare Pages deployment with:

1. **Better control**: Full control over build process in GitHub Actions
2. **Combined builds**: Both versions built and deployed together
3. **Enhanced PR previews**: Automatic comments with preview links
4. **Fork support**: Works with PRs from repository forks
5. **Cleaner architecture**: Clear separation of building vs. serving
82 changes: 82 additions & 0 deletions .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Build and Deploy to Production

on:
push:
branches:
- main
- v1
workflow_dispatch:

jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout current branch
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
token: ${{ secrets.GITHUB_TOKEN }}

- name: Initialize submodules with retry
run: |
# Try to initialize submodules, but don't fail if it doesn't work
echo "Initializing submodules..."
git submodule update --init --recursive --timeout=60 || {
echo "Warning: Submodule initialization failed, continuing without submodules"
# Create empty directories to prevent build failures
mkdir -p external/unionai-examples
touch external/unionai-examples/.gitkeep
}

- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: '0.145.0'
extended: true

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install wrangler
run: npm install -g wrangler

- name: Build combined site
run: |
./scripts/build-combined.sh --type production --output final_dist

- name: Create redirects file for Cloudflare Pages
run: |
cat > final_dist/_redirects << 'EOF'
# Root redirect to default variant
/ /docs/byoc/ 301
/docs /docs/byoc/ 301

# Version-less paths redirect to v2 (latest)
/docs/flyte/* /docs/v2/flyte/:splat 301
/docs/serverless/* /docs/v2/serverless/:splat 301
/docs/byoc/* /docs/v2/byoc/:splat 301
/docs/selfmanaged/* /docs/v2/selfmanaged/:splat 301

# Legacy domain redirects
https://docs.flyte.org/* https://www.union.ai/docs/v2/flyte/:splat 301
EOF

- name: Deploy to Cloudflare Pages
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: |
# Deploy to production
wrangler pages deploy final_dist \
--project-name=unionai-docs \
--compatibility-date=2024-01-01

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: production-build-${{ steps.versions.outputs.current_version }}-${{ github.sha }}
Copy link

Copilot AI Sep 5, 2025

Choose a reason for hiding this comment

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

The artifact name references steps.versions.outputs.current_version but there is no step with id 'versions' defined in this workflow. This will result in an empty string in the artifact name.

Copilot uses AI. Check for mistakes.

path: final_dist/
retention-days: 30
51 changes: 51 additions & 0 deletions .github/workflows/cleanup-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Clean up PR Preview

on:
pull_request:
types: [closed]
branches:
- main
- v1

jobs:
cleanup-preview:
runs-on: ubuntu-latest
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install wrangler
run: npm install -g wrangler

- name: Create preview environment name
id: preview
run: |
PREVIEW_NAME="pr-${{ github.event.number }}"
echo "preview_name=$PREVIEW_NAME" >> $GITHUB_OUTPUT

- name: Delete preview deployment
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: |
# Try to delete the preview deployment
# This might fail if the deployment doesn't exist, which is OK
wrangler pages deployment list --project-name=unionai-docs --compatibility-date=2024-01-01 | \
grep "${{ steps.preview.outputs.preview_name }}" | \
head -1 | \
awk '{print $1}' | \
xargs -r wrangler pages deployment delete --project-name=unionai-docs || true
Comment on lines +33 to +39
Copy link

Copilot AI Sep 5, 2025

Choose a reason for hiding this comment

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

The pipeline for deleting preview deployments is complex and fragile. The grep pattern could match partial strings, and the awk command assumes a specific output format. Consider using wrangler pages deployment delete with more specific parameters or JSON output parsing for more reliable cleanup.

Suggested change
# Try to delete the preview deployment
# This might fail if the deployment doesn't exist, which is OK
wrangler pages deployment list --project-name=unionai-docs --compatibility-date=2024-01-01 | \
grep "${{ steps.preview.outputs.preview_name }}" | \
head -1 | \
awk '{print $1}' | \
xargs -r wrangler pages deployment delete --project-name=unionai-docs || true
# Try to delete the preview deployment(s) using robust JSON parsing
# This might fail if the deployment doesn't exist, which is OK
DEPLOYMENT_IDS=$(wrangler pages deployment list --project-name=unionai-docs --compatibility-date=2024-01-01 --output json | \
jq -r --arg env "${{ steps.preview.outputs.preview_name }}" '.[] | select(.environment==$env) | .id')
for id in $DEPLOYMENT_IDS; do
wrangler pages deployment delete --project-name=unionai-docs "$id" || true
done

Copilot uses AI. Check for mistakes.


- name: Add cleanup comment
uses: peter-evans/create-or-update-comment@v4
with:
issue-number: ${{ github.event.number }}
body: |
<!-- PR_CLEANUP_COMMENT -->
## 🧹 Preview Cleanup

The preview environment for this PR has been cleaned up.

<sub>🤖 Generated by GitHub Actions</sub>
Loading