Skip to content

Add CI for verification and release#4

Open
RanolP wants to merge 16 commits intovlwkaos:mainfrom
RanolP:main
Open

Add CI for verification and release#4
RanolP wants to merge 16 commits intovlwkaos:mainfrom
RanolP:main

Conversation

@RanolP
Copy link
Copy Markdown

@RanolP RanolP commented Apr 10, 2026

Changes Made

  • Add automated GitHub Actions CI for both macOS and Linux (to use on Remote Linux Machine via mise).
    • Migrate scripts/release-extras.sh into real GitHub Actions CI.
      • Audited with zizmor, avoid vulnerability as much as we can.
      • Use hash-pinned package to avoid supply-chain attack, because agents can understand them easily.
    • Fix several pre-existing issues reported by the CI.
      • cargo-shear: remove unused dependencies, add it again when they really used.
      • cargo clippy: if chain, useless ref/deref, etc.
      • cargo fmt: mostly wrapping long-lines.
    • Replace tr test with awk due to long-running tests on GitHub Actions.

Note for AI use

  • I've used Claude Opus 4.6 for the whole work.
  • I've carefully reviewed the changes AI made and be proud of suggesting those changes.
  • I wrote the PR description by hand to be sure what changes I'm proposing.

Attribution

  • I've referred https://github.com/legalize-kr/compiler for their awesome CI infrastructure. But decided not to include license at code level because they followed very common best-practice and the cargo-zigbuild idea is denied here (because it may introduce regressions).

claude added 11 commits April 10, 2026 03:59
Builds ir binary and preprocessors for macOS (arm64/x86_64) and
Linux (x86_64/aarch64) on tag push. macOS preprocessors are universal
binaries via lipo matching existing release format. Includes SHA256
checksums for brew formula and mise github backend compatibility.

Asset naming (ir-{os}-{arch}.tar.gz) supports mise auto-detection.

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
The release workflow (.github/workflows/release.yml) builds and uploads
preprocessor binaries for all platforms, fully replacing this script.

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
- New ci.yml: build, test, clippy -D warnings, fmt check, cargo-shear
  (unused dep detection) on push/PR using ubuntu-24.04-arm
- release.yml: checkout@v4 → v6, add persist-credentials: false
- Patterns adopted from legalize-kr/compiler CI reference

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
On aarch64-linux, c_char is u8 (unsigned) unlike x86_64/macOS where
it's i8. Use std::ffi::c_char instead of hardcoded i8 in the
sqlite-vec extension init type alias.

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
tr uses full stdio buffering on pipes, causing deadlocks with the
line-by-line preprocessor protocol. Replace with awk + fflush() which
guarantees line-buffered output. Commands avoid spaces since spawn()
splits on whitespace. Chain test changed to lowercase + o→0 transform.

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
- needless_borrow: remove & on backend/path args already impl AsRef
- collapsible_if: merge nested if-let chains with && let syntax
- strip_prefix: use strip_prefix() instead of starts_with + slice
- manual_map: use Option::map for hyde SubQuery
- map_flatten: use and_then instead of map().flatten()
- map_or: use is_some_and instead of map_or(false, ..)
- clone for slice: use std::slice::from_ref instead of &[x.clone()]
- is_multiple_of: use .is_multiple_of(50) instead of % 50 == 0
- owned comparison: compare against Path::new() instead of PathBuf::from()
- file_create_without_truncate: add .truncate(true) to lock file
- dead_code: allow unused Script variant (match arm exists)
- too_many_arguments: per-function #[allow] on eval.rs benchmark fns
- unnecessary mut ref: pass &results instead of &mut results

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
- Pin all action references to commit SHAs (22 unpinned-uses → 0)
- Scope contents:write to release job only (was workflow-level)
- Add save-if:false to rust-cache in release workflow (cache-poisoning)

Remaining findings are informational (superfluous-actions suggestions)
and low-confidence cache-poisoning (mitigated by save-if:false).

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
Removes a third-party action dependency. Uses env var for tag name
to avoid template injection (zizmor template-injection finding).

https://claude.ai/code/session_01MYBuJxLEHKfxkBJ8yZRyph
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds GitHub Actions automation for verification and tagged releases, while aligning the Rust codebase with stricter CI (fmt/clippy/deps) and updating tests to avoid CI deadlocks.

