UmbrelApps: community app store whatsnext

Electrum Gate, Evolu Relay en Atreides Assets, met de image-recepten in tools/ en de tests in tests/. Begonnen zonder voorgeschiedenis op 09-10-2026.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HarmenandClaude Opus 5.5 committed 2026-10-09 10:40:25 +02:00
commit 85d85a1295
63 files changed
+13987

No files matched your search

+113
View File
@@ -0,0 +1,113 @@
// ═══════════════════════════════════════════════════════════════════════════════
// Toetst het herschrijven in tools/release-bump.mjs.
//
// Draaien: node tests/test_release_bump.mjs
//
// WAAROM DIT BESTAND ER IS. Dat script bestaat om één stille fout onmogelijk te
// maken: een OUDE digest onder een NIEUWE tag levert de oude image en er is niets
// dat dat meldt. Een script dat die fout zelf maakt is erger dan overtypen, want
// dan vertrouw je erop. Vandaar dat de vervanging hier op de niet-gelukkige paden
// getoetst wordt en niet alleen op het geval waarin alles klopt.
//
// De netwerkcontrole (hoort die digest bij die tag) staat hier NIET in: die vraagt
// het register en dat is geen toets maar een meting. Wat hier staat is wat zonder
// netwerk te bewijzen valt.
// ═══════════════════════════════════════════════════════════════════════════════
import assert from 'node:assert/strict';
import {
herschrijfImage, herschrijfVersie, huidigeAppVersie, kiesAppVersie, isHoger,
} from '../tools/release-bump.mjs';
const DIGEST = `sha256:${'a'.repeat(64)}`;
const OUD = `sha256:${'b'.repeat(64)}`;
function test(naam, fn) {
try {
fn();
console.log(` ok ${naam}`);
} catch (fout) {
console.log(` FOUT ${naam}`);
console.log(` ${fout.message}`);
process.exitCode = 1;
}
}
console.log('herschrijfImage');
test('vervangt de hele regel, dus de oude digest kan niet blijven staan', () => {
const compose = `services:\n server:\n image: sc.kamenier-hamer.nl/sysop/atreides-assets:0.1.0@${OUD}\n restart: on-failure\n`;
const { tekst, naam, aantal } = herschrijfImage(compose, '0.1.3', DIGEST);
assert.equal(naam, 'sc.kamenier-hamer.nl/sysop/atreides-assets');
assert.equal(aantal, 1);
assert.ok(tekst.includes(`atreides-assets:0.1.3@${DIGEST}`));
assert.ok(!tekst.includes(OUD), 'de oude digest staat er nog');
assert.ok(tekst.includes(' restart: on-failure'), 'de rest van het bestand is geraakt');
});
test('en houdt de inspringing aan die er stond', () => {
const compose = ` image: sc.kamenier-hamer.nl/sysop/x:0.1.0\n`;
assert.equal(herschrijfImage(compose, '0.2.0', DIGEST).tekst, ` image: sc.kamenier-hamer.nl/sysop/x:0.2.0@${DIGEST}\n`);
});
test('neemt twee containers uit hetzelfde image samen mee', () => {
const compose = ` a:\n image: sc.kamenier-hamer.nl/sysop/gate:0.1.0@${OUD}\n b:\n image: sc.kamenier-hamer.nl/sysop/gate:0.1.0@${OUD}\n`;
const { aantal, tekst } = herschrijfImage(compose, '0.1.1', DIGEST);
assert.equal(aantal, 2);
assert.equal(tekst.match(/0\.1\.1/g).length, 2);
});
test('laat een image van een ANDERE host met rust', () => {
const compose = ` db:\n image: postgres:16-alpine\n app:\n image: sc.kamenier-hamer.nl/sysop/relay:0.7.1\n`;
const { tekst, aantal } = herschrijfImage(compose, '0.7.2', DIGEST);
assert.equal(aantal, 1);
assert.ok(tekst.includes('image: postgres:16-alpine'), 'de vreemde image is meeverschoven');
});
test('weigert een compose zonder eigen image in plaats van er een bij te zetten', () => {
assert.throws(() => herschrijfImage(' db:\n image: postgres:16\n', '1.0.0', DIGEST), /geen image-regel/);
});
test('weigert twee verschillende eigen images, want dan is de bedoeling niet af te leiden', () => {
const compose = ` image: sc.kamenier-hamer.nl/sysop/a:0.1.0\n image: sc.kamenier-hamer.nl/sysop/b:0.1.0\n`;
assert.throws(() => herschrijfImage(compose, '0.2.0', DIGEST), /meerdere eigen images/);
});
test('weigert een digest die niet de vorm heeft, want dat is de plakfout die telt', () => {
const compose = ` image: sc.kamenier-hamer.nl/sysop/x:0.1.0\n`;
assert.throws(() => herschrijfImage(compose, '0.2.0', 'sha256:kort'), /digest heeft niet de vorm/);
assert.throws(() => herschrijfImage(compose, '0.2.0', 'a'.repeat(64)), /digest heeft niet de vorm/);
assert.throws(() => herschrijfImage(compose, 'v0.2.0', DIGEST), /versie heeft niet de vorm/);
});
console.log('de app-versie');
test('leest de huidige versie, met en zonder aanhalingstekens', () => {
assert.equal(huidigeAppVersie('id: x\nversion: "0.1.2"\nname: X\n'), '0.1.2');
assert.equal(huidigeAppVersie('version: 1.2.3\n'), '1.2.3');
});
test('vergelijkt per deel en niet als tekst', () => {
assert.equal(isHoger('0.10.0', '0.9.0'), true);
assert.equal(isHoger('0.9.0', '0.10.0'), false);
assert.equal(isHoger('1.0.0', '0.99.99'), true);
});
test('trekt gelijk als de image erboven ligt, en verhoogt anders de patch', () => {
assert.equal(kiesAppVersie('0.1.2', '0.1.3'), '0.1.3');
assert.equal(kiesAppVersie('0.2.0', '0.1.3'), '0.2.1');
// Gelijk is ook een verhoging waard: zonder verhoging rolt umbrelOS niets uit.
assert.equal(kiesAppVersie('0.1.3', '0.1.3'), '0.1.4');
});
test('schrijft de versie met aanhalingstekens terug en laat de rest staan', () => {
const manifest = 'id: x\nversion: "0.1.2"\nname: X\n';
assert.equal(herschrijfVersie(manifest, '0.1.3'), 'id: x\nversion: "0.1.3"\nname: X\n');
});
test('weigert een manifest zonder versie in plaats van er een bij te zetten', () => {
assert.throws(() => herschrijfVersie('id: x\nname: X\n', '0.1.3'), /geen `version:`/);
assert.throws(() => huidigeAppVersie('id: x\n'), /geen `version:`/);
});
if (process.exitCode) console.log('\nER ZIJN FOUTEN');
else console.log('\nalles goed');