138 lines
5.1 KiB
YAML
138 lines
5.1 KiB
YAML
name: PR Preview
|
|
|
|
on:
|
|
pull_request_target:
|
|
types: [labeled, unlabeled, closed]
|
|
|
|
jobs:
|
|
deploy:
|
|
name: Deploy Preview
|
|
# Runs when the "preview" label is added — requires collaborator write access
|
|
if: >-
|
|
github.event.action == 'labeled'
|
|
&& github.event.label.name == 'preview'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
actions: read
|
|
env:
|
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
steps:
|
|
- name: Wait for Docker build job
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
BUILD_JOB_NAME: Build & Publish Artifacts
|
|
run: |
|
|
echo "Waiting for '${BUILD_JOB_NAME}' job to complete for $HEAD_SHA..."
|
|
TIMEOUT=1800 # 30 minutes
|
|
INTERVAL=30
|
|
START=$(date +%s)
|
|
|
|
while true; do
|
|
ELAPSED=$(( $(date +%s) - START ))
|
|
if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
|
|
echo "::error::Timed out waiting for '${BUILD_JOB_NAME}' (${TIMEOUT}s)"
|
|
exit 1
|
|
fi
|
|
|
|
# Find the CI run for this SHA
|
|
RUN=$(gh api "repos/${{ github.repository }}/actions/workflows/ci.yml/runs?head_sha=${HEAD_SHA}&per_page=1" \
|
|
--jq '.workflow_runs[0] | {id, status}' 2>/dev/null || echo "")
|
|
|
|
if [ -z "$RUN" ] || [ "$RUN" = "null" ]; then
|
|
echo " No CI run found yet, waiting ${INTERVAL}s... (${ELAPSED}s elapsed)"
|
|
sleep "$INTERVAL"
|
|
continue
|
|
fi
|
|
|
|
RUN_ID=$(echo "$RUN" | jq -r '.id')
|
|
RUN_STATUS=$(echo "$RUN" | jq -r '.status')
|
|
|
|
# Look up the build job specifically (paginate — CI has 30+ jobs)
|
|
BUILD_JOB=$(gh api --paginate "repos/${{ github.repository }}/actions/runs/${RUN_ID}/jobs?per_page=100" \
|
|
--jq ".jobs[] | select(.name == \"${BUILD_JOB_NAME}\") | {status, conclusion}")
|
|
|
|
if [ -z "$BUILD_JOB" ]; then
|
|
if [ "$RUN_STATUS" = "completed" ]; then
|
|
echo "::error::CI run ${RUN_ID} completed but '${BUILD_JOB_NAME}' job was not found"
|
|
exit 1
|
|
fi
|
|
echo " '${BUILD_JOB_NAME}' job not started yet (run ${RUN_STATUS}), waiting ${INTERVAL}s... (${ELAPSED}s elapsed)"
|
|
sleep "$INTERVAL"
|
|
continue
|
|
fi
|
|
|
|
JOB_STATUS=$(echo "$BUILD_JOB" | jq -r '.status')
|
|
JOB_CONCLUSION=$(echo "$BUILD_JOB" | jq -r '.conclusion // empty')
|
|
|
|
if [ "$JOB_STATUS" = "completed" ]; then
|
|
if [ "$JOB_CONCLUSION" = "success" ]; then
|
|
echo "Docker build ready (CI run $RUN_ID)"
|
|
break
|
|
fi
|
|
echo "::error::'${BUILD_JOB_NAME}' did not succeed (conclusion: $JOB_CONCLUSION)"
|
|
exit 1
|
|
fi
|
|
|
|
echo " '${BUILD_JOB_NAME}' still ${JOB_STATUS}, waiting ${INTERVAL}s... (${ELAPSED}s elapsed)"
|
|
sleep "$INTERVAL"
|
|
done
|
|
|
|
- name: Re-check PR eligibility
|
|
id: recheck
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
PR=$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" \
|
|
--jq '{state, labels: [.labels[].name]}')
|
|
|
|
STATE=$(echo "$PR" | jq -r '.state')
|
|
HAS_LABEL=$(echo "$PR" | jq '.labels | any(. == "preview")')
|
|
|
|
if [ "$STATE" != "open" ]; then
|
|
echo "::warning::PR is no longer open ($STATE), skipping dispatch"
|
|
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
elif [ "$HAS_LABEL" != "true" ]; then
|
|
echo "::warning::preview label was removed, skipping dispatch"
|
|
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "PR still eligible for preview deploy"
|
|
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Dispatch deploy to Ghost-Moya
|
|
if: steps.recheck.outputs.skip != 'true'
|
|
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4
|
|
with:
|
|
token: ${{ secrets.CANARY_DOCKER_BUILD }}
|
|
repository: TryGhost/Ghost-Moya
|
|
event-type: preview-deploy
|
|
client-payload: >-
|
|
{
|
|
"pr_number": "${{ github.event.pull_request.number }}",
|
|
"action": "deploy",
|
|
"seed": "true"
|
|
}
|
|
|
|
destroy:
|
|
name: Destroy Preview
|
|
# Runs when "preview" label is removed, or the PR is closed/merged while labeled
|
|
if: >-
|
|
(github.event.action == 'unlabeled' && github.event.label.name == 'preview')
|
|
|| (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'preview'))
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Dispatch destroy to Ghost-Moya
|
|
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4
|
|
with:
|
|
token: ${{ secrets.CANARY_DOCKER_BUILD }}
|
|
repository: TryGhost/Ghost-Moya
|
|
event-type: preview-destroy
|
|
client-payload: >-
|
|
{
|
|
"pr_number": "${{ github.event.pull_request.number }}",
|
|
"action": "destroy"
|
|
}
|