Changes:

  • Introduces GitHub Actions CI (ci.yml) and a multi-platform release pipeline (release.yml) that builds and packages binaries/artifacts.
  • Removes the legacy scripts/release-extras.sh in favor of the release workflow.
  • Applies a broad set of Rust cleanups driven by CI (formatting, clippy fixes, unused deps removal, and replacing tr-based preprocessor tests with awk).

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/search/hybrid.rs Formatting/clippy-driven rewrites and minor refactors in hybrid search + rerank path.
src/search/fan_out.rs Minor formatting cleanup.
src/preprocess.rs Updates tests to use awk (fflush) instead of tr to avoid pipe buffering deadlocks in CI.
src/mcp.rs Formatting and small refactors around MCP tool routing and status/search tooling.
src/main.rs Formatting/clippy rewrites; adjusts result printing callsite to match print_results(&[...]).
src/llm/reranker.rs Fixes backend argument passing (avoids &&backend) and formatting.
src/llm/qwen.rs Formatting and context creation formatting cleanup.
src/llm/mod.rs Compresses HF repo constants formatting.
src/llm/expander.rs Fixes backend argument passing (avoids &&backend) and simplifies parsing logic.
src/llm/embedding.rs Fixes backend argument passing and context creation call; formatting.
src/llm/download.rs Minor refactor using let-chains for alias reuse.
src/index/mod.rs Formatting, refactors with let-chains; adds clippy allow for argument-heavy helper.
src/index/embed.rs Formatting; minor closure formatting changes.
src/index/chunker.rs Small refactor to use strip_prefix for heading parsing.
src/db/mod.rs FFI type correction (c_char), formatting, minor iterator refactors.
src/daemon.rs Formatting, minor refactors; lockfile open options adjusted.
src/config/mod.rs Formatting/refactor in preprocessor config resolution.
src/bin/eval.rs Formatting/clippy rewrites and minor standard library API cleanups.
scripts/release-extras.sh Removed; functionality migrated into GitHub Actions release workflow.
Cargo.toml Removes unused dependencies.
.github/workflows/release.yml Adds release workflow building macOS + Linux artifacts and creating GitHub releases.
.github/workflows/ci.yml Adds CI workflow for build/test/clippy/fmt and unused dependency checks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
Apply the valid Copilot review feedback on the release workflow.

- grant contents:read at workflow scope for checkout in build jobs
- build/package Linux release artifacts from the configured musl targets
- keep contents:write scoped to the release job only

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
@vlwkaos

This comment was marked as outdated.

@RanolP
Copy link
Copy Markdown
Author

RanolP commented Apr 13, 2026

  1. I have no concrete idea yet, to implement that. But It sounds shipping universal binary seems better. I'll dig this more this Sunday with my Codex. I think only having universal is best and having 3 (x86_64, aarch64, universal) is worse but working solution.
  2. I just never realized there's macos-15 and macos-26. Since we're not dealing with XCode, I think choosing the latest seems better.
  3. Conflict will be solved when the issues above solved. thx!

@vlwkaos
Copy link
Copy Markdown
Owner

vlwkaos commented Apr 13, 2026

Thanks for putting this together. Two clarifications and three required changes before this can merge.

Clarifications

macos-14 runner — correct, that's our defined baseline. No change needed.

Universal binary — we do serve a universal binary for the main ir binary (not just preprocessors). The current Package ir step produces ir-darwin-aarch64.tar.gz and ir-darwin-x86_64.tar.gz separately, but our Homebrew formula expects ir-{VERSION}-darwin-universal.tar.gz (built via lipo). The preprocessors already do this correctly — the main binary needs the same treatment.

Required Changes

1. Main ir binary: per-arch → universal with version in name

Replace the current Package ir step:

