Three tray bugs today, each caused by fixing the previous one without looking at what else the fix touched. Worth writing down as one thing rather than three. **Two dogs, again.** 0.1.4 taught the app to notice its own package being replaced and reopen. 0.1.5 added the same behaviour to `hound update`, which is the better mechanism because it works no matter which version was running — and I did not remove the first. Both fire during an update: the running app re-execs under a new pid while apt is working, so the updater kills a pid that has already moved and starts a second instance beside it. The in-app restart now waits eight seconds before acting. If the updater is doing its job this process is terminated during the pause and never restarts itself; what survives the wait is the only case the updater cannot cover, which is somebody running `apt upgrade` directly. Two mechanisms, one arbiter. **The launcher stopped working.** The single-instance lock added in 0.1.5 to prevent the duplicate icon made a second launch exit quietly, so clicking the desktop shortcut while Hound was open did nothing at all — no window, no error, no feedback. It now hands the request to the running instance, which shows, unminimises and focuses. The same channel the right-click scan already used: a launch with paths means "scan these", a launch without means "show yourself". Also in this release, and the reason the version is what it says it is: the workspace version did not get bumped. Adding the hound-watch crate pushed `version =` from line 6 to line 7 of Cargo.toml, and the bump was a line-numbered sed. The three GUI files went to 0.1.10 and the workspace stayed at 0.1.9, so the package built as 0.1.9 while the manifest would have advertised 0.1.10 — every installed agent would have offered an update forever, installed it, and still seen one available. `the_declared_versions_all_agree` caught it before the build finished. tools/bump-version.sh now does this by matching content and section rather than line numbers, asserts every substitution actually happened, and refuses to write invalid JSON. Adds crates/hound-watch: the registry firehose. npm publishes a CouchDB _changes stream and PyPI an RSS feed of every new project, both public, so this needs no user data at all — which is the answer to how a product with no telemetry grows its detection. Each new package is handed to the detectors Hound already ships, so there is one definition of "this install script is hostile" and a rule that fires in CI fires identically on the firehose. Verified against the live registries: 240 releases in one poll, 60 triaged, parsers tested against captured responses rather than the network. 476 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
40 lines
1.4 KiB
Bash
Executable file
40 lines
1.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Set the version in every file that declares one.
|
|
#
|
|
# There are four, and they must agree: a mismatch means a published release
|
|
# looks older than what is installed, so the update either never offers or
|
|
# offers forever. This exists because a line-numbered `sed` edited the wrong
|
|
# line after a new crate shifted Cargo.toml down by one, and only the
|
|
# version-drift test noticed.
|
|
set -euo pipefail
|
|
[ $# -eq 1 ] || { echo "usage: $0 <version>" >&2; exit 1; }
|
|
NEW="$1"
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
# Matched by content and by section, never by line number.
|
|
python3 - "$ROOT" "$NEW" <<'PY'
|
|
import re, sys, json, pathlib
|
|
root, new = pathlib.Path(sys.argv[1]), sys.argv[2]
|
|
|
|
def sub_toml(path, count=1):
|
|
p = root / path
|
|
s = p.read_text()
|
|
s2, n = re.subn(r'(?m)^version = "\d+\.\d+\.\d+"$', f'version = "{new}"', s, count=count)
|
|
assert n == count, f"{path}: expected {count} version line(s), changed {n}"
|
|
p.write_text(s2)
|
|
|
|
def sub_json(path):
|
|
p = root / path
|
|
s = p.read_text()
|
|
s2, n = re.subn(r'"version":\s*"\d+\.\d+\.\d+"', f'"version": "{new}"', s, count=1)
|
|
assert n == 1, f"{path}: no version field"
|
|
json.loads(s2) # refuse to write invalid JSON
|
|
p.write_text(s2)
|
|
|
|
sub_toml("Cargo.toml")
|
|
sub_toml("gui/src-tauri/Cargo.toml")
|
|
sub_json("gui/src-tauri/tauri.conf.json")
|
|
sub_json("gui/package.json")
|
|
print(f" version set to {new} in 4 files")
|
|
PY
|