Skip to content
Open
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
79 changes: 79 additions & 0 deletions .github/workflows/pr-preview-cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: PR Preview Cleanup

on:
pull_request:
types: [closed]

permissions:
contents: write
pull-requests: write

# Use the same concurrency group as the deploy workflow so cleanup and
# deploy pushes to gh-pages are always serialized.
concurrency:
group: gh-pages-deploy
cancel-in-progress: false

jobs:
cleanup:
name: Remove Preview
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository

steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 1
persist-credentials: true

- name: Delete preview directory
env:
PR_NUMBER: ${{ github.event.number }}
run: |
PREVIEW_DIR="pr-previews/${PR_NUMBER}"
if [ -d "${PREVIEW_DIR}" ]; then
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git rm -rf "${PREVIEW_DIR}"
git commit -m "chore: remove preview for PR #${PR_NUMBER}"

for attempt in 1 2 3; do
git fetch origin gh-pages
git rebase origin/gh-pages 2>/dev/null || { git rebase --abort; true; }
git push origin gh-pages && break
echo "Push attempt ${attempt} failed, retrying..."
sleep $((attempt * 5))
done
else
echo "No preview directory found for PR #${PR_NUMBER}, nothing to do."
fi

- name: Update preview comment to reflect closure
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ github.event.number }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = process.env.PR_NUMBER;
const owner = context.repo.owner;
const repo = context.repo.repo;

const marker = '<!-- pr-preview-bot -->';

// Paginate to handle PRs with more than 30 comments
const comments = await github.paginate(github.rest.issues.listComments, {
owner, repo, issue_number: prNumber,
});

const existing = comments.find(c => c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner, repo,
comment_id: existing.id,
body: marker + '\n## 📄 Documentation Preview\n\n> This preview has been removed because the PR was closed.',
});
}
154 changes: 154 additions & 0 deletions .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: PR Preview

on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'docs/**'
- 'assemblies/**'
- 'topics/**'
- '_includes/**'
- '_layouts/**'
- '_sass/**'
- 'assets/**'
- '_config.yml'
- 'Gemfile'
- 'index.md'
- '.github/workflows/pr-preview.yml'

permissions:
contents: write
pull-requests: write
Comment thread
coderabbitai[bot] marked this conversation as resolved.

# Serialize all gh-pages pushes across both workflows to prevent
# non-fast-forward failures when two PRs deploy at the same time.
concurrency:
group: gh-pages-deploy
cancel-in-progress: false

jobs:
build-and-deploy:
name: Build & Deploy Preview
runs-on: ubuntu-latest
# Skip fork PRs — GITHUB_TOKEN is read-only for forks and the push would fail.
if: github.event.pull_request.head.repo.full_name == github.repository

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
persist-credentials: true

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true

- name: Install system dependencies
run: sudo apt-get install -y asciidoctor

- name: Build site with preview base URL
env:
JEKYLL_ENV: production
PR_NUMBER: ${{ github.event.number }}
run: |
bundle exec jekyll build \
--baseurl "/mta-documentation/pr-previews/${PR_NUMBER}" \
--destination _site

- name: Deploy preview to gh-pages
env:
PR_NUMBER: ${{ github.event.number }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

mkdir -p /tmp/pr-preview
cp -r _site/. /tmp/pr-preview/

git fetch origin gh-pages 2>/dev/null || true
if git show-ref --verify --quiet refs/remotes/origin/gh-pages; then
git checkout -B gh-pages origin/gh-pages
else
git checkout --orphan gh-pages
git rm -rf . --quiet
echo "GitHub Pages for mta-documentation" > README.md
git add README.md
git commit -m "chore: initialise gh-pages branch"
fi

PREVIEW_DIR="pr-previews/${PR_NUMBER}"
rm -rf "${PREVIEW_DIR}"
mkdir -p "${PREVIEW_DIR}"
cp -r /tmp/pr-preview/. "${PREVIEW_DIR}/"

git add "${PREVIEW_DIR}"
if git diff --staged --quiet; then
echo "No changes to deploy."
else
COMMIT_SHA="${{ github.event.pull_request.head.sha }}"
git commit -m "preview: PR #${PR_NUMBER} @ ${COMMIT_SHA::7}"

# Retry push up to 3 times in case of a concurrent non-fast-forward
for attempt in 1 2 3; do
git fetch origin gh-pages
git rebase origin/gh-pages 2>/dev/null || { git rebase --abort; true; }
git push origin gh-pages && break
echo "Push attempt ${attempt} failed, retrying..."
sleep $((attempt * 5))
done
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Post or update preview comment
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ github.event.number }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = process.env.PR_NUMBER;
const sha = context.payload.pull_request.head.sha.substring(0, 7);
const owner = context.repo.owner;
const repo = context.repo.repo;

const previewUrl =
`https://${owner}.github.io/${repo}/pr-previews/${prNumber}/`;

const body = [
`## 📄 Documentation Preview`,
``,
`| | |`,
`|---|---|`,
`| **Preview URL** | ${previewUrl} |`,
`| **Commit** | \`${sha}\` |`,
`| **Updated** | ${new Date().toUTCString()} |`,
``,
`> Preview updates automatically on every push to this PR.`,
`> It will be removed when the PR is closed.`,
].join('\n');

const marker = '<!-- pr-preview-bot -->';
const markedBody = marker + '\n' + body;

// Paginate to handle PRs with more than 30 comments
const comments = await github.paginate(github.rest.issues.listComments, {
owner, repo, issue_number: prNumber,
});

const existing = comments.find(c => c.body.includes(marker));

if (existing) {
await github.rest.issues.updateComment({
owner, repo,
comment_id: existing.id,
body: markedBody,
});
} else {
await github.rest.issues.createComment({
owner, repo,
issue_number: prNumber,
body: markedBody,
});
}