release: 1.3.4

This commit is contained in:
Qiufeng
2026-09-11 18:28:03 +08:00
parent 511fc5d785
commit 5afcd98ebd
21 changed files with 403 additions and 187 deletions
+6 -7
View File
@@ -1,9 +1,10 @@
#!/usr/bin/env bash
set -Eeuo pipefail
# Build a self-contained release on the target Linux architecture. Native
# addons (SQLite, Argon2 and image processing) must be installed on the same
# architecture/libc as the artifact.
# Build a production release on the target Linux architecture. Native addons
# (SQLite, Argon2 and image processing) must be installed on the same
# architecture/libc as the artifact. Node.js itself is deliberately managed
# by the installer outside each release so application updates stay small.
ROOT=$(cd -- "$(dirname -- "$0")/.." && pwd -P)
VERSION=${1:-}
OUT_DIR=${2:-$ROOT/release}
@@ -28,7 +29,7 @@ cd "$ROOT"
pnpm build
stage=$(mktemp -d)
trap 'rm -rf "$stage"' EXIT
mkdir -p "$stage/dist" "$stage/migrations" "$stage/bin" "$stage/scripts" "$stage/systemd" "$stage/runtime/bin"
mkdir -p "$stage/dist" "$stage/migrations" "$stage/bin" "$stage/scripts" "$stage/systemd"
# Copy only the production build outputs. In particular, do not carry a
# stale dist/web-next directory from a previous local preview build.
cp -a dist/server "$stage/dist/"
@@ -40,9 +41,7 @@ cp -a bin/. "$stage/bin/"
cp -a scripts/tallynote-update.sh scripts/tallynote-update-runner.sh "$stage/scripts/"
cp uninstall.sh "$stage/uninstall.sh"
cp -a systemd/tallynote.service systemd/tallynote-update.service systemd/tallynote-update.path systemd/tallynote.env.example "$stage/systemd/"
node_path=$(command -v node)
cp -L "$node_path" "$stage/runtime/bin/node"
chmod 755 "$stage/bin/tallynote" "$stage/bin/tallynote-admin-init" "$stage/scripts"/*.sh "$stage/runtime/bin/node" "$stage/uninstall.sh"
chmod 755 "$stage/bin/tallynote" "$stage/bin/tallynote-admin-init" "$stage/scripts"/*.sh "$stage/uninstall.sh"
# pnpm's default linker creates symlinks. A release archive is deliberately
# symlink-free so the installer can reject traversal links deterministically.
+3 -6
View File
@@ -5,7 +5,7 @@ set -Eeuo pipefail
# always generated; an Ed25519 detached signature is added when a signing key
# is supplied. The script remains separate from the workflow so operators can
# dry-run the exact same asset selection locally without exposing a key.
PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin
PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin
export PATH
umask 077
@@ -205,7 +205,6 @@ fi
command -v "$CURL_BIN" >/dev/null 2>&1 || die 'curl is required'
full_assets=()
update_assets=()
for file in "$ASSET_DIR"/*.tar.gz; do
[[ -f "$file" && ! -L "$file" ]] || continue
name=$(basename -- "$file")
@@ -214,13 +213,11 @@ for file in "$ASSET_DIR"/*.tar.gz; do
asset_version=${asset_version%%-linux-*}
[[ "$asset_version" == "${TAG#v}" ]] || die "release asset version does not match tag: $name"
if [[ "$name" =~ \.update-[a-f0-9]{64}\.tar\.gz$ ]]; then
update_assets+=("$file")
else
full_assets+=("$file")
die "不再发布轻量更新资产:$name;请只保留完整生产包"
fi
full_assets+=("$file")
done
assets=("${full_assets[@]}")
if ((${#update_assets[@]})); then assets+=("${update_assets[@]}"); fi
(( ${#assets[@]} > 0 )) || die 'no .tar.gz release asset found'
(( ${#full_assets[@]} > 0 )) || die 'no full release asset found'
+31 -17
View File
@@ -1,12 +1,14 @@
#!/usr/bin/env bash
set -Eeuo pipefail
PATH=/usr/sbin:/usr/bin:/sbin:/bin
PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin
export PATH
umask 077
PREFIX=${TALLYNOTE_INSTALL_PREFIX:-/opt/tallynote}
DATA_DIR=${TALLYNOTE_DATA_DIR:-/var/lib/tallynote}
CONFIG_DIR=${TALLYNOTE_CONFIG_DIR:-/etc/tallynote}
CONFIG_FILE="$CONFIG_DIR/tallynote.env"
REQUEST_FILE="$DATA_DIR/update-request.json"
CURRENT_LINK="$PREFIX/current"
STATE_FILE="$PREFIX/.update-state"
@@ -22,6 +24,27 @@ if [[ "$HEALTH_HOST" == *:* && "$HEALTH_HOST" != \[* ]]; then HEALTH_HOST="[$HEA
die() { printf 'tallynote update runner: %s\n' "$*" >&2; exit 1; }
node_is_usable() {
local candidate=$1 major
[[ -n "$candidate" && -x "$candidate" ]] || return 1
major=$("$candidate" -p 'process.versions.node.split(".")[0]' 2>/dev/null || true)
[[ "$major" =~ ^[0-9]+$ && "$major" -ge 24 ]]
}
resolve_node() {
local candidate=${TALLYNOTE_NODE:-}
if [[ -z "$candidate" && -f "$CONFIG_FILE" && ! -L "$CONFIG_FILE" ]]; then
candidate=$(sed -n 's/^TALLYNOTE_NODE=//p' "$CONFIG_FILE" | head -n 1)
fi
if node_is_usable "$candidate"; then
printf '%s' "$candidate"
return 0
fi
candidate=$(command -v node || true)
node_is_usable "$candidate" || return 1
printf '%s' "$candidate"
}
# The runner may exit during any of the checks below. Install its EXIT cleanup
# before doing privileged preflight so a partial invocation never leaves a
# heartbeat or lock behind.
@@ -202,9 +225,7 @@ if [[ "$request_operation" == download ]]; then
trap 'exit 143' TERM
trap 'exit 130' INT
start_heartbeat
node_bin="$CURRENT_LINK/runtime/bin/node"
[[ -x "$node_bin" ]] || node_bin=$(command -v node || true)
[[ -n "$node_bin" ]] || die 'node runtime not found'
node_bin=$(resolve_node) || die 'Node.js 24+ not found'
cli="$CURRENT_LINK/dist/server/cli/update.js"
[[ -f "$cli" ]] || die 'update CLI not found in current release'
set +e
@@ -243,8 +264,7 @@ restore_initial_service() {
return "$result"
}
trap restore_initial_service EXIT
old_node="$CURRENT_LINK/runtime/bin/node"
[[ -x "$old_node" ]] || old_node=$(command -v node || true)
old_node=$(resolve_node) || die 'Node.js 24+ not found'
handled=0
write_update_state() { write_recovery_state "$1"; }
@@ -287,8 +307,7 @@ recover_stale_state() {
return 0
fi
if [[ "$state_phase" == finalizing && "$current_target" != "$state_old" ]]; then
recovery_node="$CURRENT_LINK/runtime/bin/node"
[[ -x "$recovery_node" ]] || recovery_node=$(command -v node || true)
recovery_node=$(resolve_node) || die 'Node.js 24+ not found'
for _ in 1 2 3; do
if finalize_state_job "$recovery_node" completed "$state_job"; then
rm -f -- "$REQUEST_FILE" 2>/dev/null || true
@@ -304,8 +323,7 @@ recover_stale_state() {
# that case the old link is already safe to serve, but the database row
# can still be `applying`; finish it as failed before clearing recovery
# markers so the UI does not poll forever.
recovery_node="$CURRENT_LINK/runtime/bin/node"
[[ -x "$recovery_node" ]] || recovery_node=$(command -v node || true)
recovery_node=$(resolve_node) || die 'Node.js 24+ not found'
if finalize_state_job "$recovery_node" failed "$state_job"; then
rm -f -- "$REQUEST_FILE" 2>/dev/null || true
clear_update_state || true
@@ -328,8 +346,7 @@ recover_stale_state() {
rm -f -- "$rollback_link" 2>/dev/null || true
return 1
fi
recovery_node="$CURRENT_LINK/runtime/bin/node"
[[ -x "$recovery_node" ]] || recovery_node=$(command -v node || true)
recovery_node=$(resolve_node) || die 'Node.js 24+ not found'
if ! finalize_state_job "$recovery_node" failed "$state_job"; then
# If the original queue is still present, retry it from the restored old
# release; a crash before the CLI wrote its job row is recoverable this
@@ -439,9 +456,7 @@ cleanup_after_update() {
}
trap cleanup_after_update EXIT
node_bin="$CURRENT_LINK/runtime/bin/node"
[[ -x "$node_bin" ]] || node_bin=$(command -v node || true)
[[ -n "$node_bin" ]] || die 'node runtime not found'
node_bin=$(resolve_node) || die 'Node.js 24+ not found'
cli="$CURRENT_LINK/dist/server/cli/update.js"
[[ -f "$cli" ]] || die 'update CLI not found in current release'
@@ -483,8 +498,7 @@ if (( was_active == 0 )); then
fi
write_update_state finalizing || exit 1
final_node="$CURRENT_LINK/runtime/bin/node"
[[ -x "$final_node" ]] || final_node=$(command -v node || true)
final_node=$(resolve_node) || die 'Node.js 24+ not found'
if [[ "$job_id" =~ ^[0-9a-f-]{36}$ ]]; then
finalized=0
for _ in 1 2 3; do
+16 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -Eeuo pipefail
PATH=/usr/sbin:/usr/bin:/sbin:/bin
PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin
export PATH
umask 077
@@ -10,9 +10,22 @@ umask 077
# extraction and atomic release switching.
PREFIX=${TALLYNOTE_INSTALL_PREFIX:-${TALLYNOTE_PREFIX:-/opt/tallynote}}
DATA_DIR=${TALLYNOTE_DATA_DIR:-/var/lib/tallynote}
CONFIG_DIR=${TALLYNOTE_CONFIG_DIR:-/etc/tallynote}
CONFIG_FILE="$CONFIG_DIR/tallynote.env"
REQUEST_FILE=${TALLYNOTE_UPDATE_REQUEST_FILE:-$DATA_DIR/update-request.json}
NODE=${TALLYNOTE_NODE:-}
node_is_usable() {
local candidate=$1 major
[[ -n "$candidate" && -x "$candidate" ]] || return 1
major=$("$candidate" -p 'process.versions.node.split(".")[0]' 2>/dev/null || true)
[[ "$major" =~ ^[0-9]+$ && "$major" -ge 24 ]]
}
if [[ -z "$NODE" && -f "$CONFIG_FILE" && ! -L "$CONFIG_FILE" ]]; then
NODE=$(sed -n 's/^TALLYNOTE_NODE=//p' "$CONFIG_FILE" | head -n 1)
fi
die() { printf 'tallynote update: %s\n' "$*" >&2; exit 1; }
version_sort_desc() {
if sort -V </dev/null >/dev/null 2>&1; then
@@ -71,10 +84,9 @@ if [[ -x /usr/local/libexec/tallynote-update-runner ]]; then
exec /usr/local/libexec/tallynote-update-runner
fi
if [[ -z "$NODE" ]]; then
NODE="$PREFIX/current/runtime/bin/node"
[[ -x "$NODE" ]] || NODE=$(command -v node || true)
NODE=$(command -v node || true)
fi
[[ -n "$NODE" ]] || die 'node runtime not found'
node_is_usable "$NODE" || die 'Node.js 24+ not found'
CLI="$PREFIX/current/dist/server/cli/update.js"
[[ -f "$CLI" ]] || die 'update CLI not found'
+18 -18
View File
@@ -173,23 +173,23 @@ runner_root="$tmp/runner"
runner_prefix="$runner_root/prefix"
runner_data="$runner_root/data"
runner_tools="$runner_root/tools"
mkdir -p "$runner_prefix/releases/1.0.0/runtime/bin" "$runner_prefix/releases/1.0.0/dist/server/cli" "$runner_data" "$runner_tools"
mkdir -p "$runner_prefix/releases/1.0.0/dist/server/cli" "$runner_data" "$runner_tools"
ln -s "$runner_prefix/releases/1.0.0" "$runner_prefix/current"
printf '%s\n' '{"jobId":"00000000-0000-4000-8000-000000000001","operation":"apply"}' > "$runner_data/update-request.json"
printf '%s\n' '#!/usr/bin/env bash' 'printf "%s\\n" "$*" >> "$TALLYNOTE_NODE_TRACE"' 'exit 0' > "$runner_prefix/releases/1.0.0/runtime/bin/node"
printf '%s\n' '#!/usr/bin/env bash' 'if [[ "${1:-}" == "-p" ]]; then printf "%s\n" "24"; else printf "%s\n" "$*" >> "$TALLYNOTE_NODE_TRACE"; fi' 'exit 0' > "$runner_tools/node"
printf '%s\n' cli > "$runner_prefix/releases/1.0.0/dist/server/cli/update.js"
printf '%s\n' '#!/usr/bin/env bash' 'case "${1:-}" in is-active) exit 0;; *) exit 0;; esac' > "$runner_tools/systemctl"
printf '%s\n' '#!/usr/bin/env bash' 'if [[ "${1:-}" == "-f" ]]; then shift; [[ "${1:-}" == "--" ]] && shift; /bin/realpath "$1"; else /usr/bin/readlink "$@"; fi' > "$runner_tools/readlink"
printf '%s\n' '#!/usr/bin/env bash' 'if [[ "${1:-}" == "-Tf" ]]; then shift; /bin/mv -f "$@"; else /bin/mv "$@"; fi' > "$runner_tools/mv"
printf '%s\n' '#!/usr/bin/env bash' 'exit 0' > "$runner_tools/curl"
chmod 755 "$runner_prefix/releases/1.0.0/runtime/bin/node" "$runner_tools/systemctl" "$runner_tools/readlink" "$runner_tools/mv" "$runner_tools/curl"
chmod 755 "$runner_tools/node" "$runner_tools/systemctl" "$runner_tools/readlink" "$runner_tools/mv" "$runner_tools/curl"
runner_script="$runner_root/runner.sh"
runner_path="$runner_tools:/usr/sbin:/usr/bin:/sbin:/bin"
sed "s#PATH=/usr/sbin:/usr/bin:/sbin:/bin#PATH=$runner_path#" "$root/scripts/tallynote-update-runner.sh" > "$runner_script"
sed "s#PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin#PATH=$runner_path#" "$root/scripts/tallynote-update-runner.sh" > "$runner_script"
chmod 755 "$runner_script"
runner_prefix_physical=$(cd "$runner_prefix" && pwd -P)
runner_data_physical=$(cd "$runner_data" && pwd -P)
env EUID=0 TALLYNOTE_INSTALL_PREFIX="$runner_prefix_physical" TALLYNOTE_DATA_DIR="$runner_data_physical" TALLYNOTE_NODE_TRACE="$runner_root/node.log" bash "$runner_script"
env EUID=0 TALLYNOTE_INSTALL_PREFIX="$runner_prefix_physical" TALLYNOTE_DATA_DIR="$runner_data_physical" TALLYNOTE_NODE="$runner_tools/node" TALLYNOTE_NODE_TRACE="$runner_root/node.log" bash "$runner_script"
grep -q -- '--request-file' "$runner_root/node.log"
grep -q -- '--finalize-job' "$runner_root/node.log"
[[ ! -e "$runner_data/update-request.json" ]]
@@ -202,14 +202,14 @@ download_runner_root="$tmp/download-runner"
download_runner_prefix="$download_runner_root/prefix"
download_runner_data="$download_runner_root/data"
download_runner_tools="$download_runner_root/tools"
mkdir -p "$download_runner_prefix/releases/1.0.0/runtime/bin" "$download_runner_prefix/releases/1.0.0/dist/server/cli" "$download_runner_data" "$download_runner_tools"
mkdir -p "$download_runner_prefix/releases/1.0.0/dist/server/cli" "$download_runner_data" "$download_runner_tools"
ln -s "$download_runner_prefix/releases/1.0.0" "$download_runner_prefix/current"
# The request has already been consumed; only the stale download marker is
# left, which is the narrow recovery window covered by this fixture.
download_runner_prefix_physical=$(cd "$download_runner_prefix" && pwd -P)
download_runner_data_physical=$(cd "$download_runner_data" && pwd -P)
printf '%s\n' 'job_id=00000000-0000-4000-8000-000000000002' "old_target=$download_runner_prefix_physical/releases/1.0.0" 'phase=download' > "$download_runner_prefix/.update-state"
printf '%s\n' '#!/usr/bin/env bash' 'printf "%s\n" "$*" >> "$TALLYNOTE_DOWNLOAD_NODE_TRACE"' 'exit 0' > "$download_runner_prefix/releases/1.0.0/runtime/bin/node"
printf '%s\n' '#!/usr/bin/env bash' 'if [[ "${1:-}" == "-p" ]]; then printf "%s\n" "24"; else printf "%s\n" "$*" >> "$TALLYNOTE_DOWNLOAD_NODE_TRACE"; fi' 'exit 0' > "$download_runner_tools/node"
printf '%s\n' cli > "$download_runner_prefix/releases/1.0.0/dist/server/cli/update.js"
printf '%s\n' '#!/usr/bin/env bash' 'case "${1:-}" in is-active) exit 0;; *) exit 0;; esac' > "$download_runner_tools/systemctl"
printf '%s\n' '#!/usr/bin/env bash' 'if [[ "${1:-}" == "-f" ]]; then shift; [[ "${1:-}" == "--" ]] && shift; /bin/realpath "$1"; else /usr/bin/readlink "$@"; fi' > "$download_runner_tools/readlink"
@@ -221,11 +221,11 @@ case "$*" in
*) /usr/bin/stat "$@" ;;
esac
EOF
chmod 755 "$download_runner_prefix/releases/1.0.0/runtime/bin/node" "$download_runner_tools/systemctl" "$download_runner_tools/readlink" "$download_runner_tools/stat"
chmod 755 "$download_runner_tools/node" "$download_runner_tools/systemctl" "$download_runner_tools/readlink" "$download_runner_tools/stat"
download_runner_script="$download_runner_root/runner.sh"
sed "s#PATH=/usr/sbin:/usr/bin:/sbin:/bin#PATH=$download_runner_tools:/usr/sbin:/usr/bin:/sbin:/bin#" "$root/scripts/tallynote-update-runner.sh" > "$download_runner_script"
sed "s#PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin#PATH=$download_runner_tools:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin#" "$root/scripts/tallynote-update-runner.sh" > "$download_runner_script"
chmod 755 "$download_runner_script"
env EUID=0 TALLYNOTE_INSTALL_PREFIX="$download_runner_prefix_physical" TALLYNOTE_DATA_DIR="$download_runner_data_physical" TALLYNOTE_DOWNLOAD_NODE_TRACE="$download_runner_root/node.log" bash "$download_runner_script"
env EUID=0 TALLYNOTE_INSTALL_PREFIX="$download_runner_prefix_physical" TALLYNOTE_DATA_DIR="$download_runner_data_physical" TALLYNOTE_NODE="$download_runner_tools/node" TALLYNOTE_DOWNLOAD_NODE_TRACE="$download_runner_root/node.log" bash "$download_runner_script"
[[ ! -e "$download_runner_root/node.log" ]]
[[ ! -e "$download_runner_prefix/.update-state" ]]
@@ -233,7 +233,7 @@ env EUID=0 TALLYNOTE_INSTALL_PREFIX="$download_runner_prefix_physical" TALLYNOTE
# temporary variables still exist; otherwise set -u fails at the end of main.
release_fixture="$tmp/release-fixture"
mkdir -p "$release_fixture/dist/server/cli" "$release_fixture/dist/web" "$release_fixture/bin" \
"$release_fixture/scripts" "$release_fixture/runtime/bin" "$release_fixture/systemd"
"$release_fixture/scripts" "$release_fixture/systemd"
printf '%s\n' '{"version":"1.0.0"}' > "$release_fixture/package.json"
printf '%s\n' server > "$release_fixture/dist/server/index.js"
printf '%s\n' cli > "$release_fixture/dist/server/cli/admin-init.js"
@@ -282,16 +282,16 @@ grep -Fxq "PathChanged=$tmp/custom-prefix" "$rendered_path"
# The production admin wrapper must load a release-relative runtime, change to
# the release root, and forward CLI arguments without requiring pnpm.
wrapper_prefix="$tmp/wrapper-prefix"
mkdir -p "$wrapper_prefix/releases/1.0.0/runtime/bin" "$wrapper_prefix/releases/1.0.0/dist/server/cli"
mkdir -p "$wrapper_prefix/releases/1.0.0/dist/server/cli" "$tmp/wrapper-tools"
ln -s "$wrapper_prefix/releases/1.0.0" "$wrapper_prefix/current"
printf '%s\n' '#!/usr/bin/env bash' 'pwd -P > "$TALLYNOTE_WRAPPER_LOG"' 'printf "%s\n" "$@" >> "$TALLYNOTE_WRAPPER_LOG"' > "$wrapper_prefix/releases/1.0.0/runtime/bin/node"
chmod 755 "$wrapper_prefix/releases/1.0.0/runtime/bin/node"
printf '%s\n' '#!/usr/bin/env bash' 'if [[ "${1:-}" == "-p" ]]; then printf "%s\n" "24"; else pwd -P > "$TALLYNOTE_WRAPPER_LOG"; printf "%s\n" "$@" >> "$TALLYNOTE_WRAPPER_LOG"; fi' > "$tmp/wrapper-tools/node"
chmod 755 "$tmp/wrapper-tools/node"
printf '%s\n' cli > "$wrapper_prefix/releases/1.0.0/dist/server/cli/admin-init.js"
# This fixture verifies release-relative execution and argument forwarding.
# Force the wrapper's non-root branch so the root CI runner does not need a
# real `tallynote` service account or a privileged runuser hand-off; that
# privilege boundary is validated by the production checks themselves.
env EUID=1000 TALLYNOTE_INSTALL_PREFIX="$wrapper_prefix" TALLYNOTE_CONFIG_DIR="$tmp/no-config" TALLYNOTE_WRAPPER_LOG="$tmp/wrapper.log" \
env EUID=1000 TALLYNOTE_INSTALL_PREFIX="$wrapper_prefix" TALLYNOTE_CONFIG_DIR="$tmp/no-config" TALLYNOTE_NODE="$tmp/wrapper-tools/node" TALLYNOTE_WRAPPER_LOG="$tmp/wrapper.log" \
bash "$root/bin/tallynote-admin-init" --generate
wrapper_expected_root=$(cd "$wrapper_prefix/releases/1.0.0" && pwd -P)
grep -Fxq "$wrapper_expected_root" "$tmp/wrapper.log"
@@ -590,13 +590,12 @@ env -u TALLYNOTE_PUBLIC_ORIGIN -u TALLYNOTE_ALLOW_INSECURE_HTTP \
# A release archive is extracted under umask 077, then explicitly normalized
# so the tallynote system user can traverse and execute the shipped tree.
source_tmp="$tmp/source"
mkdir -p "$source_tmp/dist/server" "$source_tmp/bin" "$source_tmp/scripts" "$source_tmp/runtime/bin"
mkdir -p "$source_tmp/dist/server" "$source_tmp/bin" "$source_tmp/scripts"
printf '%s\n' 'server' > "$source_tmp/dist/server/index.js"
printf '%s\n' '#!/bin/sh' > "$source_tmp/uninstall.sh"
printf '%s\n' '#!/bin/sh' > "$source_tmp/bin/tallynote"
printf '%s\n' '#!/bin/sh' > "$source_tmp/scripts/runner.sh"
printf '%s\n' 'node' > "$source_tmp/runtime/bin/node"
chmod 755 "$source_tmp/bin/tallynote" "$source_tmp/scripts/runner.sh" "$source_tmp/runtime/bin/node"
chmod 755 "$source_tmp/bin/tallynote" "$source_tmp/scripts/runner.sh"
chmod 755 "$source_tmp/uninstall.sh"
archive_tmp="$tmp/release.tar.gz"
tar -C "$source_tmp" -czf "$archive_tmp" .
@@ -612,6 +611,7 @@ bash -c '
[[ "$(stat_mode "$destination/dist/server/index.js")" == 644 ]]
[[ "$(stat_mode "$destination/bin/tallynote")" == 755 ]]
[[ "$(stat_mode "$destination/uninstall.sh")" == 755 ]]
[[ ! -e "$destination/runtime" ]]
' _ "$installer_lib" "$archive_tmp" "$tmp/unpacked"
# A normal public-release install only needs the detached SHA-256 manifest;
+1 -1
View File
@@ -34,7 +34,7 @@ make_fixture() {
done
printf '%s\n' '#!/usr/bin/env bash' 'PREFIX=${TALLYNOTE_INSTALL_PREFIX:-/opt/tallynote}' 'echo TallyNote' > "$fixture/usr/local/sbin/tallynote-update"
printf '%s\n' '#!/usr/bin/env bash' 'PREFIX=${TALLYNOTE_INSTALL_PREFIX:-/opt/tallynote}' 'echo TallyNote' > "$fixture/usr/local/libexec/tallynote-update-runner"
printf '%s\n' '#!/usr/bin/env bash' 'exec /opt/tallynote/current/runtime/bin/node /opt/tallynote/current/dist/server/cli/admin-init.js' > "$fixture/usr/local/sbin/tallynote-admin-init"
printf '%s\n' '#!/usr/bin/env bash' 'exec /usr/bin/node /opt/tallynote/current/dist/server/cli/admin-init.js' > "$fixture/usr/local/sbin/tallynote-admin-init"
cp "$root/uninstall.sh" "$fixture/usr/local/sbin/tallynote-uninstall"
chmod 755 "$fixture/usr/local/sbin/tallynote-update" "$fixture/usr/local/libexec/tallynote-update-runner" "$fixture/usr/local/sbin/tallynote-admin-init" "$fixture/usr/local/sbin/tallynote-uninstall"
printf '%s\n' 'sqlite' > "$fixture/var/lib/tallynote/tallynote.db"