Merge NM-App-302-run-as-service into dev
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# ServiceLicence — Systemd Integration with AITM Dashboard
|
||||
|
||||
## What Was Done
|
||||
|
||||
Registered the `ServiceLicence` .NET license server as a systemd user service and surfaced it in the AITM dashboard (Test/Services tab) with start/stop/status controls.
|
||||
|
||||
## Files Changed
|
||||
|
||||
### Outside this repo — AITM project (`/home/zuf/dev/code/AITM/`)
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/shared-types.ts` | Added `managedBy?: string`, `systemdUnit?: string` to `TestAppConfig`; `rootOverride?: string` to `TestProjectConfig` |
|
||||
| `src/types.ts` | Added `systemdUnit?: string` field; allowed `process: null` in `TestProcess` |
|
||||
| `src/test-environment/TestEnvironmentService.ts` | Systemd-aware branches in `startTestApp`, `stopTestApp`, `getTestStatus`; `rootOverride` support in `testProjectDir()` |
|
||||
| `src/socket/TestSocketHandlers.ts` | Skip dotnet build for systemd-managed apps in `test:build-and-start` and `test:start-all` |
|
||||
| `config.json` | Added `service-licence` project entry with `rootOverride` and `managedBy: "systemd"` |
|
||||
|
||||
### System file
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `~/.config/systemd/user/servicelicence.service` | New systemd user unit for ServiceLicence; `NODE_ENV=development`, `DATABASE_URL` set; `Restart=on-failure` |
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### Systemd Unit (`servicelicence.service`)
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=ServiceLicence License Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=<path to LicenseServer project>
|
||||
ExecStart=dotnet run --project <path>
|
||||
Environment=NODE_ENV=development
|
||||
Environment=DATABASE_URL=<connection string>
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
`NODE_ENV=development` was required (not `production`) so that the dev-secret default for `JWT_SECRET` is picked up — production mode requires an explicit `JWT_SECRET` env var.
|
||||
|
||||
### AITM Config Entry
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "service-licence",
|
||||
"name": "ServiceLicence",
|
||||
"managedBy": "systemd",
|
||||
"systemdUnit": "servicelicence",
|
||||
"rootOverride": "/absolute/path/to/LicenseServer"
|
||||
}
|
||||
```
|
||||
|
||||
`rootOverride` is acceptable in `config.json` (config file, not source code). `managedBy: "systemd"` gates the new code branches.
|
||||
|
||||
### Backend Systemd-Aware Logic (`TestEnvironmentService.ts`)
|
||||
|
||||
Three functions were extended with a systemd branch:
|
||||
|
||||
- **`startTestApp(id)`** — runs `systemctl --user start <unit>` instead of spawning a child process
|
||||
- **`stopTestApp(id)`** — runs `systemctl --user stop <unit>`
|
||||
- **`getTestStatus(id)`** — parses `systemctl --user is-active <unit>` → maps `active` → `running`, anything else → `stopped`; survives AITM restarts (no in-memory process reference needed)
|
||||
|
||||
### Build Skip (`TestSocketHandlers.ts`)
|
||||
|
||||
`test:build-and-start` and `test:start-all` handlers skip `dotnet build` for entries with `managedBy: "systemd"` — the service manages its own lifecycle.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
systemctl --user status servicelicence
|
||||
|
||||
# Restart
|
||||
systemctl --user restart servicelicence
|
||||
|
||||
# Via AITM API
|
||||
curl -s http://localhost:3333/api/test/status | jq '.[] | select(.id == "service-licence")'
|
||||
```
|
||||
|
||||
## Acceptance Criteria Met
|
||||
|
||||
- `systemctl --user status servicelicence` → `active (running)`
|
||||
- `curl -s http://localhost:3333/api/test/status | jq .` includes `service-licence` with valid status
|
||||
- Start/Stop buttons in AITM Test tab work for ServiceLicence
|
||||
- `npm run check:frontend` passes
|
||||
Reference in New Issue
Block a user