Skip to content

Commit a1950b1

Browse files
pszymkowiakclaude
andcommitted
Add README, CI/CD pipeline, and release infrastructure
- README with install instructions and Claude Code prompt - GitHub Actions: CI (test/fmt/clippy), release-please (auto version), release (build macOS + Linux) - install.sh for curl-based install - Homebrew formula - Version 0.0.1, release profile optimized Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 30e41e7 commit a1950b1

11 files changed

Lines changed: 524 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
12+
jobs:
13+
test:
14+
runs-on: macos-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Install Rust
19+
uses: dtolnay/rust-toolchain@stable
20+
21+
- name: Cache cargo
22+
uses: actions/cache@v4
23+
with:
24+
path: |
25+
~/.cargo/registry
26+
~/.cargo/git
27+
target
28+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
29+
30+
- name: Run tests
31+
run: cargo test
32+
33+
- name: Check formatting
34+
run: cargo fmt -- --check
35+
36+
- name: Clippy
37+
run: cargo clippy -- -D warnings
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Release Please
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
release-please:
14+
runs-on: ubuntu-latest
15+
outputs:
16+
release_created: ${{ steps.release.outputs.release_created }}
17+
tag_name: ${{ steps.release.outputs.tag_name }}
18+
steps:
19+
- uses: googleapis/release-please-action@v4
20+
id: release
21+
with:
22+
release-type: rust
23+
package-name: icm
24+
25+
build-release:
26+
name: Build and upload release assets
27+
needs: release-please
28+
if: ${{ needs.release-please.outputs.release_created == 'true' }}
29+
uses: ./.github/workflows/release.yml
30+
with:
31+
tag: ${{ needs.release-please.outputs.tag_name }}
32+
permissions:
33+
contents: write
34+
35+
update-latest-tag:
36+
name: Update 'latest' tag
37+
needs: [release-please, build-release]
38+
if: ${{ needs.release-please.outputs.release_created == 'true' }}
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v4
42+
with:
43+
fetch-depth: 0
44+
45+
- name: Update latest tag
46+
run: |
47+
git config user.name "github-actions[bot]"
48+
git config user.email "github-actions[bot]@users.noreply.github.com"
49+
git tag -fa latest -m "Latest stable release (${{ needs.release-please.outputs.tag_name }})"
50+
git push origin latest --force

