Skip to content

Commit 483217b

Browse files
Switch to using t3-env for env-var management (#230)
1 parent e8acfcc commit 483217b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+404
-484
lines changed

.dockerignore

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
Dockerfile
22
.dockerignore
3-
node_modules
43
npm-debug.log
54
README.md
6-
.next
7-
!.next/static
8-
!.next/standalone
95
.git
106
.sourcebot
11-
.env.local
7+
packages/web/.next
8+
!packages/web/.next/static
9+
!packages/web/.next/standalone
10+
**/node_modules
11+
**/.env.local
12+
**/.sentryclirc
13+
**/.env.sentry-build-plugin

Dockerfile

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
1+
# ------ Global scope variables ------
2+
# Set of global build arguments.
3+
# @see: https://docs.docker.com/build/building/variables/#scoping
4+
5+
ARG SOURCEBOT_VERSION
6+
# PAPIK = Project API Key
7+
# Note that this key does not need to be kept secret, so it's not
8+
# necessary to use Docker build secrets here.
9+
# @see: https://posthog.com/tutorials/api-capture-events#authenticating-with-the-project-api-key
10+
ARG POSTHOG_PAPIK
11+
ARG SENTRY_ENVIRONMENT
12+
113
FROM node:20-alpine3.19 AS node-alpine
214
FROM golang:1.23.4-alpine3.19 AS go-alpine
15+
# ----------------------------------
316

417
# ------ Build Zoekt ------
518
FROM go-alpine AS zoekt-builder
@@ -9,6 +22,7 @@ COPY vendor/zoekt/go.mod vendor/zoekt/go.sum ./
922
RUN go mod download
1023
COPY vendor/zoekt ./
1124
RUN CGO_ENABLED=0 GOOS=linux go build -o /cmd/ ./cmd/...
25+
# -------------------------
1226

1327
# ------ Build shared libraries ------
1428
FROM node-alpine AS shared-libs-builder
@@ -23,9 +37,24 @@ RUN yarn workspace @sourcebot/db install --frozen-lockfile
2337
RUN yarn workspace @sourcebot/schemas install --frozen-lockfile
2438
RUN yarn workspace @sourcebot/crypto install --frozen-lockfile
2539
RUN yarn workspace @sourcebot/error install --frozen-lockfile
40+
# ------------------------------------
2641

2742
# ------ Build Web ------
2843
FROM node-alpine AS web-builder
44+
ENV DOCKER_BUILD=1
45+
# -----------
46+
# Global args
47+
ARG SOURCEBOT_VERSION
48+
ENV NEXT_PUBLIC_SOURCEBOT_VERSION=$SOURCEBOT_VERSION
49+
ARG POSTHOG_PAPIK
50+
ENV NEXT_PUBLIC_POSTHOG_PAPIK=$POSTHOG_PAPIK
51+
ARG SENTRY_ENVIRONMENT
52+
ENV NEXT_PUBLIC_SENTRY_ENVIRONMENT=$SENTRY_ENVIRONMENT
53+
# Local args
54+
ARG SENTRY_WEBAPP_DSN
55+
ENV NEXT_PUBLIC_SENTRY_WEBAPP_DSN=$SENTRY_WEBAPP_DSN
56+
# -----------
57+
2958
RUN apk add --no-cache libc6-compat
3059
WORKDIR /app
3160

@@ -43,26 +72,13 @@ RUN yarn config set network-timeout 1200000
4372
RUN yarn workspace @sourcebot/web install --frozen-lockfile
4473

4574
ENV NEXT_TELEMETRY_DISABLED=1
46-
# @see: https://phase.dev/blog/nextjs-public-runtime-variables/
47-
ARG NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED=BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED
48-
ARG NEXT_PUBLIC_SOURCEBOT_VERSION=BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION
49-
ENV NEXT_PUBLIC_PUBLIC_SEARCH_DEMO=BAKED_NEXT_PUBLIC_PUBLIC_SEARCH_DEMO
50-
ENV NEXT_PUBLIC_POSTHOG_PAPIK=BAKED_NEXT_PUBLIC_POSTHOG_PAPIK
51-
ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=BAKED_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
52-
ENV NEXT_PUBLIC_SENTRY_ENVIRONMENT=BAKED_NEXT_PUBLIC_SENTRY_ENVIRONMENT
53-
ENV NEXT_PUBLIC_SENTRY_WEBAPP_DSN=BAKED_NEXT_PUBLIC_SENTRY_WEBAPP_DSN
54-
55-
# @nocheckin: This was interfering with the the `matcher` regex in middleware.ts,
56-
# causing regular expressions parsing errors when making a request. It's unclear
57-
# why exactly this was happening, but it's likely due to a bad replacement happening
58-
# in the `sed` command.
59-
# @note: leading "/" is required for the basePath property. @see: https://nextjs.org/docs/app/api-reference/next-config-js/basePath
60-
# ARG NEXT_PUBLIC_DOMAIN_SUB_PATH=/BAKED_NEXT_PUBLIC_DOMAIN_SUB_PATH
61-
6275
RUN yarn workspace @sourcebot/web build
76+
ENV DOCKER_BUILD=0
77+
# ------------------------------
6378

6479
# ------ Build Backend ------
6580
FROM node-alpine AS backend-builder
81+
ENV DOCKER_BUILD=1
6682
WORKDIR /app
6783

6884
COPY package.json yarn.lock* ./
@@ -75,10 +91,22 @@ COPY --from=shared-libs-builder /app/packages/crypto ./packages/crypto
7591
COPY --from=shared-libs-builder /app/packages/error ./packages/error
7692
RUN yarn workspace @sourcebot/backend install --frozen-lockfile
7793
RUN yarn workspace @sourcebot/backend build
78-
94+
ENV DOCKER_BUILD=0
95+
# ------------------------------
7996

8097
# ------ Runner ------
8198
FROM node-alpine AS runner
99+
# -----------
100+
# Global args
101+
ARG SOURCEBOT_VERSION
102+
ENV SOURCEBOT_VERSION=$SOURCEBOT_VERSION
103+
ARG POSTHOG_PAPIK
104+
ENV POSTHOG_PAPIK=$POSTHOG_PAPIK
105+
# Local args
106+
# -----------
107+
108+
RUN echo "Sourcebot Version: $SOURCEBOT_VERSION"
109+
82110
WORKDIR /app
83111
ENV NODE_ENV=production
84112
ENV NEXT_TELEMETRY_DISABLED=1
@@ -90,14 +118,6 @@ ENV DATABASE_URL="postgresql://postgres@localhost:5432/sourcebot"
90118
ENV REDIS_URL="redis://localhost:6379"
91119
ENV SRC_TENANT_ENFORCEMENT_MODE=strict
92120

93-
ARG SOURCEBOT_VERSION=unknown
94-
ENV SOURCEBOT_VERSION=$SOURCEBOT_VERSION
95-
RUN echo "Sourcebot Version: $SOURCEBOT_VERSION"
96-
97-
ARG PUBLIC_SEARCH_DEMO=false
98-
ENV PUBLIC_SEARCH_DEMO=$PUBLIC_SEARCH_DEMO
99-
RUN echo "Public Search Demo: $PUBLIC_SEARCH_DEMO"
100-
101121
# Valid values are: debug, info, warn, error
102122
ENV SOURCEBOT_LOG_LEVEL=info
103123

@@ -106,18 +126,9 @@ ENV SOURCEBOT_LOG_LEVEL=info
106126
# will serve from http(s)://example.com/sb
107127
ENV DOMAIN_SUB_PATH=/
108128

109-
# PAPIK = Project API Key
110-
# Note that this key does not need to be kept secret, so it's not
111-
# necessary to use Docker build secrets here.
112-
# @see: https://posthog.com/tutorials/api-capture-events#authenticating-with-the-project-api-key
113-
ARG POSTHOG_PAPIK=
114-
ENV POSTHOG_PAPIK=$POSTHOG_PAPIK
115-
116129
# Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable.
117130
# ENV SOURCEBOT_TELEMETRY_DISABLED=1
118131

119-
ENV STRIPE_PUBLISHABLE_KEY=""
120-
121132
# Configure zoekt
122133
COPY vendor/zoekt/install-ctags-alpine.sh .
123134
RUN ./install-ctags-alpine.sh && rm install-ctags-alpine.sh
@@ -178,4 +189,5 @@ COPY default-config.json .
178189
EXPOSE 3000
179190
ENV PORT=3000
180191
ENV HOSTNAME="0.0.0.0"
181-
ENTRYPOINT ["/sbin/tini", "--", "./entrypoint.sh"]
192+
ENTRYPOINT ["/sbin/tini", "--", "./entrypoint.sh"]
193+
# ------------------------------

entrypoint.sh

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -108,102 +108,6 @@ fi
108108
echo "{\"version\": \"$SOURCEBOT_VERSION\", \"install_id\": \"$SOURCEBOT_INSTALL_ID\"}" > "$FIRST_RUN_FILE"
109109

110110

111-
# Update NextJs public env variables w/o requiring a rebuild.
112-
# @see: https://phase.dev/blog/nextjs-public-runtime-variables/
113-
{
114-
# Infer NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED if it is not set
115-
if [ -z "$NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED" ] && [ ! -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
116-
export NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED="$SOURCEBOT_TELEMETRY_DISABLED"
117-
fi
118-
119-
# Infer NEXT_PUBLIC_SOURCEBOT_VERSION if it is not set
120-
if [ -z "$NEXT_PUBLIC_SOURCEBOT_VERSION" ] && [ ! -z "$SOURCEBOT_VERSION" ]; then
121-
export NEXT_PUBLIC_SOURCEBOT_VERSION="$SOURCEBOT_VERSION"
122-
fi
123-
124-
# Infer NEXT_PUBLIC_PUBLIC_SEARCH_DEMO if it is not set
125-
if [ -z "$NEXT_PUBLIC_PUBLIC_SEARCH_DEMO" ] && [ ! -z "$PUBLIC_SEARCH_DEMO" ]; then
126-
export NEXT_PUBLIC_PUBLIC_SEARCH_DEMO="$PUBLIC_SEARCH_DEMO"
127-
fi
128-
129-
# Always infer NEXT_PUBLIC_POSTHOG_PAPIK
130-
export NEXT_PUBLIC_POSTHOG_PAPIK="$POSTHOG_PAPIK"
131-
132-
# Always infer NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
133-
export NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="$STRIPE_PUBLISHABLE_KEY"
134-
135-
# Always infer NEXT_PUBLIC_SENTRY_ENVIRONMENT
136-
export NEXT_PUBLIC_SENTRY_ENVIRONMENT="$SENTRY_ENVIRONMENT"
137-
138-
# Always infer NEXT_PUBLIC_SENTRY_WEBAPP_DSN
139-
export NEXT_PUBLIC_SENTRY_WEBAPP_DSN="$SENTRY_WEBAPP_DSN"
140-
141-
# Iterate over all .js files in .next & public, making substitutions for the `BAKED_` sentinal values
142-
# with their actual desired runtime value.
143-
find /app/packages/web/public /app/packages/web/.next -type f -name "*.js" |
144-
while read file; do
145-
sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED|${NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED}|g" "$file"
146-
sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION|${NEXT_PUBLIC_SOURCEBOT_VERSION}|g" "$file"
147-
sed -i "s|BAKED_NEXT_PUBLIC_POSTHOG_PAPIK|${NEXT_PUBLIC_POSTHOG_PAPIK}|g" "$file"
148-
sed -i "s|BAKED_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY|${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}|g" "$file"
149-
sed -i "s|BAKED_NEXT_PUBLIC_SENTRY_ENVIRONMENT|${NEXT_PUBLIC_SENTRY_ENVIRONMENT}|g" "$file"
150-
sed -i "s|BAKED_NEXT_PUBLIC_SENTRY_WEBAPP_DSN|${NEXT_PUBLIC_SENTRY_WEBAPP_DSN}|g" "$file"
151-
sed -i "s|BAKED_NEXT_PUBLIC_PUBLIC_SEARCH_DEMO|${NEXT_PUBLIC_PUBLIC_SEARCH_DEMO}|g" "$file"
152-
done
153-
}
154-
155-
# @nocheckin: This was interfering with the the `matcher` regex in middleware.ts,
156-
# causing regular expressions parsing errors when making a request. It's unclear
157-
# why exactly this was happening, but it's likely due to a bad replacement happening
158-
# in the `sed` command.
159-
#
160-
# # Update specifically NEXT_PUBLIC_DOMAIN_SUB_PATH w/o requiring a rebuild.
161-
# # Ultimately, the DOMAIN_SUB_PATH sets the `basePath` param in the next.config.mjs.
162-
# # Similar to above, we pass in a `BAKED_` sentinal value into next.config.mjs at build
163-
# # time. Unlike above, the `basePath` configuration is set in files other than just javascript
164-
# # code (e.g., manifest files, css files, etc.), so this section has subtle differences.
165-
# #
166-
# # @see: https://nextjs.org/docs/app/api-reference/next-config-js/basePath
167-
# # @see: https://phase.dev/blog/nextjs-public-runtime-variables/
168-
# {
169-
# if [ ! -z "$DOMAIN_SUB_PATH" ]; then
170-
# # If the sub-path is "/", this creates problems with certain replacements. For example:
171-
# # /BAKED_NEXT_PUBLIC_DOMAIN_SUB_PATH/_next/image -> //_next/image (notice the double slash...)
172-
# # To get around this, we default to an empty sub-path, which is the default when no sub-path is defined.
173-
# if [ "$DOMAIN_SUB_PATH" = "/" ]; then
174-
# DOMAIN_SUB_PATH=""
175-
176-
# # Otherwise, we need to ensure that the sub-path starts with a slash, since this is a requirement
177-
# # for the basePath property. For example, assume DOMAIN_SUB_PATH=/bot, then:
178-
# # /BAKED_NEXT_PUBLIC_DOMAIN_SUB_PATH/_next/image -> /bot/_next/image
179-
# elif [[ ! "$DOMAIN_SUB_PATH" =~ ^/ ]]; then
180-
# DOMAIN_SUB_PATH="/$DOMAIN_SUB_PATH"
181-
# fi
182-
# fi
183-
184-
# if [ ! -z "$DOMAIN_SUB_PATH" ]; then
185-
# echo -e "\e[34m[Info] DOMAIN_SUB_PATH was set to "$DOMAIN_SUB_PATH". Overriding default path.\e[0m"
186-
# fi
187-
188-
# # Always set NEXT_PUBLIC_DOMAIN_SUB_PATH to DOMAIN_SUB_PATH (even if it is empty!!)
189-
# export NEXT_PUBLIC_DOMAIN_SUB_PATH="$DOMAIN_SUB_PATH"
190-
191-
# # Iterate over _all_ files in the web directory, making substitutions for the `BAKED_` sentinal values
192-
# # with their actual desired runtime value.
193-
# find /app/packages/web -type f |
194-
# while read file; do
195-
# # @note: the leading "/" is required here as it is included at build time. See Dockerfile.
196-
# sed -i "s|/BAKED_NEXT_PUBLIC_DOMAIN_SUB_PATH|${NEXT_PUBLIC_DOMAIN_SUB_PATH}|g" "$file"
197-
# done
198-
# }
199-
200-
# Upload sourcemaps to Sentry
201-
# @nocheckin
202-
su -c "sentry-cli login --auth-token $SENTRY_AUTH_TOKEN"
203-
su -c "sentry-cli sourcemaps inject --org sourcebot --project backend /app/packages/backend/dist"
204-
su -c "sentry-cli sourcemaps upload --org sourcebot --project backend /app/packages/backend/dist"
205-
206-
207111
# Start the database and wait for it to be ready before starting any other service
208112
if [ "$DATABASE_URL" = "postgresql://postgres@localhost:5432/sourcebot" ]; then
209113
su postgres -c "postgres -D $DB_DATA_DIR" &

packages/backend/.env

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"@sourcebot/db": "^0.1.0",
3333
"@sourcebot/error": "^0.1.0",
3434
"@sourcebot/schemas": "^0.1.0",
35+
"@t3-oss/env-core": "^0.12.0",
3536
"@types/express": "^5.0.0",
3637
"argparse": "^2.0.1",
3738
"bullmq": "^5.34.10",
@@ -47,6 +48,7 @@
4748
"prom-client": "^15.1.3",
4849
"simple-git": "^3.27.0",
4950
"strip-json-comments": "^5.0.1",
50-
"winston": "^3.15.0"
51+
"winston": "^3.15.0",
52+
"zod": "^3.24.2"
5153
}
5254
}

