mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-12 18:57:51 -04:00
ee69be7073
# Description of Changes `Internal Tests` invoke another workflow. If the calling workflow is cancelled, now we also cancel the invoked workflow. # API and ABI breaking changes None. # Expected complexity level and risk 2 # Testing - [x] Push multiple commits to this PR, see that the invoked job is cancelled - [x] Manually cancel the `Internal Tests` job, see that the invoked job is cancelled --------- Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
149 lines
5.6 KiB
YAML
149 lines
5.6 KiB
YAML
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- master
|
|
|
|
name: Internal Tests
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || format('sha-{0}', github.sha) }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
run-tests:
|
|
# Skip if this is an external contribution. GitHub secrets will be empty, so the step would fail anyway.
|
|
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
TARGET_OWNER: clockworklabs
|
|
TARGET_REPO: SpacetimeDBPrivate
|
|
steps:
|
|
- id: dispatch
|
|
name: Trigger tests
|
|
uses: actions/github-script@v7
|
|
with:
|
|
github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }}
|
|
script: |
|
|
const workflowId = 'ci.yml';
|
|
const targetRef = 'master';
|
|
const targetOwner = process.env.TARGET_OWNER;
|
|
const targetRepo = process.env.TARGET_REPO;
|
|
// Use the ref for pull requests because the head sha is brittle (github does some extra dance where it merges in master).
|
|
const publicRef = (context.eventName === 'pull_request') ? context.payload.pull_request.head.ref : context.sha;
|
|
const preDispatch = new Date().toISOString();
|
|
|
|
console.log("context.eventName =", context.eventName);
|
|
console.log("context.ref =", context.ref);
|
|
console.log("context.sha =", context.sha);
|
|
console.log("Dispatch workflow with publicRef =", publicRef);
|
|
|
|
// Dispatch the workflow in the target repository
|
|
await github.rest.actions.createWorkflowDispatch({
|
|
owner: targetOwner,
|
|
repo: targetRepo,
|
|
workflow_id: workflowId,
|
|
ref: targetRef,
|
|
inputs: { public_ref: publicRef }
|
|
});
|
|
|
|
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
|
|
// Find the dispatched run by name
|
|
let runId = null;
|
|
for (let attempt = 0; attempt < 20 && !runId; attempt++) { // up to ~10 minutes to locate the run
|
|
await sleep(5000);
|
|
const runsResp = await github.rest.actions.listWorkflowRuns({
|
|
owner: targetOwner,
|
|
repo: targetRepo,
|
|
workflow_id: workflowId,
|
|
event: 'workflow_dispatch',
|
|
branch: targetRef,
|
|
per_page: 50,
|
|
});
|
|
|
|
const expectedName = `CI [public_ref=${publicRef}]`;
|
|
const candidates = runsResp.data.workflow_runs
|
|
.filter(r => r.name === expectedName && new Date(r.created_at) >= new Date(preDispatch))
|
|
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
|
|
|
if (candidates.length > 0) {
|
|
runId = candidates[0].id;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!runId) {
|
|
core.setFailed('Failed to locate dispatched run in the private repository.');
|
|
return;
|
|
}
|
|
|
|
// Provide direct link and context prior to waiting
|
|
const runUrl = `https://github.com/${targetOwner}/${targetRepo}/actions/runs/${runId}`;
|
|
core.info(`View run: ${runUrl}`);
|
|
|
|
core.setOutput('run_id', String(runId));
|
|
core.setOutput('run_url', runUrl);
|
|
|
|
- name: Wait for Internal Tests to complete
|
|
uses: actions/github-script@v7
|
|
with:
|
|
github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }}
|
|
script: |
|
|
const targetOwner = process.env.TARGET_OWNER;
|
|
const targetRepo = process.env.TARGET_REPO;
|
|
const runId = Number(`${{ steps.dispatch.outputs.run_id }}`);
|
|
const runUrl = `${{ steps.dispatch.outputs.run_url }}`;
|
|
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
|
|
core.info(`Waiting for workflow result... ${runUrl}`);
|
|
|
|
let conclusion = null;
|
|
for (let attempt = 0; attempt < 240; attempt++) { // up to ~2 hours
|
|
const runResp = await github.rest.actions.getWorkflowRun({
|
|
owner: targetOwner,
|
|
repo: targetRepo,
|
|
run_id: runId
|
|
});
|
|
const { status, conclusion: c } = runResp.data;
|
|
if (status === 'completed') {
|
|
conclusion = c || 'success';
|
|
break;
|
|
}
|
|
await sleep(30000);
|
|
}
|
|
|
|
if (!conclusion) {
|
|
core.setFailed('Timed out waiting for private workflow to complete.');
|
|
return;
|
|
}
|
|
|
|
core.info(`Private workflow conclusion: ${conclusion}`);
|
|
if (conclusion !== 'success') {
|
|
core.setFailed(`Private workflow failed with conclusion: ${conclusion}`);
|
|
}
|
|
|
|
- name: Cancel invoked run if workflow cancelled
|
|
if: ${{ cancelled() }}
|
|
uses: actions/github-script@v7
|
|
with:
|
|
github-token: ${{ secrets.SPACETIMEDB_PRIVATE_TOKEN }}
|
|
script: |
|
|
const targetOwner = process.env.TARGET_OWNER;
|
|
const targetRepo = process.env.TARGET_REPO;
|
|
const runId = Number(`${{ steps.dispatch.outputs.run_id }}`);
|
|
if (!runId) {
|
|
core.warning('No run_id available to cancel.');
|
|
return;
|
|
}
|
|
core.info(`Cancelling private workflow run ${runId} in ${targetOwner}/${targetRepo}...`);
|
|
await github.rest.actions.cancelWorkflowRun({
|
|
owner: targetOwner,
|
|
repo: targetRepo,
|
|
run_id: runId,
|
|
});
|
|
core.info('Cancellation requested.');
|