diff --git a/workflows/auto_deploy.yml b/workflows/auto_deploy.yml new file mode 100644 index 00000000..a8dafe05 --- /dev/null +++ b/workflows/auto_deploy.yml @@ -0,0 +1,67 @@ +name: Auto Deploy Preview + +on: + workflow_call: + inputs: + base: + type: string + required: true + head: + type: string + required: true + +permissions: + contents: write + statuses: read + +jobs: + signal: + runs-on: ubuntu-latest + steps: + - name: Emit repository_dispatch to App + uses: actions/github-script@v7 + with: + script: | + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: context.repo.repo, + event_type: "auto-deploy", + client_payload: { base: inputs.base, head: inputs.head } + }) + - name: Wait for World Forge status + uses: actions/github-script@v7 + with: + script: | + const owner = context.repo.owner, repo = context.repo.repo, ref = inputs.head; + const prefix = "world-forge/auto-deploy"; + const initDeadline = Date.now() + 2*60*1000; + const hardDeadline = Date.now() + 45*60*1000; + const sleep = (ms) => new Promise(r => setTimeout(r, ms)); + async function allStatuses() { + const { data } = await github.rest.repos.getCombinedStatusForRef({ owner, repo, ref }); + return data.statuses || []; + } + let expected = null; + while (Date.now() < initDeadline) { + const statuses = await allStatuses(); + const aggFail = statuses.find(s => s.context === prefix && (s.state === "failure" || s.state === "error")); + if (aggFail) { core.setFailed(aggFail.description || "Auto-deploy aggregate failed"); return; } + const aggs = statuses.filter(s => s.context === prefix && s.state === "pending"); + for (const a of aggs) { + const n = parseInt(a.description || "0", 10); + if (!Number.isNaN(n) && n > 0) { expected = n; break; } + } + if (expected) break; + await sleep(5000); + } + if (!expected) { core.setFailed("Auto-deploy did not publish expected deployment count."); return; } + while (Date.now() < hardDeadline) { + const statuses = await allStatuses(); + const perProject = statuses.filter(s => s.context.startsWith(prefix + "/")); + const success = perProject.filter(s => s.state === "success").length; + const failed = perProject.filter(s => s.state === "failure" || s.state === "error").length; + if (success + failed >= expected) { if (failed > 0) core.setFailed(`Deploy failures: ${failed}/${expected}`); return; } + await sleep(10000); + } + core.setFailed("Timed out waiting for auto-deploy results."); + \ No newline at end of file