release: container images when a release is published; version 0.0.1

.github/workflows/release.yml runs on Gitea and on the GitHub mirror (release: published only)
and pushes selfphoneng-api and selfphoneng-asterisk to that forge's registry: ghcr.io with the
job token, the Gitea registry with secrets REGISTRY_USER + REGISTRY_TOKEN (Gitea's job token
can't push packages). Tags: the version, plus <major>.<minor> and latest unless it's a
pre-release. It stops unless the tag is v + package.json's version, and checks the images
before pushing.

Run locally with act_runner exec against a throwaway registry: v0.0.1 pushed 0.0.1, 0.0 and
latest for both images (VERSION 0.0.1, OCI labels, source archive selfphoneng-0.0.1/);
v9.9.9 failed at the version check.

Version 0.0.1 in all package.json files, CHANGELOG.md started, release steps in 08 §3.1.

Task: none (owner request, 2026-10-20)
This commit is contained in:
iamdoubz committed 2026-10-20 13:27:49 -05:00
1 parent f6a9b9a4b1
commit 9e5cbb18ac
9 files changed
+149 -6

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@selfphoneng/api",
"version": "0.0.0",
"version": "0.0.1",
"private": true,
"license": "AGPL-3.0-or-later",
"type": "module",
+8 -2
View File
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
// The System page (05 §2): status, the event log, and /api/about (08 §4, no sign-in).
import { readFileSync } from 'node:fs';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import type { LightMyRequestResponse } from 'fastify';
import type { TrunkLive } from '@selfphoneng/shared';
@@ -10,6 +11,11 @@ import { setSetting } from '../src/services/settings.ts';
import { hasTestDb } from './db.ts';
import { ADMIN, H, createTestApp } from './app.ts';
/** The root package.json's: what a release is tagged with (08 §3.1). */
const VERSION = JSON.parse(
readFileSync(new URL('../../../package.json', import.meta.url), 'utf8'),
).version;
/** The inserts are fire-and-forget: wait for them (a fixed sleep was too short under load). */
const rowsWhen = async (n: number) => {
for (let i = 0; i < 100; i++) {
@@ -39,7 +45,7 @@ describe.skipIf(!hasTestDb)('system status, event log, about', () => {
await setSetting(t.db, 'sip.tlsEnabled', true);
const s = (await get('/api/system/status')).json();
expect(s).toMatchObject({
version: '0.0.0',
version: VERSION,
hostname: expect.any(String),
companyName: expect.any(String),
publicIp: '203.0.113.5',
@@ -162,7 +168,7 @@ describe.skipIf(!hasTestDb)('system status, event log, about', () => {
const r = await get('/api/about', '');
expect(r.statusCode).toBe(200);
expect(r.json()).toEqual({
version: '0.0.0',
version: VERSION,
repoUrl: 'https://git.dou.bet/spng/selfphoneng',
source: null,
});