packages/backend/src/env.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { createEnv } from "@t3-oss/env-core";
2+
import { z } from "zod";
3+
import dotenv from 'dotenv';
4+
5+
dotenv.config({
6+
path: './.env',
7+
});
8+
9+
dotenv.config({
10+
path: './.env.local',
11+
override: true
12+
});
13+
14+
export const env = createEnv({
15+
server: {
16+
SOURCEBOT_ENCRYPTION_KEY: z.string(),
17+
SOURCEBOT_LOG_LEVEL: z.enum(["info", "debug", "warn", "error"]).default("info"),
18+
SOURCEBOT_TELEMETRY_DISABLED: z.enum(["true", "false"]).default("false"),
19+
SOURCEBOT_INSTALL_ID: z.string().default("unknown"),
20+
SOURCEBOT_VERSION: z.string().default("unknown"),
21+
22+
POSTHOG_PAPIK: z.string().optional(),
23+
POSTHOG_HOST: z.string().url().default('https://us.i.posthog.com'),
24+
25+
FALLBACK_GITHUB_TOKEN: z.string().optional(),
26+
FALLBACK_GITLAB_TOKEN: z.string().optional(),
27+
FALLBACK_GITEA_TOKEN: z.string().optional(),
28+
29+
REDIS_URL: z.string().url().optional().default("redis://localhost:6379"),
30+
31+
SENTRY_BACKEND_DSN: z.string().optional(),
32+
SENTRY_ENVIRONMENT: z.string().optional(),
33+
34+
LOGTAIL_TOKEN: z.string().optional(),
35+
LOGTAIL_HOST: z.string().url().optional(),
36+
},
37+
runtimeEnv: process.env,
38+
emptyStringAsUndefined: true,
39+
// Skip environment variable validation in Docker builds.
40+
skipValidation: process.env.DOCKER_BUILD === "1",
41+
});

packages/backend/src/environment.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)