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
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.
This commit is contained in:
@@ -132,6 +132,34 @@ jobs:
|
||||
rm -rf $RELEASE_DIR/wwwroot/web && \
|
||||
ln -s ../../../shared/wwwroot-web $RELEASE_DIR/wwwroot/web"
|
||||
|
||||
# Optional plugin modules (future modular support): a compiled SlpModularCms.Modules.*.dll
|
||||
# dropped into shared/modules survives every release, the same persistence pattern as
|
||||
# shared/wwwroot-web above — except there's no cross-account permission dance here, since
|
||||
# shared/modules lives entirely under gitea-workflow's own tree (unlike wwwroot-web, which
|
||||
# reaches into webadmin's). ModuleOrchestrator.DiscoverModules() already scans its own base
|
||||
# directory on disk for matching assemblies at startup (SlpModularCms.Core/Hosting/
|
||||
# ModuleOrchestrator.cs) and loads whatever it finds via reflection — no code change needed,
|
||||
# only somewhere for the DLL to still be after the next deploy replaces releases/{timestamp}.
|
||||
# `ls ... 2>/dev/null` piped to a `while read` (rather than a bare glob loop) keeps this
|
||||
# POSIX-sh safe and correct when shared/modules is empty, which is the common case today.
|
||||
- name: Link persistent modules
|
||||
env:
|
||||
SSH_USER: ${{ secrets.PI_MAIN_USERNAME }}
|
||||
SSH_PASS: ${{ secrets.PI_MAIN_PASSWORD }}
|
||||
SSH_PORT: ${{ secrets.PI_MAIN_PORT }}
|
||||
SSH_HOST: ${{ secrets.PI_MAIN_ADDRESS }}
|
||||
run: |
|
||||
RELEASE_DIR="${{ inputs.deploy_path }}/releases/${{ steps.release.outputs.timestamp }}"
|
||||
sshpass -p "$SSH_PASS" ssh \
|
||||
-p "$SSH_PORT" \
|
||||
-o StrictHostKeyChecking=no \
|
||||
"$SSH_USER@$SSH_HOST" \
|
||||
"mkdir -p ${{ inputs.deploy_path }}/shared/modules && \
|
||||
ls ${{ inputs.deploy_path }}/shared/modules/*.dll 2>/dev/null | while read -r f; do \
|
||||
name=\$(basename \"\$f\"); \
|
||||
ln -sf \"../../shared/modules/\$name\" \"$RELEASE_DIR/\$name\"; \
|
||||
done"
|
||||
|
||||
# Atomic release switch (FR-06, D-27): `ln -sfn` replaces the `current` symlink target in a
|
||||
# single filesystem operation, so there is no moment where `current` points at a half-written
|
||||
# directory. The process is then restarted so it picks up the new assemblies — a running .NET
|
||||
|
||||
+25
-3
@@ -148,6 +148,28 @@ sudo chgrp -R webshared /mnt/storage1/www/html/slpsoftware/<env>
|
||||
and make sure webadmin's FTP server creates new uploads group-readable (`g+rx`, not just
|
||||
owner-readable) — a one-time permission setup, not something either pipeline touches per deploy.
|
||||
|
||||
**`shared/modules` is the equivalent mechanism for optional plugin modules** (future modular
|
||||
support) — but simpler, since it lives entirely under `gitea-workflow`'s own tree, with no
|
||||
cross-account permission dance:
|
||||
|
||||
👤 **pi-main / `gitea-workflow`:**
|
||||
```bash
|
||||
mkdir -p ~/apps/slpsoftware/<env>/shared/modules
|
||||
```
|
||||
|
||||
`deploy-scp.yaml`'s "Link persistent modules" step already runs this `mkdir -p` on every deploy, so
|
||||
this line is only useful if you want the directory to exist before the very first deploy — it isn't
|
||||
required. To add a module: build a `SlpModularCms.Modules.<Name>.dll` against the same version of
|
||||
`SlpModularCms.Core` the running app was built against (mismatched contracts are caught per-module
|
||||
by `ModuleOrchestrator`'s existing try/catch — logged and skipped, not a crash), `scp`/`sftp` it as
|
||||
`gitea-workflow` into `~/apps/slpsoftware/<env>/shared/modules/`, then either wait for the next
|
||||
deploy or restart the service by hand:
|
||||
```bash
|
||||
systemctl --user restart slpsoftware-<env>.service
|
||||
```
|
||||
Either way, `ModuleOrchestrator.DiscoverModules()` picks it up from the release directory the next
|
||||
time the process starts — no CI run required to add a module this way.
|
||||
|
||||
### 1.5 Runtime Configuration File
|
||||
One file per environment, **outside** the release directory so it survives every switch:
|
||||
|
||||
@@ -498,9 +520,9 @@ Already built (U5/U6) — this is the read-only walkthrough for whoever operates
|
||||
1. Push to `master`, or a manual `workflow_dispatch` → the six gates run
|
||||
2. `publish-test` runs (and `publish-production`, only if `workflow_dispatch` with the flag)
|
||||
3. `deploy-test` (always, if gates pass) calls `deploy-scp.yaml`, which uploads into a new
|
||||
`releases/{timestamp}/`, links `shared/wwwroot-web` in, switches `current`, restarts
|
||||
`slpsoftware-test.service`, verifies `https://test.slpsoftware.nl/health`, then prunes old
|
||||
releases (only test — `run_db_backup: false`)
|
||||
`releases/{timestamp}/`, links `shared/wwwroot-web` and any `shared/modules/*.dll` in, switches
|
||||
`current`, restarts `slpsoftware-test.service`, verifies `https://test.slpsoftware.nl/health`,
|
||||
then prunes old releases (only test — `run_db_backup: false`)
|
||||
4. `deploy-production` (only with the flag) does the same, plus a database backup first
|
||||
(`run_db_backup: true`) — see § 4
|
||||
|
||||
|
||||
Reference in New Issue
Block a user