Skip to content

fix(docker): make compose stack boot from a fresh .env - #1674

Merged
LucasSantana-Dev merged 4 commits into
LucasSantana-Dev:mainfrom
Adolanium:fix/docker-compose-cold-start
Jul 27, 2026
Merged

LucasSantana-Dev merged 4 commits into
LucasSantana-Dev:mainfrom
Adolanium:fix/docker-compose-cold-start

Conversation

@Adolanium

@Adolanium Adolanium commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Following the documented Docker quickstart on a clean checkout fails before the bot starts:

cp .env.example .env
# set DISCORD_TOKEN and CLIENT_ID
docker compose up -d

Two separate issues block it.

1. Missing POSTGRES_PASSWORD

The compose file requires it (${POSTGRES_PASSWORD?POSTGRES_PASSWORD_required}), but .env.example only carries it inside a commented block further down. The copied .env has no active value, so compose exits right away:

POSTGRES_PASSWORD_required

2. DIRECT_URL resolves to localhost inside the container

The bot runs prisma migrate deploy on startup, and the Prisma CLI reads DIRECT_URL. The shared app env overrides DATABASE_URL to the postgres service but leaves DIRECT_URL on the .env localhost value, so the migration step fails:

Error: P1001: Can't reach database server at `localhost:5432`

Fix

  • .env.example: add an active POSTGRES_PASSWORD in the database section, with a command to generate one.
  • docker-compose.yml: override DIRECT_URL next to DATABASE_URL in the shared app env, so both point at the postgres service.

Verification

With both changes, docker compose config resolves DIRECT_URL to postgresql://discordbot:***@postgres:5432/discordbot for the bot and backend, and the documented quickstart brings the bot up with migrations applied and no manual edits.

Checklist

  • Tests pass locally (config-only change, no code paths touched; docker compose config validated)
  • CHANGELOG.md updated (if user-facing)
  • TypeScript builds cleanly (no TypeScript changed)

Destructive / irreversible interaction (Tier A)

Not applicable. No Discord actions are added or changed.

Feature-removal sweep

Not applicable. Nothing is removed.


Summary by cubic

Fixes the Docker quickstart so the compose stack boots from a fresh .env without manual edits. Validates a URL-safe hex POSTGRES_PASSWORD and overrides DIRECT_URL in compose so Prisma migrations reach the postgres service.

  • Bug Fixes
    • .env.example: add an active, empty POSTGRES_PASSWORD with openssl rand -hex 24 guidance; require URL-safe hex; note compose overrides DATABASE_URL/DIRECT_URL inside containers.
    • docker-compose.yml: use ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD_required} to fail on unset or empty; set DIRECT_URL to the postgres service to avoid Prisma P1001.
    • Docs: quickstart now generates POSTGRES_PASSWORD before the first docker compose up; env table and rotation steps require URL-safe hex and show how to generate it.

Written for commit 9cd5d2f. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • Updated the example environment file to include a POSTGRES_PASSWORD placeholder with clearer guidance for local vs Docker-based Postgres setups.
    • Improved Docker Compose configuration by setting Prisma’s DIRECT_URL to the Postgres service hostname, enabling reliable in-container migrations.

@github-actions github-actions Bot added the infra label Jul 2, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a POSTGRES_PASSWORD variable with explanatory comments to .env.example, and adds a container-reachable Prisma DIRECT_URL to the shared Docker Compose environment.

Changes

Environment configuration

Layer / File(s) Summary
Postgres password and Prisma DIRECT_URL setup
.env.example, docker-compose.yml
Adds POSTGRES_PASSWORD with password-generation instructions and configures Prisma’s DIRECT_URL to use the postgres service hostname.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Possibly related PRs

Suggested labels: size/xs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: making the Docker compose stack work from a fresh .env.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.env.example:
- Around line 57-60: The comment on POSTGRES_PASSWORD overstates how
DATABASE_URL and DIRECT_URL are derived; update the surrounding explanatory text
in .env.example so it only says the password is required by docker-compose and
is used for the in-container setup, without implying the placeholder
DATABASE_URL/DIRECT_URL values are built from it. Keep the guidance aligned with
the POSTGRES_PASSWORD entry and the DATABASE_URL/DIRECT_URL placeholders so
users aren’t misled about manual configuration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 742a397b-d750-4862-9fd4-fce54159449b

