updater fixed

This commit is contained in:
NuklearRabbit
2026-07-28 00:03:33 +02:00
parent f990c26014
commit d4d77c827a
18 changed files with 451 additions and 71 deletions
+31 -2
View File
@@ -108,18 +108,32 @@ test('creates controlled pull requests and reads branch protection', async () =>
await assert.rejects(() => service.createPullRequest({ owner: 'owner', repo: 'app', head: 'main', base: 'main', title: 'Invalid' }), /different/);
});
test('downloads release assets through the release-scoped Gitea endpoint', async () => {
test('resolves release attachment metadata before downloading the actual asset', async () => {
const service = new GiteaService(makeStore());
let metadataPath = '';
let requested = '';
service.request = async (pathname) => {
metadataPath = pathname;
return {
data: {
id: 412,
browser_download_url: 'https://gitea.example.test/attachments/release.exe',
},
};
};
service.downloadAuthenticated = async (pathname) => {
requested = pathname;
return Buffer.from('asset');
};
const asset = await service.downloadReleaseAsset('Jens', 'ForgeFlow', 107, 412);
assert.equal(asset.toString(), 'asset');
assert.equal(
metadataPath,
'/repos/Jens/ForgeFlow/releases/107/assets/412',
);
assert.equal(
requested,
'/api/v1/repos/Jens/ForgeFlow/releases/107/assets/412',
'https://gitea.example.test/attachments/release.exe',
);
await assert.rejects(
() => service.downloadReleaseAsset('Jens', 'ForgeFlow', null, 412),
@@ -127,6 +141,21 @@ test('downloads release assets through the release-scoped Gitea endpoint', async
);
});
test('uses a release-provided browser download URL without requesting metadata again', async () => {
const service = new GiteaService(makeStore());
service.request = async () => { throw new Error('metadata lookup should not run'); };
let requested = '';
service.downloadAuthenticated = async (pathname) => {
requested = pathname;
return Buffer.from('asset');
};
const asset = await service.downloadReleaseAsset('Jens', 'ForgeFlow', 107, 412, {
downloadUrl: 'https://gitea.example.test/attachments/direct.exe',
});
assert.equal(asset.toString(), 'asset');
assert.equal(requested, 'https://gitea.example.test/attachments/direct.exe');
});
test('creates conservative default branch protection rules', async () => {
const service = new GiteaService(makeStore());
let request = null;
+63 -1
View File
@@ -242,6 +242,11 @@ test("release publisher verifies Gitea and bootstraps the installed updater serv
assert.match(script, /package-lock\.json/);
assert.match(script, /non-reproducible update/);
assert.match(script, /npm run check/);
assert.match(script, /npm run dist:win/);
assert.match(script, /npm run release:binary/);
assert.match(script, /SkipBinaryRelease/);
assert.match(script, /ForgeFlow-Setup-\$version-win-x64\.exe/);
assert.match(script, /ForgeFlow-Portable-\$version-win-x64\.exe/);
assert.match(script, /git ls-remote origin/);
assert.match(script, /publishedCommit -ne \$localCommit/);
assert.match(script, /scripts\\apply-source-update\.ps1/);
@@ -255,6 +260,57 @@ test("release publisher verifies Gitea and bootstraps the installed updater serv
assert.doesNotMatch(script, /Copy-Item[^\n]+package\.json/);
});
test("one-click Windows release wrapper invokes the atomic publisher", async () => {
const script = await readFile(
new URL("../PUBLISH-AND-ENABLE-UPDATE.cmd", import.meta.url),
"utf8",
);
assert.match(script, /ExecutionPolicy Bypass/);
assert.match(script, /Publish-ForgeFlow-Release\.ps1/);
assert.match(script, /older ForgeFlow updater can now install/);
assert.match(script, /exit \/b %forgeflowExitCode%/);
});
test("missing binary release recovery script builds the exact Gitea commit and uploads all assets", async () => {
const script = await readFile(
new URL("../Publish-Missing-Binary-Release.ps1", import.meta.url),
"utf8",
);
assert.match(script.trimStart(), /^param\(/);
assert.match(script, /git clone --branch \$Branch --single-branch/);
assert.match(script, /git -C \$clone ls-remote origin/);
assert.match(script, /npm ci --no-audit --no-fund/);
assert.match(script, /npm run check/);
assert.match(script, /npm run dist:win/);
assert.match(script, /npm run release:binary/);
assert.match(script, /FORGEFLOW_USER_DATA/);
assert.match(script, /ForgeFlow-Setup-\$version-win-x64\.exe/);
assert.match(script, /ForgeFlow-Portable-\$version-win-x64\.exe/);
});
test("binary publisher derives repository coordinates from ForgeFlow settings", async () => {
const script = await readFile(
new URL("../scripts/publish-binary-release.cjs", import.meta.url),
"utf8",
);
assert.match(script, /config\.updates\?\.owner/);
assert.match(script, /config\.updates\?\.repo/);
assert.match(script, /config\.updates\?\.branch/);
assert.match(script, /encodeURIComponent\(owner\)/);
assert.match(script, /encodeURIComponent\(repo\)/);
assert.doesNotMatch(script, /\/repos\/Jens\/ForgeFlow\/releases/);
});
test("packaged updater passes Gitea browser download URLs to the asset downloader", async () => {
const source = await readFile(
new URL("../src/main/update-service.cjs", import.meta.url),
"utf8",
);
assert.match(source, /downloadUrl: asset\.browser_download_url/);
assert.match(source, /downloadUrl: checksumAsset\.browser_download_url/);
assert.match(source, /RELEASE_ASSET_METADATA_RECEIVED/);
});
test("PowerShell helper replaces an existing launching status with a Windows-safe file API", async () => {
const script = await readFile(
new URL("../scripts/apply-source-update.ps1", import.meta.url),
@@ -354,8 +410,14 @@ test("packaged updater downloads only a published checksum-matched Windows asset
],
};
},
async downloadReleaseAsset(_owner, _repo, releaseId, assetId) {
async downloadReleaseAsset(_owner, _repo, releaseId, assetId, options) {
assert.equal(releaseId, 82);
assert.equal(
options.downloadUrl,
assetId === 42
? "http://wrong-origin.test/checksum"
: "http://wrong-origin.test/setup",
);
return assetId === 42 ? Buffer.from(`${sha256} ${assetName}\n`) : binary;
},
};