Compare commits

...
Author SHA1 Message Date
james.maes 7726835b3c Merge pull request 'ci: deploy through Argo CD Image Updater' (#83) from ci/deploy-via-image-updater into main
container / build (push) Successful in 10m54s
build / container (push) Successful in 10m54s
2026-11-07 21:43:25 +00:00
james.maesandClaude Opus 5.5 4141008a1b ci: deploy through Argo CD Image Updater
container / build (push) Successful in 6m11s
build / container (push) Successful in 6m11s
cluster-gitops #302 follows this repo's newest pushed image, so the build no longer needs a
GitOps write token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 21:02:40 +00:00
james.maes 0757348c5a Merge pull request 'ci: use shared ci-workflows container workflow' (#82) from ci/ci-workflows into main
container / build (push) Failing after 14m45s
build / container (push) Failing after 14m45s
2026-11-07 17:32:25 +00:00
james.maesandClaude Opus 5.5 c3aacfb711 ci: use shared ci-workflows container workflow
container / build (push) Successful in 17m44s
build / container (push) Successful in 17m44s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 16:59:04 +00:00
james.maes 12fc9beb23 Merge pull request 'ci: remove workflows that call the retired CI system' (#81) from retire/old-ci into main 2026-11-07 13:37:12 +00:00
james.maesandClaude Opus 5.5 55aad6e251 ci: remove workflows that call the retired CI system
Owner decision 2026-11-07: only KofTwentyTwo/ci-workflows remains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 13:31:12 +00:00
forge-recovery 9b59f7f6cd Merge pull request 'ci: use the shared Gitea release workflow' (#80) from ci/nuncio-shared-release-caller-20261102 into main
KofTwentyTwo/ci-policy: ci / fork-guard (push) Skipped
KofTwentyTwo/ci-policy: ci / go-0 (push) Skipped
KofTwentyTwo/ci-policy: ci / go-nix-1 (push) Skipped
KofTwentyTwo/ci-policy: ci / gradle-2 (push) Skipped
KofTwentyTwo/ci-policy: ci / gradle-3 (push) Skipped
KofTwentyTwo/ci-policy: ci / java-docker-4 (push) Skipped
KofTwentyTwo/ci-policy: ci / manifests-6 (push) Skipped
KofTwentyTwo/ci-policy: ci / java-maven-5 (push) Skipped
KofTwentyTwo/ci-policy: ci / nix-7 (push) Skipped
KofTwentyTwo/ci-policy: ci / python-9 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-10 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-11 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-12 (push) Skipped
KofTwentyTwo/ci-policy: ci / source-config-13 (push) Skipped
KofTwentyTwo/ci-policy: ci / source-config-14 (push) Skipped
KofTwentyTwo/ci-policy: ci / source-config-15 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-0 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-1 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-3 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-4 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-5 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-6 (push) Skipped
KofTwentyTwo/ci-policy: ci / image-build-7 (push) Skipped
KofTwentyTwo/ci-policy: ci / not-enrolled (push) Skipped
KofTwentyTwo/ci-policy: native / fork-deny (push) Skipped
KofTwentyTwo/ci-policy: native / build-macos-0 (push) Skipped
KofTwentyTwo/ci-policy: native / build-macos-1 (push) Skipped
KofTwentyTwo/ci-policy: native / build-macos-2 (push) Skipped
KofTwentyTwo/ci-policy: native / build-macos-3 (push) Skipped
KofTwentyTwo/ci-policy: native / build-windows-4 (push) Skipped
KofTwentyTwo/ci-policy: native / build-windows-7 (push) Skipped
KofTwentyTwo/ci-policy: native / dotnet-8 (push) Skipped
KofTwentyTwo/ci-policy: native / dotnet-9 (push) Skipped
KofTwentyTwo/ci-policy: native / dotnet-11 (push) Skipped
KofTwentyTwo/ci-policy: native / build-windows-5 (push) Skipped
KofTwentyTwo/ci-policy: native / build-windows-6 (push) Skipped
KofTwentyTwo/ci-policy: native / dotnet-10 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-12 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-13 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-14 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-15 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-16 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-17 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-18 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-19 (push) Skipped
Shared Node CI / secrets (push) Successful in 14s
KOF release (central) / baseline-website-backend (push) Skipped
KOF release (central) / build-website-backend (push) Skipped
KOF release (central) / baseline-website-frontend (push) Skipped
KOF release (central) / build-website-frontend (push) Skipped
KofTwentyTwo/ci-policy: Shared Node CI / secrets (push) Successful in 13s
KOF release (central) / baseline-investinginchester (push) Skipped
KOF release (central) / build-investinginchester (push) Skipped
KOF release (central) / baseline-theimpactbuilding (push) Skipped
KOF release (central) / build-theimpactbuilding (push) Skipped
KofTwentyTwo/ci-policy: native / native-result (push) Successful in 6s
Shared Node CI / verify (push) Successful in 2m38s
KofTwentyTwo/ci-policy: Shared Node CI / verify (push) Successful in 2m38s
Shared Node CI / gate (push) Successful in 11s
KofTwentyTwo/ci-policy: Shared Node CI / gate (push) Successful in 11s
KOF release (central) / baseline-nuncio-website (push) Successful in 2m53s
KofTwentyTwo/ci-policy: ci / node-8 (push) Successful in 2m51s
KofTwentyTwo/ci-policy: Shared image build CI / build (push) Successful in 9m25s
KofTwentyTwo/ci-policy: ci / image-build-2 (push) Successful in 9m25s
KofTwentyTwo/ci-policy: ci / ci-result (push) Successful in 4s
release / release (push) Successful in 1h16m22s
KOF release (central) / build-nuncio-website (push) Successful in 8m45s
2026-11-02 17:41:52 +00:00
forge-recoveryandCodex 05e65f904c ci: use the shared Gitea release workflow
KofTwentyTwo/ci-policy: Shared Node CI / verify (pull_request) Successful in 2m17s
KofTwentyTwo/ci-policy: Shared Node CI / gate (pull_request) Successful in 9s
KofTwentyTwo/ci-policy: ci / node-8 (pull_request) Successful in 2m31s
KofTwentyTwo/ci-policy: native / fork-deny (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-2 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-5 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-macos-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / build-windows-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-8 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-10 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-9 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / dotnet-11 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-12 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-13 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-14 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-15 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-16 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-17 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-18 (pull_request) Skipped
KofTwentyTwo/ci-policy: native / swift-19 (pull_request) Skipped
KofTwentyTwo/ci-policy: Shared Node CI / secrets (pull_request) Successful in 27s
KofTwentyTwo/ci-policy: native / native-result (pull_request) Successful in 6s
KofTwentyTwo/ci-policy: ci / fork-guard (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / go-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / go-nix-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / java-docker-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / manifests-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / gradle-2 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / gradle-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / java-maven-5 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / nix-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / python-9 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-14 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-10 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-11 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / rust-12 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-13 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / source-config-15 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-0 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-1 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-3 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-4 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-5 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-6 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / image-build-7 (pull_request) Skipped
KofTwentyTwo/ci-policy: ci / not-enrolled (pull_request) Skipped
KofTwentyTwo/ci-policy: Shared image build CI / build (pull_request) Successful in 8m31s
KofTwentyTwo/ci-policy: ci / image-build-2 (pull_request) Successful in 8m32s
KofTwentyTwo/ci-policy: ci / ci-result (pull_request) Successful in 5s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-02 17:20:40 +00:00
2e99a3b0a9 fix: patch and qualify the website container for local releases (#77)
* fix(deps): update next, postcss, sharp, js-yaml and nanoid for security advisories

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: qualify patched website container for local releases

Preserve the security update, align Next and lint versions, refresh compatible dependencies and Alpine runtime packages, and exercise application HTTP behavior.

Co-Authored-By: Codex <noreply@openai.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: James Maes <jmaes@dmdbrands.com>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 14:08:58 -05:00
james.maesandJames Maes 4f9fcaef0a fix(deps): resolve npm audit high-severity advisories + add audit CI step (#32)
* security(deps): resolve high-severity npm audit advisories via minimatch override

All 9 high-severity advisories stemmed from a single transitive chain:
eslint/eslint-config-next tooling depend on a vulnerable minimatch
(<=10.0.2) that pulls in brace-expansion <=5.0.7 (GHSA-mh99-v99m-4gvg,
DoS via unbounded expansion). These are dev/build-time only packages,
not shipped in the runtime image.

Bumping eslint itself would require a semver-major jump (9.x -> 10.x).
Instead, pin minimatch to ^10.0.3 via package.json overrides, which
drops the vulnerable brace-expansion dependency entirely (newer
minimatch uses @isaacs/brace-expansion). Verified npm audit reports 0
vulnerabilities and both npm run lint and npm run build still pass.

* ci(app): add non-blocking npm audit step to lint-and-build job

Surface high-severity advisories in CI logs without gating merges on
build-time dev-dependency findings a solo dev can triage async.

---------

Co-authored-by: James Maes <jmaes@dmdbrands.com>
2026-07-29 16:40:17 +00:00
6 changed files with 330 additions and 350 deletions

No files matched your search

+14
View File
@@ -0,0 +1,14 @@
name: build
on:
push:
jobs:
container:
uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/container.yaml@v1
secrets: inherit
with:
images: nuncio-website|Dockerfile
# The Dockerfile runs the install and build; nothing to run before it.
prebuild: 'true'
publish-branch: main
# Deploys: Argo CD Image Updater in cluster-gitops follows the newest image pushed from
# this branch, so CI needs no GitOps write token.
+4
View File
@@ -25,6 +25,10 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Audit dependencies (report-only)
run: npm audit --audit-level=high
continue-on-error: true
- name: Lint
run: npm run lint
+2 -1
View File
@@ -26,7 +26,8 @@ ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
RUN addgroup --system --gid 1001 nodejs && \
RUN apk upgrade --no-cache && \
addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# Strip build-time package-manager tooling inherited from the base image.
+236 -343
View File
File diff suppressed because it is too large. Load diff
+10 -6
View File
@@ -10,7 +10,8 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint src"
"lint": "eslint src",
"test": "node --test tests/http-smoke.test.mjs"
},
"dependencies": {
"@headlessui/react": "^2.2.6",
@@ -18,9 +19,9 @@
"@tailwindcss/typography": "^0.5.16",
"clsx": "^2.1.1",
"lucide-react": "^1.26.0",
"next": "^16.2.11",
"next": "16.4.3",
"next-themes": "^0.4.6",
"postcss": "^8.5.22",
"postcss": "^8.5.28",
"react": "19.2.8",
"react-dom": "19.2.4",
"tailwindcss": "^4.2.0",
@@ -31,10 +32,13 @@
"@types/react": "19.2.17",
"@types/react-dom": "19.2.3",
"eslint": "^9.39.5",
"eslint-config-next": "16.1.6"
"eslint-config-next": "16.4.3"
},
"overrides": {
"sharp": "^0.35.0",
"postcss": "$postcss"
"sharp": "^0.35.4",
"postcss": "$postcss",
"minimatch": "^10.0.3",
"js-yaml": "^4.3.2",
"nanoid": "^3.3.18"
}
}
+64
View File
@@ -0,0 +1,64 @@
import assert from 'node:assert/strict';
import { spawn } from 'node:child_process';
import { once } from 'node:events';
import { after, before, test } from 'node:test';
const base = process.env.SMOKE_BASE_URL || 'http://127.0.0.1:3210';
let server;
let logs = '';
before(async () => {
if (process.env.SMOKE_BASE_URL) return;
server = spawn(process.execPath, [
'node_modules/next/dist/bin/next', 'dev', '--webpack',
'--hostname', '127.0.0.1', '--port', '3210',
], { env: { ...process.env, NEXT_TELEMETRY_DISABLED: '1' }, stdio: ['ignore', 'pipe', 'pipe'] });
for (const stream of [server.stdout, server.stderr]) {
stream.on('data', chunk => { logs = (logs + chunk).slice(-8000); });
}
const deadline = Date.now() + 120_000;
while (Date.now() < deadline) {
if (server.exitCode !== null) throw new Error(`Next exited: ${logs}`);
try {
const response = await fetch(`${base}/icon.svg`, { signal: AbortSignal.timeout(2000) });
if (response.ok) return;
} catch {}
await new Promise(resolve => setTimeout(resolve, 500));
}
throw new Error(`Next did not become ready: ${logs}`);
}, { timeout: 125_000 });
after(async () => {
if (!server || server.exitCode !== null) return;
const exited = once(server, 'exit');
server.kill('SIGTERM');
const force = setTimeout(() => server.kill('SIGKILL'), 5000);
await exited;
clearTimeout(force);
});
for (const path of ['/', '/features', '/security', '/docs/account-setup']) {
test(`renders ${path} as a real application page`, { timeout: 120_000 }, async () => {
const response = await fetch(base + path, { signal: AbortSignal.timeout(110_000) });
assert.equal(response.status, 200, `${path}: ${logs}`);
assert.match(response.headers.get('content-type'), /text\/html/);
const html = await response.text();
assert.match(html, /<title>[^<]*Nuncio/);
assert.match(html, /<h1(?:\s|>)/);
assert.doesNotMatch(html, /Application error: a server-side exception/);
});
}
test('serves the brand icon as SVG', async () => {
const response = await fetch(base + '/icon.svg');
assert.equal(response.status, 200);
assert.match(response.headers.get('content-type'), /image\/svg\+xml/);
assert.match(await response.text(), /<svg/);
});
test('unknown routes return 404 rather than a misleading successful page', { timeout: 120_000 }, async () => {
const response = await fetch(base + '/qualification-route-that-does-not-exist', {
signal: AbortSignal.timeout(110_000),
});
assert.equal(response.status, 404);
});