Publish curated ForgeFlow source from 63022ccf9a37242d573297c8ce7f15db61acc34e
ForgeFlow quality gate / secret-scan (push) Successful in 4s
ForgeFlow signed release / release (push) Failing after 18m45s
ForgeFlow quality gate / quality (push) Canceled after 0s

This commit is contained in:
Public Source Publisher committed 2026-09-30 21:27:28 +00:00
1 parent bdfcc1585d
commit 04cbfccbdb
19 files changed
+233 -77

No files matched your search

+14
View File
@@ -48,6 +48,20 @@ test("load creates missing config and recovers malformed JSON", async (t) => {
assert.ok((await readdir(directory)).some((name) => name.includes(".corrupt-")));
});
test("legacy ForgeFlow update endpoint migrates to the signed public releases", async (t) => {
const { directory, store } = await storeFixture(t);
assert.equal(store.data.updates.repo, "ForgeFlow-Public");
await writeFile(store.filePath, JSON.stringify({
updates: { owner: "Jens", repo: "ForgeFlow", branch: "main", autoCheck: true },
}), "utf8");
await store.load();
assert.equal(store.data.updates.repo, "ForgeFlow-Public");
assert.equal(JSON.parse(await readFile(store.filePath, "utf8")).updates.repo, "ForgeFlow-Public");
assert.equal(store.migrate({ updates: { owner: "Team", repo: "ForgeFlow" } }).updates.repo, "ForgeFlow");
assert.equal(store.migrate({ updates: { owner: "Jens", repo: "CustomUpdates" } }).updates.repo, "CustomUpdates");
assert.equal(store.migrate({ updates: { owner: "Jens", repo: "ForgeFlow", branch: "custom" } }).updates.repo, "ForgeFlow");
});
test("server normalization rejects unsafe targets and preserves bounded scan configuration", async (t) => {
const { store } = await storeFixture(t);
assert.throws(() => store.normalizeServer({ host: "bad host", username: "root" }), /hostname/);
+21
View File
@@ -0,0 +1,21 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import releasePolicy from '../src/shared/release-policy.cjs';
const { windowsReleaseAssetNames, existingReleaseState } = releasePolicy;
const commit = 'a'.repeat(40);
const version = '0.10.16';
test('a draft for another commit cannot receive replacement release assets', () => {
assert.throws(() => existingReleaseState({ target_commitish: 'b'.repeat(40), draft: true }, version, commit), /Bump the version/);
});
test('a matching draft can resume while a complete published release is immutable', () => {
assert.equal(existingReleaseState({ target_commitish: commit, draft: true }, version, commit), 'draft');
assert.equal(existingReleaseState({ target_commitish: commit, draft: false, assets: windowsReleaseAssetNames(version).map((name) => ({ name })) }, version, commit), 'published');
});
test('a published release missing its signature cannot be treated as complete', () => {
const assets = windowsReleaseAssetNames(version).filter((name) => !name.endsWith('.sig')).map((name) => ({ name }));
assert.throws(() => existingReleaseState({ target_commitish: commit, draft: false, assets }, version, commit), /release-manifest.json.sig/);
});
+34 -5
View File
@@ -118,6 +118,33 @@ test("update repository parts reject path injection", async () => {
await rm(temp, { recursive: true, force: true });
});
test("packaged updates pin the published release commit despite later source-only changes", async (t) => {
const temp = await mkdtemp(path.join(os.tmpdir(), "forgeflow-release-check-"));
t.after(() => rm(temp, { recursive: true, force: true }));
const releaseCommit = "b".repeat(40);
const service = new UpdateService({
store: { data: { updates: {} }, save: async () => {} },
gitea: {
async getLatestRelease(owner, repo) {
assert.equal(repo, "ForgeFlow-Public");
return { tag_name: "v0.10.16", target_commitish: releaseCommit, draft: false, prerelease: false };
},
async getBranch() { throw new Error("Packaged updates must not follow mutable main."); },
async getRepositoryFile(input) {
assert.equal(input.ref, releaseCommit);
return { decoded: JSON.stringify({ name: "forgeflow", version: "0.10.16" }) };
},
},
appInfo: { version: "0.10.14", packaged: true },
sourcePath: temp,
userDataPath: temp,
});
const result = await service.check();
assert.equal(result.available, true);
assert.equal(result.remoteSha, releaseCommit);
assert.equal(result.releaseTag, "v0.10.16");
});
test("source updater refuses an unsigned archive before launching a helper", async () => {
const temp = await mkdtemp(
path.join(os.tmpdir(), "forgeflow-update-handshake-"),
@@ -734,11 +761,13 @@ test("Windows release pipeline emits signed provenance, manifest and SBOM eviden
assert.doesNotMatch(releaseWorkflow, /checkout@v\d|setup-node@v\d/);
assert.match(releaseWorkflow, /checkout@[a-f0-9]{40}/);
assert.match(releaseWorkflow, /setup-node@[a-f0-9]{40}/);
assert.ok(
releaseWorkflow.indexOf("Validate version bump and build release artifacts") <
releaseWorkflow.indexOf("FORGEFLOW_RELEASE_SIGNING_KEY_PEM"),
"signing secrets must not be present during dependency installation and quality checks",
);
const buildStart = releaseWorkflow.indexOf("- name: Build and validate release artifacts");
const signingStart = releaseWorkflow.indexOf("- name: Sign and publish validated artifacts");
assert.ok(buildStart >= 0 && signingStart > buildStart);
assert.doesNotMatch(releaseWorkflow.slice(buildStart, signingStart), /FORGEFLOW_RELEASE_SIGNING_KEY_PEM/);
assert.match(releaseWorkflow, /push:\s*\n\s*branches: \[main\]/);
assert.match(releaseWorkflow, /should_release=false/);
assert.match(releaseWorkflow, /should_release=true/);
assert.match(releaseWorkflow, /finally \{/);
assert.match(releaseWorkflow, /Remove-Item -LiteralPath \$privateKeyPath -Force/);
const publisher = await readFile(new URL("../scripts/publish-binary-release.cjs", import.meta.url), "utf8");