Compare commits
No commits in common. "5818541721575903b72cd4df2acc3b0960e5d675" and "f95e9a1cd028b0367cc625b8b1b7a2d03404703d" have entirely different histories.
5818541721
...
f95e9a1cd0
@ -1,12 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v1.7.56-alpha (2026-05-14)
|
|
||||||
|
|
||||||
- Health notifications now clear when an app is no longer unhealthy, including stale alerts for removed containers such as Portainer.
|
|
||||||
- Quadlet environment values with spaces or shell metacharacters are quoted consistently, preventing env drift recreate loops for apps like nostr-rs-relay and Grafana.
|
|
||||||
- Boot/bootstrap reconcile avoids restarting running Bitcoin containers while repairing RPC config, preserving IBD progress on active nodes.
|
|
||||||
- Exit code 137 is labeled as SIGKILL instead of assuming OOM, avoiding false OOM alerts for orchestrator-managed recreates.
|
|
||||||
|
|
||||||
## v1.7.55-alpha (2026-05-13)
|
## v1.7.55-alpha (2026-05-13)
|
||||||
|
|
||||||
- Container reconcile now force-recreates Podman records stuck in `Stopping`, preserving bind-mounted app data while recovering wedged containers automatically.
|
- Container reconcile now force-recreates Podman records stuck in `Stopping`, preserving bind-mounted app data while recovering wedged containers automatically.
|
||||||
|
|||||||
2
core/Cargo.lock
generated
2
core/Cargo.lock
generated
@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.56-alpha"
|
version = "1.7.55-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"archipelago-container",
|
"archipelago-container",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.56-alpha"
|
version = "1.7.55-alpha"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||||
authors = ["Archipelago Team"]
|
authors = ["Archipelago Team"]
|
||||||
|
|||||||
@ -65,9 +65,7 @@ pub async fn ensure_doctor_installed() {
|
|||||||
Err(e) => warn!("Nginx bootstrap failed (non-fatal): {:#}", e),
|
Err(e) => warn!("Nginx bootstrap failed (non-fatal): {:#}", e),
|
||||||
}
|
}
|
||||||
match run_bitcoin_rpc_repair().await {
|
match run_bitcoin_rpc_repair().await {
|
||||||
Ok(true) => {
|
Ok(true) => info!("Repaired Bitcoin RPC bind settings; running Bitcoin containers left untouched"),
|
||||||
info!("Repaired Bitcoin RPC bind settings; running Bitcoin containers left untouched")
|
|
||||||
}
|
|
||||||
Ok(false) => debug!("Bitcoin RPC bind settings already usable"),
|
Ok(false) => debug!("Bitcoin RPC bind settings already usable"),
|
||||||
Err(e) => warn!("Bitcoin RPC repair failed (non-fatal): {:#}", e),
|
Err(e) => warn!("Bitcoin RPC repair failed (non-fatal): {:#}", e),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -298,11 +298,7 @@ fn shell_join(parts: &[String]) -> String {
|
|||||||
|
|
||||||
fn quote_environment(env: &str) -> String {
|
fn quote_environment(env: &str) -> String {
|
||||||
let env = env.replace(['\r', '\n'], " ");
|
let env = env.replace(['\r', '\n'], " ");
|
||||||
if env.is_empty()
|
if env.is_empty() || env.chars().any(|c| c.is_whitespace() || "\"\\$`".contains(c)) {
|
||||||
|| env
|
|
||||||
.chars()
|
|
||||||
.any(|c| c.is_whitespace() || "\"\\$`".contains(c))
|
|
||||||
{
|
|
||||||
let escaped = env
|
let escaped = env
|
||||||
.replace('\\', "\\\\")
|
.replace('\\', "\\\\")
|
||||||
.replace('"', "\\\"")
|
.replace('"', "\\\"")
|
||||||
@ -797,10 +793,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn quote_environment_quotes_values_with_spaces() {
|
fn quote_environment_quotes_values_with_spaces() {
|
||||||
assert_eq!(
|
assert_eq!(quote_environment("BITCOIN_RPC_PASS=secret"), "BITCOIN_RPC_PASS=secret");
|
||||||
quote_environment("BITCOIN_RPC_PASS=secret"),
|
|
||||||
"BITCOIN_RPC_PASS=secret"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
quote_environment("RELAY_NAME=Archipelago Nostr Relay"),
|
quote_environment("RELAY_NAME=Archipelago Nostr Relay"),
|
||||||
"\"RELAY_NAME=Archipelago Nostr Relay\""
|
"\"RELAY_NAME=Archipelago Nostr Relay\""
|
||||||
|
|||||||
@ -514,14 +514,7 @@ async fn cleanup_stale_podman_healthcheck_units(live_container_ids: &HashSet<Str
|
|||||||
async fn stale_healthcheck_units_from_systemd(live_container_ids: &HashSet<String>) -> Vec<String> {
|
async fn stale_healthcheck_units_from_systemd(live_container_ids: &HashSet<String>) -> Vec<String> {
|
||||||
let mut units = Vec::new();
|
let mut units = Vec::new();
|
||||||
for args in [
|
for args in [
|
||||||
[
|
["--user", "list-timers", "--all", "--no-legend", "--no-pager"].as_slice(),
|
||||||
"--user",
|
|
||||||
"list-timers",
|
|
||||||
"--all",
|
|
||||||
"--no-legend",
|
|
||||||
"--no-pager",
|
|
||||||
]
|
|
||||||
.as_slice(),
|
|
||||||
["--user", "list-units", "--all", "--no-legend", "--no-pager"].as_slice(),
|
["--user", "list-units", "--all", "--no-legend", "--no-pager"].as_slice(),
|
||||||
] {
|
] {
|
||||||
let output = match tokio::time::timeout(
|
let output = match tokio::time::timeout(
|
||||||
@ -840,21 +833,6 @@ pub fn spawn_health_monitor(state: Arc<StateManager>, data_dir: PathBuf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let unhealthy_app_ids: HashSet<&str> = unhealthy
|
|
||||||
.iter()
|
|
||||||
.map(|container| container.app_id.as_str())
|
|
||||||
.collect();
|
|
||||||
let before = data.notifications.len();
|
|
||||||
data.notifications.retain(|n| {
|
|
||||||
!n.id.starts_with("health-")
|
|
||||||
|| n.app_id
|
|
||||||
.as_deref()
|
|
||||||
.is_some_and(|app_id| unhealthy_app_ids.contains(app_id))
|
|
||||||
});
|
|
||||||
if data.notifications.len() != before {
|
|
||||||
state_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort by startup tier: databases first, then core, then dependent, then apps, then UIs
|
// Sort by startup tier: databases first, then core, then dependent, then apps, then UIs
|
||||||
unhealthy.sort_by_key(|c| container_tier(&c.name));
|
unhealthy.sort_by_key(|c| container_tier(&c.name));
|
||||||
|
|
||||||
@ -1368,9 +1346,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(parse_podman_healthcheck_unit("grafana.service"), None);
|
assert_eq!(parse_podman_healthcheck_unit("grafana.service"), None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_podman_healthcheck_unit(
|
parse_podman_healthcheck_unit("nothexzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz-x.timer"),
|
||||||
"nothexzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz-x.timer"
|
|
||||||
),
|
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
4
neode-ui/package-lock.json
generated
4
neode-ui/package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"version": "1.7.56-alpha",
|
"version": "1.7.55-alpha",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"version": "1.7.56-alpha",
|
"version": "1.7.55-alpha",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.7.56-alpha",
|
"version": "1.7.55-alpha",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "./start-dev.sh",
|
"start": "./start-dev.sh",
|
||||||
|
|||||||
@ -1,28 +1,27 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.56-alpha",
|
"version": "1.7.55-alpha",
|
||||||
"release_date": "2026-05-14",
|
"release_date": "2026-05-13",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Health notifications now clear when an app is no longer unhealthy, including stale alerts for removed containers such as Portainer.",
|
"Container reconcile now force-recreates Podman records stuck in `Stopping`, preserving bind-mounted app data while recovering wedged containers automatically.",
|
||||||
"Quadlet environment values with spaces or shell metacharacters are quoted consistently, preventing env drift recreate loops for apps like nostr-rs-relay and Grafana.",
|
"`.198` is green after the container-layer hardening pass: focused and broad non-destructive lifecycle audits pass, raw Podman health/state sweep is clean, and direct app probes return healthy responses.",
|
||||||
"Boot/bootstrap reconcile avoids restarting running Bitcoin containers while repairing RPC config, preserving IBD progress on active nodes.",
|
"Release-candidate artifacts are staged separately from live update publishing while Gitea artifact hosting is repaired."
|
||||||
"Exit code 137 is labeled as SIGKILL instead of assuming OOM, avoiding false OOM alerts for orchestrator-managed recreates."
|
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"name": "archipelago",
|
"name": "archipelago",
|
||||||
"current_version": "1.7.56-alpha",
|
"current_version": "1.7.55-alpha",
|
||||||
"new_version": "1.7.56-alpha",
|
"new_version": "1.7.55-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago",
|
||||||
"sha256": "11217a0e40c1704ee9f5bbcdeb59e38c9efc5e00ea7c673c5c3f0f69de720109",
|
"sha256": "f2caba778f63c7435431fb1b95cf6470bd43c4769ebe6adee2cbd2721707a663",
|
||||||
"size_bytes": 42647960
|
"size_bytes": 42580880
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "archipelago-frontend-1.7.56-alpha.tar.gz",
|
"name": "archipelago-frontend-1.7.55-alpha.tar.gz",
|
||||||
"current_version": "1.7.56-alpha",
|
"current_version": "1.7.55-alpha",
|
||||||
"new_version": "1.7.56-alpha",
|
"new_version": "1.7.55-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago-frontend-1.7.56-alpha.tar.gz",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago-frontend-1.7.55-alpha.tar.gz",
|
||||||
"sha256": "9cee503e260891267fed33e4c97f067a4a592b10695ecea4cbf730d517ff6c8b",
|
"sha256": "fe37425aad25724db49ec2be8d602342cfdc5fb99f08b4a3f04709751a3ed560",
|
||||||
"size_bytes": 166493666
|
"size_bytes": 166464949
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,28 +1,27 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.56-alpha",
|
"version": "1.7.55-alpha",
|
||||||
"release_date": "2026-05-14",
|
"release_date": "2026-05-13",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Health notifications now clear when an app is no longer unhealthy, including stale alerts for removed containers such as Portainer.",
|
"Container reconcile now force-recreates Podman records stuck in `Stopping`, preserving bind-mounted app data while recovering wedged containers automatically.",
|
||||||
"Quadlet environment values with spaces or shell metacharacters are quoted consistently, preventing env drift recreate loops for apps like nostr-rs-relay and Grafana.",
|
"`.198` is green after the container-layer hardening pass: focused and broad non-destructive lifecycle audits pass, raw Podman health/state sweep is clean, and direct app probes return healthy responses.",
|
||||||
"Boot/bootstrap reconcile avoids restarting running Bitcoin containers while repairing RPC config, preserving IBD progress on active nodes.",
|
"Release-candidate artifacts are staged separately from live update publishing while Gitea artifact hosting is repaired."
|
||||||
"Exit code 137 is labeled as SIGKILL instead of assuming OOM, avoiding false OOM alerts for orchestrator-managed recreates."
|
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"name": "archipelago",
|
"name": "archipelago",
|
||||||
"current_version": "1.7.56-alpha",
|
"current_version": "1.7.55-alpha",
|
||||||
"new_version": "1.7.56-alpha",
|
"new_version": "1.7.55-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago",
|
||||||
"sha256": "11217a0e40c1704ee9f5bbcdeb59e38c9efc5e00ea7c673c5c3f0f69de720109",
|
"sha256": "f2caba778f63c7435431fb1b95cf6470bd43c4769ebe6adee2cbd2721707a663",
|
||||||
"size_bytes": 42647960
|
"size_bytes": 42580880
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "archipelago-frontend-1.7.56-alpha.tar.gz",
|
"name": "archipelago-frontend-1.7.55-alpha.tar.gz",
|
||||||
"current_version": "1.7.56-alpha",
|
"current_version": "1.7.55-alpha",
|
||||||
"new_version": "1.7.56-alpha",
|
"new_version": "1.7.55-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago-frontend-1.7.56-alpha.tar.gz",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago-frontend-1.7.55-alpha.tar.gz",
|
||||||
"sha256": "9cee503e260891267fed33e4c97f067a4a592b10695ecea4cbf730d517ff6c8b",
|
"sha256": "fe37425aad25724db49ec2be8d602342cfdc5fb99f08b4a3f04709751a3ed560",
|
||||||
"size_bytes": 166493666
|
"size_bytes": 166464949
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user