aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-27 21:16:16 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-27 21:16:16 +0300
commit3325304f89d56990f3134a3d01749e5de498725d (patch)
treeb10823a00f5e0de8b394c91b30d3fb2091d452c2
parent7ebc72f3f5de24a293db144cd1745cea52c3e717 (diff)
ci: fix build checks and mobile nav
-rw-r--r--.github/workflows/nix.yml9
-rw-r--r--nix/package.nix2
-rw-r--r--tests/live_handoff.rs83
-rw-r--r--website/astro.config.mjs7
-rw-r--r--website/css/style.css84
-rw-r--r--website/index.html20
-rw-r--r--website/src/components/MarketingLayout.astro20
-rw-r--r--website/src/components/SiteTitle.astro2
-rw-r--r--website/src/pages/compare.astro20
9 files changed, 219 insertions, 28 deletions
diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml
index 81306b1a..142b4054 100644
--- a/.github/workflows/nix.yml
+++ b/.github/workflows/nix.yml
@@ -38,15 +38,6 @@ jobs:
experimental-features = nix-command flakes
always-allow-substitutes = true
- - name: Enable Magic Nix Cache
- if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
- uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13
- continue-on-error: true
- with:
- source-tag: v0.1.6
- use-flakehub: disabled
- diagnostic-endpoint: ""
-
- name: Run Nix flake check
run: |
nix flake check --print-build-logs
diff --git a/nix/package.nix b/nix/package.nix
index ba9206d8..ab23e31c 100644
--- a/nix/package.nix
+++ b/nix/package.nix
@@ -42,7 +42,7 @@ rustPlatform.buildRustPackage {
);
};
- cargoLock.lockFile = ../Cargo.lock;
+ cargoHash = "sha256-5WvdZUD0Axr6xQ9Nm1XV1eJ0w4xUl8BQDnNs7pv6C8o=";
nativeBuildInputs = [
git
diff --git a/tests/live_handoff.rs b/tests/live_handoff.rs
index b8e9ad76..d9a8b34f 100644
--- a/tests/live_handoff.rs
+++ b/tests/live_handoff.rs
@@ -21,6 +21,11 @@ struct SpawnedHerdr {
child: Box<dyn Child + Send + Sync>,
}
+struct RequestError {
+ retryable: bool,
+ message: String,
+}
+
impl Drop for SpawnedHerdr {
fn drop(&mut self) {
let pid = self.child.process_id();
@@ -162,14 +167,56 @@ fn spawn_default_session_server(config_home: &Path, runtime_dir: &Path) -> Spawn
}
}
-fn request(socket_path: &Path, request: serde_json::Value) -> serde_json::Value {
- let mut stream = UnixStream::connect(socket_path).unwrap();
- stream.write_all(request.to_string().as_bytes()).unwrap();
- stream.write_all(b"\n").unwrap();
- stream.flush().unwrap();
+fn try_request(
+ socket_path: &Path,
+ request: serde_json::Value,
+) -> Result<serde_json::Value, RequestError> {
+ let mut stream = UnixStream::connect(socket_path).map_err(|err| RequestError {
+ retryable: true,
+ message: format!("connect {}: {err}", socket_path.display()),
+ })?;
+ let request_text = request.to_string();
+ stream
+ .write_all(request_text.as_bytes())
+ .map_err(|err| RequestError {
+ retryable: true,
+ message: format!("write request to {}: {err}", socket_path.display()),
+ })?;
+ stream.write_all(b"\n").map_err(|err| RequestError {
+ retryable: true,
+ message: format!("write newline to {}: {err}", socket_path.display()),
+ })?;
+ stream.flush().map_err(|err| RequestError {
+ retryable: true,
+ message: format!("flush request to {}: {err}", socket_path.display()),
+ })?;
let mut line = String::new();
- BufReader::new(stream).read_line(&mut line).unwrap();
- serde_json::from_str(&line).unwrap()
+ BufReader::new(stream)
+ .read_line(&mut line)
+ .map_err(|err| RequestError {
+ retryable: true,
+ message: format!("read response from {}: {err}", socket_path.display()),
+ })?;
+ if line.is_empty() {
+ return Err(RequestError {
+ retryable: true,
+ message: format!(
+ "empty response from {} for request {request_text}",
+ socket_path.display()
+ ),
+ });
+ }
+ serde_json::from_str(&line).map_err(|err| RequestError {
+ retryable: false,
+ message: format!(
+ "parse response from {} for request {request_text}: {err}; response was {line:?}",
+ socket_path.display()
+ ),
+ })
+}
+
+fn request(socket_path: &Path, request: serde_json::Value) -> serde_json::Value {
+ try_request(socket_path, request).unwrap_or_else(|err| panic!("{}", err.message))
}
fn assert_ok(response: serde_json::Value) {
@@ -181,19 +228,25 @@ fn assert_ok(response: serde_json::Value) {
fn wait_for_api(socket_path: &Path, timeout: Duration) {
let deadline = Instant::now() + timeout;
+ let mut last_error = String::new();
while Instant::now() < deadline {
- if UnixStream::connect(socket_path).is_ok() {
- let response = request(
- socket_path,
- serde_json::json!({"id":"test:ping","method":"ping","params":{}}),
- );
- if response.get("result").is_some() {
- return;
+ match try_request(
+ socket_path,
+ serde_json::json!({"id":"test:ping","method":"ping","params":{}}),
+ ) {
+ Ok(response) if response.get("result").is_some() => return,
+ Ok(response) => panic!("api ping returned non-success response: {response}"),
+ Err(err) if !err.retryable => panic!("{}", err.message),
+ Err(err) => {
+ last_error = err.message;
}
}
thread::sleep(Duration::from_millis(25));
}
- panic!("api did not become ready at {}", socket_path.display());
+ panic!(
+ "api did not become ready at {}; last error: {last_error}",
+ socket_path.display()
+ );
}
fn wait_for_output(socket_path: &Path, pane_id: &str, needle: &str) {
diff --git a/website/astro.config.mjs b/website/astro.config.mjs
index 6adb9e5b..badd2873 100644
--- a/website/astro.config.mjs
+++ b/website/astro.config.mjs
@@ -125,6 +125,13 @@ export default defineConfig({
{ label: 'Agent skill file', slug: 'docs/agent-skill' },
],
},
+ {
+ label: 'Updates',
+ items: [
+ { label: 'Releases', link: '/releases/' },
+ { label: 'Blog', link: '/blog/' },
+ ],
+ },
],
}),
],
diff --git a/website/css/style.css b/website/css/style.css
index fcadb011..74be689f 100644
--- a/website/css/style.css
+++ b/website/css/style.css
@@ -433,6 +433,82 @@ samp {
font-family: var(--mono);
}
+.nav-menu {
+ position: relative;
+ display: none;
+ margin-left: auto;
+}
+
+.nav-menu-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ gap: 0.22rem;
+ width: 2.1rem;
+ height: 2.1rem;
+ border: 1px solid var(--line);
+ border-radius: var(--radius-md);
+ color: var(--ink-soft);
+ cursor: pointer;
+ list-style: none;
+ transition:
+ color 120ms ease,
+ border-color 120ms ease,
+ background 120ms ease;
+}
+
+.nav-menu-button::-webkit-details-marker {
+ display: none;
+}
+
+.nav-menu-button::marker {
+ content: "";
+}
+
+.nav-menu-button span {
+ display: block;
+ width: 0.92rem;
+ height: 1px;
+ background: currentColor;
+}
+
+.nav-menu-button:hover,
+.nav-menu[open] .nav-menu-button {
+ color: var(--accent);
+ border-color: color-mix(in srgb, var(--accent) 38%, var(--line));
+ background: var(--accent-soft);
+}
+
+.nav-menu-panel {
+ position: absolute;
+ top: calc(100% + 0.65rem);
+ right: 0;
+ z-index: 30;
+ display: grid;
+ min-width: min(18rem, calc(100vw - 2rem));
+ padding: 0.35rem;
+ border: 1px solid var(--line-strong);
+ border-radius: var(--radius-md);
+ background: var(--bg-elevated);
+ box-shadow: 0 16px 44px rgba(0, 0, 0, 0.16);
+}
+
+.nav-menu-panel a {
+ border-radius: var(--radius-sm);
+ padding: 0.62rem 0.7rem;
+ color: var(--ink-soft);
+ font-family: var(--mono);
+ font-size: 0.86rem;
+ font-weight: 600;
+}
+
+.nav-menu-panel a:hover,
+.nav-menu-panel a[aria-current="page"] {
+ background: var(--accent-soft);
+ color: var(--accent);
+}
+
.nav-links a,
.footer a,
.inline-links a {
@@ -2462,10 +2538,18 @@ td:last-child {
padding-inline: 1rem;
}
+ .nav-menu {
+ display: block;
+ }
+
.nav-links {
display: none;
}
+ .nav-tools {
+ display: none;
+ }
+
.section,
.awareness-section,
.demo-section,
diff --git a/website/index.html b/website/index.html
index a844442d..1de94a14 100644
--- a/website/index.html
+++ b/website/index.html
@@ -57,7 +57,7 @@
document.documentElement.setAttribute("data-palette", saved || system);
})();
</script>
- <link rel="stylesheet" href="/css/style.css?v=20" />
+ <link rel="stylesheet" href="/css/style.css?v=21" />
</head>
<body>
<header class="site-header">
@@ -66,6 +66,24 @@
<span class="brand-logo" aria-hidden="true"></span>
<span>herdr</span>
</a>
+ <details class="nav-menu">
+ <summary class="nav-menu-button" aria-label="Open navigation">
+ <span></span>
+ <span></span>
+ <span></span>
+ </summary>
+ <div class="nav-menu-panel">
+ <a href="/">Home</a>
+ <a href="/compare/">Compare</a>
+ <a href="/releases/">Releases</a>
+ <a href="/blog/">Blog</a>
+ <a href="/docs/quick-start/">Quick start</a>
+ <a href="/docs/">Docs</a>
+ <a href="/docs/socket-api/">API</a>
+ <a href="/docs/install/">Install</a>
+ <a href="https://github.com/ogulcancelik/herdr">GitHub</a>
+ </div>
+ </details>
<div class="nav-links">
<a href="/">Home</a>
<a href="/compare/">Compare</a>
diff --git a/website/src/components/MarketingLayout.astro b/website/src/components/MarketingLayout.astro
index 5e39e011..9ecd7ac3 100644
--- a/website/src/components/MarketingLayout.astro
+++ b/website/src/components/MarketingLayout.astro
@@ -48,7 +48,7 @@ const canonicalUrl = new URL(canonicalPath, 'https://herdr.dev').toString();
document.documentElement.setAttribute("data-palette", saved || system);
})();
</script>
- <link rel="stylesheet" href="/css/style.css" />
+ <link rel="stylesheet" href="/css/style.css?v=21" />
</head>
<body>
<header class="site-header">
@@ -57,6 +57,24 @@ const canonicalUrl = new URL(canonicalPath, 'https://herdr.dev').toString();
<span class="brand-logo" aria-hidden="true"></span>
<span>herdr</span>
</a>
+ <details class="nav-menu">
+ <summary class="nav-menu-button" aria-label="Open navigation">
+ <span></span>
+ <span></span>
+ <span></span>
+ </summary>
+ <div class="nav-menu-panel">
+ <a href="/">Home</a>
+ <a href="/compare/">Compare</a>
+ <a href="/releases/">Releases</a>
+ <a href="/blog/">Blog</a>
+ <a href="/docs/quick-start/">Quick start</a>
+ <a href="/docs/">Docs</a>
+ <a href="/docs/socket-api/">API</a>
+ <a href="/docs/install/">Install</a>
+ <a href="https://github.com/ogulcancelik/herdr">GitHub</a>
+ </div>
+ </details>
<div class="nav-links">
<a href="/">Home</a>
<a href="/compare/">Compare</a>
diff --git a/website/src/components/SiteTitle.astro b/website/src/components/SiteTitle.astro
index ee979e9d..1173f2b6 100644
--- a/website/src/components/SiteTitle.astro
+++ b/website/src/components/SiteTitle.astro
@@ -9,6 +9,8 @@ const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute;
</a>
<nav class="title-nav" aria-label="Primary">
<a href="/docs/">Docs</a>
+ <a href="/releases/">Releases</a>
+ <a href="/blog/">Blog</a>
</nav>
</div>
diff --git a/website/src/pages/compare.astro b/website/src/pages/compare.astro
index 0c173f6f..96f1a7ee 100644
--- a/website/src/pages/compare.astro
+++ b/website/src/pages/compare.astro
@@ -45,7 +45,7 @@
document.documentElement.setAttribute("data-palette", saved || system);
})();
</script>
- <link rel="stylesheet" href="/css/style.css?v=compare2" />
+ <link rel="stylesheet" href="/css/style.css?v=21" />
</head>
<body>
<header class="site-header">
@@ -54,6 +54,24 @@
<span class="brand-logo" aria-hidden="true"></span>
<span>herdr</span>
</a>
+ <details class="nav-menu">
+ <summary class="nav-menu-button" aria-label="Open navigation">
+ <span></span>
+ <span></span>
+ <span></span>
+ </summary>
+ <div class="nav-menu-panel">
+ <a href="/">Home</a>
+ <a href="/compare/" aria-current="page">Compare</a>
+ <a href="/releases/">Releases</a>
+ <a href="/blog/">Blog</a>
+ <a href="/docs/quick-start/">Quick start</a>
+ <a href="/docs/">Docs</a>
+ <a href="/docs/socket-api/">API</a>
+ <a href="/docs/install/">Install</a>
+ <a href="https://github.com/ogulcancelik/herdr">GitHub</a>
+ </div>
+ </details>
<div class="nav-links">
<a href="/">Home</a>
<a href="/compare/" aria-current="page">Compare</a>