Pass PostHog key at build time (#92)

This commit is contained in:
Brendan Kellam 2024-11-25 21:04:52 -08:00 committed by GitHub
parent c73c34428c
commit 33b5418bbf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 48 additions and 34 deletions

View file

@ -75,6 +75,7 @@ jobs:
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
build-args: | build-args: |
SOURCEBOT_VERSION=${{ github.ref_name }} SOURCEBOT_VERSION=${{ github.ref_name }}
POSTHOG_PAPIK=${{ secrets.POSTHOG_PAPIK }}
- name: Export digest - name: Export digest
run: | run: |

View file

@ -26,6 +26,7 @@ ENV NEXT_TELEMETRY_DISABLED=1
# @see: https://phase.dev/blog/nextjs-public-runtime-variables/ # @see: https://phase.dev/blog/nextjs-public-runtime-variables/
ARG NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED=BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED ARG NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED=BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED
ARG NEXT_PUBLIC_SOURCEBOT_VERSION=BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION ARG NEXT_PUBLIC_SOURCEBOT_VERSION=BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION
ENV NEXT_PUBLIC_POSTHOG_PAPIK=BAKED_NEXT_PUBLIC_POSTHOG_PAPIK
# @note: leading "/" is required for the basePath property. @see: https://nextjs.org/docs/app/api-reference/next-config-js/basePath # @note: leading "/" is required for the basePath property. @see: https://nextjs.org/docs/app/api-reference/next-config-js/basePath
ARG NEXT_PUBLIC_DOMAIN_SUB_PATH=/BAKED_NEXT_PUBLIC_DOMAIN_SUB_PATH ARG NEXT_PUBLIC_DOMAIN_SUB_PATH=/BAKED_NEXT_PUBLIC_DOMAIN_SUB_PATH
RUN yarn workspace @sourcebot/web build RUN yarn workspace @sourcebot/web build
@ -61,9 +62,12 @@ ENV SOURCEBOT_LOG_LEVEL=info
# will serve from http(s)://example.com/sb # will serve from http(s)://example.com/sb
ENV DOMAIN_SUB_PATH=/ ENV DOMAIN_SUB_PATH=/
# @note: This is also set in .env # PAPIK = Project API Key
ENV POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS # Note that this key does not need to be kept secret, so it's not
ENV NEXT_PUBLIC_POSTHOG_KEY=$POSTHOG_KEY # necessary to use Docker build secrets here.
# @see: https://posthog.com/tutorials/api-capture-events#authenticating-with-the-project-api-key
ARG POSTHOG_PAPIK=
ENV POSTHOG_PAPIK=$POSTHOG_PAPIK
# Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable. # Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable.
# ENV SOURCEBOT_TELEMETRY_DISABLED=1 # ENV SOURCEBOT_TELEMETRY_DISABLED=1

View file

@ -3,6 +3,12 @@ set -e
echo -e "\e[34m[Info] Sourcebot version: $SOURCEBOT_VERSION\e[0m" echo -e "\e[34m[Info] Sourcebot version: $SOURCEBOT_VERSION\e[0m"
# If we don't have a PostHog key, then we need to disable telemetry.
if [ -z "$POSTHOG_PAPIK" ]; then
echo -e "\e[33m[Warning] POSTHOG_PAPIK was not set. Setting SOURCEBOT_TELEMETRY_DISABLED.\e[0m"
export SOURCEBOT_TELEMETRY_DISABLED=1
fi
# Issue a info message about telemetry # Issue a info message about telemetry
if [ ! -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then if [ ! -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
echo -e "\e[34m[Info] Disabling telemetry since SOURCEBOT_TELEMETRY_DISABLED was set.\e[0m" echo -e "\e[34m[Info] Disabling telemetry since SOURCEBOT_TELEMETRY_DISABLED was set.\e[0m"
@ -25,7 +31,7 @@ if [ ! -f "$FIRST_RUN_FILE" ]; then
# (if telemetry is enabled) # (if telemetry is enabled)
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
curl -L -s --header "Content-Type: application/json" -d '{ curl -L -s --header "Content-Type: application/json" -d '{
"api_key": "'"$POSTHOG_KEY"'", "api_key": "'"$POSTHOG_PAPIK"'",
"event": "install", "event": "install",
"distinct_id": "'"$SOURCEBOT_INSTALL_ID"'", "distinct_id": "'"$SOURCEBOT_INSTALL_ID"'",
"properties": { "properties": {
@ -43,7 +49,7 @@ else
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
curl -L -s --header "Content-Type: application/json" -d '{ curl -L -s --header "Content-Type: application/json" -d '{
"api_key": "'"$POSTHOG_KEY"'", "api_key": "'"$POSTHOG_PAPIK"'",
"event": "upgrade", "event": "upgrade",
"distinct_id": "'"$SOURCEBOT_INSTALL_ID"'", "distinct_id": "'"$SOURCEBOT_INSTALL_ID"'",
"properties": { "properties": {
@ -83,12 +89,16 @@ echo -e "\e[34m[Info] Using config file at: '$CONFIG_PATH'.\e[0m"
export NEXT_PUBLIC_SOURCEBOT_VERSION="$SOURCEBOT_VERSION" export NEXT_PUBLIC_SOURCEBOT_VERSION="$SOURCEBOT_VERSION"
fi fi
# Always infer NEXT_PUBLIC_POSTHOG_PAPIK
export NEXT_PUBLIC_POSTHOG_PAPIK="$POSTHOG_PAPIK"
# Iterate over all .js files in .next & public, making substitutions for the `BAKED_` sentinal values # Iterate over all .js files in .next & public, making substitutions for the `BAKED_` sentinal values
# with their actual desired runtime value. # with their actual desired runtime value.
find /app/packages/web/public /app/packages/web/.next -type f -name "*.js" | find /app/packages/web/public /app/packages/web/.next -type f -name "*.js" |
while read file; do while read file; do
sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED|${NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED}|g" "$file" sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED|${NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED}|g" "$file"
sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION|${NEXT_PUBLIC_SOURCEBOT_VERSION}|g" "$file" sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION|${NEXT_PUBLIC_SOURCEBOT_VERSION}|g" "$file"
sed -i "s|BAKED_NEXT_PUBLIC_POSTHOG_PAPIK|${NEXT_PUBLIC_POSTHOG_PAPIK}|g" "$file"
done done
} }

View file

@ -1,4 +1 @@
POSTHOG_HOST=https://us.i.posthog.com POSTHOG_HOST=https://us.i.posthog.com
# @note: This is also set in the Dockerfile
POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS

View file

@ -1,6 +1,6 @@
import dotenv from 'dotenv'; import dotenv from 'dotenv';
export const getEnv = (env: string | undefined, defaultValue = '') => { export const getEnv = (env: string | undefined, defaultValue?: string) => {
return env ?? defaultValue; return env ?? defaultValue;
} }
@ -15,9 +15,9 @@ dotenv.config({
path: './.env', path: './.env',
}); });
export const SOURCEBOT_LOG_LEVEL = getEnv(process.env.SOURCEBOT_LOG_LEVEL, 'info'); export const SOURCEBOT_LOG_LEVEL = getEnv(process.env.SOURCEBOT_LOG_LEVEL, 'info')!;
export const SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.env.SOURCEBOT_TELEMETRY_DISABLED, false); export const SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.env.SOURCEBOT_TELEMETRY_DISABLED, false)!;
export const SOURCEBOT_INSTALL_ID = getEnv(process.env.SOURCEBOT_INSTALL_ID, 'unknown'); export const SOURCEBOT_INSTALL_ID = getEnv(process.env.SOURCEBOT_INSTALL_ID, 'unknown')!;
export const SOURCEBOT_VERSION = getEnv(process.env.SOURCEBOT_VERSION, 'unknown'); export const SOURCEBOT_VERSION = getEnv(process.env.SOURCEBOT_VERSION, 'unknown')!;
export const POSTHOG_KEY = getEnv(process.env.POSTHOG_KEY); export const POSTHOG_PAPIK = getEnv(process.env.POSTHOG_PAPIK);
export const POSTHOG_HOST = getEnv(process.env.POSTHOG_HOST); export const POSTHOG_HOST = getEnv(process.env.POSTHOG_HOST);

View file

@ -1,20 +1,24 @@
import { PostHog } from 'posthog-node'; import { PostHog } from 'posthog-node';
import { PosthogEvent, PosthogEventMap } from './posthogEvents.js'; import { PosthogEvent, PosthogEventMap } from './posthogEvents.js';
import { POSTHOG_HOST, POSTHOG_KEY, SOURCEBOT_INSTALL_ID, SOURCEBOT_TELEMETRY_DISABLED, SOURCEBOT_VERSION } from './environment.js'; import { POSTHOG_HOST, POSTHOG_PAPIK, SOURCEBOT_INSTALL_ID, SOURCEBOT_TELEMETRY_DISABLED, SOURCEBOT_VERSION } from './environment.js';
const posthog = new PostHog( let posthog: PostHog | undefined = undefined;
POSTHOG_KEY,
{ if (POSTHOG_PAPIK) {
host: POSTHOG_HOST, posthog = new PostHog(
} POSTHOG_PAPIK,
); {
host: POSTHOG_HOST,
}
);
}
export function captureEvent<E extends PosthogEvent>(event: E, properties: PosthogEventMap[E]) { export function captureEvent<E extends PosthogEvent>(event: E, properties: PosthogEventMap[E]) {
if (SOURCEBOT_TELEMETRY_DISABLED) { if (SOURCEBOT_TELEMETRY_DISABLED) {
return; return;
} }
posthog.capture({ posthog?.capture({
distinctId: SOURCEBOT_INSTALL_ID, distinctId: SOURCEBOT_INSTALL_ID,
event: event, event: event,
properties: { properties: {
@ -24,4 +28,4 @@ export function captureEvent<E extends PosthogEvent>(event: E, properties: Posth
}); });
} }
await posthog.shutdown(); await posthog?.shutdown();

View file

@ -1,6 +1,3 @@
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
NEXT_PUBLIC_POSTHOG_ASSET_HOST=https://us-assets.i.posthog.com NEXT_PUBLIC_POSTHOG_ASSET_HOST=https://us-assets.i.posthog.com
NEXT_PUBLIC_POSTHOG_UI_HOST=https://us.posthog.com NEXT_PUBLIC_POSTHOG_UI_HOST=https://us.posthog.com
# @note: This is also set in the Dockerfile.
NEXT_PUBLIC_POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS

View file

@ -1,15 +1,16 @@
'use client' 'use client'
import { NEXT_PUBLIC_POSTHOG_KEY, NEXT_PUBLIC_POSTHOG_UI_HOST, NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED } from '@/lib/environment.client' import { NEXT_PUBLIC_POSTHOG_PAPIK, NEXT_PUBLIC_POSTHOG_UI_HOST, NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED } from '@/lib/environment.client'
import posthog from 'posthog-js' import posthog from 'posthog-js'
import { PostHogProvider } from 'posthog-js/react' import { PostHogProvider } from 'posthog-js/react'
import { resolveServerPath } from './api/(client)/client' import { resolveServerPath } from './api/(client)/client'
import { isDefined } from '@/lib/utils'
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
if (!NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED) { if (!NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED && isDefined(NEXT_PUBLIC_POSTHOG_PAPIK)) {
// @see next.config.mjs for path rewrites to the "/ingest" route. // @see next.config.mjs for path rewrites to the "/ingest" route.
const posthogHostPath = resolveServerPath('/ingest'); const posthogHostPath = resolveServerPath('/ingest');
posthog.init(NEXT_PUBLIC_POSTHOG_KEY!, { posthog.init(NEXT_PUBLIC_POSTHOG_PAPIK, {
api_host: posthogHostPath, api_host: posthogHostPath,
ui_host: NEXT_PUBLIC_POSTHOG_UI_HOST, ui_host: NEXT_PUBLIC_POSTHOG_UI_HOST,
person_profiles: 'identified_only', person_profiles: 'identified_only',

View file

@ -2,10 +2,10 @@ import 'client-only';
import { getEnv, getEnvBoolean } from "./utils"; import { getEnv, getEnvBoolean } from "./utils";
export const NEXT_PUBLIC_POSTHOG_KEY = getEnv(process.env.NEXT_PUBLIC_POSTHOG_KEY); export const NEXT_PUBLIC_POSTHOG_PAPIK = getEnv(process.env.NEXT_PUBLIC_POSTHOG_PAPIK);
export const NEXT_PUBLIC_POSTHOG_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_HOST); export const NEXT_PUBLIC_POSTHOG_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_HOST);
export const NEXT_PUBLIC_POSTHOG_UI_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_UI_HOST); export const NEXT_PUBLIC_POSTHOG_UI_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_UI_HOST);
export const NEXT_PUBLIC_POSTHOG_ASSET_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_ASSET_HOST); export const NEXT_PUBLIC_POSTHOG_ASSET_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_ASSET_HOST);
export const NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.env.NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED, false); export const NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.env.NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED, false);
export const NEXT_PUBLIC_SOURCEBOT_VERSION = getEnv(process.env.NEXT_PUBLIC_SOURCEBOT_VERSION, "unknown"); export const NEXT_PUBLIC_SOURCEBOT_VERSION = getEnv(process.env.NEXT_PUBLIC_SOURCEBOT_VERSION, "unknown")!;
export const NEXT_PUBLIC_DOMAIN_SUB_PATH = getEnv(process.env.NEXT_PUBLIC_DOMAIN_SUB_PATH, ""); export const NEXT_PUBLIC_DOMAIN_SUB_PATH = getEnv(process.env.NEXT_PUBLIC_DOMAIN_SUB_PATH, "")!;

View file

@ -2,7 +2,7 @@ import 'server-only';
import { getEnv, getEnvNumber } from "./utils"; import { getEnv, getEnvNumber } from "./utils";
export const ZOEKT_WEBSERVER_URL = getEnv(process.env.ZOEKT_WEBSERVER_URL, "http://localhost:6070"); export const ZOEKT_WEBSERVER_URL = getEnv(process.env.ZOEKT_WEBSERVER_URL, "http://localhost:6070")!;
export const SHARD_MAX_MATCH_COUNT = getEnvNumber(process.env.SHARD_MAX_MATCH_COUNT, 10000); export const SHARD_MAX_MATCH_COUNT = getEnvNumber(process.env.SHARD_MAX_MATCH_COUNT, 10000);
export const TOTAL_MAX_MATCH_COUNT = getEnvNumber(process.env.TOTAL_MAX_MATCH_COUNT, 100000); export const TOTAL_MAX_MATCH_COUNT = getEnvNumber(process.env.TOTAL_MAX_MATCH_COUNT, 100000);
export const NODE_ENV = process.env.NODE_ENV; export const NODE_ENV = process.env.NODE_ENV;

View file

@ -99,7 +99,7 @@ export const isServiceError = (data: unknown): data is ServiceError => {
'message' in data; 'message' in data;
} }
export const getEnv = (env: string | undefined, defaultValue = '') => { export const getEnv = (env: string | undefined, defaultValue?: string) => {
return env ?? defaultValue; return env ?? defaultValue;
} }