This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
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"
|
||||
}
|
||||
Reference in New Issue
Block a user