📥 Commits

Reviewing files that changed from the base of the PR and between 62f5333 and dce87ac.

📒 Files selected for processing (2)
  • .env.example
  • docker-compose.yml

Comment thread .env.example Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .env.example Outdated
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jul 2, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Auto-approved: Docker config fixes: adds POSTGRES_PASSWORD default and DIRECT_URL override for Prisma in docker-compose. Low-risk configuration-only changes.

Re-trigger cubic

@LucasSantana-Dev

Copy link
Copy Markdown
Owner

👋 Heads-up: I'm draining the open-PR backlog. main just landed a CI fix (#1809: npm@12 strict-ci needed the lockfile's eslint bumped to 10.7.0) — your branch is currently BEHIND, so a rebase/update-branch will pull that in and get your Docker Build green. I'm not touching or merging this PR (it's yours) — just flagging so it doesn't sit stuck on the stale-base failure. Ping me if you'd like a hand.

LucasSantana-Dev added a commit that referenced this pull request Jul 13, 2026
…rations (#1830)

## Summary

Adds missing `DIRECT_URL` environment variable to
`docker-compose.staging.yml` and `docker-compose.dev.yml`.

**Why:** Prisma `migrate deploy` requires a non-pooled `DIRECT_URL`
connection for schema migrations. PR #1674 added this to
`docker-compose.yml` (production), but the staging and dev compose files
were missing it, causing P1001 errors on fresh Docker stack boots.

**What:** Mirrors the `DIRECT_URL` value to both environments, set
identical to `DATABASE_URL` (no pgbouncer in these stacks).

- `docker-compose.staging.yml`: Added to `x-common-app-env` anchor (line
47)
- `docker-compose.dev.yml`: Added to `lucky-bot-dev` service environment
(line 66)

Closes #1793

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Add `DIRECT_URL` to `docker-compose.staging.yml` and
`docker-compose.dev.yml` so Prisma `migrate deploy` uses a direct
(non-pooled) connection. Set it equal to `DATABASE_URL` to avoid P1001
errors on fresh boots (closes #1793).

<sup>Written for commit 7714582.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1830?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated development and staging configurations with an additional
direct database connection setting.
* Services using the shared staging configuration now inherit the direct
database connection automatically.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@Adolanium
Adolanium force-pushed the fix/docker-compose-cold-start branch from d23c167 to 8e86111 Compare July 21, 2026 03:27
@Adolanium

Copy link
Copy Markdown
Contributor Author

@LucasSantana-Dev thanks for the heads-up. Rebased onto latest main (clean, no conflicts). The two commits are still just the .env.example POSTGRES_PASSWORD default and the DIRECT_URL override in docker-compose.yml.

Fork CI workflows are sitting on action_required on my side, so I cannot approve the runs myself. If you get a chance to approve the workflows on this PR, that should clear the remaining checks. Happy to re-push if anything else comes up.

@Adolanium
Adolanium force-pushed the fix/docker-compose-cold-start branch from 8e86111 to 912cf66 Compare July 21, 2026 03:56
@LucasSantana-Dev

Copy link
Copy Markdown
Owner

Kimi review (kimi-code/kimi-for-coding, via local subscription)

• VERDICT: ISSUES

  • [SEVERITY medium] docker-compose.yml:34-37 — POSTGRES_PASSWORD is interpolated raw into DIRECT_URL (and the pre-existing DATABASE_URL), so URL-reserved characters in the password break connection-string parsing. Fix: document that POSTGRES_PASSWORD must be URL-safe/hex only, or build the URLs in an init script that URL-encodes the password before exporting them.

Head 912cf66. Posted by kimi-review-watch (launchd).

@Adolanium

Copy link
Copy Markdown
Contributor Author

Addressed in dca1840. The example and dashboard docs now require a URL-safe hexadecimal POSTGRES_PASSWORD and include the openssl command used to generate one. docker compose config passes with the updated example. The branch is up to date with main.

@LucasSantana-Dev LucasSantana-Dev left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sticking with this one, it's been open a while and the diagnosis is right.

The DIRECT_URL fix is the valuable part. The Prisma CLI reading DIRECT_URL while the runtime client reads DATABASE_URL is genuinely non-obvious, and falling back to a localhost value that's unreachable from inside the container is a horrible first-run failure to debug. The comment explaining it is exactly what a future reader needs. Using ${POSTGRES_PASSWORD?POSTGRES_PASSWORD_required} instead of a :- default is also the right instinct: fail loudly rather than boot with a silently wrong credential.

The docs changes are good too. Calling out URL-safe hexadecimal and giving the exact openssl rand -hex 24 command matters here, because the value goes straight into a Postgres URL where a stray @, : or / breaks parsing in a way that looks like anything but a quoting bug. Both the Docs.tsx table entry and the rotation bullet now say the same thing.

The one thing I want to change: the placeholder cancels out the guard.

POSTGRES_PASSWORD=000000000000000000000000000000000000000000000000

The ? guard in docker-compose.yml only fires when the variable is unset or empty. This line sets it, so the guard can't trigger for anyone doing the documented thing of copying .env.example to .env — which is the exact flow this PR exists to make work. The old commented-out # POSTGRES_PASSWORD=change-me-in-production did trigger it.

So docker compose up now succeeds out of the box with a 48-zero database password, and the operator is never forced to look at it. "It booted, so it must be configured" is the failure mode, and this repo's compose stack is what runs on my homelab, so that's not purely hypothetical.

I recognise the tension: the whole point of the PR is a stack that boots from a fresh .env, and an empty required variable works against that. I'm working through the options now (empty value plus a one-line setup command, versus generating it in a setup script or Make target) and I'll follow up here with a direction so you're not guessing. Everything else in the PR is good to go.

On the red checks: danger / danger fails with Request failed [403]: .../issues/1674/comments, which is a token permission problem posting its comment on a fork PR, not anything in your diff. The npm ci errors are a stale lockfile on main, Security was an unpassable repo-wide gate, and kimi-review fails on every PR because an API key isn't set (#1877). Those three are fixed in #1876; rebase once it lands and I'll sort the danger permission separately.

@LucasSantana-Dev

Copy link
Copy Markdown
Owner

Following up with the direction I promised, and I owe you a correction: my instinct about how to fix this was wrong, and testing it is what caught the problem.

I'd assumed that shipping POSTGRES_PASSWORD= (empty) in .env.example would keep your ? guard working, because in POSIX shell empty and unset are equivalent for ${VAR?err}. Docker Compose does not behave that way. Tested against docker-compose 5.1.4:

.env state ${VAR?err} ${VAR:?err}
unset errors errors
POSTGRES_PASSWORD= (empty) passes errors
real value passes passes

So the guard you inherited only ever protected against a missing line. An empty placeholder under it would have booted Postgres with an empty password, which is worse than your 48 zeros. Good thing I checked before asking you to change it.

I've fixed the guard itself in #1881: both interpolation sites move from ? to :?, so empty is rejected too. That's a pre-existing weakness in the compose file, not something you introduced.

What that means for this PR, once #1881 lands:

  1. .env.example → POSTGRES_PASSWORD= (empty). Please keep your comment block as-is, the URL-safe-hex explanation and the openssl rand -hex 24 line are the useful part and I'm keeping them.
  2. The DIRECT_URL line you're adding → use :? to match:
    DIRECT_URL: postgresql://discordbot:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD_required}@postgres:5432/discordbot
  3. Nothing else changes. The DIRECT_URL fix is the valuable part of this PR and it's right.

I've also added the generation step to the README setup block in #1881, so cp .env.example .env is followed by echo "POSTGRES_PASSWORD=$(openssl rand -hex 24)" >> .env. (Duplicate keys in .env resolve last-wins, verified, and >> avoids the sed -i GNU/BSD portability trap.) That means the "boots from a fresh .env" goal is served by the README rather than by a checked-in default value, which I think is the right split: DISCORD_TOKEN and CLIENT_ID have to be hand-edited anyway, so the stack was never going to boot untouched.

Full reasoning and the alternatives I rejected (including a scripts/setup-env.sh, which is the most likely thing to revisit) are in decisions/2026-07-26-postgres-password-env-guard.md in #1881. The PGDATA rotation trap you may hit while testing is #1882.

Sorry for the extra round trip. Thanks for the patience on this one, it's been open longer than it should have been.

@LucasSantana-Dev

Copy link
Copy Markdown
Owner

Heads-up: the CI blockers I mentioned are fixed on main now (#1876, merged as ca410d2c).

What that clears:

  • Security — it ran npm audit --audit-level=high across devDependencies and could never pass, which is why it was red on every PR including this one. It now audits production deps only, with an explicit allowlist pinned to individual advisory ids.
  • npm ci / Build — shared / Quality Gates — main's lockfile was stale and npm@12's stricter ci rejected it (lock file's eslint@10.7.0 does not satisfy eslint@10.8.0). Resynced.
  • compressed-size — it installs the base branch too, so it was failing on main's lockfile rather than on your changes.
  • kimi-review — removed in ci: remove kimi-review until an api key is set #1884; the API key was never set, so it failed on every PR in the repo.

Please rebase onto main and push. The auto-update workflow only touches branches whose authors enabled auto-merge, so it deliberately won't rewrite yours. A rebase should turn the checks green without any change to your code.

The review feedback above is separate and still stands.

@Adolanium
Adolanium force-pushed the fix/docker-compose-cold-start branch from 0526e44 to aaededf Compare July 27, 2026 03:48
@Adolanium

Adolanium commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Addressed in 853a9bd (squashed, rebased onto main).

  • .env.example now has POSTGRES_PASSWORD= (empty) so the compose guard can fire for the documented cp .env.example .env flow.
  • DATABASE_URL, DIRECT_URL, and the postgres service password all use :? so empty and unset both fail.
  • URL-safe hex comment + openssl line kept as-is. Generation step stays with fix(docker): treat an empty db password as missing in compose guards #1881 / the README work you described.

@Adolanium
Adolanium force-pushed the fix/docker-compose-cold-start branch from aaededf to 853a9bd Compare July 27, 2026 03:51

@LucasSantana-Dev LucasSantana-Dev left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: approve with nits

The fix is correct and matches the repo's Prisma/compose architecture. Only the "no manual edits" claim is overstated, plus consistency nits.

P2 — quickstart claim vs reality: the added .env.example:60 placeholder is POSTGRES_PASSWORD= (empty), and the compose change deliberately uses ${POSTGRES_PASSWORD:?...} which errors on set-but-empty. So cp .env.example .env && docker compose up -d still exits with POSTGRES_PASSWORD_required until the user generates and fills the password. The design itself is right (shipping a default DB password would be worse) and the failure is loud and actionable; please adjust the PR body / docs quickstart to list generating the password (openssl rand -hex 24) as a required step.

P3 (nits): docker-compose.dev.yml:66 and docker-compose.staging.yml:47 still use the lax ${POSTGRES_PASSWORD?...} form now hardened to :? in prod (follow-up, not this PR); the .env.example:56 section header still says "Optional" directly above the now-required-for-Docker password; no CI gate runs docker compose config, so interpolation regressions are only caught manually (optional hardening).

What's good: the ? → :? hardening is the non-obvious correct pairing for the empty placeholder — the old form accepts set-but-empty, which would have silently passed an empty password to postgres initdb. The DIRECT_URL override lands at exactly the right layer (prisma/prisma.config.ts:19 resolves DIRECT_URL ?? DATABASE_URL; the bot entrypoint runs prisma migrate deploy; compose environment: takes precedence over env_file), matching what dev/staging compose already did. Comments state the why in both files, and Docs.tsx is updated in the same PR.

Override DIRECT_URL inside compose so Prisma migrate reaches postgres
from the container. Document URL-safe hex passwords, leave
POSTGRES_PASSWORD empty in .env.example, and use :? guards so empty and
unset both fail loudly.
@Adolanium
Adolanium force-pushed the fix/docker-compose-cold-start branch from 853a9bd to 8ed8465 Compare July 27, 2026 16:19
@Adolanium

Copy link
Copy Markdown
Contributor Author

Addressed the approve-with-nits feedback.

  • Docs quickstart now lists generating POSTGRES_PASSWORD (openssl rand -hex 24) as a required step before docker compose up.
  • .env.example section header no longer calls the database block "Optional" above a compose-required password.
  • Empty placeholder + :? guard stays as designed: fail loud, no default DB password.

Rebased onto main. Danger 403 / SonarCloud on the fork side look like token/permission noise rather than this diff.

LucasSantana-Dev added a commit that referenced this pull request Jul 27, 2026
## Summary

Two structural failures block every fork PR's required checks (seen on
#1863, #1864, #1865, #1866, #1867, #1674 after their CI was approved):

- **SonarCloud Scan (required) hard-fails on forks**: fork PRs get no
secrets, so `SONAR_TOKEN` is never present and the token-policy step
exits 1. Now the sonar job is skipped for fork PRs (a skipped required
check counts as passing). Same pattern deploy-staging already uses.
- **danger 403s on forks**: `review-tools.yml` ran on `pull_request`,
where the fork token is forced read-only and the comment POST fails with
403. Switched to `pull_request_target`; the reusable workflow checks out
and executes base-repo code only (documented in the file header, same
safety rule as the other target workflows).

## Test plan
- [x] actionlint clean on both files
- [ ] Next push to an external contributor PR: SonarCloud Scan shows
skipped, danger posts its comment

After merge I will update the seven open contributor branches to main so
they pick this up.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Unblocks fork PRs by fixing CI gates for SonarCloud and `danger`. Fork
PRs now pass required checks without secrets and get review comments.

- Bug Fixes
- Skip SonarCloud Scan on fork PRs to avoid failing when `SONAR_TOKEN`
is unavailable (skipped required check counts as passing).
- Run review tools on `pull_request_target` so `danger` can comment on
forks; workflow executes base-repo code only.

<sup>Written for commit 316f567.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1898?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
@github-actions

github-actions Bot commented Jul 27, 2026 •

Copy link
Copy Markdown
Warnings
⚠️

User-facing change without a CHANGELOG.md update. Add a line under ## [Unreleased] if this should appear in release notes. (Or apply the skip-changelog label if this PR does not affect end users.)

Generated by 🚫 dangerJS against 9cd5d2f

LucasSantana-Dev added a commit that referenced this pull request Jul 27, 2026
## Summary

PR #1674 (external contributor) fails danger with no possible
resolution: the `.env*` protection rule fires on `.env.example`, and its
own message demands "explicit confirmation per project policy" but the
code offers no confirmation mechanism. Any PR touching the tracked
template fails forever.

Fix: exempt the standard template names (`.env.example`, `.env.sample`,
`.env.template`) from the fail. Real `.env` files still fail.

Danger runs on `pull_request_target` against base-repo code, so once
this merges, re-running danger on #1674 picks it up without a branch
update.

## Test plan
- [ ] danger re-run on #1674 passes (only the changelog warning remains)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Exempts `.env.example`, `.env.sample`, and `.env.template` from the
Danger `.env*` protection so template updates don’t fail CI, while still
blocking real `.env` files. This unblocks PRs that touch tracked env
templates (e.g., #1674).

- **Bug Fixes**
- Updated `dangerfile.ts` to ignore standard env templates in the
`.env*` check.
  - The rule still fails on actual `.env` files.
  - Re-running Danger on affected PRs will pass.

<sup>Written for commit 0520fe5.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1899?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
@LucasSantana-Dev

Copy link
Copy Markdown
Owner

A note from the maintainer side: sorry this PR waited as long as it did for a proper review, and sorry for the rounds of branch updates and re-running checks today. The churn was on our side, not yours.

Your PRs exposed real gaps in how this repo handled external contributions: CI runs sat in a silent approval queue, some gates could never pass on fork PRs (SonarCloud, danger), and the team had no notification when external PRs arrived. Those are all fixed as of today:

  • CI auto-approves for returning contributors, no more waiting on a manual click.
  • All gates now pass on fork PRs (SonarCloud skips gracefully without a token, danger runs and comments correctly).
  • The team gets notified the moment an external PR is opened.

Your branch is up to date and the full suite is green. Thanks for the patience and for the contribution. External contributors are very welcome here.

@LucasSantana-Dev
LucasSantana-Dev merged commit babe0ef into LucasSantana-Dev:main Jul 27, 2026
41 checks passed
LucasSantana-Dev added a commit that referenced this pull request Jul 27, 2026
…1881)

## What

`docker-compose.yml` guarded the Postgres password with
`${POSTGRES_PASSWORD?POSTGRES_PASSWORD_required}`. Docker Compose fires
that form **only when the variable is absent**. A present-but-empty
value passes straight through, so `POSTGRES_PASSWORD=` in `.env` starts
Postgres with an empty password and no warning.

Verified against `docker-compose` 5.1.4:

| `.env` state | `${VAR?err}` | `${VAR:?err}` |
|---|---|---|
| unset | errors | errors |
| `POSTGRES_PASSWORD=` (empty) | **passes** | errors |
| real value | passes | passes |

Both interpolation sites now use `:?`, so the guard means what it looks
like it means. Confirmed against the real compose file: empty value now
fails with `required variable POSTGRES_PASSWORD is missing a value:
POSTGRES_PASSWORD_required`, a real value renders the URL normally.

Also documents generating the value in the README setup block. It is
interpolated straight into a `postgres://` URL, so it has to be
URL-safe, hence `openssl rand -hex 24`. Duplicate keys in `.env` resolve
last-wins (verified), so `>>` is safe, and it avoids the `sed -i`
GNU/BSD portability trap in a public README.

## Why now

Came out of reviewing #1674, which proposes an **active** 48-zero
placeholder in `.env.example`. That would permanently disable this guard
for anyone following the documented `cp .env.example .env` flow. The fix
there is an empty placeholder, which only works once the guard actually
rejects empty values, which is this PR.

This is a pre-existing weakness, not something #1674 introduced.

## Decision record

`decisions/2026-07-26-postgres-password-env-guard.md` covers the
alternatives, including the `scripts/setup-env.sh` option and why it is
the most likely thing to revisit.

## Not addressed here

Changing `POSTGRES_PASSWORD` in `.env` after first boot does not change
the password, because `PGDATA` is initialised once and the volume
persists the original. Pre-existing; filed separately.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Treats an empty `POSTGRES_PASSWORD` as missing in Docker Compose so dev
and staging stacks fail fast instead of starting Postgres with an empty
password. Updates the README to generate a URL‑safe password and adds a
decision record.

- **Bug Fixes**
- Switched guards to `${POSTGRES_PASSWORD:?POSTGRES_PASSWORD_required}`
in `docker-compose.staging.yml` and `docker-compose.dev.yml` for
`DATABASE_URL`, `DIRECT_URL`, and the Postgres service.

- **Migration**
- Set a non-empty, URL-safe `POSTGRES_PASSWORD` before `docker compose
up`, e.g. `echo "POSTGRES_PASSWORD=$(openssl rand -hex 24)" >> .env`

<sup>Written for commit eacd52b.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1881?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
LucasSantana-Dev added a commit that referenced this pull request Jul 27, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>2.38.0</summary>

##
[2.38.0](v2.37.3...v2.38.0)
(2026-07-27)


### Features

* **bot:** add /ticket-setup for support category and agent role
([#1863](#1863))
([3f4af39](3f4af39))
* **frontend:** per-action loading and connection gating on music
controls
([#1866](#1866))
([2dda60f](2dda60f))
* **frontend:** show stale progress when music SSE lags
([#1867](#1867))
([4952e73](4952e73))
* **music:** surface recommendationReason in nowplaying and queue
([#1864](#1864))
([960fd62](960fd62))
* **ops:** blue/green zero-downtime deploys — Phase 1 web tier
([#1786](#1786))
([f5f7597](f5f7597))


### Bug Fixes

* **docker:** make compose stack boot from a fresh .env
([#1674](#1674))
([babe0ef](babe0ef))
* **docker:** treat an empty db password as missing in compose guards
([#1881](#1881))
([718c0ad](718c0ad))
* **frontend:** make landing page usable at mobile widths
([#1865](#1865))
([6190350](6190350))
* **frontend:** stop hero grid columns overflowing on narrow viewports
([#1874](#1874))
([ce5cea0](ce5cea0))
* **invite:** add /invite where cloudflare pages reads it
([#1895](#1895))
([0528f66](0528f66))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
This was referenced Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants