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
4 changes: 4 additions & 0 deletions .oxlintrc.effect.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,21 @@
"!apps/cli/src/shared/auth/**",
"!apps/cli/src/shared/compute/**",
"!apps/cli/src/shared/config/**",
"!apps/cli/src/shared/feedback/**",
"!apps/cli/src/shared/functions/functions-docker.ts",
"!apps/cli/src/shared/functions/functions-docker.unit.test.ts",
"!apps/cli/src/shared/functions/serve.ts",
"!apps/cli/src/shared/functions/serve.unit.test.ts",
"!apps/cli/src/shared/git/**",
"!apps/cli/src/shared/init/**",
"!apps/cli/src/shared/issue/**",
"!apps/cli/src/shared/runtime/**",
"!apps/cli/src/shared/services/**",
"!apps/cli/src/shared/telemetry/**",
// Last match wins across the whole list: keep bare re-exclusions after every
// `!` entry that would otherwise re-include them.
"apps/cli/src/shared/compute/stacks/**",
"apps/cli/src/shared/feedback/database.types.ts",
"!apps/cli/tests/helpers/branches-live.ts",
"!apps/cli/tests/helpers/compute.ts",
"!apps/cli/tests/helpers/migration-live.ts",
Expand Down
10 changes: 6 additions & 4 deletions apps/cli/src/command-internal/db-bootstrap/db-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Data, Effect, type FileSystem, Option, type Path, Schedule } from "effe
import type { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";

import type { LocalServiceVersionOverrides } from "../../shared/services/services.shared.ts";
import { slimImagesEnabled } from "../../shared/services/slim-images.ts";
import { Output } from "../../shared/output/output.service.ts";
import { RuntimeInfo } from "../../shared/runtime/runtime-info.service.ts";
import {
Expand Down Expand Up @@ -139,11 +140,12 @@ export interface StartDbSetupImages {
*/
function resolveDbSetupImages(
serviceVersionOverrides: LocalServiceVersionOverrides,
slim: boolean,
): StartDbSetupImages {
return {
realtime: resolvePinnedImage("realtime", "realtime", serviceVersionOverrides),
storage: resolvePinnedImage("storage", "storage", serviceVersionOverrides),
auth: resolvePinnedImage("gotrue", "auth", serviceVersionOverrides),
realtime: resolvePinnedImage("realtime", "realtime", serviceVersionOverrides, slim),
storage: resolvePinnedImage("storage", "storage", serviceVersionOverrides, slim),
auth: resolvePinnedImage("gotrue", "auth", serviceVersionOverrides, slim),
};
}

Expand All @@ -169,7 +171,7 @@ export const resolveDbSetupPrelude = <E>(setup: {
const output = yield* Output;
yield* output.raw("Initialising schema...\n", "stderr");
const jwks = setup.majorVersion >= 15 && setup.realtimeEnabledForSetup ? yield* setup.jwks : "";
const images = resolveDbSetupImages(setup.serviceVersionOverrides);
const images = resolveDbSetupImages(setup.serviceVersionOverrides, yield* slimImagesEnabled);
return { jwks, images };
});

Expand Down
2 changes: 2 additions & 0 deletions apps/cli/src/command-internal/db-bootstrap/pinned-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ export function resolvePinnedImage(
alias: string,
localServiceName: LocalServiceVersionName,
serviceVersions: LocalServiceVersionOverrides,
slim: boolean,
): string {
return slimImageForCurrentPin(
alias,
dockerfileServiceImageRaw(alias),
serviceVersions[localServiceName],
slim,
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { describe, expect, it } from "vitest";

import { dockerfileServiceImageRaw } from "../../shared/services/dockerfile-images.ts";
import { toSlimImage } from "../../shared/services/slim-images.ts";
Expand All @@ -12,67 +12,62 @@ const currentPoolerTag = currentTag("supavisor");
const currentPostgres = dockerfileServiceImageRaw("pg");
const currentPostgresTag = currentTag("pg");

afterEach(() => {
vi.unstubAllEnvs();
});

describe("resolvePinnedImage", () => {
it("resolves docker.io images while the slim flag is off", () => {
vi.stubEnv("SUPABASE_USE_SLIM_IMAGES", "");
expect(resolvePinnedImage("gotrue", "auth", {})).toBe(currentAuth);
expect(resolvePinnedImage("gotrue", "auth", { auth: "v2.100.0" })).toBe(
expect(resolvePinnedImage("gotrue", "auth", {}, false)).toBe(currentAuth);
expect(resolvePinnedImage("gotrue", "auth", { auth: "v2.100.0" }, false)).toBe(
"supabase/gotrue:v2.100.0",
);
expect(resolvePinnedImage("supavisor", "pooler", { pooler: "2.0.0" })).toBe(
expect(resolvePinnedImage("supavisor", "pooler", { pooler: "2.0.0" }, false)).toBe(
"supabase/supavisor:2.0.0",
);
});

it("resolves slim images when the flag is on and the pin is current", () => {
vi.stubEnv("SUPABASE_USE_SLIM_IMAGES", "true");
expect(resolvePinnedImage("gotrue", "auth", {})).toBe(toSlimImage("gotrue", currentAuth));
expect(resolvePinnedImage("gotrue", "auth", { auth: currentAuthTag })).toBe(
expect(resolvePinnedImage("gotrue", "auth", {}, true)).toBe(toSlimImage("gotrue", currentAuth));
expect(resolvePinnedImage("gotrue", "auth", { auth: currentAuthTag }, true)).toBe(
toSlimImage("gotrue", currentAuth),
);
});

it("keeps a historical pin on docker.io", () => {
vi.stubEnv("SUPABASE_USE_SLIM_IMAGES", "true");
expect(resolvePinnedImage("gotrue", "auth", { auth: "v2.100.0" })).toBe(
expect(resolvePinnedImage("gotrue", "auth", { auth: "v2.100.0" }, true)).toBe(
"supabase/gotrue:v2.100.0",
);
expect(resolvePinnedImage("storage", "storage", { storage: "v1.67.0" })).toBe(
expect(resolvePinnedImage("storage", "storage", { storage: "v1.67.0" }, true)).toBe(
"supabase/storage-api:v1.67.0",
);
expect(resolvePinnedImage("supavisor", "pooler", { pooler: "2.0.0" })).toBe(
expect(resolvePinnedImage("supavisor", "pooler", { pooler: "2.0.0" }, true)).toBe(
"supabase/supavisor:2.0.0",
);
});

it("normalizes a current pooler pin onto the slim tag scheme", () => {
vi.stubEnv("SUPABASE_USE_SLIM_IMAGES", "true");
expect(resolvePinnedImage("supavisor", "pooler", { pooler: currentPoolerTag })).toBe(
expect(resolvePinnedImage("supavisor", "pooler", { pooler: currentPoolerTag }, true)).toBe(
toSlimImage("supavisor", currentPooler),
);
expect(
resolvePinnedImage("supavisor", "pooler", {
pooler: currentPoolerTag.startsWith("v")
? currentPoolerTag.slice(1)
: `v${currentPoolerTag}`,
}),
resolvePinnedImage(
"supavisor",
"pooler",
{
pooler: currentPoolerTag.startsWith("v")
? currentPoolerTag.slice(1)
: `v${currentPoolerTag}`,
},
true,
),
).toBe(toSlimImage("supavisor", currentPooler));
});

it("keeps a historical postgres pin on docker.io", () => {
vi.stubEnv("SUPABASE_USE_SLIM_IMAGES", "");
expect(resolvePinnedImage("pg", "postgres", { postgres: "17.4.1.1" })).toBe(
expect(resolvePinnedImage("pg", "postgres", { postgres: "17.4.1.1" }, false)).toBe(
"supabase/postgres:17.4.1.1",
);
vi.stubEnv("SUPABASE_USE_SLIM_IMAGES", "1");
expect(resolvePinnedImage("pg", "postgres", { postgres: "17.4.1.1" })).toBe(
expect(resolvePinnedImage("pg", "postgres", { postgres: "17.4.1.1" }, true)).toBe(
"supabase/postgres:17.4.1.1",
);
expect(resolvePinnedImage("pg", "postgres", { postgres: currentPostgresTag })).toBe(
expect(resolvePinnedImage("pg", "postgres", { postgres: currentPostgresTag }, true)).toBe(
toSlimImage("pg", currentPostgres),
);
});
Expand Down
8 changes: 5 additions & 3 deletions apps/cli/src/command-internal/db-bootstrap/shadow-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
} from "./pgdata-snapshot.ts";
import type { PgDataArchiveProblem, PgDataSnapshotUnavailable } from "./pgdata-snapshot.ts";
import { resolvePinnedImage } from "./pinned-image.ts";
import { slimImagesEnabled } from "../../shared/services/slim-images.ts";
import {
createShadowDatabase,
removeShadowDatabase,
Expand Down Expand Up @@ -290,13 +291,14 @@ const resolveShadowCacheKeyInputs = <E>(
const realtimeConsumesJwks =
input.setup.majorVersion >= 15 && input.setup.config.realtime.enabled;
const jwks = realtimeConsumesJwks ? yield* input.setup.jwks : "";
const slim = yield* slimImagesEnabled;
const realtimeImage = yield* resolveJobImage(
resolvePinnedImage("realtime", "realtime", overrides),
resolvePinnedImage("realtime", "realtime", overrides, slim),
);
const storageImage = yield* resolveJobImage(
resolvePinnedImage("storage", "storage", overrides),
resolvePinnedImage("storage", "storage", overrides, slim),
);
const authImage = yield* resolveJobImage(resolvePinnedImage("gotrue", "auth", overrides));
const authImage = yield* resolveJobImage(resolvePinnedImage("gotrue", "auth", overrides, slim));
if (Option.isNone(realtimeImage) || Option.isNone(storageImage) || Option.isNone(authImage)) {
return Option.none();
}
Expand Down
7 changes: 4 additions & 3 deletions apps/cli/src/command-internal/db-image.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Effect, type FileSystem, type Path } from "effect";
import { dockerfileServiceImageRaw } from "../shared/services/dockerfile-images.ts";
import { postgresImageForDbMajorVersion } from "../shared/services/services.shared.ts";
import { slimImageForCurrentPin } from "../shared/services/slim-images.ts";
import { slimImageForCurrentPin, slimImagesEnabled } from "../shared/services/slim-images.ts";

/**
* Resolves the local Postgres Docker image for commands that run a pg_dump/shadow-DB container
Expand Down Expand Up @@ -73,7 +73,8 @@ export const resolveDbImage = Effect.fnUntraced(function* (
: `supabase/postgres:orioledb-${orioledbVersion}`;
return { image, configImage: image };
}
const currentRaw = postgresImageForDbMajorVersion(majorVersion) ?? pgImageRaw();
const slim = yield* slimImagesEnabled;
const currentRaw = postgresImageForDbMajorVersion(majorVersion, slim) ?? pgImageRaw();
let appliedPin: string | undefined;
if (majorVersion > 14) {
const versionPath = path.join(workdir, "supabase", ".temp", "postgres-version");
Expand All @@ -96,7 +97,7 @@ export const resolveDbImage = Effect.fnUntraced(function* (
const configImage =
appliedPin !== undefined ? replaceImageTag(currentRaw, appliedPin) : currentRaw;
return {
image: slimImageForCurrentPin("pg", currentRaw, appliedPin),
image: slimImageForCurrentPin("pg", currentRaw, appliedPin, slim),
configImage,
};
});
2 changes: 1 addition & 1 deletion apps/cli/src/command-internal/db-image.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe("resolveDbImage", () => {
configImage: POSTGRES_FALLBACK_IMAGE_PG15,
});
expect(yield* resolve(dir, 17)).toEqual({
image: dockerfileServiceImage("pg"),
image: dockerfileServiceImage("pg", false),
configImage: currentPostgres,
});
rmSync(dir, { recursive: true, force: true });
Expand Down
16 changes: 11 additions & 5 deletions apps/cli/src/command-internal/edge-runtime-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ import {
dockerfileServiceImage,
dockerfileServiceImageRaw,
} from "../shared/services/dockerfile-images.ts";
import { slimImageForCurrentPin } from "../shared/services/slim-images.ts";
import { slimImageForCurrentPin, slimImagesEnabled } from "../shared/services/slim-images.ts";

/**
* Resolves the edge-runtime Docker image: the default tag comes from the Dockerfile image, a
* pinned tag in `supabase/.temp/edge-runtime-version` overrides it, and
* `edge_runtime.deno_version = 1` selects the legacy `deno1` image instead.
*/

// Read per call, not captured at import time, so `SUPABASE_USE_SLIM_IMAGES` is
// observed by the resolver (and by tests that stub the env).
export const edgeRuntimeDockerfileImage = () => dockerfileServiceImage("edgeruntime");
// Read per run, not captured at import time, so `SUPABASE_USE_SLIM_IMAGES` is observed.
export const edgeRuntimeDockerfileImage = Effect.map(slimImagesEnabled, (slim) =>
dockerfileServiceImage("edgeruntime", slim),
);
// Used when `deno_version = 1`. No slim build exists for it, so it stays on docker.io regardless
// of the flag — the same exception `edgeRuntimeImage` (`shared/functions/functions.shared.ts`)
// applies for the functions Docker paths reading the same pin file.
Expand Down Expand Up @@ -44,5 +45,10 @@ export const resolveEdgeRuntimeImage = Effect.fnUntraced(function* (
if (pinned === DENO1_EDGE_RUNTIME_VERSION) {
return EDGE_RUNTIME_DENO1_IMAGE;
}
return slimImageForCurrentPin("edgeruntime", raw, pinned.length > 0 ? pinned : undefined);
return slimImageForCurrentPin(
"edgeruntime",
raw,
pinned.length > 0 ? pinned : undefined,
yield* slimImagesEnabled,
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
dockerfileServiceImage,
dockerfileServiceImageRaw,
} from "../shared/services/dockerfile-images.ts";
import { toSlimImage } from "../shared/services/slim-images.ts";
import { slimImagesEnabled, toSlimImage } from "../shared/services/slim-images.ts";
import { resolveEdgeRuntimeImage } from "./edge-runtime-image.ts";

const currentEdgeRuntime = dockerfileServiceImageRaw("edgeruntime");
Expand All @@ -26,10 +26,10 @@ const resolve = (workdir: string, denoVersion: number) =>
describe("resolveEdgeRuntimeImage", () => {
it.effect("returns the edge-runtime image from the Dockerfile when nothing is pinned", () => {
const dir = mkdtempSync(join(tmpdir(), "edge-img-"));
return resolve(dir, 2).pipe(
Effect.tap((image) =>
return Effect.zip(resolve(dir, 2), slimImagesEnabled).pipe(
Effect.tap(([image, slim]) =>
Effect.sync(() => {
expect(image).toBe(dockerfileServiceImage("edgeruntime"));
expect(image).toBe(dockerfileServiceImage("edgeruntime", slim));
rmSync(dir, { recursive: true, force: true });
}),
),
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/src/commands/db/diff/diff.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2076,7 +2076,7 @@ describe("db diff", () => {
yield* dbDiff(flags({ usePgAdmin: Option.some(true) }));
expect(s.differCalls).toHaveLength(1);
const call = s.differCalls[0] as DockerRunOpts;
expect(call.image).toBe(dockerfileServiceImage("differ"));
expect(call.image).toBe(dockerfileServiceImage("differ", false));
expect(call.image).toBe("supabase/pgadmin-schema-diff:cli-0.0.5");
expect(call.cmd).toEqual(["--json-diff", PGADMIN_SOURCE_URL, PGADMIN_TARGET_URL]);
expect(call.env).toEqual({});
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/src/commands/db/diff/pgadmin-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import { trimGoSpace } from "../shared/go-string.ts";
import { INTERNAL_SCHEMAS } from "../../../command-internal/pg-dump.env.ts";
import { DbDiffPgAdminError } from "./diff.errors.ts";

const DIFFER_IMAGE = dockerfileServiceImage("differ");
// `differ` has no slim build, so the slim flag never applies to it.
const DIFFER_IMAGE = dockerfileServiceImage("differ", false);

/**
* Only the front of the buffer is trimmed, not every occurrence — a real pgAdmin4
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect, it } from "@effect/vitest";
import { BunCrypto } from "@effect/platform-bun";
import { dockerfileServiceImage } from "../../../shared/services/dockerfile-images.ts";
import { slimImagesEnabled } from "../../../shared/services/slim-images.ts";
import {
Config,
ConfigProvider,
Expand Down Expand Up @@ -596,7 +597,7 @@ describe("functions download", () => {
// The unbundle tail is always the last 6 args regardless of whether
// `--add-host` (Linux-only) was inserted before it.
expect(runCommand?.args.slice(-6)).toEqual([
`public.ecr.aws/${dockerfileServiceImage("edgeruntime")}`,
`public.ecr.aws/${dockerfileServiceImage("edgeruntime", yield* slimImagesEnabled)}`,
"unbundle",
"--eszip",
"/root/eszips/output_hello-world.eszip",
Expand Down Expand Up @@ -2044,7 +2045,7 @@ describe("functions download", () => {

const runCommand = child.spawned.find((spawned) => spawned.args[0] === "run");
expect(runCommand?.args.slice(-6)[0]).toBe(
`ghcr.io/${dockerfileServiceImage("edgeruntime")}`,
`ghcr.io/${dockerfileServiceImage("edgeruntime", yield* slimImagesEnabled)}`,
);
expect(
child.spawned.filter(
Expand Down Expand Up @@ -2123,7 +2124,7 @@ describe("functions download", () => {
).toHaveLength(2);
const runCommand = child.spawned.find((spawned) => spawned.args[0] === "run");
expect(runCommand?.args.slice(-6)[0]).toBe(
`ghcr.io/${dockerfileServiceImage("edgeruntime")}`,
`ghcr.io/${dockerfileServiceImage("edgeruntime", yield* slimImagesEnabled)}`,
);
}).pipe(Effect.provide(layer));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
} from "../../../shared/runtime/process-control.service.ts";
import { RuntimeInfo } from "../../../shared/runtime/runtime-info.service.ts";
import { dockerfileServiceImage } from "../../../shared/services/dockerfile-images.ts";
import { slimImagesEnabled } from "../../../shared/services/slim-images.ts";
import { getRegistryImageUrl } from "../../../command-internal/docker-registry.ts";
import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts";
import {
Expand Down Expand Up @@ -1031,7 +1032,7 @@ describe("functions serve integration", () => {
}

expect(dockerRun.args).toContain(
yield* getRegistryImageUrl(dockerfileServiceImage("edgeruntime")),
yield* getRegistryImageUrl(dockerfileServiceImage("edgeruntime", yield* slimImagesEnabled)),
);
expect(dockerRun.args.join(" ")).not.toContain(multilineValue);
expect(dockerRun.args.join(" ")).not.toContain("EOF_ENV_0");
Expand Down
5 changes: 3 additions & 2 deletions apps/cli/src/commands/gen/types/types.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
withTempHome,
} from "../../../../tests/helpers/cli.ts";
import { dockerfileServiceImage } from "../../../shared/services/dockerfile-images.ts";
import { slimImagesEnabled } from "../../../shared/services/slim-images.ts";
import { localDbContainerId } from "../../../command-internal/docker-ids.ts";
import {
RESOLVE_BUDGET_MS,
Expand All @@ -21,7 +22,6 @@ const TYPEGEN_LANGS: ReadonlyArray<string> = languages
.map((language) => language.name);
type TypegenLang = string;

const LOCAL_POSTGRES_IMAGE = dockerfileServiceImage("pg");
const LOCAL_POSTGRES_TIMEOUT_MS = 120_000;
const TYPEGEN_TIMEOUT_MS = 90_000;
// Image resolution runs inside the test body, so its timeout must add on top of the
Expand Down Expand Up @@ -214,8 +214,9 @@ const startLocalPostgres = Effect.fnUntraced(function* (input: {
}) {
const containerName = localDbContainerId(input.projectId);
const imageDeadline = resolveDeadline(LOCAL_IMAGE_BUDGET_MS);
const localPostgresImage = dockerfileServiceImage("pg", yield* slimImagesEnabled);
const postgresImage = yield* Effect.tryPromise({
try: () => ensureImage(LOCAL_POSTGRES_IMAGE, imageDeadline - RESOLVE_BUDGET_MS),
try: () => ensureImage(localPostgresImage, imageDeadline - RESOLVE_BUDGET_MS),
catch: (cause) => new TypegenE2eSetupError({ message: "failed to ensure Docker image", cause }),
});

Expand Down
Loading
Loading