4 Commits

Author SHA1 Message Date
josh a4b5c20993 Merge pull request 'fix: clear instance history on delete and import' (#37) from fix/delete-clears-history into dev
CI / test (push) Successful in 13s
CI / build-dev (push) Successful in 20s
Reviewed-on: #37
2026-03-28 15:38:15 -04:00
josh d17f364fc5 fix: clear instance history on delete and import
CI / test (pull_request) Successful in 14s
CI / build-dev (pull_request) Has been skipped
deleteInstance now removes history rows for that vmid before removing
the instance. importInstances clears all history before replacing
instances. Prevents stale history appearing when a vmid is reused.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 15:37:45 -04:00
josh 5f79eec3dd Merge pull request 'fix: categorize release notes into New Features / Bug Fixes, drop chores' (#36) from fix/release-notes-format into dev
CI / test (push) Successful in 12s
CI / build-dev (push) Successful in 20s
Reviewed-on: #36
2026-03-28 15:36:27 -04:00
josh ed98bb57c0 fix: categorize release notes into New Features / Bug Fixes, drop chores
CI / test (pull_request) Successful in 13s
CI / build-dev (pull_request) Has been skipped
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 15:35:53 -04:00
3 changed files with 45 additions and 2 deletions
+23 -1
View File
@@ -79,7 +79,29 @@ jobs:
- name: Create Gitea release - name: Create Gitea release
run: | run: |
python3 -c "import json,os; v=os.environ['VERSION']; img=os.environ['IMAGE']; notes=open('/tmp/release_notes.txt').read(); open('/tmp/release_body.json','w').write(json.dumps({'tag_name':'v'+v,'name':'Catalyst v'+v,'body':'### Changes\n\n'+notes+'\n\n### Image\n\n'+img+':'+v,'draft':False,'prerelease':False}))" cat > /tmp/make_release.py << 'PYEOF'
import json, os
v = os.environ['VERSION']
img = os.environ['IMAGE']
raw = open('/tmp/release_notes.txt').read().strip()
feats, fixes = [], []
for line in raw.splitlines():
msg = line.lstrip('- ').strip()
if msg.startswith('feat:'):
feats.append('- ' + msg[5:].strip())
elif msg.startswith('fix:'):
fixes.append('- ' + msg[4:].strip())
sections = []
if feats:
sections.append('### New Features\n\n' + '\n'.join(feats))
if fixes:
sections.append('### Bug Fixes\n\n' + '\n'.join(fixes))
notes = '\n\n'.join(sections) or '_No changes_'
body = notes + '\n\n### Image\n\n' + img + ':' + v
payload = {'tag_name': 'v'+v, 'name': 'Catalyst v'+v, 'body': body, 'draft': False, 'prerelease': False}
open('/tmp/release_body.json', 'w').write(json.dumps(payload))
PYEOF
python3 /tmp/make_release.py
curl -sf -X POST \ curl -sf -X POST \
-H "Authorization: token ${{ secrets.TOKEN }}" \ -H "Authorization: token ${{ secrets.TOKEN }}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
+3 -1
View File
@@ -151,11 +151,13 @@ export function updateInstance(vmid, data) {
} }
export function deleteInstance(vmid) { export function deleteInstance(vmid) {
return db.prepare('DELETE FROM instances WHERE vmid = ?').run(vmid); db.prepare('DELETE FROM instance_history WHERE vmid = ?').run(vmid);
db.prepare('DELETE FROM instances WHERE vmid = ?').run(vmid);
} }
export function importInstances(rows) { export function importInstances(rows) {
db.exec('BEGIN'); db.exec('BEGIN');
db.exec('DELETE FROM instance_history');
db.exec('DELETE FROM instances'); db.exec('DELETE FROM instances');
const insert = db.prepare(` const insert = db.prepare(`
INSERT INTO instances INSERT INTO instances
+19
View File
@@ -164,6 +164,19 @@ describe('deleteInstance', () => {
expect(getInstance(1)).toBeNull(); expect(getInstance(1)).toBeNull();
expect(getInstance(2)).not.toBeNull(); expect(getInstance(2)).not.toBeNull();
}); });
it('clears history for the deleted instance', () => {
createInstance({ ...base, name: 'a', vmid: 1 });
deleteInstance(1);
expect(getInstanceHistory(1)).toHaveLength(0);
});
it('does not clear history for other instances', () => {
createInstance({ ...base, name: 'a', vmid: 1 });
createInstance({ ...base, name: 'b', vmid: 2 });
deleteInstance(1);
expect(getInstanceHistory(2).length).toBeGreaterThan(0);
});
}); });
// ── importInstances ─────────────────────────────────────────────────────────── // ── importInstances ───────────────────────────────────────────────────────────
@@ -183,6 +196,12 @@ describe('importInstances', () => {
importInstances([]); importInstances([]);
expect(getInstances()).toEqual([]); expect(getInstances()).toEqual([]);
}); });
it('clears history for all replaced instances', () => {
createInstance({ ...base, name: 'old', vmid: 1 });
importInstances([{ ...base, name: 'new', vmid: 2 }]);
expect(getInstanceHistory(1)).toHaveLength(0);
});
}); });
// ── instance history ───────────────────────────────────────────────────────── // ── instance history ─────────────────────────────────────────────────────────