From b9808ac2cf4521030ddba4155ca3df0940240f75 Mon Sep 17 00:00:00 2001 From: cc Date: Wed, 25 Feb 2026 00:58:11 -0500 Subject: [PATCH 1/3] fix(ci): align release versioning and remove dead tmux capture path Sync Cargo.toml version from release tags for cargo-dist, limit npm publish workflow to tag pushes, and add stale automation. Remove unused tmux capture-pane code/tests that were failing and unreferenced. --- .github/workflows/publish-npm.yaml | 5 -- .github/workflows/release.yml | 88 ++++++++++++++++++++++++++++++ .github/workflows/stale.yaml | 17 ++++++ src/tmux/mod.rs | 86 ----------------------------- 4 files changed, 105 insertions(+), 91 deletions(-) create mode 100644 .github/workflows/stale.yaml diff --git a/.github/workflows/publish-npm.yaml b/.github/workflows/publish-npm.yaml index b097686..1ce84ec 100644 --- a/.github/workflows/publish-npm.yaml +++ b/.github/workflows/publish-npm.yaml @@ -2,13 +2,8 @@ name: Publish npm on: push: - branches: - - main tags: - "v*.*.*" - pull_request: - branches: - - main permissions: contents: read diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d9aa406..cac4dfb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,6 +60,28 @@ jobs: with: persist-credentials: false submodules: recursive + - name: Sync Cargo.toml version from tag + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + set -euo pipefail + version="${GITHUB_REF_NAME#v}" + if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then + echo "Unsupported tag version: ${GITHUB_REF_NAME}" + exit 1 + fi + python3 - <<'PY' + import os + import re + from pathlib import Path + + version = os.environ["GITHUB_REF_NAME"][1:] + cargo_toml = Path("Cargo.toml") + text = cargo_toml.read_text() + updated = re.sub(r'^version = ".*"$', f'version = "{version}"', text, count=1, flags=re.MULTILINE) + cargo_toml.write_text(updated) + print(f"Set Cargo.toml package version to {version}") + PY - name: Install dist # we specify bash to get pipefail; it guards against the `curl` command # failing. otherwise `sh` won't catch that `curl` returned non-0 @@ -120,6 +142,28 @@ jobs: with: persist-credentials: false submodules: recursive + - name: Sync Cargo.toml version from tag + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + set -euo pipefail + version="${GITHUB_REF_NAME#v}" + if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then + echo "Unsupported tag version: ${GITHUB_REF_NAME}" + exit 1 + fi + python3 - <<'PY' + import os + import re + from pathlib import Path + + version = os.environ["GITHUB_REF_NAME"][1:] + cargo_toml = Path("Cargo.toml") + text = cargo_toml.read_text() + updated = re.sub(r'^version = ".*"$', f'version = "{version}"', text, count=1, flags=re.MULTILINE) + cargo_toml.write_text(updated) + print(f"Set Cargo.toml package version to {version}") + PY - name: Install Rust non-interactively if not already installed if: ${{ matrix.container }} run: | @@ -179,6 +223,28 @@ jobs: with: persist-credentials: false submodules: recursive + - name: Sync Cargo.toml version from tag + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + set -euo pipefail + version="${GITHUB_REF_NAME#v}" + if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then + echo "Unsupported tag version: ${GITHUB_REF_NAME}" + exit 1 + fi + python3 - <<'PY' + import os + import re + from pathlib import Path + + version = os.environ["GITHUB_REF_NAME"][1:] + cargo_toml = Path("Cargo.toml") + text = cargo_toml.read_text() + updated = re.sub(r'^version = ".*"$', f'version = "{version}"', text, count=1, flags=re.MULTILINE) + cargo_toml.write_text(updated) + print(f"Set Cargo.toml package version to {version}") + PY - name: Install cached dist uses: actions/download-artifact@v7 with: @@ -229,6 +295,28 @@ jobs: with: persist-credentials: false submodules: recursive + - name: Sync Cargo.toml version from tag + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + set -euo pipefail + version="${GITHUB_REF_NAME#v}" + if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then + echo "Unsupported tag version: ${GITHUB_REF_NAME}" + exit 1 + fi + python3 - <<'PY' + import os + import re + from pathlib import Path + + version = os.environ["GITHUB_REF_NAME"][1:] + cargo_toml = Path("Cargo.toml") + text = cargo_toml.read_text() + updated = re.sub(r'^version = ".*"$', f'version = "{version}"', text, count=1, flags=re.MULTILINE) + cargo_toml.write_text(updated) + print(f"Set Cargo.toml package version to {version}") + PY - name: Install cached dist uses: actions/download-artifact@v7 with: diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 0000000..8bb607d --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,17 @@ +name: Close stale issues and pull requests + +on: + schedule: + - cron: "30 1 * * *" + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - name: Mark stale issues and pull requests + uses: actions/stale@v10 diff --git a/src/tmux/mod.rs b/src/tmux/mod.rs index 58fac4b..d582ed2 100644 --- a/src/tmux/mod.rs +++ b/src/tmux/mod.rs @@ -183,29 +183,6 @@ pub fn tmux_list_sessions() -> Vec { sessions } -pub fn tmux_capture_pane(session_name: &str, lines: usize) -> Result { - let start = format!("-{lines}"); - let output = tmux_command() - .args(capture_pane_window_args(session_name, &start)) - .output() - .context("failed to run tmux capture-pane")?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr); - if stderr.contains("can't find window: 0") { - let retry = tmux_command() - .args(capture_pane_session_args(session_name, &start)) - .output() - .context("failed to rerun tmux capture-pane")?; - ensure_success(&retry, "capture-pane")?; - return Ok(String::from_utf8_lossy(&retry.stdout).to_string()); - } - } - - ensure_success(&output, "capture-pane") - .map(|_| String::from_utf8_lossy(&output.stdout).to_string()) -} - pub fn tmux_get_pane_pid(session_name: &str) -> Option { let output = tmux_command() .args(list_panes_args(session_name)) @@ -392,28 +369,6 @@ fn list_sessions_args() -> Vec { ] } -fn capture_pane_window_args(session_name: &str, start: &str) -> Vec { - vec![ - "capture-pane".to_string(), - "-t".to_string(), - format!("{session_name}:0.0"), - "-p".to_string(), - "-S".to_string(), - start.to_string(), - ] -} - -fn capture_pane_session_args(session_name: &str, start: &str) -> Vec { - vec![ - "capture-pane".to_string(), - "-t".to_string(), - session_name.to_string(), - "-p".to_string(), - "-S".to_string(), - start.to_string(), - ] -} - fn list_panes_args(session_name: &str) -> Vec { vec![ "list-panes".to_string(), @@ -691,22 +646,6 @@ mod tests { ); } - #[test] - fn test_capture_pane_window_args_builder() { - assert_eq!( - capture_pane_window_args("ok-test", "-50"), - vec!["capture-pane", "-t", "ok-test:0.0", "-p", "-S", "-50"] - ); - } - - #[test] - fn test_capture_pane_session_args_builder() { - assert_eq!( - capture_pane_session_args("ok-test", "-50"), - vec!["capture-pane", "-t", "ok-test", "-p", "-S", "-50"] - ); - } - #[test] fn test_list_panes_args_builder() { assert_eq!( @@ -744,31 +683,6 @@ mod tests { assert!(!tmux_session_exists(&session_name)); } - #[test] - fn test_tmux_capture_pane() { - if !tmux_available() { - return; - } - let session_name = unique_session_name("capture"); - let _cleanup = SessionCleanup::new(session_name.clone()); - - tmux_create_session( - &session_name, - Path::new("."), - Some("printf 'line-one\\nline-two\\n'; sleep 2"), - ) - .expect("create session should succeed"); - - assert!(wait_for_session(&session_name, Duration::from_secs(2))); - let captured = tmux_capture_pane(&session_name, 20).expect("capture should succeed"); - assert!(captured.contains("line-one")); - assert!(captured.contains("line-two")); - - if tmux_session_exists(&session_name) { - let _ = tmux_kill_session(&session_name); - } - } - fn tmux_available() -> bool { Command::new("tmux") .arg("-V") From 6e15f67d24707573eed8d3376db7409f008641e5 Mon Sep 17 00:00:00 2001 From: cc Date: Wed, 25 Feb 2026 01:13:31 -0500 Subject: [PATCH 2/3] fix(ci): allow custom cargo-dist workflow edits Enable dist allow-dirty for ci so release workflow customizations don't fail dist plan with out-of-date generated-file checks. --- dist-workspace.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dist-workspace.toml b/dist-workspace.toml index d35b364..aa46fbc 100644 --- a/dist-workspace.toml +++ b/dist-workspace.toml @@ -5,6 +5,8 @@ members = ["cargo:."] [dist] # The preferred dist version to use in CI (Cargo.toml SemVer syntax) cargo-dist-version = "0.31.0" +# Allow local customizations to generated CI workflow without forcing dist init +allow-dirty = ["ci"] # CI backends to support ci = "github" # The installers to generate for each app From 16da7033f8c945e259c97fba81c2946adbfb011d Mon Sep 17 00:00:00 2001 From: cc Date: Wed, 25 Feb 2026 01:26:13 -0500 Subject: [PATCH 3/3] ci: test build --- .github/workflows/ci.yaml | 17 +++++++++++++++++ .github/workflows/release.yml | 1 - 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fb2f184..f0fa59a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,6 +10,23 @@ env: CARGO_TERM_COLOR: always jobs: + pr-linux-release-build: + name: PR Linux release build + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + targets: x86_64-unknown-linux-gnu + + - name: Build Linux release binary + run: cargo build --release --target x86_64-unknown-linux-gnu + test: name: Test runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cac4dfb..7e80cd7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,7 +39,6 @@ permissions: # If there's a prerelease-style suffix to the version, then the release(s) # will be marked as a prerelease. on: - pull_request: push: tags: - '**[0-9]+.[0-9]+.[0-9]+*'