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
71 changes: 71 additions & 0 deletions packages/api/scripts/dependent-types-check-cache.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { execFileSync } from "node:child_process";
import { closeSync, mkdtempSync, openSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, test } from "vitest";

// The scheduled API sync only rewrites this package, and the project-config mirror lives in
// @supabase/config, so apps/cli's type-level drift guards only run on a PR touching either if turbo
// folds that package's files into the dependent's cached `types:check` hash via `transit`.

const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const packageDir = path.join(scriptDir, "..");
const repoDir = path.join(packageDir, "..", "..");
const turboBin = path.join(repoDir, "node_modules", ".bin", "turbo");

type DryRunTask = { readonly taskId: string; readonly dependencies: ReadonlyArray<string> };

function dryRunTypesCheckForDependents(packageName: string): ReadonlyArray<DryRunTask> {
// Redirects stdout to a file: Bun on Linux truncates a child's piped stdout at ~219 KB, and
// the dry-run JSON lists every hashed input file.
const tempDir = mkdtempSync(path.join(tmpdir(), "turbo-dry-run-"));
try {
const outputPath = path.join(tempDir, "dry-run.json");
const fd = openSync(outputPath, "w");
try {
execFileSync(turboBin, ["run", "types:check", `--filter=...${packageName}`, "--dry=json"], {
cwd: repoDir,
stdio: ["ignore", fd, "pipe"],
});
} finally {
closeSync(fd);
}
return JSON.parse(readFileSync(outputPath, "utf8")).tasks;
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
}

function reachableTaskIds(tasks: ReadonlyArray<DryRunTask>, from: string): ReadonlySet<string> {
const byId = new Map(tasks.map((task) => [task.taskId, task]));
const seen = new Set<string>();
const pending = [from];
while (pending.length > 0) {
const taskId = pending.pop();
if (taskId === undefined || seen.has(taskId)) continue;
seen.add(taskId);
pending.push(...(byId.get(taskId)?.dependencies ?? []));
}
return seen;
}

describe("dependent types:check cache key", () => {
test.each(["@supabase/api", "@supabase/config"])(
"includes %s's files for every workspace that depends on it",
(packageName) => {
const tasks = dryRunTypesCheckForDependents(packageName);
const dependentTypesChecks = tasks
.map((task) => task.taskId)
.filter(
(taskId) => taskId.endsWith("#types:check") && !taskId.startsWith(`${packageName}#`),
);

expect(dependentTypesChecks).toContain("supabase#types:check");
for (const taskId of dependentTypesChecks) {
expect(reachableTaskIds(tasks, taskId), taskId).toContain(`${packageName}#transit`);
Comment thread
avallete marked this conversation as resolved.
Resolved
}
},
60_000,
);
});
4 changes: 4 additions & 0 deletions packages/config/src/project-config/api-attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { Schema } from "effect";
const postgresSettingsAttributes = Schema.Struct({
effective_cache_size: Schema.optionalKey(Schema.String),
logical_decoding_work_mem: Schema.optionalKey(Schema.String),
autovacuum_max_workers: Schema.optionalKey(Schema.Unknown),
autovacuum_work_mem: Schema.optionalKey(Schema.Unknown),
log_autovacuum_min_duration: Schema.optionalKey(Schema.Unknown),
log_checkpoints: Schema.optionalKey(Schema.Unknown),
log_connections: Schema.optionalKey(Schema.Unknown),
Expand Down Expand Up @@ -48,6 +50,8 @@ const postgresSettingsAttributes = Schema.Struct({
checkpoint_timeout: Schema.optionalKey(Schema.Unknown),
hot_standby_feedback: Schema.optionalKey(Schema.Unknown),
cron_log_statement: Schema.optionalKey(Schema.Unknown),
pg_net_batch_size: Schema.optionalKey(Schema.Unknown),
pg_stat_statements_max: Schema.optionalKey(Schema.Unknown),
});

// `allowed_cidrs` is mapped (`filterCidrAddresses`, `./registry.ts`); the rest are unmapped.
Expand Down
7 changes: 6 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
"strictTaskEntrypointSelection": true
},
"tasks": {
"transit": {
"dependsOn": ["^transit"]
},
"types:check": {
"cache": true
"cache": true,
"dependsOn": ["transit"]
},
"lint:check": {
"cache": false
Expand Down Expand Up @@ -33,6 +37,7 @@
},
"@supabase/docs#types:check": {
"cache": true,
"dependsOn": ["transit"],
"outputs": [".source/**"]
},
"test:unit:run": {
Expand Down
Loading