diff --git a/.env.example b/.env.example index 5429a7a34d..9bd79356bd 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +# Local development. For Docker self-hosting, use selfhost.env.example. + CLICKHOUSE_URL="http://default:@localhost:8123/databuddy_analytics" # Required by DQL. This must use the separately provisioned dql_user account; # never point it at the application/admin ClickHouse credentials. @@ -6,13 +8,6 @@ DATABASE_URL="postgres://databuddy:databuddy_dev_password@localhost:5432/databud REDIS_URL="redis://localhost:6379" BULLMQ_REDIS_URL="redis://localhost:6379" -# Required only by docker-compose.selfhost.yml. Use URL-safe passwords and make -# the local database URLs above use the same credentials before initialization. -IMAGE_TAG="" -POSTGRES_PASSWORD="" -CLICKHOUSE_PASSWORD="" -REDIS_PASSWORD="" - # Public URLs. Local development uses built-in localhost defaults when blank. DASHBOARD_URL="" API_URL="" @@ -31,7 +26,7 @@ FIRECRAWL_API_KEY="" SUPERMEMORY_API_KEY="" BETTER_AUTH_URL="http://localhost:3000" -# Required by docker-compose.selfhost.yml. Generate independent random values. +# Generate independent random values for sessions and encryption. BETTER_AUTH_SECRET="generate-a-random-32-byte-base64-secret" DATABUDDY_ENCRYPTION_KEY="" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86dd13240c..37f79fb5fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -186,6 +186,7 @@ jobs: run: >- bun test --no-env-file apps/dashboard/next-config.test.ts apps/dashboard/app/layout.test.ts + apps/dashboard/lib/app-url.test.ts 'apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.test.ts' 'apps/dashboard/app/(main)/onboarding/_components/step-install-tracking.test.ts' packages/auth/src/selfhost-config.test.ts diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index f4f93f52d4..06a9a5571c 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -49,7 +49,7 @@ jobs: EVENT_NAME: ${{ github.event_name }} BEFORE_SHA: ${{ github.event.before }} run: | - ALL='["api","basket","dashboard","insights","links","uptime"]' + ALL='["api","basket","dashboard","init","insights","links","uptime"]' if [[ "$EVENT_NAME" != "push" ]]; then echo "services=$ALL" >> "$GITHUB_OUTPUT" exit 0 @@ -60,19 +60,16 @@ jobs: fi export TURBO_SCM_BASE="$BEFORE_SHA" export TURBO_SCM_HEAD="HEAD" - affected=() + # The init image ships the schema and tooling for every release. + affected=('"init"') for svc in api basket dashboard insights links uptime; do count=$(bunx turbo ls --affected --filter="@databuddy/$svc" --output=json | jq -r '.packages.count') if [[ "$count" != "0" ]]; then affected+=("\"$svc\"") fi done - if [[ ${#affected[@]} -eq 0 ]]; then - echo "services=[]" >> "$GITHUB_OUTPUT" - else - IFS=, - echo "services=[${affected[*]}]" >> "$GITHUB_OUTPUT" - fi + IFS=, + echo "services=[${affected[*]}]" >> "$GITHUB_OUTPUT" build: name: Build ${{ matrix.service }} (${{ matrix.platform.arch }}) @@ -136,6 +133,7 @@ jobs: api) text="Databuddy API service - analytics backend" ;; basket) text="Databuddy Basket service - event ingestion" ;; dashboard) text="Databuddy Dashboard service - web analytics UI" ;; + init) text="Databuddy database initialization and schema tools" ;; insights) text="Databuddy Insights service - queued insight generation" ;; links) text="Databuddy Links service - URL shortening and tracking" ;; uptime) text="Databuddy Uptime service - availability monitoring" ;; diff --git a/.github/workflows/health-check.yml b/.github/workflows/health-check.yml index 8deaef1510..a9732ed045 100644 --- a/.github/workflows/health-check.yml +++ b/.github/workflows/health-check.yml @@ -5,6 +5,9 @@ on: branches: [main] paths: - "*.Dockerfile" + - "docker-compose.selfhost.yml" + - "selfhost.env.example" + - "scripts/test-selfhost-init.sh" - ".dockerignore" - "apps/api/**" - "apps/basket/**" @@ -15,11 +18,15 @@ on: - "bun.lock" - "package.json" - "turbo.json" + - "tsconfig/**" - ".github/workflows/health-check.yml" pull_request: branches: [main, staging] paths: - "*.Dockerfile" + - "docker-compose.selfhost.yml" + - "selfhost.env.example" + - "scripts/test-selfhost-init.sh" - ".dockerignore" - "apps/api/**" - "apps/basket/**" @@ -30,6 +37,7 @@ on: - "bun.lock" - "package.json" - "turbo.json" + - "tsconfig/**" - ".github/workflows/health-check.yml" permissions: @@ -40,6 +48,14 @@ concurrency: cancel-in-progress: true jobs: + selfhost-init: + name: Self-host Database Initialization + runs-on: blacksmith-4vcpu-ubuntu-2404 + timeout-minutes: 15 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + - run: bash scripts/test-selfhost-init.sh + vector-config-check: name: Vector Delivery Canary runs-on: blacksmith-2vcpu-ubuntu-2404 diff --git a/apps/dashboard/app/(main)/monitors/status-pages/[id]/page.tsx b/apps/dashboard/app/(main)/monitors/status-pages/[id]/page.tsx index 20632444ef..ea3755fbf4 100644 --- a/apps/dashboard/app/(main)/monitors/status-pages/[id]/page.tsx +++ b/apps/dashboard/app/(main)/monitors/status-pages/[id]/page.tsx @@ -76,6 +76,7 @@ export default function StatusPageDetailsPage() { }); const statusPage = statusPageQuery.data; + const statusPageUrl = statusPage && getStatusPageUrl(statusPage.slug); const monitorToRemoveData = statusPage?.monitors.find( (m: StatusPageMonitor) => m.id === monitorToRemove @@ -215,17 +216,19 @@ export default function StatusPageDetailsPage() {
{statusPage ? ( <> - - View Page - + {statusPageUrl && ( + + View Page + + )}