Commit Graph
10 Commits
Author SHA1 Message Date
Sluijsens 7c1d2aa520 Fixes /admin 404 by building the admin SPA before dotnet publish, not via an MSBuild target
Continuous Integration / config (pull_request) Successful in 10s
Continuous Integration / backend-build (pull_request) Successful in 4m52s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m50s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m44s
Continuous Integration / backend-test (pull_request) Successful in 5m37s
Continuous Integration / frontend-build (pull_request) Successful in 2m11s
Continuous Integration / frontend-test (pull_request) Successful in 4m33s
Continuous Integration / frontend-lint (pull_request) Successful in 2m2s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m14s
Deploy (SCP) / deploy (pull_request) Successful in 1m20s
Continuous Integration / deploy-test (pull_request) Successful in 1m21s
The BuildAndCopyAdminFrontend MSBuild target (BeforeTargets=Publish) never actually
worked: files it created after project evaluation were silently absent from the
publish output, and forcing them in via an explicit Content item collided with the
SDK's own static-web-asset resolution. Verified locally with a clean obj/bin and a
fresh node_modules - every deploy so far genuinely shipped without wwwroot/admin.
Moves the frontend build + copy into its own CI step ahead of dotnet publish, so the
SDK's ordinary wwwroot handling picks it up with no custom MSBuild involved.

Also fixes unreadable <code> badges on the website placeholder page (no explicit
text color, relying on inherited body color pairing unreliably with the badge
background).
2026-07-30 11:10:17 +02:00
Sluijsens 9b44a5e85e Adds a shared/modules symlink mechanism for optional plugin modules
Continuous Integration / config (pull_request) Successful in 9s
Continuous Integration / backend-build (pull_request) Successful in 5m4s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m23s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m40s
Continuous Integration / backend-test (pull_request) Successful in 5m46s
Continuous Integration / frontend-build (pull_request) Successful in 2m18s
Continuous Integration / frontend-test (pull_request) Successful in 4m33s
Continuous Integration / frontend-lint (pull_request) Successful in 2m0s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m11s
Deploy (SCP) / deploy (pull_request) Successful in 1m25s
Continuous Integration / deploy-test (pull_request) Successful in 1m25s
ModuleOrchestrator already discovers SlpModularCms.Modules.*.dll from disk at
startup via reflection, so this needed no code change — only a persistent
location (mirroring shared/wwwroot-web) that survives release swaps, and a
deploy-scp.yaml step to symlink its contents into each new release before
restart.
2026-07-30 10:09:53 +02:00
SluijsensandClaude Sonnet 5 d51285d9dd Removes the secret-diagnosis debug step, fixes wwwroot symlink parent dir
Continuous Integration / config (pull_request) Successful in 10s
Continuous Integration / backend-build (pull_request) Successful in 4m34s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m39s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m45s
Continuous Integration / backend-test (pull_request) Successful in 5m15s
Continuous Integration / frontend-build (pull_request) Successful in 2m14s
Continuous Integration / frontend-test (pull_request) Successful in 4m27s
Continuous Integration / frontend-lint (pull_request) Successful in 1m57s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 5m51s
Deploy (SCP) / deploy (pull_request) Failing after 11m46s
Continuous Integration / deploy-test (pull_request) Failing after 11m47s
The PI_MAIN_USERNAME/PASSWORD debug step served its purpose (found the
shell-metacharacter password bug fixed in 51488d6) and is removed now
that deploy-test gets past authentication.

