Compare commits
2 Commits
f95e9a1cd0
...
5818541721
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5818541721 | ||
|
|
b8053c00ca |
@ -1,5 +1,12 @@
|
|||||||
# 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.55-alpha"
|
version = "1.7.56-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"archipelago-container",
|
"archipelago-container",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.55-alpha"
|
version = "1.7.56-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,7 +65,9 @@ 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) => info!("Repaired Bitcoin RPC bind settings; running Bitcoin containers left untouched"),
|
Ok(true) => {
|
||||||
|
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,7 +298,11 @@ 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() || env.chars().any(|c| c.is_whitespace() || "\"\\$`".contains(c)) {
|
if env.is_empty()
|
||||||
|
|| env
|
||||||
|
.chars()
|
||||||
|
.any(|c| c.is_whitespace() || "\"\\$`".contains(c))
|
||||||
|
{
|
||||||
let escaped = env
|
let escaped = env
|
||||||
.replace('\\', "\\\\")
|
.replace('\\', "\\\\")
|
||||||
.replace('"', "\\\"")
|
.replace('"', "\\\"")
|
||||||
@ -793,7 +797,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn quote_environment_quotes_values_with_spaces() {
|
fn quote_environment_quotes_values_with_spaces() {
|
||||||
assert_eq!(quote_environment("BITCOIN_RPC_PASS=secret"), "BITCOIN_RPC_PASS=secret");
|
assert_eq!(
|
||||||
|
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,7 +514,14 @@ 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(
|
||||||
@ -833,6 +840,21 @@ 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));
|
||||||
|
|
||||||
@ -1346,7 +1368,9 @@ 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("nothexzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz-x.timer"),
|
parse_podman_healthcheck_unit(
|
||||||
|
"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.55-alpha",
|
"version": "1.7.56-alpha",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"version": "1.7.55-alpha",
|
"version": "1.7.56-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.55-alpha",
|
"version": "1.7.56-alpha",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "./start-dev.sh",
|
"start": "./start-dev.sh",
|
||||||
|
|||||||
@ -1,27 +1,28 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.55-alpha",
|
"version": "1.7.56-alpha",
|
||||||
"release_date": "2026-05-13",
|
"release_date": "2026-05-14",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Container reconcile now force-recreates Podman records stuck in `Stopping`, preserving bind-mounted app data while recovering wedged containers automatically.",
|
"Health notifications now clear when an app is no longer unhealthy, including stale alerts for removed containers such as Portainer.",
|
||||||
"`.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.",
|
"Quadlet environment values with spaces or shell metacharacters are quoted consistently, preventing env drift recreate loops for apps like nostr-rs-relay and Grafana.",
|
||||||
"Release-candidate artifacts are staged separately from live update publishing while Gitea artifact hosting is repaired."
|
"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."
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"name": "archipelago",
|
"name": "archipelago",
|
||||||
"current_version": "1.7.55-alpha",
|
"current_version": "1.7.56-alpha",
|
||||||
"new_version": "1.7.55-alpha",
|
"new_version": "1.7.56-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago",
|
||||||
"sha256": "f2caba778f63c7435431fb1b95cf6470bd43c4769ebe6adee2cbd2721707a663",
|
"sha256": "11217a0e40c1704ee9f5bbcdeb59e38c9efc5e00ea7c673c5c3f0f69de720109",
|
||||||
"size_bytes": 42580880
|
"size_bytes": 42647960
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "archipelago-frontend-1.7.55-alpha.tar.gz",
|
"name": "archipelago-frontend-1.7.56-alpha.tar.gz",
|
||||||
"current_version": "1.7.55-alpha",
|
"current_version": "1.7.56-alpha",
|
||||||
"new_version": "1.7.55-alpha",
|
"new_version": "1.7.56-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago-frontend-1.7.55-alpha.tar.gz",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago-frontend-1.7.56-alpha.tar.gz",
|
||||||
"sha256": "fe37425aad25724db49ec2be8d602342cfdc5fb99f08b4a3f04709751a3ed560",
|
"sha256": "9cee503e260891267fed33e4c97f067a4a592b10695ecea4cbf730d517ff6c8b",
|
||||||
"size_bytes": 166464949
|
"size_bytes": 166493666
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +1,28 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.55-alpha",
|
"version": "1.7.56-alpha",
|
||||||
"release_date": "2026-05-13",
|
"release_date": "2026-05-14",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Container reconcile now force-recreates Podman records stuck in `Stopping`, preserving bind-mounted app data while recovering wedged containers automatically.",
|
"Health notifications now clear when an app is no longer unhealthy, including stale alerts for removed containers such as Portainer.",
|
||||||
"`.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.",
|
"Quadlet environment values with spaces or shell metacharacters are quoted consistently, preventing env drift recreate loops for apps like nostr-rs-relay and Grafana.",
|
||||||
"Release-candidate artifacts are staged separately from live update publishing while Gitea artifact hosting is repaired."
|
"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."
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"name": "archipelago",
|
"name": "archipelago",
|
||||||
"current_version": "1.7.55-alpha",
|
"current_version": "1.7.56-alpha",
|
||||||
"new_version": "1.7.55-alpha",
|
"new_version": "1.7.56-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago",
|
||||||
"sha256": "f2caba778f63c7435431fb1b95cf6470bd43c4769ebe6adee2cbd2721707a663",
|
"sha256": "11217a0e40c1704ee9f5bbcdeb59e38c9efc5e00ea7c673c5c3f0f69de720109",
|
||||||
"size_bytes": 42580880
|
"size_bytes": 42647960
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "archipelago-frontend-1.7.55-alpha.tar.gz",
|
"name": "archipelago-frontend-1.7.56-alpha.tar.gz",
|
||||||
"current_version": "1.7.55-alpha",
|
"current_version": "1.7.56-alpha",
|
||||||
"new_version": "1.7.55-alpha",
|
"new_version": "1.7.56-alpha",
|
||||||
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.55-alpha/archipelago-frontend-1.7.55-alpha.tar.gz",
|
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.56-alpha/archipelago-frontend-1.7.56-alpha.tar.gz",
|
||||||
"sha256": "fe37425aad25724db49ec2be8d602342cfdc5fb99f08b4a3f04709751a3ed560",
|
"sha256": "9cee503e260891267fed33e4c97f067a4a592b10695ecea4cbf730d517ff6c8b",
|
||||||
"size_bytes": 166464949
|
"size_bytes": 166493666
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user