opkg считает пакет уже установленным при равенстве версий, поэтому
пересборка под тем же тегом молча не применялась: задание завершалось
успехом, билд оставался старым. Добавлен --force-reinstall в
pkg_install_files_command (opkg) и в install.sh; apk не тронут, он
всегда пишет переданный файл.
Детект пересборки больше не зависит только от SHA, которого нет в
релизах старше f974e4a0: добавлен отпечаток билда по published_at и
метаданным ipk-ассета, решение вынесено в tachyon_build_differs с
префиксным сравнением SHA разной длины. Отпечаток установленного
билда пишется в state-файл и попадает в extra.
Telegram уведомляет о пересборках: check_notified_updates пропускает
outdated_same_release, дедуп идёт по версии и SHA, текст показывает
короткие SHA вместо пары одинаковых версий.
Кэш проверки обновлений сохраняет current_sha из результата действия
вместо безусловного latest, иначе неудачная установка выглядела как
"актуально".
Фронт пересобран из TS, ручная правка main.js снята. Добавлен
describeSameReleaseBuild с фолбэк-текстом, когда SHA недоступен.
157 lines
4.9 KiB
Bash
157 lines
4.9 KiB
Bash
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib"
|
|
UPDATES_UC="$TACHYON_LIB/components/updates.uc"
|
|
WORK_DIR="$(mktemp -d)"
|
|
|
|
cleanup() {
|
|
rm -rf "$WORK_DIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
fail() {
|
|
printf 'FAIL: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
fake_lib="$WORK_DIR/lib"
|
|
cache_dir="$WORK_DIR/cache"
|
|
job_dir="$WORK_DIR/jobs"
|
|
state_file="$job_dir/manual.json"
|
|
output_file="$job_dir/manual.out"
|
|
timestamp_file="$WORK_DIR/component-update-check.timestamp"
|
|
mkdir -p \
|
|
"$fake_lib/core" \
|
|
"$fake_lib/config" \
|
|
"$fake_lib/components" \
|
|
"$fake_lib/service" \
|
|
"$fake_lib/providers/zapret" \
|
|
"$fake_lib/providers/zapret2" \
|
|
"$fake_lib/providers/byedpi" \
|
|
"$job_dir"
|
|
|
|
cat >"$fake_lib/core/uci.uc" <<'UCODE'
|
|
function get_all(_config, section) {
|
|
if (section == "settings") {
|
|
return {
|
|
component_update_check_enabled: getenv("TEST_COMPONENT_UPDATE_CHECK_ENABLED") || "0",
|
|
component_update_check_interval: getenv("TEST_COMPONENT_UPDATE_CHECK_INTERVAL") || "1d"
|
|
};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
function section_objects(_config, _type) {
|
|
return [];
|
|
}
|
|
|
|
return {
|
|
get_all,
|
|
section_objects
|
|
};
|
|
UCODE
|
|
|
|
cat >"$fake_lib/config/connections.uc" <<'UCODE'
|
|
return {};
|
|
UCODE
|
|
|
|
cat >"$fake_lib/components/action.uc" <<'UCODE'
|
|
#!/usr/bin/env ucode
|
|
let component = ARGV[1] || "tachyon";
|
|
let action = ARGV[2] || "check_update";
|
|
let result = {
|
|
success: true,
|
|
component,
|
|
action,
|
|
message: "Update is available",
|
|
current_version: "1.0.0",
|
|
latest_version: "1.1.0",
|
|
release_url: "https://example.com/release",
|
|
changed: 0,
|
|
status: "outdated"
|
|
};
|
|
// An install reports which build it actually put on disk; a same-tag rebuild is
|
|
// only distinguishable by that value.
|
|
if (getenv("TEST_ACTION_CURRENT_SHA")) {
|
|
result.current_sha = getenv("TEST_ACTION_CURRENT_SHA");
|
|
result.latest_sha = getenv("TEST_ACTION_CURRENT_SHA");
|
|
result.status = "latest";
|
|
result.changed = 1;
|
|
}
|
|
print(sprintf("%J\n", result));
|
|
UCODE
|
|
|
|
cat >"$fake_lib/providers/zapret/runtime.uc" <<'UCODE'
|
|
#!/usr/bin/env ucode
|
|
exit(1);
|
|
UCODE
|
|
cp "$fake_lib/providers/zapret/runtime.uc" "$fake_lib/providers/zapret2/runtime.uc"
|
|
cp "$fake_lib/providers/zapret/runtime.uc" "$fake_lib/providers/byedpi/runtime.uc"
|
|
|
|
cat >"$fake_lib/service/state.uc" <<'UCODE'
|
|
#!/usr/bin/env ucode
|
|
exit(0);
|
|
UCODE
|
|
|
|
updates_ucode() {
|
|
TEST_COMPONENT_UPDATE_CHECK_ENABLED="${TEST_COMPONENT_UPDATE_CHECK_ENABLED:-1}" \
|
|
TEST_COMPONENT_UPDATE_CHECK_INTERVAL="${TEST_COMPONENT_UPDATE_CHECK_INTERVAL:-1d}" \
|
|
TACHYON_LIB="$fake_lib" \
|
|
TACHYON_COMPONENT_UPDATE_CHECK_CACHE_DIR="$cache_dir" \
|
|
TACHYON_COMPONENT_UPDATE_CHECK_STATE_FILE="$timestamp_file" \
|
|
UPDATES_JOB_DIR="$job_dir" \
|
|
ucode -L "$fake_lib" -L "$TACHYON_LIB" "$UPDATES_UC" "$@"
|
|
}
|
|
|
|
updates_ucode component-action-worker "$state_file" "$output_file" zapret check_update
|
|
[ -s "$cache_dir/zapret.json" ] ||
|
|
fail "manual checks must be cached while automatic checks are enabled"
|
|
|
|
manual_cache="$(updates_ucode component-update-check-cache)"
|
|
node -e '
|
|
const value = JSON.parse(process.argv[1]);
|
|
if (!value.enabled || value.results.length !== 1 ||
|
|
value.results[0].component !== "zapret" ||
|
|
value.results[0].status !== "outdated" ||
|
|
value.results[0].latest_version !== "1.1.0") process.exit(1);
|
|
' "$manual_cache" || fail "cached manual check response is invalid"
|
|
|
|
rm -rf "$cache_dir"
|
|
TEST_COMPONENT_UPDATE_CHECK_ENABLED=0 updates_ucode \
|
|
component-action-worker "$state_file" "$output_file" zapret check_update
|
|
[ ! -e "$cache_dir/zapret.json" ] ||
|
|
fail "manual checks must not be cached while automatic checks are disabled"
|
|
|
|
# A successful install must record the build identity it installed, not just
|
|
# "latest". A release tag can be rebuilt, so without the SHA the next check has
|
|
# nothing to compare against and either re-offers the same build or hides an
|
|
# install that silently changed nothing.
|
|
rm -rf "$cache_dir"
|
|
rm -f "$state_file"
|
|
TEST_ACTION_CURRENT_SHA=abc1234 updates_ucode \
|
|
component-action-worker "$state_file" "$output_file" tachyon install
|
|
[ -s "$cache_dir/tachyon.json" ] ||
|
|
fail "a successful install must refresh the Tachyon cache entry"
|
|
|
|
install_cache="$(updates_ucode component-update-check-cache)"
|
|
node -e '
|
|
const value = JSON.parse(process.argv[1]);
|
|
const entry = value.results.find((item) => item.component === "tachyon");
|
|
if (!entry) process.exit(1);
|
|
if (entry.status !== "latest") process.exit(1);
|
|
if (entry.current_sha !== "abc1234") process.exit(1);
|
|
if (entry.latest_sha !== "abc1234") process.exit(1);
|
|
' "$install_cache" || fail "install must cache the installed build sha"
|
|
|
|
rm -rf "$cache_dir"
|
|
rm -f "$state_file" "$timestamp_file"
|
|
updates_ucode component-updates-if-due
|
|
[ -s "$cache_dir/tachyon.json" ] ||
|
|
fail "automatic checks must cache the Tachyon result"
|
|
[ -s "$timestamp_file" ] ||
|
|
fail "automatic checks must record their last run"
|
|
|
|
printf 'component update check cache checks passed\n'
|