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
91 changes: 51 additions & 40 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,32 @@ This document describes the CI/CD architecture for the Apache Teaclave website.

```
.github/workflows/
├── _reusable-build.yml # [Reusable] Shared build logic for Docker + website
├── pr-validation.yml # PR validation workflow (read-only)
├── deploy-staging.yml # Deployment workflow for staging
└── README.md # This file
├── _reusable-build.yml # [Reusable] Shared build logic for Docker + website
├── pr-validation.yml # PR validation workflow (read-only)
├── deploy-staging.yml # Deploys build to asf-staging branch
├── promote-staging-to-production.yml # [Manual] Replaces asf-site with asf-staging
└── README.md # This file
```

### Naming Convention

- **`pr-*.yml`** - PR validation workflows (read-only permissions)
- **`deploy-*.yml`** - Deployment workflows (write permissions)
- **`promote-*.yml`** - Manual promotion workflows (e.g. staging → production)
- **`_reusable-*.yml`** - Reusable workflows (called by others, underscore prefix)

## 🌐 Website Update Flow

1. **PR merged** (or push to `master`) → **Deploy Staging** runs → build is deployed to the **asf-staging** branch. Staging site is updated.
2. **Verify** → Visit the staging website and confirm everything looks correct.
3. **Promote to production** → Go to **Actions** → **"Promote Staging to Production"** → **Run workflow**. This replaces the **asf-site** branch with the content of **asf-staging**, updating the final live website.

| Step | What happens |
|------|----------------|
| Merge / push to master | `deploy-staging.yml` → `asf-staging` updated |
| Manual check | You verify the staging site |
| Manual trigger | `promote-staging-to-production.yml` → `asf-site` = `asf-staging` |

## 🏗️ Architecture Overview

### Design Principles
Expand All @@ -31,40 +45,37 @@ This document describes the CI/CD architecture for the Apache Teaclave website.
### Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Repository Events │
│ │
│ Pull Request Push to master Manual Trigger │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │pr-validation│ │deploy- │ │deploy- │ │
│ │.yml │ │staging.yml │ │staging.yml │ │
│ └────┬────────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ │ ┌────────────┴──────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ _reusable-build.yml (Shared Logic) │ │
│ │ │ │
│ │ ┌──────────────────┐ ┌────────────────────┐ │ │
│ │ │ build-docker- │─▶│ build-website │ │ │
│ │ │ image │ │ │ │ │
│ │ └──────────────────┘ └────────────────────┘ │ │
│ │ │ │
│ │ Outputs: │ │
│ │ - docker-artifact-name │ │
│ │ - build-artifact-name │ │
│ └─────────────────┬────────────────┬─────────────┘ │
│ │ │ │
│ ┌────────────┘ └────────────┐ │
│ ▼ ▼ │
│ ┌─────────┐ ┌──────────────┐ │
│ │validate │ │deploy-staging│ │
│ │ │ │ │ │
│ └─────────┘ └──────────────┘ │
│ │
│ Result: ✓ PR Check Result: ✓ Deployed │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ GitHub Repository Events │
│ │
│ Pull Request Push to master Manual Trigger │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │pr-validation│ │deploy- │ │promote-staging-to- │ │
│ │.yml │ │staging.yml │ │production.yml │ │
│ └────┬────────┘ └──────┬───────┘ │ (manual only) │ │
│ │ │ └──────────┬─────────────┘ │
│ │ │ │ │
│ ▼ ▼ │ │
│ ┌────────────────────────────────────────┐ │ │
│ │ _reusable-build.yml (Shared Logic) │ │ │
│ │ build-docker-image → build-website │ │ │
│ └────────────────────┬───────────────────┘ │ │
│ │ │ │
│ ┌────────────────┴────────────────┐ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ validate│ │deploy-staging│ │ promote │ │
│ └─────────┘ └──────┬───────┘ │ (asf-staging│ │
│ │ │ │ → asf-site)│ │
│ │ ▼ └──────┬───────┘ │
│ │ asf-staging │ │
│ │ (staging site) ▼ │
│ │ │ asf-site │
│ │ │ (live site) │
│ │ │ │
│ ▼ └──► Verify staging, then run │
│ Result: ✓ PR Check "Promote Staging to Production" │
└─────────────────────────────────────────────────────────────────────────┘
```
85 changes: 85 additions & 0 deletions .github/workflows/promote-staging-to-production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Promote Staging to Production
#
# Manual-only workflow: after verifying the staging site, run this to replace
# the production branch (asf-site) with the content of asf-staging.
#
# Flow:
# 1. PR merged → deploy-staging.yml runs → asf-staging updated
# 2. Visit staging website, verify it looks correct
# 3. Go to Actions → "Promote Staging to Production" → Run workflow
# 4. asf-site is replaced with asf-staging → final website updated

name: Promote Staging to Production

on:
workflow_dispatch:

# Permissions to push to the production branch
permissions:
contents: write

# Prevent concurrent promotions
concurrency:
group: promote-staging-to-production
cancel-in-progress: false

jobs:
promote:
name: Replace asf-site with asf-staging
runs-on: ubuntu-22.04
timeout-minutes: 10
environment:
name: production
url: https://teaclave.apache.org

steps:
- name: Checkout repository
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false

- name: Fetch asf-staging
run: |
git fetch origin asf-staging
if ! git rev-parse --verify origin/asf-staging >/dev/null 2>&1; then
echo "Error: Branch asf-staging not found. Run deploy-staging first."
exit 1
fi
echo "asf-staging is at: $(git rev-parse origin/asf-staging)"

- name: Replace asf-site with asf-staging
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail

cleanup() {
git config --local --unset-all http.https://github.com/.extraheader 2>/dev/null || true
}
trap cleanup EXIT INT TERM

git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git config --local http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n x-access-token:${GITHUB_TOKEN} | base64)"

# Push asf-staging to asf-site (replace production with staging content)
git push https://github.com/${GITHUB_REPOSITORY}.git origin/asf-staging:asf-site --force

echo "✅ Production branch (asf-site) updated with content from asf-staging"

- name: Promotion Summary
run: |
echo "### ✅ Production Updated" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The **asf-site** branch has been replaced with the content of **asf-staging**." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "#### Details" >> $GITHUB_STEP_SUMMARY
echo "- **Source:** \`asf-staging\`" >> $GITHUB_STEP_SUMMARY
echo "- **Target:** \`asf-site\` (production)" >> $GITHUB_STEP_SUMMARY
echo "- **Triggered by:** @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
echo "- **Timestamp:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The live website will reflect the new content shortly." >> $GITHUB_STEP_SUMMARY
18 changes: 8 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,17 @@ The official website for Apache Teaclave™, generated with the Docusaurus stati
make build
```

### Deployment
### Deployment (CI/CD)

To deploy the generated site to the staging and production environments:
Deployment is handled by GitHub Actions:

```bash
# Deploy to staging
ghp-import --no-history --force site/build/ -b asf-staging
git push -f asf-staging
1. **Merge a PR** (or push to `master`) → the **Deploy Staging** workflow runs and updates the **asf-staging** branch.
2. **Verify** the staging site.
3. **Promote to production** → In the repo, go to **Actions** → **"Promote Staging to Production"** → **Run workflow**. This updates **asf-site** with the content of **asf-staging**.

# Deploy to production
ghp-import --no-history --force site/build/ -b asf-site
git push -f asf-site
```
For workflow details and architecture, see [.github/workflows/README.md](.github/workflows/README.md).

Manual deployment from a local build (e.g. `make staging` / `make site` in `site/`) is still supported; see `site/Makefile`.

### Website URLs

Expand Down