mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
ci(env-check): enforce manifest <-> example lockstep
scripts/check-env.ts shipped in v1.4.42 but only ran locally. A new workflow runs pnpm check-env --file .env.production.example on every push and PR against main/develop. Adds .env.production.example so a contributor introducing a new required env var to the manifest must update the example in the same PR, otherwise the workflow fails with grep-friendly annotations naming every missing variable. The example carries placeholder strings for every required group so the presence check passes; optional groups are commented out so operators can see the full surface without the workflow flagging silent-disable patterns as failures.
This commit is contained in:
1 parent
938d840670
commit
a5c244c4d9
2 files changed
+135
No files matched your search
@@ -0,0 +1,62 @@
|
||||
# =============================================================================
|
||||
# HealthLog -- production .env example
|
||||
# =============================================================================
|
||||
# Mirrors `scripts/env-manifest.json`. The `pnpm check-env --file
|
||||
# .env.production.example` CI step (see `.github/workflows/env-check.yml`)
|
||||
# enforces every variable declared `required: true` in the manifest has a
|
||||
# non-empty placeholder here, so a contributor who introduces a new
|
||||
# required var without updating this file fails the workflow.
|
||||
#
|
||||
# Placeholders are syntactic only -- replace with real secrets before
|
||||
# deploying. The check-env presence rule treats any non-empty,
|
||||
# non-whitespace string as "set", so the `<placeholder>` style below
|
||||
# satisfies the manifest without leaking a usable credential.
|
||||
#
|
||||
# Generate the two crypto secrets locally with:
|
||||
# $ openssl rand -hex 32
|
||||
# =============================================================================
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Core -- required for boot
|
||||
# -----------------------------------------------------------------------------
|
||||
DATABASE_URL="postgresql://healthlog:<password>@db:5432/healthlog?schema=public"
|
||||
POSTGRES_PASSWORD="<openssl rand -base64 24>"
|
||||
NEXT_PUBLIC_APP_URL="https://healthlog.example.com"
|
||||
APP_URL="https://healthlog.example.com"
|
||||
ENCRYPTION_KEY="<openssl rand -hex 32>"
|
||||
API_TOKEN_HMAC_KEY="<openssl rand -hex 32>"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Withings OAuth -- optional integration
|
||||
# -----------------------------------------------------------------------------
|
||||
# WITHINGS_CLIENT_ID=""
|
||||
# WITHINGS_CLIENT_SECRET=""
|
||||
# WITHINGS_WEBHOOK_SECRET=""
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# APNs -- iOS push (optional, all-or-none)
|
||||
# -----------------------------------------------------------------------------
|
||||
# APNS_KEY_ID=""
|
||||
# APNS_TEAM_ID=""
|
||||
# APNS_BUNDLE_ID=""
|
||||
# APNS_KEY="" # OR APNS_KEY_FILE -- either one satisfies the manifest
|
||||
# APNS_KEY_FILE=""
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Deploy webhook -- Coolify -> HealthLog auto-deploy feedback
|
||||
# -----------------------------------------------------------------------------
|
||||
# DEPLOY_WEBHOOK_SECRET=""
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Off-host backups -- all-or-none
|
||||
# -----------------------------------------------------------------------------
|
||||
# BACKUP_S3_ENDPOINT=""
|
||||
# BACKUP_S3_BUCKET=""
|
||||
# BACKUP_S3_ACCESS_KEY=""
|
||||
# BACKUP_S3_SECRET_KEY=""
|
||||
# BACKUP_ENCRYPTION_KEY=""
|
||||
@@ -0,0 +1,73 @@
|
||||
name: Env-manifest <-> example lockstep
|
||||
|
||||
# v1.4.43 B5 -- enforce that `.env.production.example` stays in lockstep
|
||||
# with `scripts/env-manifest.json`. A contributor adding a new required
|
||||
# variable to the manifest must also add a placeholder to the example
|
||||
# file in the same PR, otherwise the workflow fails with a grep-friendly
|
||||
# list of missing required vars. Optional vars are reported but do not
|
||||
# fail the build -- they exist for operator discovery, not deploy
|
||||
# blocking.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
env-check:
|
||||
name: pnpm check-env against .env.production.example
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Assert example file exists
|
||||
run: |
|
||||
if [ ! -f .env.production.example ]; then
|
||||
echo "::error::.env.production.example is missing -- contributors must keep this file in lockstep with scripts/env-manifest.json. See docs/ops/env-check.md."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The check-env script exits non-zero when at least one required
|
||||
# variable from the manifest is missing/empty in the example file.
|
||||
# We additionally grep the rendered output for `[MISSING-REQUIRED]`
|
||||
# rows and surface them as GitHub Actions error annotations so the
|
||||
# PR reviewer can see the missing var names without expanding the
|
||||
# log.
|
||||
- name: pnpm check-env --file .env.production.example
|
||||
id: check
|
||||
run: |
|
||||
set +e
|
||||
OUT=$(pnpm --silent check-env --file .env.production.example)
|
||||
EC=$?
|
||||
echo "$OUT"
|
||||
if [ $EC -ne 0 ]; then
|
||||
echo ""
|
||||
echo "::group::Missing required variables"
|
||||
echo "$OUT" | grep -E '^\s*\[MISSING-REQUIRED\]' | while IFS= read -r line; do
|
||||
name=$(echo "$line" | sed -E 's/.*\[MISSING-REQUIRED\] ([A-Z0-9_]+).*/\1/')
|
||||
echo "::error file=.env.production.example::Required env var $name missing from .env.production.example -- add a placeholder so the file stays in lockstep with scripts/env-manifest.json."
|
||||
done
|
||||
echo "::endgroup::"
|
||||
echo ""
|
||||
echo "::error::pnpm check-env reported missing required variables in .env.production.example. Either add a placeholder for each missing var, or downgrade the manifest entry to required:false if the variable is genuinely optional. See docs/ops/env-check.md."
|
||||
exit $EC
|
||||
fi
|
||||
Reference in new issue
Block a user