Skip to content
Merged
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
145 changes: 0 additions & 145 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -878,151 +878,6 @@ jobs:
exit 1
}

internal-tests:
name: Internal Tests
needs: [lints]
# Skip if not a PR or a push to master
# 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_name == 'push' && github.ref == 'refs/heads/master'))
&& (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }}
permissions:
contents: read
pull-requests: read
runs-on: ubuntu-latest
env:
TARGET_OWNER: clockworklabs
TARGET_REPO: SpacetimeDBPrivate
steps:
# Skip the private dispatch entirely when only `docs/` is touched. The job
# itself still completes successfully so required-status-check gating is
# satisfied without spending private-runner time on a docs-only change.
- name: Detect non-docs changes
id: filter
uses: dorny/paths-filter@v3
with:
filters: |
non_docs:
- '!docs/**'

- id: dispatch
name: Trigger tests
if: steps.filter.outputs.non_docs == 'true'
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 publicPrNumber = context.payload.pull_request?.number ?? context.payload.inputs?.pr_number;
const preDispatch = new Date().toISOString();
const inputs = { public_ref: publicRef };
if (publicPrNumber) {
inputs.public_pr_number = String(publicPrNumber);
}

// Dispatch the workflow in the target repository
await github.rest.actions.createWorkflowDispatch({
owner: targetOwner,
repo: targetRepo,
workflow_id: workflowId,
ref: targetRef,
inputs,
});

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;
}

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
if: steps.filter.outputs.non_docs == 'true'
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;
}

if (conclusion !== 'success') {
core.setFailed(`Private workflow failed with conclusion: ${conclusion}`);
}

- name: Cancel invoked run if workflow cancelled
if: ${{ cancelled() && steps.dispatch.outputs.run_id }}
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) return;
await github.rest.actions.cancelWorkflowRun({
owner: targetOwner,
repo: targetRepo,
run_id: runId,
});

global_json_policy:
name: Verify global.json files are symlinks
runs-on: ubuntu-latest
Expand Down
161 changes: 161 additions & 0 deletions .github/workflows/internal-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: Internal Tests

on:
pull_request:
push:
branches:
- master
merge_group:
workflow_dispatch:

run-name: Internal Tests [ref=${{ github.ref }}]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
pull-requests: read

jobs:
internal-tests:
name: Internal Tests
# Skip if not a PR or a push to master
# 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_name == 'push' && github.ref == 'refs/heads/master'))
&& (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }}
runs-on: ubuntu-latest
env:
TARGET_OWNER: clockworklabs
TARGET_REPO: SpacetimeDBPrivate
steps:
# Skip the private dispatch entirely when only `docs/` is touched. The job
# itself still completes successfully so required-status-check gating is
# satisfied without spending private-runner time on a docs-only change.
- name: Detect non-docs changes
id: filter
uses: dorny/paths-filter@v3
with:
filters: |
non_docs:
- '!docs/**'

- id: dispatch
name: Trigger tests
if: steps.filter.outputs.non_docs == 'true'
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 publicPrNumber = context.payload.pull_request?.number;
const preDispatch = new Date().toISOString();
const inputs = { public_ref: publicRef };
if (publicPrNumber) {
inputs.public_pr_number = String(publicPrNumber);
}

// Dispatch the workflow in the target repository
await github.rest.actions.createWorkflowDispatch({
owner: targetOwner,
repo: targetRepo,
workflow_id: workflowId,
ref: targetRef,
inputs,
});

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;
}

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
if: steps.filter.outputs.non_docs == 'true'
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;
}

if (conclusion !== 'success') {
core.setFailed(`Private workflow failed with conclusion: ${conclusion}`);
}

- name: Cancel invoked run if workflow cancelled
if: ${{ cancelled() && steps.dispatch.outputs.run_id }}
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) return;
await github.rest.actions.cancelWorkflowRun({
owner: targetOwner,
repo: targetRepo,
run_id: runId,
});
Loading