Template tests / tests (pull_request) Failing after 31s
Phase 3 of the improvement plan (PR 8 of the sequence): the apt/X11 packaging half of Linux support, in separate Linux-specific files. Replaces the old scripts/package-linux.sh, which the audit flagged as "not production packaging" (it copied the whole dev node_modules — including vulnerable build deps — plus docs/prompts/examples/audit files, hardcoded amd64, declared only xinput, lacked desktop/icon/MIME integration, and could build without node_modules). Production builder (packaging/linux/debian/package.sh): - Stages ONLY runtime files: app code, a fixed Electron runtime, and the production npm deps (enumerated via npm ls --omit=dev). Never copies the development node_modules; guards against electron-builder/app-builder-lib leaking in. Fails if node_modules is absent instead of shipping an unusable artifact. - Detects architecture (dpkg --print-architecture, x64/arm64) rather than hardcoding amd64. Generates DEBIAN/control from control.in with proper runtime Depends, real maintainer, and homepage. - Installs a desktop entry, hicolor icons (16–512), .sfgz/.sfglt MIME registration, the launcher, and the license. postinst makes chrome-sandbox setuid and refreshes desktop/MIME/icon caches; postrm cleans them. - Emits a .deb, a portable tarball that now INCLUDES /usr/bin/stepforge (the old tarball omitted it), and a sha256 sums file. Launcher (packaging/linux/common/launcher.sh): - Runs sandboxed; prefers the user-namespace sandbox, accepts a root-owned setuid helper, and otherwise refuses to launch with an actionable message. --no-sandbox requires an explicit STEPFORGE_ALLOW_NO_SANDBOX opt-in. Never installs anything at runtime. Setup (separate build vs runtime, apt only): - scripts/linux/apt/install-runtime-deps.sh (Chromium/Electron libs, X11 tools, portal/PipeWire) and install-build-deps.sh (dpkg-dev, fakeroot, xvfb). Runtime script installs no build tools. Assets: original StepForge icon — packaging/assets/stepforge.svg plus a generator (scripts/make-icons.js) that renders the PNG set with the repo's own rasterizer/PNG writer (no third-party art). npm run icons regenerates them. Wiring: package.json gains package:linux:deb / package:linux:rpm / icons; build-release.sh uses the production builder and requires node_modules; README points at the apt/dnf guides. Tests: tests/unit/packaging-linux.test.js (structural: files present in their separate locations, old script gone, valid desktop entry, templated arch + runtime Depends, launcher gates --no-sandbox, builder requires node_modules and guards dev-dep leaks, apt build/runtime dep separation, original icon set generates a valid PNG) runs in the normal suite; tests/integration/linux/package-deb.test.sh builds a real .deb and asserts the right files present and the dev tree / build tooling / app docs absent (honest skip only when dpkg-deb/node_modules are genuinely missing). Verified locally: 276 unit tests pass; the integration test builds and validates stepforge_0.3.2_amd64.deb; build-release E2E passes with the new production package. Co-Authored-By: Claude Fable 5 <[email protected]>
70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
// Generate the StepForge PNG icon set from original geometry using the repo's
|
|
// own rasterizer + PNG writer (no external image tooling or third-party art).
|
|
// Mirrors packaging/assets/stepforge.svg. Output: packaging/assets/icons/.
|
|
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const { createImage, fillRect, fillOval } = require('../core/raster');
|
|
const { encodePng } = require('../core/png');
|
|
|
|
const OUT_DIR = path.join(__dirname, '..', 'packaging', 'assets', 'icons');
|
|
const SIZES = [16, 32, 48, 64, 128, 256, 512];
|
|
|
|
const BG_TOP = [37, 99, 235, 255];
|
|
const BG_BOTTOM = [30, 58, 138, 255];
|
|
const WHITE = [255, 255, 255, 255];
|
|
const SPARK = [250, 204, 21, 255];
|
|
|
|
function lerp(a, b, t) {
|
|
return [
|
|
Math.round(a[0] + (b[0] - a[0]) * t),
|
|
Math.round(a[1] + (b[1] - a[1]) * t),
|
|
Math.round(a[2] + (b[2] - a[2]) * t),
|
|
255,
|
|
];
|
|
}
|
|
|
|
function renderIcon(size) {
|
|
const img = createImage(size, size, [0, 0, 0, 0]);
|
|
const s = size / 256; // scale from the 256px reference design
|
|
|
|
// Rounded-square background approximated by a vertical gradient fill.
|
|
for (let y = 0; y < size; y += 1) {
|
|
fillRect(img, 0, y, size, 1, lerp(BG_TOP, BG_BOTTOM, y / size));
|
|
}
|
|
|
|
// Three ascending steps (x, y, w, h in reference px).
|
|
const steps = [
|
|
[52, 150, 52, 54],
|
|
[102, 116, 52, 88],
|
|
[152, 82, 52, 122],
|
|
];
|
|
for (const [x, y, w, h] of steps) {
|
|
fillRect(img, Math.round(x * s), Math.round(y * s), Math.round(w * s), Math.round(h * s), WHITE);
|
|
}
|
|
|
|
// Capture spark on the top step.
|
|
const r = Math.max(2, Math.round(16 * s));
|
|
fillOval(img, Math.round(178 * s - r), Math.round(60 * s - r), r * 2, r * 2, SPARK);
|
|
|
|
return img;
|
|
}
|
|
|
|
function main() {
|
|
fs.mkdirSync(OUT_DIR, { recursive: true });
|
|
for (const size of SIZES) {
|
|
const png = encodePng(renderIcon(size));
|
|
fs.writeFileSync(path.join(OUT_DIR, `stepforge-${size}.png`), png);
|
|
}
|
|
// A conventional default name for the desktop entry / hicolor 256px slot.
|
|
fs.copyFileSync(path.join(OUT_DIR, 'stepforge-256.png'), path.join(OUT_DIR, 'stepforge.png'));
|
|
console.log(`wrote ${SIZES.length + 1} icons to ${OUT_DIR}`);
|
|
}
|
|
|
|
if (require.main === module) main();
|
|
|
|
module.exports = { renderIcon, SIZES };
|