Ship the Bare ELF in the release and stop baking host paths into the service.
Rolling release / release (push) Failing after 6m40s
Rolling release / release (push) Failing after 6m40s
The rolling bundle already contains the runtime binary. The installer now starts that file through a relative launcher, and the checkout unit is no longer packed for other users. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -31,6 +31,7 @@ jobs:
|
|||||||
mkdir -p /tmp/jarvis-ci-models
|
mkdir -p /tmp/jarvis-ci-models
|
||||||
printf '%s\n' '{"cacheDirectory":"/tmp/jarvis-ci-models"}' > "$QVAC_CONFIG_PATH"
|
printf '%s\n' '{"cacheDirectory":"/tmp/jarvis-ci-models"}' > "$QVAC_CONFIG_PATH"
|
||||||
npm run package
|
npm run package
|
||||||
|
tar -tzf dist/jarvis-qvac-bare-linux-*.tar.gz | grep -E 'node_modules/bare-runtime-linux-.*/bin/bare$'
|
||||||
- name: Publish rolling prerelease to Gitea
|
- name: Publish rolling prerelease to Gitea
|
||||||
env:
|
env:
|
||||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||||
|
|||||||
@@ -40,10 +40,11 @@ npm run bare:smoke
|
|||||||
npm run package:bare
|
npm run package:bare
|
||||||
```
|
```
|
||||||
|
|
||||||
The installer executes `node_modules/bare-runtime-linux-*/bin/bare` directly.
|
The installer requires `node_modules/bare-runtime-linux-*/bin/bare` inside the
|
||||||
The `node_modules/.bin/bare` convenience script is a Node launcher and is not
|
installed tree. It does not fall back to a `bare` binary on `PATH`. The user
|
||||||
used by the service. The generated systemd unit therefore has no Node
|
unit starts `%h/.local/share/jarvis-qvac/packaging/jarvisd-launch.sh`, which
|
||||||
executable in its `ExecStart` line.
|
resolves that ELF relative to the install. The unit does not contain a
|
||||||
|
machine path, and the checkout unit under `systemd/user/` is not shipped.
|
||||||
|
|
||||||
GPU policy remains strict. The Bare QVAC engine must report a visible GPU and
|
GPU policy remains strict. The Bare QVAC engine must report a visible GPU and
|
||||||
the master load path passes `device: "gpu"`, full GPU layer offload, and GPU
|
the master load path passes `device: "gpu"`, full GPU layer offload, and GPU
|
||||||
|
|||||||
+4
-5
@@ -50,11 +50,10 @@ journalctl --user -u jarvisd.service -f
|
|||||||
```
|
```
|
||||||
|
|
||||||
The unit at `packaging/jarvisd.service` (installed to
|
The unit at `packaging/jarvisd.service` (installed to
|
||||||
`~/.config/systemd/user/jarvisd.service`) starts Bare on
|
`~/.config/systemd/user/jarvisd.service`) starts the bundled Bare ELF through
|
||||||
`daemon/bare-entry.js` with working directory `~/.local/share/jarvis-qvac` and
|
`packaging/jarvisd-launch.sh`. It uses `%h` for the install directory and does
|
||||||
`QVAC_CONFIG_PATH=~/.config/jarvis/qvac.config.json`. The repository
|
not record a host path. The file `systemd/user/jarvisd.service` is a checkout
|
||||||
development unit uses the checkout path; use the packaged unit when testing
|
helper only and is not included in the release archive.
|
||||||
installation behavior.
|
|
||||||
|
|
||||||
Restart after daemon code changes:
|
Restart after daemon code changes:
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ mkdir -p "${OUT_DIR}"
|
|||||||
BUNDLE_DIR="${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}"
|
BUNDLE_DIR="${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}"
|
||||||
rm -rf "${BUNDLE_DIR}" "${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}.tar.gz"
|
rm -rf "${BUNDLE_DIR}" "${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}.tar.gz"
|
||||||
mkdir -p "${BUNDLE_DIR}"
|
mkdir -p "${BUNDLE_DIR}"
|
||||||
tar --exclude='.git' --exclude='./.agents' --exclude='./.codex' --exclude='./dist' --exclude='./vendor/agent-harness/node_modules' --exclude='*/__pycache__' --exclude='*.pyc' -cf - -C "${ROOT_DIR}" . | tar -xf - -C "${BUNDLE_DIR}"
|
# The checkout unit points at a developer tree and Node. Do not ship it.
|
||||||
|
tar --exclude='.git' --exclude='./.agents' --exclude='./.codex' --exclude='./dist' --exclude='./systemd' --exclude='./vendor/agent-harness/node_modules' --exclude='*/__pycache__' --exclude='*.pyc' -cf - -C "${ROOT_DIR}" . | tar -xf - -C "${BUNDLE_DIR}"
|
||||||
cp -a "${ROOT_DIR}/node_modules" "${BUNDLE_DIR}/"
|
cp -a "${ROOT_DIR}/node_modules" "${BUNDLE_DIR}/"
|
||||||
# QVAC publishes one package containing native prebuilds for every supported
|
# QVAC publishes one package containing native prebuilds for every supported
|
||||||
# platform. The rolling asset is architecture-specific: retain all Linux x64
|
# platform. The rolling asset is architecture-specific: retain all Linux x64
|
||||||
@@ -31,6 +32,18 @@ fi
|
|||||||
if [[ "${JARVIS_VERIFY_VOICE_MODELS:-0}" == "1" ]]; then
|
if [[ "${JARVIS_VERIFY_VOICE_MODELS:-0}" == "1" ]]; then
|
||||||
(cd "${BUNDLE_DIR}" && bash packaging/bare-launch.sh packaging/bare-run.js packaging/voice-model-smoke.js)
|
(cd "${BUNDLE_DIR}" && bash packaging/bare-launch.sh packaging/bare-run.js packaging/voice-model-smoke.js)
|
||||||
fi
|
fi
|
||||||
|
chmod 755 "${BUNDLE_DIR}/packaging/jarvisd-launch.sh" "${BUNDLE_DIR}/node_modules/bare-runtime-${PLATFORM}/bin/bare"
|
||||||
tar -C "${OUT_DIR}" -czf "${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}.tar.gz" "jarvis-qvac-bare-${PLATFORM}"
|
tar -C "${OUT_DIR}" -czf "${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}.tar.gz" "jarvis-qvac-bare-${PLATFORM}"
|
||||||
rm -rf "${BUNDLE_DIR}"
|
rm -rf "${BUNDLE_DIR}"
|
||||||
echo "${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}.tar.gz"
|
ARCHIVE="${OUT_DIR}/jarvis-qvac-bare-${PLATFORM}.tar.gz"
|
||||||
|
MEMBER="jarvis-qvac-bare-${PLATFORM}/node_modules/bare-runtime-${PLATFORM}/bin/bare"
|
||||||
|
if ! tar -tzf "${ARCHIVE}" | grep -qx "${MEMBER}"; then
|
||||||
|
echo "Release archive is missing the Bare runtime executable: ${MEMBER}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if tar -tzf "${ARCHIVE}" | grep -q 'systemd/user/jarvisd.service'; then
|
||||||
|
echo "Release archive still contains the developer systemd unit." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Packaged Bare runtime ${MEMBER}"
|
||||||
|
echo "${ARCHIVE}"
|
||||||
|
|||||||
@@ -114,14 +114,13 @@ case "$(uname -m)" in
|
|||||||
aarch64|arm64) BARE_BIN="${APP_DIR}/node_modules/bare-runtime-linux-arm64/bin/bare" ;;
|
aarch64|arm64) BARE_BIN="${APP_DIR}/node_modules/bare-runtime-linux-arm64/bin/bare" ;;
|
||||||
*) BARE_BIN="" ;;
|
*) BARE_BIN="" ;;
|
||||||
esac
|
esac
|
||||||
if [[ ! -x "${BARE_BIN}" ]]; then BARE_BIN="$(command -v bare || true)"; fi
|
|
||||||
if [[ -z "${BARE_BIN}" || ! -x "${BARE_BIN}" ]]; then
|
if [[ -z "${BARE_BIN}" || ! -x "${BARE_BIN}" ]]; then
|
||||||
log "error: no Bare runtime for $(uname -m) in the installed bundle"
|
log "error: no Bare runtime for $(uname -m) in the installed bundle"
|
||||||
echo "The installed bundle does not contain a Bare runtime for $(uname -m). Install the official rolling bundle or build it with npm run package:bare." >&2
|
echo "The installed bundle does not contain a Bare runtime for $(uname -m). Install the official rolling bundle. A Bare binary from PATH is not used." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
chmod 755 "${BARE_BIN}"
|
chmod 755 "${BARE_BIN}" "${ROOT_DIR}/packaging/jarvisd-launch.sh"
|
||||||
log "using Bare runtime ${BARE_BIN}"
|
log "using bundled Bare runtime ${BARE_BIN}"
|
||||||
NODE_BIN="$(command -v node || true)"
|
NODE_BIN="$(command -v node || true)"
|
||||||
if [[ -z "${NODE_BIN}" || ! -x "${NODE_BIN}" ]]; then
|
if [[ -z "${NODE_BIN}" || ! -x "${NODE_BIN}" ]]; then
|
||||||
NODE_BIN="$(bash -lc 'command -v node' 2>/dev/null || true)"
|
NODE_BIN="$(bash -lc 'command -v node' 2>/dev/null || true)"
|
||||||
@@ -193,7 +192,7 @@ activate_extension() {
|
|||||||
log "GNOME extension ${EXT_UUID} is installed but not active in this session; log out and back in, or run: gnome-extensions enable ${EXT_UUID}"
|
log "GNOME extension ${EXT_UUID} is installed but not active in this session; log out and back in, or run: gnome-extensions enable ${EXT_UUID}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
sed -e "s#__JARVIS_BARE__#${BARE_BIN}#" -e "s#__JARVIS_NODE__#${NODE_BIN}#" "${ROOT_DIR}/packaging/jarvisd.service" > "${HOME}/.config/systemd/user/jarvisd.service"
|
sed -e "s#__JARVIS_NODE__#${NODE_BIN}#" "${ROOT_DIR}/packaging/jarvisd.service" > "${HOME}/.config/systemd/user/jarvisd.service"
|
||||||
log "wrote ${HOME}/.config/systemd/user/jarvisd.service"
|
log "wrote ${HOME}/.config/systemd/user/jarvisd.service"
|
||||||
DBUS_DIR="${XDG_DATA_HOME:-${HOME}/.local/share}/dbus-1/services"
|
DBUS_DIR="${XDG_DATA_HOME:-${HOME}/.local/share}/dbus-1/services"
|
||||||
mkdir -p "${DBUS_DIR}"
|
mkdir -p "${DBUS_DIR}"
|
||||||
|
|||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Start the Bare ELF shipped with this install. Never use a bare from PATH.
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64) BIN="${ROOT}/node_modules/bare-runtime-linux-x64/bin/bare" ;;
|
||||||
|
aarch64|arm64) BIN="${ROOT}/node_modules/bare-runtime-linux-arm64/bin/bare" ;;
|
||||||
|
*) echo "Unsupported architecture: $(uname -m)" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
if [[ ! -x "${BIN}" ]]; then
|
||||||
|
echo "This Jarvis install has no Bare runtime at ${BIN}." >&2
|
||||||
|
echo "Install the official rolling bundle. A Bare binary from PATH is not used." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec "${BIN}" "$@"
|
||||||
@@ -7,7 +7,7 @@ PartOf=graphical-session.target
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=%h/.local/share/jarvis-qvac
|
WorkingDirectory=%h/.local/share/jarvis-qvac
|
||||||
ExecStart=__JARVIS_BARE__ %h/.local/share/jarvis-qvac/daemon/bare-entry.js
|
ExecStart=%h/.local/share/jarvis-qvac/packaging/jarvisd-launch.sh %h/.local/share/jarvis-qvac/daemon/bare-entry.js
|
||||||
Environment=QVAC_CONFIG_PATH=%h/.config/jarvis/qvac.config.json
|
Environment=QVAC_CONFIG_PATH=%h/.config/jarvis/qvac.config.json
|
||||||
Environment=JARVIS_GPU_REQUIRED=1
|
Environment=JARVIS_GPU_REQUIRED=1
|
||||||
Environment=JARVIS_QVAC_OWNER=jarvisd
|
Environment=JARVIS_QVAC_OWNER=jarvisd
|
||||||
|
|||||||
@@ -32,8 +32,15 @@ created="$(curl -fsS -X POST "${AUTH[@]}" "${JSON[@]}" "${API}/releases" --data
|
|||||||
release_id="$(jq -r '.id // empty' <<<"${created}")"
|
release_id="$(jq -r '.id // empty' <<<"${created}")"
|
||||||
test -n "${release_id}"
|
test -n "${release_id}"
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
bare_assets=(dist/jarvis-qvac-bare-*.tar.gz)
|
||||||
|
if (( ${#bare_assets[@]} == 0 )); then
|
||||||
|
echo "Refusing to publish: the Bare runtime bundle is missing." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shopt -u nullglob
|
||||||
for asset in dist/jarvis-qvac_*.deb dist/jarvis-qvac-extension.zip dist/jarvis-qvac-bare-*.tar.gz dist/SHA256SUMS; do
|
for asset in dist/jarvis-qvac_*.deb dist/jarvis-qvac-extension.zip dist/jarvis-qvac-bare-*.tar.gz dist/SHA256SUMS; do
|
||||||
[[ -f "${asset}" ]] || continue
|
[[ -f "${asset}" ]] || { echo "Refusing to publish: missing ${asset}" >&2; exit 1; }
|
||||||
curl -fsS -X POST "${AUTH[@]}" \
|
curl -fsS -X POST "${AUTH[@]}" \
|
||||||
"${API}/releases/${release_id}/assets?name=$(basename "${asset}")" \
|
"${API}/releases/${release_id}/assets?name=$(basename "${asset}")" \
|
||||||
-F "attachment=@${asset}" >/dev/null
|
-F "attachment=@${asset}" >/dev/null
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ test('install.sh replaces leftover files from an older version and keeps config'
|
|||||||
await mkdir(bin, { recursive: true });
|
await mkdir(bin, { recursive: true });
|
||||||
await cp(path.join(repo, 'packaging/install.sh'), path.join(root, 'packaging/install.sh'));
|
await cp(path.join(repo, 'packaging/install.sh'), path.join(root, 'packaging/install.sh'));
|
||||||
await cp(path.join(repo, 'packaging/jarvisd.service'), path.join(root, 'packaging/jarvisd.service'));
|
await cp(path.join(repo, 'packaging/jarvisd.service'), path.join(root, 'packaging/jarvisd.service'));
|
||||||
|
await cp(path.join(repo, 'packaging/jarvisd-launch.sh'), path.join(root, 'packaging/jarvisd-launch.sh'));
|
||||||
await cp(path.join(repo, 'packaging/qvac.config.template.json'), path.join(root, 'packaging/qvac.config.template.json'));
|
await cp(path.join(repo, 'packaging/qvac.config.template.json'), path.join(root, 'packaging/qvac.config.template.json'));
|
||||||
await cp(path.join(repo, 'apps/gnome-extension/[email protected]'), path.join(root, 'apps/gnome-extension/[email protected]'), { recursive: true });
|
await cp(path.join(repo, 'apps/gnome-extension/[email protected]'), path.join(root, 'apps/gnome-extension/[email protected]'), { recursive: true });
|
||||||
await writeFile(path.join(root, 'node_modules', bareName, 'bin', 'bare'), '#!/bin/sh\nexit 0\n');
|
await writeFile(path.join(root, 'node_modules', bareName, 'bin', 'bare'), '#!/bin/sh\nexit 0\n');
|
||||||
@@ -108,7 +109,9 @@ exit 0
|
|||||||
assert.equal(await readFile(path.join(appDir, 'daemon-marker'), 'utf8'), 'new-tree\n');
|
assert.equal(await readFile(path.join(appDir, 'daemon-marker'), 'utf8'), 'new-tree\n');
|
||||||
assert.equal(await readFile(path.join(configDir, 'config.json'), 'utf8'), '{"wakePhrase":"hey jarvis","ttsEnabled":true}\n');
|
assert.equal(await readFile(path.join(configDir, 'config.json'), 'utf8'), '{"wakePhrase":"hey jarvis","ttsEnabled":true}\n');
|
||||||
const unit = await readFile(path.join(home, '.config/systemd/user/jarvisd.service'), 'utf8');
|
const unit = await readFile(path.join(home, '.config/systemd/user/jarvisd.service'), 'utf8');
|
||||||
assert.match(unit, /bare-runtime-linux/);
|
const execStart = unit.split('\n').find((line) => line.startsWith('ExecStart='));
|
||||||
|
assert.match(execStart, /ExecStart=%h\/\.local\/share\/jarvis-qvac\/packaging\/jarvisd-launch\.sh/);
|
||||||
|
assert.doesNotMatch(execStart, /\/home\/|dev\/jarvis|__JARVIS_BARE__|\/usr\/bin\/node/);
|
||||||
assert.match(unit, /WantedBy=default\.target/);
|
assert.match(unit, /WantedBy=default\.target/);
|
||||||
assert.match(unit, /Restart=always/);
|
assert.match(unit, /Restart=always/);
|
||||||
assert.doesNotMatch(unit, /ExecStart=\/usr\/bin\/node/);
|
assert.doesNotMatch(unit, /ExecStart=\/usr\/bin\/node/);
|
||||||
@@ -152,6 +155,7 @@ test('install.sh seeds default config when missing and does not require first-ru
|
|||||||
await mkdir(bin, { recursive: true });
|
await mkdir(bin, { recursive: true });
|
||||||
await cp(path.join(repo, 'packaging/install.sh'), path.join(root, 'packaging/install.sh'));
|
await cp(path.join(repo, 'packaging/install.sh'), path.join(root, 'packaging/install.sh'));
|
||||||
await cp(path.join(repo, 'packaging/jarvisd.service'), path.join(root, 'packaging/jarvisd.service'));
|
await cp(path.join(repo, 'packaging/jarvisd.service'), path.join(root, 'packaging/jarvisd.service'));
|
||||||
|
await cp(path.join(repo, 'packaging/jarvisd-launch.sh'), path.join(root, 'packaging/jarvisd-launch.sh'));
|
||||||
await cp(path.join(repo, 'packaging/qvac.config.template.json'), path.join(root, 'packaging/qvac.config.template.json'));
|
await cp(path.join(repo, 'packaging/qvac.config.template.json'), path.join(root, 'packaging/qvac.config.template.json'));
|
||||||
await cp(path.join(repo, 'apps/gnome-extension/[email protected]'), path.join(root, 'apps/gnome-extension/[email protected]'), { recursive: true });
|
await cp(path.join(repo, 'apps/gnome-extension/[email protected]'), path.join(root, 'apps/gnome-extension/[email protected]'), { recursive: true });
|
||||||
await writeFile(path.join(root, 'node_modules', bareName, 'bin', 'bare'), '#!/bin/sh\nexit 0\n');
|
await writeFile(path.join(root, 'node_modules', bareName, 'bin', 'bare'), '#!/bin/sh\nexit 0\n');
|
||||||
|
|||||||
Reference in New Issue
Block a user