Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ node_modules
.claude
.omc
coverage
dist
debian
packaging
scripts
tests
*.md
.env*
Expand Down
20 changes: 12 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
# LINBO Patchless — example runtime configuration
#
# Production: copy to /etc/linbo-patchless/env, keep it root-owned and mode 0640.
# install.sh creates this file, the API key, SSH key, and host fingerprint safely.
# Installation creates this file, the SSH key, and host fingerprint safely.

# HTTP server
# HTTP server. The Debian configurator replaces these safe template defaults
# on a fresh linuxmuster installation only when it can identify one private,
# locally assigned addc server address unambiguously.
PATCHLESS_HOST=127.0.0.1
# Installer acknowledgement only; setting this true does not add TLS.
# Explicit operator acknowledgement only; setting this true does not add TLS.
PATCHLESS_ALLOW_PLAINTEXT_REMOTE=false
PATCHLESS_PORT=3001
NODE_ENV=production

# Host header(s) accepted for /api behind a reverse proxy. Loopback hosts are
# always accepted. A deliberate direct interface bind must list its exposed
# name or address here as well. Comma-separate names; do not use '*'.
# PATCHLESS_ALLOWED_HOSTS=linbo-drivers.example.internal

# Logging: trace, debug, info, warn, error, fatal
LOG_LEVEL=info
# LOG_PRETTY=false

# Authentication. Prefer the root-managed file; do not commit a raw key.
PATCHLESS_API_KEY_FILE=/etc/linbo-patchless/api-key
# PATCHLESS_API_KEY=

# Same-origin is the secure default. Set only when a separate UI origin is used.
# Same-origin is the secure default. Set only when a separate UI origin is used;
# configured origins are also accepted as API Host names.
# CORS_ORIGIN=https://linbo-admin.example.org
# Configure only behind a trusted reverse proxy; use its explicit hop count.
# TRUST_PROXY=1
Expand Down
111 changes: 111 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,114 @@ jobs:
with:
name: coverage
path: coverage/

package:
needs: test
runs-on: ubuntu-latest
container: ubuntu:26.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- name: Install package build dependencies
run: |
apt-get update
apt-get install --yes --no-install-recommends \
build-essential debhelper devscripts lintian nodejs npm rsync

- name: Validate Debian source package
run: dpkg-source --build .

- name: Build Debian package
run: ./scripts/build-deb.sh

- name: Inspect Debian package
run: |
package="$(find dist -maxdepth 1 -type f -name '*.deb' -print -quit)"
test -n "$package"
dpkg-deb --info "$package"
dpkg-deb --contents "$package"
lintian --fail-on error "$package"

control_dir="$(mktemp -d)"
package_root="$(mktemp -d)"
dpkg-deb --control "$package" "$control_dir"
dpkg-deb --extract "$package" "$package_root"
sh -n "$control_dir/postinst"
sh -n "$control_dir/postrm"

test -f "$package_root/usr/lib/linbo-patchless/src/index.js"
test ! -e "$package_root/usr/lib/linbo-patchless/package-lock.json"
node -e '
const pkg = require(process.argv[1]);
if (pkg.devDependencies || pkg.scripts) process.exit(1);
' "$package_root/usr/lib/linbo-patchless/package.json"
find "$package_root/usr/share/doc/linbo-patchless" \
-name 'THIRD-PARTY-NOTICES.txt*' -print -quit | grep -q .
if find "$package_root/usr/lib/linbo-patchless" \
-type f -name '*.node' -print -quit | grep -q .; then
echo 'Architecture-all package contains a native Node module' >&2
exit 1
fi
if find "$package_root/usr/lib/linbo-patchless/node_modules" -type f \
\( -name '.eslintrc' -o -name '.eslintrc.*' -o -name '.eslintignore' \
-o -name '.npmignore' -o -name '.gitattributes' -o -name '.gitignore' \
-o -name '.nycrc' -o -name '.nycrc.*' -o -name '.travis.yml' \
-o -name '.coveralls.yml' \
-o -name '.prettierignore' -o -name '.prettierrc' -o -name '.prettierrc.*' \
-o -name 'eslint.config.js' -o -name 'eslint.config.mjs' \
-o -name 'tsconfig.json' -o -name 'Jenkinsfile' -o -name 'Makefile' \) \
-print -quit | grep -q .; then
echo 'Package contains npm development metadata rejected by Lintian' >&2
exit 1
fi
if find "$package_root/usr/lib/linbo-patchless/node_modules" -type d \
\( -iname test -o -iname tests -o -iname bench -o -iname benchmark \
-o -iname benchmarks -o -iname example -o -iname examples \
-o -iname fixture -o -iname fixtures -o -iname help \
-o -iname doc -o -iname docs \
-o -name '.*' \) \
-print -quit | grep -q .; then
echo 'Package contains npm tests, benchmarks, or CI metadata' >&2
exit 1
fi
if find "$package_root/usr/lib/linbo-patchless/node_modules" -type f \
\( -iname 'bench.js' -o -iname 'benchmark.js' -o -iname '*.bench.js' \
-o -iname 'test.js' -o -iname 'test-*.js' -o -iname '*.test.js' \
-o -iname '*-test.js' -o -iname 'tests.js' -o -iname '*.test-d.ts' \
-o -iname 'example.js' -o -iname 'example-*.js' -o -iname '*-example.js' \
-o -iname '*.d.ts' -o -iname '*.d.cts' -o -iname '*.d.mts' \
-o -iname '*.ts' -o -iname '*.cts' -o -iname '*.mts' -o -iname '*.map' \
-o -iname '*.gyp' -o -iname '*.gypi' -o -iname '*.c' -o -iname '*.cc' \
-o -iname '*.bat' -o -iname '*.exe' -o -iname '*.sh' \
-o -iname '*.png' -o -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.gif' \
-o -iname '*.ico' -o -iname '*.svg' -o -name 'CNAME' -o -name '.*' \
-o -name 'id_rsa*' \
-o -name 'id_dsa*' -o -name 'id_ecdsa*' -o -name 'id_ed25519*' \
-o -name '*.ppk' -o -name '*_key.pem' \) \
-print -quit | grep -q .; then
echo 'Package contains npm benchmark files or private test keys' >&2
exit 1
fi
if find "$package_root/usr/lib/linbo-patchless/node_modules" -type f \
\( -iname '*.md' -o -iname '*.markdown' \) \
! -iname 'license*' ! -iname 'copying*' ! -iname 'notice*' \
-print -quit | grep -q .; then
echo 'Package contains non-license npm documentation' >&2
exit 1
fi
test ! -e "$package_root/usr/lib/linbo-patchless/node_modules/.bin"
test ! -e "$package_root/usr/lib/linbo-patchless/node_modules/mime/src/build.js"
test ! -e "$package_root/usr/lib/linbo-patchless/node_modules/pino-pretty/coverage-map.js"
test ! -e "$package_root/usr/lib/linbo-patchless/node_modules/pino/index.html"
node scripts/sanitize-production-manifests.js \
"$package_root/usr/lib/linbo-patchless/node_modules" --check
node -e 'require(process.argv[1]); require(process.argv[2])' \
"$package_root/usr/lib/linbo-patchless/src/index.js" \
"$package_root/usr/lib/linbo-patchless/node_modules/ssh2"

- uses: actions/upload-artifact@v4
with:
name: linbo-patchless-deb
path: dist/*.deb
if-no-files-found: error
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ node_modules/
!.env.example
*.log
coverage/
dist/
debian/.debhelper/
debian/.node-build/
debian/linbo-patchless/
debian/debhelper-build-stamp
debian/files
*.buildinfo
*.changes
.DS_Store
.claude/settings.local.json
.omc/
Loading
Loading