Commit Graph

4 Commits

Author SHA1 Message Date
Paul Nothaft a40ab6a9b1 ci: required-check workflows now fire on every PR (no paths filter)
Branch protection on `main` + `stable` lists `upgrade-from-bootstrap`
and `fresh-install` as REQUIRED checks. The producing workflows had
`paths:` filters in their `pull_request` triggers, so they correctly
skipped on PRs that didn't touch migrations / package.json. But a
skipped workflow doesn't satisfy a required check — it leaves the
status "missing", which blocks merge on every unrelated PR.

Concretely surfaced on PR #692 (security bumps): all 12 visible checks
were green, but the merge button was blocked because the two
path-filtered workflows skipped and their required-check names never
reported.

This PR drops the `paths:` filter from both workflows so they always
fire on PRs against `main` + `stable`. Costs:
- `schema-drift` (`upgrade-from-bootstrap`): ~75 s per PR (Postgres
  service boot + migrate:safe run + schema assertion).
- `install-smoke` (`fresh-install`): ~2 min per PR (full Docker
  Compose boot + login).

Both are buying unconditional safety nets on the install + migration
paths, which is what the required-check gate is supposed to model.

Also fixes the trigger branch list while in the file: `[main, beta]`
→ `[main, stable]`, completing the post-#669 rename for these two
workflows that were missed in PR #686.

## What this does NOT fix

`GitGuardian Security Checks` is the third required check that's
currently missing on PRs — but that's a separate problem. The
GitGuardian GitHub App was installed at the user-account level
(`the-luap`) before the org transfer and didn't move with the repo.
Re-installing it on the org via the GitHub Marketplace is a UI step
the maintainer needs to do; can't be done via API.
2026-06-30 00:07:44 +02:00
Luca bbceac6cb0 ci: make GHA cache export non-fatal (ignore-error=true)
The frontend/backend image builds + pushes succeed, then the final
'exporting to GitHub Actions Cache' step intermittently fails with
'error writing layer blob: not_found' (a known flaky type=gha cache backend
issue), failing the whole job. Add ignore-error=true to every cache-to so a
cache-write hiccup can't break an otherwise-successful, already-pushed build.
2026-06-12 17:56:06 +02:00
Paul Nothaft 763fd4593f ci(install-smoke): use BusyBox-compatible ps in node-user check
Alpine ships BusyBox ps (no -p PID, no pgrep), which failed CI on the
first run of this workflow with "ps: unrecognized option: p". Replace
the pgrep-then-ps chain with `ps -o user,comm | awk '$2=="node"'`
which works on both BusyBox (Alpine, in the container) and procps
(the GitHub runner host, though we don't use it here).
2026-05-18 10:28:29 +02:00
Paul Nothaft 1505775678 fix(install): self-chowning entrypoint kills fresh-install restart loop (#484)
The fresh-install restart loop reported by @MrGabri (and confirmed by
@AloePacci with the user:0:0 workaround) had a clear root cause:

  - Dockerfile pinned USER nodejs (UID 1001) before the entrypoint
    ran, so the existing chown branch in init-production.sh:13 was
    dead code.
  - wait-for-db.sh (the actual entrypoint, not init-production.sh)
    silently swallowed mkdir/EACCES on bind mounts with || true,
    then a downstream migration error surfaced as the visible failure.
  - Net effect on a typical Linux host where the bind-mount dir is
    owned by UID 1000: container can't write, exits non-zero,
    restarts forever with no clear error.

Switch to the standard Docker drop-privileges pattern:

  1. Install su-exec, drop `USER nodejs` from the Dockerfile —
     container now starts as root.
  2. wait-for-db.sh: if running as root, chown /app/storage,
     /app/data, /app/logs to nodejs and re-exec self via
     su-exec nodejs:nodejs. App still ends up running as UID 1001.
  3. Preflight check for non-root invocations (compose `user:`
     overrides): verify the bind mounts are actually writable
     before continuing. If not, exit 1 immediately with an
     actionable error pointing at the docs — no more silent
     restart loops.

Also:

  - Delete backend/init-production.sh. It was an orphan — no caller
    in the Dockerfile, compose, or anywhere else. Its chown logic
    looked authoritative enough that @MrGabri ran it manually trying
    to debug, which is what finally surfaced the EACCES.
  - docker-compose.yml: drop user: + PUID/PGID env. The pattern-B
    UID-matching workaround they implemented is obsolete now that
    pattern A (root-then-drop) is in place.
  - .env.example + README: drop PUID/PGID documentation.
  - Add fresh-install smoke test workflow. Boots backend + postgres
    against bind mounts owned by UID 1000 (the GitHub runner UID,
    and the common-mismatch case on Linux hosts) and verifies:
    + container reaches healthy without restart-looping
    + chown happened (dirs now owned by 1001 inside the container)
    + node runs as nodejs, not root (su-exec drop worked)
    + /health returns status:ok
    + with --user 5005:5005 + unwritable mounts, preflight exits
      loud with the expected error string

Verified locally end-to-end against a fresh Postgres + UID-501-owned
bind mount: backend reaches healthy in ~20s, chown applied, node
runs as nodejs, no restart loop. Docs in picpeak-docs cover the new
behavior + a Troubleshooting section for the install-path bugs
fixed in #484/#494/#511/#488.

Refs: #484
2026-05-17 22:29:29 +02:00