- name: Package ir (universal)
  run: |
    VERSION=${GITHUB_REF_NAME#v}
    lipo -create -output ir \
      target/aarch64-apple-darwin/release/ir \
      target/x86_64-apple-darwin/release/ir
    tar -czf "ir-${VERSION}-darwin-universal.tar.gz" ir
    rm ir

The version in the filename is required — the Homebrew formula URL references it directly.

2. Homebrew bottle

The local release pipeline produces ir-{VERSION}.all.bottle.tar.gz which the formula's bottle do block references. Add this step in build-macos after packaging ir:

- name: Build Homebrew bottle
  run: |
    VERSION=${GITHUB_REF_NAME#v}
    BOTTLE_DIR=$(mktemp -d)
    mkdir -p "$BOTTLE_DIR/ir/${VERSION}/bin"
    lipo -create -output "$BOTTLE_DIR/ir/${VERSION}/bin/ir" \
      target/aarch64-apple-darwin/release/ir \
      target/x86_64-apple-darwin/release/ir
    tar -czf "ir-${VERSION}.all.bottle.tar.gz" -C "$BOTTLE_DIR" ir
    rm -rf "$BOTTLE_DIR"

3. Homebrew tap update

After creating the GitHub release, the formula in the tap repo needs to be regenerated with the new tarball URL, tarball sha256, and bottle sha256. Add this step to the release job using a TAP_TOKEN secret (I'll set that up on the repo):

- name: Update Homebrew tap
  env:
    GH_TOKEN: ${{ secrets.TAP_TOKEN }}
    TAG: ${{ github.ref_name }}
  run: |
    VERSION=${TAG#v}
    TARBALL="ir-${VERSION}-darwin-universal.tar.gz"
    BOTTLE="ir-${VERSION}.all.bottle.tar.gz"
    SHA256=$(grep "$TARBALL" SHA256SUMS | awk '{print $1}')
    BOTTLE_SHA256=$(grep "$BOTTLE" SHA256SUMS | awk '{print $1}')
    DESC=$(grep '^description' Cargo.toml | head -1 | sed 's/description = "\(.*\)"/\1/')

    gh repo clone vlwkaos/homebrew-tap tap-repo
    cat > tap-repo/Formula/ir.rb <<FORMULA
class Ir < Formula
  desc "${DESC}"
  homepage "https://github.com/vlwkaos/ir"
  url "https://github.com/vlwkaos/ir/releases/download/${TAG}/${TARBALL}"
  version "${VERSION}"
  sha256 "${SHA256}"
  license "MIT"

  bottle do
    root_url "https://github.com/vlwkaos/ir/releases/download/${TAG}"
    sha256 cellar: :any_skip_relocation, all: "${BOTTLE_SHA256}"
  end

  def install
    bin.install "ir"
  end

  test do
    assert_predicate bin/"ir", :executable?
  end
end
FORMULA

    cd tap-repo
    git config user.name "github-actions[bot]"
    git config user.email "github-actions[bot]@users.noreply.github.com"
    git add Formula/ir.rb
    git commit -m "ir ${VERSION}"
    git push

Minor note

The release job uses ubuntu-latest (unpinned) while the build jobs use specific runner versions. Not a blocker, but worth aligning for consistency.

RanolP and others added 2 commits April 20, 2026 15:09
Align the release workflow with the upstream Homebrew formula requirements.

- package the macOS ir binary as a versioned universal tarball
- add the Homebrew bottle tarball to macOS release artifacts
- update vlwkaos/homebrew-tap after creating the GitHub release

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Merge upstream/main before updating PR vlwkaos#4.

- accept upstream source changes for merge conflicts
- keep the release workflow universal macOS artifact and tap update changes
- run cargo fmt after accepting upstream code

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
@vlwkaos
Copy link
Copy Markdown
Owner

vlwkaos commented Apr 22, 2026

The three required changes from the last round are all addressed. Universal binary, bottle, and tap update are in. Looks good overall.

One thing before I merge: in ci.yml, actions/checkout should be the first step, before dtolnay/rust-toolchain and taiki-e/install-action. It works today because there's no rust-toolchain.toml, but the order is wrong and will silently break if one is ever added. One-line move.

Fix that and this is ready to merge.

RanolP and others added 2 commits April 23, 2026 13:14
Move actions/checkout to the first CI step so future rust-toolchain.toml files are visible before toolchain setup.

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Use c_char for sqlite3_auto_extension init so aarch64 Linux matches the platform ABI.

Refresh Cargo.lock after upstream removed unused dependencies.

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
@vlwkaos
Copy link
Copy Markdown
Owner

vlwkaos commented Apr 23, 2026

@RanolP Seems like change from formatting differences, since there were few major upstream pushes, I'd suggest you cherry pick your change and clean up branch history and force push the branch. How does that sound? After that we will have to see if the action actually works, I am expecting some trial and error but that is ok. Thanks for looking into this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants