Files
vercel__workflow/scripts/create-community-worlds-matrix.mjs
Pranay Prakash 4708a77a35 CI: drop setup-command input from reusable community-world workflows (#1828)
* drop setup-command input from reusable community-world workflows

The community-world matrix is produced by running
scripts/create-community-worlds-matrix.mjs in the fork PR's checkout,
so any field on it is attacker-controlled. Forwarding
matrix.world.setup-command into the reusable workflow and eval-ing it
let a malicious fork PR execute arbitrary shell on the runner.

Replace the pass-through with a hardcoded per-world-id case in the
reusable workflows (only turso currently needs a setup step) and drop
the setup field from the matrix generator.

* rename step to "Per-world setup"

Addresses Copilot review feedback: the step no longer executes an
arbitrary command, so the old name was misleading.
2026-05-14 17:14:49 -07:00

72 lines
1.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Generates a GitHub Actions matrix for community world testing.
* Reads from worlds-manifest.json and filters to testable community worlds.
*
* Usage: node scripts/create-community-worlds-matrix.mjs
*
* Output format (JSON):
* {
* "world": [
* {
* "id": "starter",
* "name": "Starter",
* "package": "@workflow-worlds/starter",
* "service-type": "none",
* "env-vars": "{\"WORKFLOW_TARGET_WORLD\":\"@workflow-worlds/starter\"}"
* },
* ...
* ]
* }
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.join(__dirname, '..');
// Read the manifest
const manifestPath = path.join(rootDir, 'worlds-manifest.json');
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
// Filter to community worlds that can be tested in CI
const testableWorlds = manifest.worlds.filter((world) => {
// Only community worlds
if (world.type !== 'community') return false;
// Skip worlds that require external credentials (e.g., Jazz needs API keys)
if (world.requiresCredentials) return false;
return true;
});
// Build the matrix
const matrix = {
world: testableWorlds.map((world) => {
// Determine service type based on services array
let serviceType = 'none';
if (world.services && world.services.length > 0) {
// Use the first service's name as the service type
// Currently supports: mongodb, redis
const serviceName = world.services[0].name;
if (['mongodb', 'redis'].includes(serviceName)) {
serviceType = serviceName;
}
}
return {
id: world.id,
name: world.name,
package: world.package,
'service-type': serviceType,
'env-vars': JSON.stringify(world.env || {}),
};
}),
};
// Output JSON for GitHub Actions
console.log(JSON.stringify(matrix));