hygiene: prepare ForgeFlow for public release
Managed validation / full (pull_request) Successful in 27s
Managed validation / full (pull_request) Successful in 27s
This commit is contained in:
@@ -21,6 +21,8 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
full:
|
full:
|
||||||
name: full
|
name: full
|
||||||
|
# Public fork code must never execute automatically on the private runner.
|
||||||
|
if: ${{ gitea.event_name != 'pull_request' || gitea.event.pull_request.head.repo.full_name == gitea.repository }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
ForgeFlow's detailed security model is documented in [`docs/SECURITY.md`](docs/SECURITY.md).
|
ForgeFlow's detailed security model is documented in [`docs/SECURITY.md`](docs/SECURITY.md).
|
||||||
|
|
||||||
Report suspected vulnerabilities privately to the repository owner. Do not publish Gitea tokens, SSH credentials, update-signing material, private server addresses, support bundles containing sensitive data or other operational secrets in a public issue.
|
Report suspected vulnerabilities privately to `security@itworx.tech`. Do not publish Gitea tokens, SSH credentials, update-signing material, private server addresses, support bundles containing sensitive data or other operational secrets in a public issue.
|
||||||
|
|
||||||
For a useful report, include the affected ForgeFlow version/commit, component, minimal reproduction steps, expected and observed behaviour and security impact. Use sanitized or synthetic repository/server data whenever possible.
|
For a useful report, include the affected ForgeFlow version/commit, component, minimal reproduction steps, expected and observed behaviour and security impact. Use sanitized or synthetic repository/server data whenever possible.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
1. Close ForgeFlow completely.
|
1. Close ForgeFlow completely.
|
||||||
2. Extract `ForgeFlow-0.4.0-update-from-0.3.2.zip`.
|
2. Extract `ForgeFlow-0.4.0-update-from-0.3.2.zip`.
|
||||||
3. Copy the contents of the included `ForgeFlow` folder into your existing
|
3. Copy the contents of the included `ForgeFlow` folder into your existing
|
||||||
`C:\Users\Jens\dyad-apps\ForgeFlow` folder and replace existing files.
|
`C:\Users\your-name\Apps\ForgeFlow` folder and replace existing files.
|
||||||
4. Do not create a nested `ForgeFlow\ForgeFlow` folder.
|
4. Do not create a nested `ForgeFlow\ForgeFlow` folder.
|
||||||
5. Open Windows PowerShell in the existing ForgeFlow folder and run:
|
5. Open Windows PowerShell in the existing ForgeFlow folder and run:
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ for every repository. ForgeFlow now:
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Default project root: C:\Users\Jens\Projects
|
Default project root: C:\Users\your-name\Projects
|
||||||
Gitea repository: Jens/Portfolio
|
Gitea repository: Jens/Portfolio
|
||||||
Automatic target: C:\Users\Jens\Projects\Portfolio
|
Automatic target: C:\Users\your-name\Projects\Portfolio
|
||||||
```
|
```
|
||||||
|
|
||||||
A separate **Choose another location** action remains available for exceptional
|
A separate **Choose another location** action remains available for exceptional
|
||||||
|
|||||||
+2
-2
@@ -53,13 +53,13 @@ The binary publisher refuses to upload when local `HEAD` differs from the config
|
|||||||
Extract the complete source ZIP so this file exists:
|
Extract the complete source ZIP so this file exists:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
C:\Users\Jens\Downloads\ForgeFlow-<version>\ForgeFlow\package.json
|
C:\Users\your-name\Downloads\ForgeFlow-<version>\ForgeFlow\package.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd C:\Users\Jens\Downloads\ForgeFlow-<version>\ForgeFlow
|
cd C:\Users\your-name\Downloads\ForgeFlow-<version>\ForgeFlow
|
||||||
Set-ExecutionPolicy -Scope Process Bypass
|
Set-ExecutionPolicy -Scope Process Bypass
|
||||||
.\Publish-ForgeFlow-Release.ps1
|
.\Publish-ForgeFlow-Release.ps1
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -176,7 +176,7 @@
|
|||||||
username: "root",
|
username: "root",
|
||||||
authType: "privateKey",
|
authType: "privateKey",
|
||||||
basePath: "/mnt/user/appdata",
|
basePath: "/mnt/user/appdata",
|
||||||
privateKeyPath: "C:\\Users\\Jens\\.ssh\\id_ed25519",
|
privateKeyPath: "C:\\Users\\your-name\\.ssh\\id_ed25519",
|
||||||
hostFingerprint: "SHA256:demo",
|
hostFingerprint: "SHA256:demo",
|
||||||
hasPassword: false,
|
hasPassword: false,
|
||||||
hasPassphrase: false,
|
hasPassphrase: false,
|
||||||
|
|||||||
@@ -665,7 +665,7 @@ function createMockDeploymentBridge(context) {
|
|||||||
async exportDiagnostics(privacyMode = "standard") {
|
async exportDiagnostics(privacyMode = "standard") {
|
||||||
await wait(500);
|
await wait(500);
|
||||||
return {
|
return {
|
||||||
path: `C:\Users\Jens\Downloads\ForgeFlow-Diagnostics-demo.zip`,
|
path: `C:\Users\your-name\Downloads\ForgeFlow-Diagnostics-demo.zip`,
|
||||||
bytes: 38221,
|
bytes: 38221,
|
||||||
size: "37.3 KB",
|
size: "37.3 KB",
|
||||||
sha256: "b".repeat(64),
|
sha256: "b".repeat(64),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function createMockRepositoryBridge(context) {
|
|||||||
},
|
},
|
||||||
async selectKeyFile() {
|
async selectKeyFile() {
|
||||||
await wait();
|
await wait();
|
||||||
return "C:\\Users\\Jens\\.ssh\\id_ed25519";
|
return "C:\\Users\\your-name\\.ssh\\id_ed25519";
|
||||||
},
|
},
|
||||||
async setupPreflight({ baseUrl, token, roots = [] }) {
|
async setupPreflight({ baseUrl, token, roots = [] }) {
|
||||||
await wait(240);
|
await wait(240);
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ test('rewrites Gitea internal HTTP release URLs to the configured public origin'
|
|||||||
return Buffer.from('asset');
|
return Buffer.from('asset');
|
||||||
};
|
};
|
||||||
await service.downloadReleaseAsset('Jens', 'ForgeFlow', 107, 412, {
|
await service.downloadReleaseAsset('Jens', 'ForgeFlow', 107, 412, {
|
||||||
downloadUrl: 'http://192.168.10.150:3000/Jens/ForgeFlow/releases/download/v0.10.1/ForgeFlow.exe',
|
downloadUrl: 'http://192.168.56.10:3000/Jens/ForgeFlow/releases/download/v0.10.1/ForgeFlow.exe',
|
||||||
});
|
});
|
||||||
assert.equal(requested, 'https://gitea.example.test/Jens/ForgeFlow/releases/download/v0.10.1/ForgeFlow.exe');
|
assert.equal(requested, 'https://gitea.example.test/Jens/ForgeFlow/releases/download/v0.10.1/ForgeFlow.exe');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ test('redacts runtime credentials, structured secrets, private keys and URL cred
|
|||||||
test('sanitizes nested sensitive keys and aliases user paths', () => {
|
test('sanitizes nested sensitive keys and aliases user paths', () => {
|
||||||
const value = {
|
const value = {
|
||||||
accessToken: 'do-not-keep',
|
accessToken: 'do-not-keep',
|
||||||
nested: { password: 'do-not-keep-either', path: 'C:\\Users\\Jens\\Projects\\ForgeFlow' },
|
nested: { password: 'do-not-keep-either', path: 'C:\\Users\\example-user\\Projects\\ForgeFlow' },
|
||||||
home: '/home/jens/projects/forgeflow'
|
home: '/home/jens/projects/forgeflow'
|
||||||
};
|
};
|
||||||
const sanitized = sanitizeForDiagnostics(value, { homeDir: '/home/jens', cwd: '/work/ForgeFlow' });
|
const sanitized = sanitizeForDiagnostics(value, { homeDir: '/home/jens', cwd: '/work/ForgeFlow' });
|
||||||
@@ -48,7 +48,7 @@ test('strict privacy redacts private addresses, infrastructure URLs and server p
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('path aliasing handles slash variants', () => {
|
test('path aliasing handles slash variants', () => {
|
||||||
const result = pathAlias('C:\\Users\\Jens\\src and C:/Users/Jens/src', { homeDir: 'C:\\Users\\Jens', cwd: 'D:\\ForgeFlow' });
|
const result = pathAlias('C:\\Users\\example-user\\src and C:/Users/example-user/src', { homeDir: 'C:\\Users\\example-user', cwd: 'D:\\ForgeFlow' });
|
||||||
assert.doesNotMatch(result, /Users[\\/]Jens/);
|
assert.doesNotMatch(result, /Users[\\/]Jens/);
|
||||||
assert.match(result, /<HOME>/);
|
assert.match(result, /<HOME>/);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -121,10 +121,10 @@ test("server pull prefers the linked checkout origin over stale detected SSH end
|
|||||||
const repository = {
|
const repository = {
|
||||||
fullName: "Jens/Portfolio",
|
fullName: "Jens/Portfolio",
|
||||||
localStatus: { remoteUrl: "git@gitea.itworx.tech:Jens/Portfolio.git" },
|
localStatus: { remoteUrl: "git@gitea.itworx.tech:Jens/Portfolio.git" },
|
||||||
sshUrl: "ssh://git@192.168.10.150:222/Jens/Portfolio.git",
|
sshUrl: "ssh://git@192.168.56.10:222/Jens/Portfolio.git",
|
||||||
preferredCloneUrl: "ssh://git@192.168.10.150:222/Jens/Portfolio.git",
|
preferredCloneUrl: "ssh://git@192.168.56.10:222/Jens/Portfolio.git",
|
||||||
};
|
};
|
||||||
const profile = { cloneUrl: "ssh://git@192.168.10.150:222/Jens/Portfolio.git" };
|
const profile = { cloneUrl: "ssh://git@192.168.56.10:222/Jens/Portfolio.git" };
|
||||||
|
|
||||||
assert.equal(service.serverGitRemote(repository, profile), "git@gitea.itworx.tech:Jens/Portfolio.git");
|
assert.equal(service.serverGitRemote(repository, profile), "git@gitea.itworx.tech:Jens/Portfolio.git");
|
||||||
assert.deepEqual(service.serverGitHost(repository, profile), { host: "gitea.itworx.tech", port: 22 });
|
assert.deepEqual(service.serverGitHost(repository, profile), { host: "gitea.itworx.tech", port: 22 });
|
||||||
@@ -894,7 +894,7 @@ test("DockerMan metadata uses dockerman labels, a template WebUI and lowercase-s
|
|||||||
remoteFolder: "Portfolio",
|
remoteFolder: "Portfolio",
|
||||||
environment: "production",
|
environment: "production",
|
||||||
hostPort: 5150,
|
hostPort: 5150,
|
||||||
webUiUrl: "http://192.168.10.150:5150/admin",
|
webUiUrl: "http://192.168.56.10:5150/admin",
|
||||||
dockerShell: "/bin/sh",
|
dockerShell: "/bin/sh",
|
||||||
},
|
},
|
||||||
{ name: "Portfolio" },
|
{ name: "Portfolio" },
|
||||||
@@ -927,7 +927,7 @@ test("DockerMan integration writes a persistent template fallback and invalidate
|
|||||||
remoteFolder: "Portfolio",
|
remoteFolder: "Portfolio",
|
||||||
environment: "production",
|
environment: "production",
|
||||||
hostPort: 5150,
|
hostPort: 5150,
|
||||||
webUiUrl: "http://192.168.10.150:5150/",
|
webUiUrl: "http://192.168.56.10:5150/",
|
||||||
dockerShell: "/bin/sh",
|
dockerShell: "/bin/sh",
|
||||||
manageDockerMan: true,
|
manageDockerMan: true,
|
||||||
generatedCompose: true,
|
generatedCompose: true,
|
||||||
@@ -1124,7 +1124,7 @@ test("existing Unraid deployment discovery derives profile values from Docker, C
|
|||||||
defaultBranch: "main",
|
defaultBranch: "main",
|
||||||
sshUrl: "ssh://git@gitea/Jens/blockpilot-autonomous.git",
|
sshUrl: "ssh://git@gitea/Jens/blockpilot-autonomous.git",
|
||||||
},
|
},
|
||||||
server: { id: "unraid", host: "192.168.10.150" },
|
server: { id: "unraid", host: "192.168.56.10" },
|
||||||
remoteFolder: "blockpilot-autonomous",
|
remoteFolder: "blockpilot-autonomous",
|
||||||
remotePath: "/mnt/user/appdata/blockpilot-autonomous",
|
remotePath: "/mnt/user/appdata/blockpilot-autonomous",
|
||||||
payload: {
|
payload: {
|
||||||
@@ -1399,7 +1399,7 @@ test("push bundle preflight does not require Git or Gitea credentials on Unraid"
|
|||||||
getServer: () => ({
|
getServer: () => ({
|
||||||
id: "unraid",
|
id: "unraid",
|
||||||
name: "Unraid",
|
name: "Unraid",
|
||||||
host: "192.168.10.150",
|
host: "192.168.56.10",
|
||||||
port: 22,
|
port: 22,
|
||||||
username: "root",
|
username: "root",
|
||||||
basePath: "/mnt/user/appdata",
|
basePath: "/mnt/user/appdata",
|
||||||
|
|||||||
Reference in New Issue
Block a user