Skip to content

Commit ab2f18f

Browse files
committed
feat: support test and mainnet
1 parent cbbd6be commit ab2f18f

10 files changed

Lines changed: 50 additions & 22 deletions

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ generated
1313
.env
1414
.env.local
1515
.env*.local
16+
# Per-network env files generated by env:propagate (contain injected secrets)
17+
.env.mainnet
18+
.env.testnet
19+
.env.build.mainnet
20+
.env.build.testnet
1621

1722
# Environment configuration: config.json is COMMITTED with non-secret values
1823
# only. Secrets (RPC/sentinel URLs, OAuth secrets, session password) are injected

ansible/roles/deploy/tasks/main.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,17 @@
55
chdir: "{{ app_dir }}"
66
loop: "{{ dashtec_networks }}"
77
changed_when: true
8+
9+
# Apply Prisma migrations against each network's database. Runs a one-off using
10+
# the indexer-ponder image (which includes prisma + the migrations dir) and that
11+
# network's DATABASE_URL. `migrate deploy` is idempotent — only new migrations
12+
# apply. Any materializer/indexer errors before this completes self-heal on retry.
13+
- name: Apply database migrations for each network
14+
ansible.builtin.command:
15+
cmd: >-
16+
docker compose --profile {{ item }} run --rm --no-deps -T
17+
--entrypoint sh {{ 'indexer-ponder' if item == 'mainnet' else 'indexer-ponder-testnet' }}
18+
-c "pnpm --filter @dashtec/database db:deploy"
19+
chdir: "{{ app_dir }}"
20+
loop: "{{ dashtec_networks }}"
21+
changed_when: true

apps/web/Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
2828
FROM deps AS builder
2929
WORKDIR /app
3030

31+
# Which network's build-time env to bake (NEXT_PUBLIC_* differ per network).
32+
ARG NETWORK=mainnet
33+
3134
# Copy workspace package source code
3235
COPY packages/contract-calls ./packages/contract-calls
3336
COPY packages/shared-types ./packages/shared-types
@@ -39,7 +42,7 @@ COPY packages/logger ./packages/logger
3942
COPY apps/web ./apps/web
4043

4144
# Load build-time env vars (NEXT_PUBLIC_* are inlined during next build)
42-
RUN if [ -f ./apps/web/.env.build ]; then cp ./apps/web/.env.build ./apps/web/.env.production; fi
45+
RUN if [ -f "./apps/web/.env.build.${NETWORK}" ]; then cp "./apps/web/.env.build.${NETWORK}" ./apps/web/.env.production; fi
4346

4447
# Build workspace packages in dependency order:
4548
# logger -> database (needs logger; prisma generated first) -> shared-types

docker-compose.yml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ services:
55
build:
66
context: .
77
dockerfile: apps/web/Dockerfile
8+
args:
9+
NETWORK: mainnet
810
image: dashtec-web:latest
911
container_name: dashtec-web
1012
ports:
1113
- "${WEB_PORT:-3000}:3000"
1214
env_file:
13-
- apps/web/.env
15+
- apps/web/.env.mainnet
1416
environment:
1517
DATABASE_URL: postgresql://dashtec:dashtec@${DB_HOST:-postgres-mainnet}:5432/dashtec
1618
REDIS_URL: redis://:dashtec@${REDIS_HOST:-redis-mainnet}:6379
@@ -35,7 +37,7 @@ services:
3537
ports:
3638
- "${PONDER_PORT:-42069}:42069"
3739
env_file:
38-
- packages/indexer-ponder/.env
40+
- packages/indexer-ponder/.env.mainnet
3941
environment:
4042
DATABASE_SCHEMA: ponder_prod
4143
DATABASE_URL: postgresql://dashtec:dashtec@${DB_HOST:-postgres-mainnet}:5432/dashtec
@@ -64,7 +66,7 @@ services:
6466
- "${COLLECTOR_VALIDATOR_MIGRATION_PORT:-4003}:4003"
6567
- "${COLLECTOR_PROVIDER_LIST_PORT:-4004}:4004"
6668
env_file:
67-
- packages/indexer-custom/.env
69+
- packages/indexer-custom/.env.mainnet
6870
environment:
6971
DATABASE_URL: postgresql://dashtec:dashtec@${DB_HOST:-postgres-mainnet}:5432/dashtec
7072
DATABASE_READ_REPLICA_URL: postgresql://dashtec:dashtec@${DB_HOST:-postgres-mainnet}:5432/dashtec
@@ -87,7 +89,7 @@ services:
8789
image: dashtec-materializer:latest
8890
container_name: dashtec-materializer
8991
env_file:
90-
- packages/materializer/.env
92+
- packages/materializer/.env.mainnet
9193
environment:
9294
DATABASE_URL: postgresql://dashtec:dashtec@${DB_HOST:-postgres-mainnet}:5432/dashtec
9395
PONDER_SCHEMA: ponder_prod
@@ -106,12 +108,14 @@ services:
106108
build:
107109
context: .
108110
dockerfile: apps/web/Dockerfile
111+
args:
112+
NETWORK: testnet
109113
image: dashtec-web:testnet
110114
container_name: dashtec-web-testnet
111115
ports:
112116
- "${WEB_TESTNET_PORT:-3001}:3000"
113117
env_file:
114-
- apps/web/.env
118+
- apps/web/.env.testnet
115119
environment:
116120
DATABASE_URL: postgresql://dashtec:dashtec@postgres-testnet:5432/dashtec
117121
REDIS_URL: redis://:dashtec@redis-testnet:6379
@@ -137,7 +141,7 @@ services:
137141
ports:
138142
- "${PONDER_TESTNET_PORT:-42070}:42069"
139143
env_file:
140-
- packages/indexer-ponder/.env
144+
- packages/indexer-ponder/.env.testnet
141145
environment:
142146
DATABASE_SCHEMA: ponder_prod
143147
DATABASE_URL: postgresql://dashtec:dashtec@postgres-testnet:5432/dashtec
@@ -166,7 +170,7 @@ services:
166170
- "${COLLECTOR_VALIDATOR_MIGRATION_TESTNET_PORT:-4013}:4003"
167171
- "${COLLECTOR_PROVIDER_LIST_TESTNET_PORT:-4014}:4004"
168172
env_file:
169-
- packages/indexer-custom/.env
173+
- packages/indexer-custom/.env.testnet
170174
environment:
171175
DATABASE_URL: postgresql://dashtec:dashtec@postgres-testnet:5432/dashtec
172176
DATABASE_READ_REPLICA_URL: postgresql://dashtec:dashtec@postgres-testnet:5432/dashtec
@@ -190,7 +194,7 @@ services:
190194
image: dashtec-materializer:testnet
191195
container_name: dashtec-materializer-testnet
192196
env_file:
193-
- packages/materializer/.env
197+
- packages/materializer/.env.testnet
194198
environment:
195199
DATABASE_URL: postgresql://dashtec:dashtec@postgres-testnet:5432/dashtec
196200
PONDER_SCHEMA: ponder_prod

