Skip to content

Commit b602254

Browse files
authored
Merge c6b9d20 into 0896b7d
2 parents 0896b7d + c6b9d20 commit b602254

4 files changed

Lines changed: 72 additions & 7 deletions

File tree

.github/workflows/ci-checks.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: CI Checks
2+
3+
# Lightweight, portable PR gate: a TypeScript typecheck via the repo's own
4+
# `typecheck` turbo tasks (tsc --noEmit).
5+
#
6+
# It intentionally does NOT use `vp check` / `vp test`: those load
7+
# vite.config.ts, which imports the `vite-plus` package. `vite-plus` is
8+
# provisioned by the local `vp` toolchain but is not a declared dependency and
9+
# is not resolvable in a clean CI checkout, so any vite-config-loading command
10+
# fails there. This gate is also separate from the heavy Nix `om ci` workflow.
11+
#
12+
# `@stackpanel/sdk` is excluded because its typecheck has a pre-existing failure
13+
# (its tsconfig does not pull in node types) unrelated to this gate. Remove the
14+
# `--filter` exclusion once that's fixed so the gate covers every package that
15+
# defines a `typecheck` script.
16+
on:
17+
pull_request:
18+
push:
19+
branches: [main]
20+
21+
# Least-privilege GITHUB_TOKEN (CodeQL: workflows should set explicit permissions).
22+
permissions:
23+
contents: read
24+
25+
concurrency:
26+
group: ci-checks-${{ github.workflow }}-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
jobs:
30+
typecheck:
31+
name: typecheck
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v4
35+
36+
- name: Set up Bun
37+
uses: oven-sh/setup-bun@v2
38+
with:
39+
bun-version: "1.3.2"
40+
41+
- name: Install dependencies
42+
run: bun install --frozen-lockfile
43+
44+
- name: Typecheck (tsc --noEmit)
45+
run: bunx turbo run typecheck --filter='!@stackpanel/sdk'

nix/stackpanel/lib/containers.nix

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,13 @@ let
9494
else
9595
let
9696
spec = defaultBaseImageSpecs.${type} or defaultBaseImageSpecs.alpine;
97+
# Refuse to build from an unpinned base image: the unpinned specs carry
98+
# lib.fakeSha256, which would otherwise fail later as a cryptic hash
99+
# mismatch. Pin with `nix-prefetch-docker` (set imageDigest + sha256).
100+
isPinned = (spec.sha256 or lib.fakeSha256) != lib.fakeSha256;
97101
in
102+
assert lib.assertMsg isPinned
103+
"stackpanel: base image '${spec.imageName}' is not pinned (still lib.fakeSha256); pin it with nix-prefetch-docker before building a container from it.";
98104
nix2containerLib.pullImage spec;
99105

100106
# ---------------------------------------------------------------------------

packages/auth/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
}
1010
},
1111
"type": "module",
12-
"scripts": {},
12+
"scripts": {
13+
"typecheck": "tsc --noEmit"
14+
},
1315
"devDependencies": {
1416
"@stackpanel/config": "workspace:*"
1517
},

packages/auth/src/lib/polar-products.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,25 @@ const SANDBOX_FREE = "6abf1427-cf83-4251-90d7-8852e7e5ca21";
2626
*/
2727
export function polarProducts(
2828
env: DeployEnv = resolveDeployEnv(),
29+
{ strict = true }: { strict?: boolean } = {},
2930
): Record<PlanId, string> {
3031
switch (env) {
31-
case "production":
32-
return {
33-
pro: process.env.POLAR_PRO_PRODUCT_ID_PRODUCTION ?? SANDBOX_PRO,
34-
free: process.env.POLAR_FREE_PRODUCT_ID_PRODUCTION ?? SANDBOX_FREE,
35-
};
32+
case "production": {
33+
const pro = process.env.POLAR_PRO_PRODUCT_ID_PRODUCTION;
34+
const free = process.env.POLAR_FREE_PRODUCT_ID_PRODUCTION;
35+
if (pro && free) return { pro, free };
36+
if (strict) {
37+
throw new Error(
38+
"Polar production product IDs are not configured. Set " +
39+
"POLAR_PRO_PRODUCT_ID_PRODUCTION and POLAR_FREE_PRODUCT_ID_PRODUCTION. " +
40+
"Refusing to silently fall back to sandbox products in production — " +
41+
"that would serve sandbox checkouts to real users and never charge real cards.",
42+
);
43+
}
44+
// Non-strict callers (e.g. the webhook inverse-lookup, which may run
45+
// outside a production runtime) only need id->plan resolution.
46+
return { pro: pro ?? SANDBOX_PRO, free: free ?? SANDBOX_FREE };
47+
}
3648
case "preview":
3749
case "dev":
3850
default:
@@ -65,7 +77,7 @@ export function planForProduct(productId: string | null | undefined): PlanId | "
6577
if (!productId) return "unknown";
6678
const envs: DeployEnv[] = ["production", "preview", "dev"];
6779
for (const env of envs) {
68-
const products = polarProducts(env);
80+
const products = polarProducts(env, { strict: false });
6981
for (const [plan, id] of Object.entries(products) as [PlanId, string][]) {
7082
if (id === productId) return plan;
7183
}

0 commit comments

Comments
 (0)