"Link persistent website content" then failed with `ln: failed to
create symbolic link '.../wwwroot/web': No such file or directory` -
dotnet publish only emits a wwwroot/ folder when the source project's
own wwwroot has content, so a release built before any frontend/website
content exists can land with no wwwroot/ directory at all, not merely
an empty wwwroot/web/. `ln -s` can't create the missing parent
directory itself. Added `mkdir -p $RELEASE_DIR/wwwroot` before the
existing rm/ln pair to guarantee the parent exists either way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig
2026-07-30 00:28:29 +02:00
SluijsensandClaude Sonnet 5 51488d6d94 Routes PI_MAIN_* secrets through env vars instead of inline interpolation
Continuous Integration / config (pull_request) Successful in 9s
Continuous Integration / backend-build (pull_request) Successful in 4m57s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m21s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m28s
Continuous Integration / backend-test (pull_request) Successful in 5m3s
Continuous Integration / frontend-build (pull_request) Successful in 2m10s
Continuous Integration / frontend-test (pull_request) Successful in 4m42s
Continuous Integration / frontend-lint (pull_request) Successful in 1m56s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m30s
Deploy (SCP) / deploy (pull_request) Failing after 57s
Continuous Integration / deploy-test (pull_request) Failing after 58s
Every ssh/scp step interpolated ${{ secrets.PI_MAIN_PASSWORD }} and
${{ secrets.PI_MAIN_USERNAME }} directly into the run: shell text.
Gitea/GitHub Actions substitutes that as literal text before bash ever
sees it, so any shell-metacharacter in the password ($, `, ", \) gets
re-interpreted by bash instead of passed through - silently changing
what sshpass actually receives. This plausibly explains a persistent
"Permission denied" even after the username and password length were
both confirmed correct via the debug step (which used env: and so
never hit this).

All five steps now receive SSH_USER/SSH_PASS/SSH_PORT/SSH_HOST via
env:, which bash treats as opaque values with no re-parsing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig
2026-07-29 20:42:57 +02:00
SluijsensandClaude Sonnet 5 3776c0f27b Adds a trimmed-length check to the PI_MAIN_PASSWORD debug step
Continuous Integration / config (pull_request) Successful in 9s
Continuous Integration / backend-build (pull_request) Successful in 4m39s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m15s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m47s
Continuous Integration / backend-test (pull_request) Successful in 5m15s
Continuous Integration / frontend-build (pull_request) Successful in 2m11s
Continuous Integration / frontend-test (pull_request) Successful in 4m40s
Continuous Integration / frontend-lint (pull_request) Successful in 1m58s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m25s
Deploy (SCP) / deploy (pull_request) Failing after 56s
Continuous Integration / deploy-test (pull_request) Failing after 57s
Username is now confirmed correct (14 chars, exact match). This checks
whether the password secret carries leading/trailing whitespace or a
stray newline picked up when it was pasted into Gitea - the length
differs from the trimmed length if so, without ever logging the
password's actual characters.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig
2026-07-29 20:39:36 +02:00
SluijsensandClaude Sonnet 5 92547efd47 Allows deploy-test to run on pull_request events too
Continuous Integration / config (pull_request) Canceled after 0s
Continuous Integration / backend-build (pull_request) Canceled after 0s
Continuous Integration / backend-test (pull_request) Canceled after 0s
Continuous Integration / vulnerability-scan (pull_request) Canceled after 0s
Continuous Integration / frontend-prepare (pull_request) Canceled after 0s
Continuous Integration / frontend-build (pull_request) Canceled after 0s
Continuous Integration / frontend-test (pull_request) Canceled after 0s
Continuous Integration / frontend-lint (pull_request) Canceled after 0s
Continuous Integration / publish-test (pull_request) Canceled after 0s
Continuous Integration / publish-production (pull_request) Canceled after 0s
Continuous Integration / deploy-test (pull_request) Canceled after 0s
Continuous Integration / deploy-production (pull_request) Canceled after 0s
So PR pushes deploy straight to the test environment, without a manual
workflow_dispatch each time. Only one test environment exists, so this
means concurrent PRs would overwrite each other's deploy - acceptable
with a single active PR, worth revisiting once that's no longer true.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig
2026-07-29 19:41:17 +02:00
SluijsensandClaude Sonnet 5 56f4f6fe0f Adds Monitoring Setup docs and deploy-scp troubleshooting/debug fixes
Continuous Integration / config (pull_request) Successful in 9s
Continuous Integration / backend-build (pull_request) Successful in 4m27s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m10s
Continuous Integration / backend-test (pull_request) Canceled after 0s
Continuous Integration / frontend-build (pull_request) Canceled after 0s
Continuous Integration / frontend-test (pull_request) Canceled after 0s
Continuous Integration / frontend-lint (pull_request) Canceled after 0s
Continuous Integration / publish-test (pull_request) Canceled after 0s
Continuous Integration / publish-production (pull_request) Canceled after 0s
Continuous Integration / deploy-test (pull_request) Canceled after 0s
Continuous Integration / deploy-production (pull_request) Canceled after 0s
Continuous Integration / frontend-prepare (pull_request) Canceled after 50s
Monitoring Setup: operations/plans/monitoring-setup-plan.md and
operations/monitoring/monitoring-instructions.md, covering Sentry alert
rules on the security_event tag, UptimeRobot's 6 liveness monitors, and
the two new Umami website entries for the admin SPA.

deployment-instructions.md gains a missing Observability__Environment
host var (without it, both environments would tag Sentry events as
"Production"), the nginx client_max_body_size fix for the 413 seen on
publish-test/production artifact uploads, and two troubleshooting notes
on Gitea Actions re-run behaviour: re-running deploy-test/production
alone loses the run's uploaded artifact, and re-running all jobs on an
existing (rather than a brand new) run can replay stale secrets.

deploy-scp.yaml: step names no longer show literal unresolved
${{ inputs.* }} text (Gitea doesn't interpolate that context in step
names), and a temporary debug step logs PI_MAIN_USERNAME/PASSWORD
length plus a username equality check to diagnose a persistent
Permission denied during the SSH steps, without ever logging the
secret values themselves.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig
2026-07-29 19:39:44 +02:00
Sluijsens 2cd8c4aa88 Renames the backup script to match the instance, not the software
Continuous Integration / config (pull_request) Successful in 10s
Continuous Integration / backend-build (pull_request) Successful in 4m6s
Continuous Integration / vulnerability-scan (pull_request) Successful in 3m39s
Continuous Integration / frontend-prepare (pull_request) Failing after 58s
Continuous Integration / frontend-build (pull_request) Skipped
Continuous Integration / frontend-test (pull_request) Skipped
Continuous Integration / frontend-lint (pull_request) Skipped
Continuous Integration / backend-test (pull_request) Successful in 4m26s
Continuous Integration / publish-test (pull_request) Skipped
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-test (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
backup-slpmodularcms-db.sh named the CMS; this backs up slpsoftware
specifically, same as every other instance-scoped path already does.
Hardcoded in deploy-scp.yaml itself, so this is the actual pipeline
code, not just docs describing it.
2026-07-29 14:17:41 +02:00
Sluijsens 9f4ae475e7 U5 — the gate everything else has to pass
continuous_integration.yaml: six blocking checks, then a separate
publish per environment so a Vite build never gets tagged for the
wrong one, then a call into last commit's deploy workflow. Along the
way: the lint list had drifted (two problems not in the requirement,
one already fixed), and the Umami-origin gate needed a variable pair
of its own since the backend's side of that comparison lives on the
host, not in CI. Pinned the two vulnerable packages while at it.
2026-07-28 16:07:03 +02:00
Sluijsens bd2a963498 U6 — the deploy workflow itself
deploy-scp.yaml: download, back up the production database before
touching anything, upload into a timestamped release, symlink the
persistent website in, switch current and restart, verify /health
with retries, prune old releases only once that check passes. No
sudo, no container actions, one shared interface U5 will call next.
2026-07-28 15:33:03 +02:00