packages/indexer-custom/src/config/config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ const envSchema = z.object({
2727
VALIDATOR_MIGRATION_ENABLED: z.coerce.boolean(),
2828
VALIDATOR_MIGRATION_POLL_INTERVAL_MS: z.coerce.number().int().positive(),
2929
VALIDATOR_MIGRATION_BATCH_SIZE: z.coerce.number().int().positive(),
30-
VALIDATOR_MIGRATION_SOURCE_DB_URL: z.string().url().optional(),
30+
// Empty string is valid (migration disabled). .optional() alone still runs
31+
// .url() on "", so accept an empty literal too.
32+
VALIDATOR_MIGRATION_SOURCE_DB_URL: z.union([z.string().url(), z.literal('')]).optional(),
3133
STAKING_APP_API_URL: z.string().optional(),
3234
PROVIDER_LIST_POLL_INTERVAL_MS: z.coerce.number().optional(),
3335
NODE_ENV: z.enum(['development', 'production', 'test']),

scripts/env/propagate-app.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ if (!existsSync(appsDir)) {
6464

6565
const contentRuntime = buildEnvContent(network, envMapRuntime);
6666
const contentBuild = buildEnvContent(network, envMapBuild);
67-
writeFileSync(join(appsDir, '.env'), contentRuntime);
68-
writeFileSync(join(appsDir, '.env.build'), contentBuild);
69-
console.log(`✓ Generated apps/web/.env for ${network}`);
70-
console.log(`✓ Generated apps/web/.env.build for ${network}`);
67+
writeFileSync(join(appsDir, `.env.${network}`), contentRuntime);
68+
writeFileSync(join(appsDir, `.env.build.${network}`), contentBuild);
69+
console.log(`✓ Generated apps/web/.env.${network}`);
70+
console.log(`✓ Generated apps/web/.env.build.${network}`);

scripts/env/propagate-database.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ const envMap = {
1717
};
1818

1919
const content = buildEnvContent(network, envMap);
20-
const envPath = join(ROOT_DIR, 'packages', 'database', '.env');
20+
const envPath = join(ROOT_DIR, 'packages', 'database', `.env.${network}`);
2121
writeFileSync(envPath, content);
22-
console.log(`✓ Generated packages/database/.env for ${network}`);
22+
console.log(`✓ Generated packages/database/.env.${network}`);

scripts/env/propagate-indexer-custom.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@ const envMap = {
5757
};
5858

5959
const content = buildEnvContent(network, envMap);
60-
const envPath = join(ROOT_DIR, 'packages', 'indexer-custom', '.env');
60+
const envPath = join(ROOT_DIR, 'packages', 'indexer-custom', `.env.${network}`);
6161
writeFileSync(envPath, content);
62-
console.log(`✓ Generated packages/indexer-custom/.env for ${network}`);
62+
console.log(`✓ Generated packages/indexer-custom/.env.${network}`);

scripts/env/propagate-indexer-ponder.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ const envMap = {
4040
};
4141

4242
const content = buildEnvContent(network, envMap);
43-
const envPath = join(ROOT_DIR, 'packages', 'indexer-ponder', '.env');
43+
const envPath = join(ROOT_DIR, 'packages', 'indexer-ponder', `.env.${network}`);
4444
writeFileSync(envPath, content);
45-
console.log(`✓ Generated packages/indexer-ponder/.env for ${network}`);
45+
console.log(`✓ Generated packages/indexer-ponder/.env.${network}`);

scripts/env/propagate-materializer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ const envMap = {
2323
};
2424

2525
const content = buildEnvContent(network, envMap);
26-
const envPath = join(ROOT_DIR, 'packages', 'materializer', '.env');
26+
const envPath = join(ROOT_DIR, 'packages', 'materializer', `.env.${network}`);
2727
writeFileSync(envPath, content);
28-
console.log(`✓ Generated packages/materializer/.env for ${network}`);
28+
console.log(`✓ Generated packages/materializer/.env.${network}`);

0 commit comments

Comments
 (0)