.github/workflows/release.yml

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
name: Release
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_call:
7+
inputs:
8+
tag:
9+
description: 'Tag to release'
10+
required: true
11+
type: string
12+
workflow_dispatch:
13+
inputs:
14+
tag:
15+
description: 'Tag to release (e.g., v0.0.1)'
16+
required: true
17+
18+
permissions:
19+
contents: write
20+
21+
env:
22+
CARGO_TERM_COLOR: always
23+
24+
jobs:
25+
build:
26+
name: Build ${{ matrix.target }}
27+
runs-on: ${{ matrix.os }}
28+
strategy:
29+
fail-fast: false
30+
matrix:
31+
include:
32+
- target: x86_64-apple-darwin
33+
os: macos-latest
34+
archive: tar.gz
35+
- target: aarch64-apple-darwin
36+
os: macos-latest
37+
archive: tar.gz
38+
- target: x86_64-unknown-linux-gnu
39+
os: ubuntu-latest
40+
archive: tar.gz
41+
- target: aarch64-unknown-linux-gnu
42+
os: ubuntu-latest
43+
archive: tar.gz
44+
45+
steps:
46+
- name: Checkout
47+
uses: actions/checkout@v4
48+
49+
- name: Install Rust
50+
uses: dtolnay/rust-toolchain@stable
51+
with:
52+
targets: ${{ matrix.target }}
53+
54+
- name: Install cross-compilation tools
55+
if: matrix.target == 'aarch64-unknown-linux-gnu'
56+
run: |
57+
sudo apt-get update
58+
sudo apt-get install -y gcc-aarch64-linux-gnu
59+
60+
- name: Build
61+
run: cargo build --release --target ${{ matrix.target }} -p icm-cli
62+
env:
63+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
64+
65+
- name: Package
66+
run: |
67+
cd target/${{ matrix.target }}/release
68+
tar -czvf ../../../icm-${{ matrix.target }}.${{ matrix.archive }} icm
69+
cd ../../..
70+
71+
- name: Upload artifact
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: icm-${{ matrix.target }}
75+
path: icm-${{ matrix.target }}.${{ matrix.archive }}
76+
77+
release:
78+
name: Create Release
79+
needs: [build]
80+
runs-on: ubuntu-latest
81+
steps:
82+
- name: Checkout
83+
uses: actions/checkout@v4
84+
85+
- name: Download all artifacts
86+
uses: actions/download-artifact@v4
87+
with:
88+
path: artifacts
89+
90+
- name: Get version
91+
id: version
92+
run: |
93+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
94+
echo "version=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
95+
elif [ "${{ github.event_name }}" = "workflow_call" ]; then
96+
echo "version=${{ inputs.tag }}" >> $GITHUB_OUTPUT
97+
elif [ "${{ github.event_name }}" = "release" ]; then
98+
echo "version=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
99+
fi
100+
101+
- name: Flatten artifacts
102+
run: |
103+
mkdir -p release
104+
find artifacts -type f -name "*.tar.gz" -exec cp {} release/ \;
105+
106+
- name: Create checksums
107+
run: |
108+
cd release
109+
sha256sum * > checksums.txt
110+
111+
- name: Upload Release Assets
112+
if: github.event_name == 'release' || github.event_name == 'workflow_call'
113+
uses: softprops/action-gh-release@v2
114+
with:
115+
tag_name: ${{ steps.version.outputs.version }}
116+
files: release/*
117+
env:
118+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
119+
120+
- name: Create Release
121+
if: github.event_name == 'workflow_dispatch'
122+
uses: softprops/action-gh-release@v2
123+
with:
124+
tag_name: ${{ steps.version.outputs.version }}
125+
name: icm ${{ steps.version.outputs.version }}
126+
draft: false
127+
prerelease: false
128+
generate_release_notes: true
129+
files: release/*
130+
env:
131+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.0.1"
3+
}

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ members = [
77
"crates/icm-cli",
88
]
99

10+
[profile.release]
11+
opt-level = 3
12+
lto = true
13+
codegen-units = 1
14+
panic = "abort"
15+
strip = true
16+
1017
[workspace.dependencies]
1118
# Database
1219
rusqlite = { version = "0.34", features = ["bundled", "modern_sqlite"] }

Formula/icm.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
# Homebrew formula for icm
5+
# To install: brew tap rtk-ai/tap && brew install icm
6+
class Icm < Formula
7+
desc "Permanent memory for AI agents"
8+
homepage "https://github.com/rtk-ai/icm"
9+
version "0.0.1"
10+
license "MIT"
11+
12+
on_macos do
13+
on_intel do
14+
url "https://github.com/rtk-ai/icm/releases/download/v#{version}/icm-x86_64-apple-darwin.tar.gz"
15+
sha256 "PLACEHOLDER_SHA256_INTEL"
16+
end
17+
18+
on_arm do
19+
url "https://github.com/rtk-ai/icm/releases/download/v#{version}/icm-aarch64-apple-darwin.tar.gz"
20+
sha256 "PLACEHOLDER_SHA256_ARM"
21+
end
22+
end
23+
24+
on_linux do
25+
on_intel do
26+
url "https://github.com/rtk-ai/icm/releases/download/v#{version}/icm-x86_64-unknown-linux-gnu.tar.gz"
27+
sha256 "PLACEHOLDER_SHA256_LINUX_INTEL"
28+
end
29+
30+
on_arm do
31+
url "https://github.com/rtk-ai/icm/releases/download/v#{version}/icm-aarch64-unknown-linux-gnu.tar.gz"
32+
sha256 "PLACEHOLDER_SHA256_LINUX_ARM"
33+
end
34+
end
35+
36+
def install
37+
bin.install "icm"
38+
end
39+
40+
test do
41+
assert_match "icm #{version}", shell_output("#{bin}/icm --version")
42+
end
43+
end

0 commit comments

Comments
 (0)