Prepare ForgeFlow for public release
Managed validation / full (pull_request) Successful in 44s
ChatGPT validation / quality (push) Failing after 2m28s

This commit is contained in:
NuklearRabbit
2026-08-31 20:10:07 +02:00
parent 57929ea973
commit 8cca1bfc01
29 changed files with 400 additions and 343 deletions
+2 -2
View File
@@ -212,8 +212,8 @@ and last exit code. See `STATUS_ENDPOINT.md`.
## v0.4 services
- `UpdateService` reads `package.json` at an exact Gitea branch SHA, downloads an
authenticated archive and launches the rollback-capable Windows source updater.
- `UpdateService` reports `package.json` at an exact Gitea branch SHA, refuses
unsigned source replacement and applies only publisher-signed packaged updates.
- `SshService` provides pinned-host SSH execution with encrypted password or
private-key passphrase storage.
- `UnraidDeploymentService` inspects existing application folders and performs
+63
View File
@@ -0,0 +1,63 @@
# Deployment migration example
This example shows how to bring an existing Git-backed Docker or Unraid application under ForgeFlow control without exposing or overwriting runtime data.
Use synthetic names and values while testing. Replace them with your own repository, server and paths only in ForgeFlow's local configuration; do not commit credentials or environment-specific diagnostics.
## 1. Establish the authoritative repository
Before deploying, verify that the server checkout and Gitea repository represent the same application:
- compare the complete 40-character commit SHA;
- confirm the configured remote belongs to the intended Gitea origin and repository;
- preserve the root `.git` directory for exact-SHA verification and rollback;
- resolve any remote URL mismatch explicitly instead of silently rewriting it.
ForgeFlow blocks deployment when the existing origin conflicts with the selected repository unless the user explicitly approves alignment.
## 2. Protect runtime data
Typical persistent paths include:
```text
.env
appdata/
config/
data/
logs/
compose.override.yml
```
Keep those paths outside the tracked deployment payload and add runtime-only directories to `.dockerignore` when they are not build inputs. ForgeFlow uses a controlled Git reset without `git clean`, but the repository's own Compose and ignore rules remain authoritative.
## 3. Reuse the maintained Compose definition
Prefer the repository's existing `compose.yml` or `docker-compose.yml` when it already defines ports, volumes, device mappings, labels and health checks. These application-specific settings should be reviewed and versioned with the application rather than regenerated during deployment.
## 4. Handle nested repositories separately
A historical checkout such as `source/` may contain another `.git` directory. Treat this as a migration warning:
1. verify that the root Compose file builds from the intended root;
2. back up the application folder;
3. stop modifying the nested checkout;
4. rename it temporarily;
5. rebuild and verify the application from the root checkout;
6. remove the legacy copy only after rollback has also been tested.
ForgeFlow reports nested repositories but does not delete them automatically.
## 5. Recommended profile
```text
Provider: SSH / Unraid
Server folder: example-app
Branch: main
Compose mode: Repository/server Compose
Compose file: compose.yml
Clone URL: a Git URL reachable from the server
Healthcheck: the application's existing health endpoint
Preserve paths: .env, appdata, config, data, logs, compose.override.yml
```
Complete a preflight first, deploy one exact commit, verify both the live SHA and runtime health, and test rollback before treating the migration as production-ready.
-147
View File
@@ -1,147 +0,0 @@
# LumaOps server versus Gitea audit
This audit compares the supplied `lumaops_server.zip` and `LumaOps_gitea.zip`.
## Main result
The main Unraid working tree and the supplied Gitea checkout point to exactly the same commit:
```text
d42d4a7f08240c478d07466e3fabec654dc71367
```
Latest subject:
```text
Preserve colors across Aura zone updates
```
There is therefore no source-version drift at the root of the live LumaOps folder.
## Root Git repository
The root `.git` directory should remain in place. It enables:
- exact-SHA verification;
- controlled fetch and reset;
- a reliable previous-version reference;
- rollback without copying a second complete source tree.
The archived server copy showed one root status difference for `scripts/unraid-hardware-setup.sh`: file mode `100755 → 100644`. This is consistent with Unix executable bits being lost during ZIP handling. The file content did not differ. Check the executable bit directly on Unraid before deployment.
## Origin URL mismatch to resolve
The supplied server root uses:
```text
ssh://git@127.0.0.1:222/NuklearRabbit/LumaOps.git
```
The supplied Gitea checkout uses:
```text
https://gitea.itworx.tech/Jens/LumaOps.git
```
Although both archives currently point to the same commit, these are different
repository paths. Before the first ForgeFlow deployment, choose the server-
reachable URL for the authoritative `Jens/LumaOps` repository, for example an
SSH URL through `127.0.0.1:222` when Gitea runs on the same Unraid host.
ForgeFlow 0.4 detects this mismatch. Deployment is blocked unless the profile
matches the existing origin or **Align an existing server origin to this URL**
is explicitly enabled.
## Runtime and persistent paths
The server copy contains runtime data that must not be replaced by source updates:
- `appdata/`
- `data/`
- `logs/`
- `.env` and application-specific configuration
The repository `.gitignore` already excludes the principal runtime paths. ForgeFlow's SSH strategy uses Git reset without `git clean`, so untracked persistent data remains in place.
## Compose and Unraid integration
The root `docker-compose.yml` is already suitable as the authoritative deployment definition. It includes:
- build context at the project root;
- container name `lumaops`;
- the Unraid `dockerman` label;
- a Web UI label;
- an Unraid icon label;
- `${WEB_PORT:-1223}:${APP_PORT:-8080}`;
- persistent relative volumes;
- USB, HID and I²C devices;
- a healthcheck.
ForgeFlow should use this existing Compose file rather than generate a replacement. Ports and complex device mappings belong in the repository's maintained Compose definition.
The supplied `.dockerignore` already excludes `.git`, so keeping the root Git
working tree does **not** copy Git history into the Docker build context. It does
not yet explicitly exclude the existing runtime/legacy folders `appdata/`,
`data/`, `logs/` and `source/`. Before the first production rebuild, add the
paths that are not build inputs:
```text
appdata/
data/
logs/
source/
.forgeflow/
```
ForgeFlow 0.4 detects existing preserved paths and nested Git repositories that
are missing from `.dockerignore` and reports them as a preflight warning. The
tool does not silently edit a source-controlled `.dockerignore`; the correction
should be committed to Gitea so every deployment uses the same build context.
## Nested `source/` repository
The server archive also contains a nested Git working tree under:
```text
source/
```
Its HEAD is:
```text
b746a52af1613f4291235f5e8165b8197a269a79
```
It was ahead of its own upstream and included rebase metadata in the supplied archive. The root Compose file uses build context `.` and does not reference `source/`. This strongly indicates that `source/` is an abandoned or historical checkout rather than the active deployment source.
ForgeFlow reports this as a nested-repository warning and does not remove it automatically.
Recommended migration:
1. Back up `/mnt/user/appdata/lumaops`.
2. Verify on Unraid that `docker compose config` uses the root project.
3. Stop changing files in `source/`.
4. Rename it temporarily to `source.legacy-backup`.
5. Rebuild and test LumaOps from the root.
6. Remove the legacy copy only after a successful validation period.
Do not delete the root `.git` directory. Also do not delete the nested `source/`
directory as part of the first ForgeFlow test. Treat its cleanup as a separate,
backed-up migration after the root deployment and rollback have both been
validated.
## Recommended ForgeFlow profile
```text
Provider: SSH / Unraid
Server folder: lumaops
Branch: main
Compose mode: Repository/server Compose
Compose file: docker-compose.yml
Clone URL: the Git URL reachable from Unraid
Healthcheck: the existing LumaOps health URL, when exposed
Preserve paths: .env, appdata, data, logs, config, compose.override.yml
```
No folder rename is required for LumaOps because `lumaops` already aligns with the repository name.
+2 -2
View File
@@ -48,9 +48,9 @@ Deployment profiles support:
- runtime-data preservation;
- rollback to the previous SHA.
## LumaOps audit
## Deployment migration example
The supplied server and Gitea roots both match commit `d42d4a7f08240c478d07466e3fabec654dc71367`. The root Git checkout and Compose file should remain. A stale nested `source/` Git checkout is documented for controlled cleanup.
The documented migration flow keeps the root Git checkout and maintained Compose file in place, verifies the complete commit SHA and treats a stale nested `source/` checkout as separate, controlled cleanup.
## Validation
+5 -4
View File
@@ -23,7 +23,7 @@ flexibility.
- session-only fallback when OS encryption is unavailable;
- token omitted from renderer-visible public state;
- encrypted token blob excluded from diagnostic bundles;
- blank settings token field preserves the existing token;
- a blank settings token field preserves the existing token only when the normalized Gitea origin is unchanged;
- atomic config replacement and restrictive permissions where supported;
- service URLs reject embedded user credentials;
- no token is required by setup/build scripts or documentation.
@@ -128,9 +128,10 @@ included model uses:
require the exact user-confirmed pinned fingerprint;
- remote folders and Compose paths are validated against traversal;
- tracked server-side changes block exact-SHA reset;
- updater tokens are sent only to the configured Gitea origin;
- updater tokens are sent only to the configured Gitea origin, and changing that origin requires a newly entered token;
- non-loopback Gitea connections require HTTPS;
- packaged updates require a publisher-signed Ed25519 manifest that binds the
source commit, artifact identity, byte length and SHA-256 digest;
- update archives are checksummed and validated by the full local quality gate;
- source backup is restored when an update fails.
- packaged update bytes are rehashed immediately before apply;
- integrated source replacement is disabled until source archives carry the
same independent publisher signature.
+9 -21
View File
@@ -2,31 +2,19 @@
ForgeFlow stores credentials, repository mappings, preferences, deployment profiles, diagnostics and operation history outside the source directory.
## Built-in source update
## Source checkouts
Open **Settings → ForgeFlow updates** and choose:
Integrated source replacement is disabled until source archives are covered by the same independent publisher signature as packaged releases. A server-provided commit SHA and a checksum calculated from the downloaded archive do not independently authenticate its publisher, while dependency installation can execute package lifecycle scripts.
1. **Check now**
2. **Download update**
3. **Apply & restart**
Update a source checkout through Git instead:
The default update source is the configured Gitea instance, repository `Jens/ForgeFlow`, branch `main`.
1. fetch the configured upstream;
2. review the exact commit and release notes;
3. switch to the intended release commit or tag;
4. run `npm ci --ignore-scripts` and review the dependency lifecycle allowlist;
5. run `npm run check` before starting ForgeFlow.
The updater pins the download to the exact remote commit, checks the archive SHA-256, starts an external PowerShell helper and waits for a structured `started` marker. ForgeFlow closes only after that marker exists. The helper then:
1. waits for the old process to exit;
2. backs up the current source;
3. extracts and validates the requested semantic version;
4. mirrors the incoming source;
5. runs `npm ci --no-audit --no-fund` when the published release contains `package-lock.json`, otherwise a pinned direct-dependency `npm install`;
6. runs `npm run check`;
7. writes the successful installation result before restart;
8. launches the installed Electron executable directly;
9. persists `success`, `failed` or `rolled-back` state for the next launch.
A failed validation restores the previous source. A successful installation is not rolled back merely because automatic restart fails; start ForgeFlow manually and the persisted result is shown.
Update logs and status files are stored beneath ForgeFlow's local user-data `updates` folder and exclude the Gitea token.
The in-app updater remains available for signed packaged Windows releases.
## Packaged Windows updates