Skip to content

Commit 05f19d4

Browse files
makingclaude
andcommitted
Add comprehensive Rust CLI for Entry API
This commit introduces a complete command-line interface for the Entry API, built in Rust. The CLI provides full CRUD operations for entries, categories, and tags, with support for authentication, configuration management, and multiple output formats. Key Features: - Full Entry API integration (list, get, create, update, delete entries) - Category and tag management - Authentication support (Basic Auth) - Multi-tenant support with configurable tenant IDs - Multiple output formats (table, JSON, markdown) - Configuration management with profiles - Interactive editing with $EDITOR support - Comprehensive error handling - Cross-platform GitHub Actions build pipeline Technical Implementation: - Built with Rust using tokio, reqwest, clap, and serde - 43 comprehensive tests (32 unit tests + 11 integration tests) - HTTP client with proper error handling and authentication - Configuration stored in TOML format - GitHub Actions workflow for cross-platform builds (Linux, macOS, Windows) - Development release automation with pyTooling/Actions/releaser CLI Commands: - entry: list, get, create, update, delete, search, template - category: list - tag: list - config: init, show, set Output Features: - Entry tables with :: separator for categories - Category lists with > separator for hierarchy - Tag lists without version column (as requested) - JSON and markdown output options - Colored terminal output 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 5109c82 commit 05f19d4

17 files changed

Lines changed: 3484 additions & 0 deletions

File tree

.github/workflows/cli-build.yml

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
name: Build CLI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'cli/**'
8+
- '.github/workflows/cli-build.yml'
9+
pull_request:
10+
branches: [ main ]
11+
paths:
12+
- 'cli/**'
13+
- '.github/workflows/cli-build.yml'
14+
release:
15+
types: [ published ]
16+
17+
env:
18+
CARGO_TERM_COLOR: always
19+
20+
jobs:
21+
build:
22+
strategy:
23+
matrix:
24+
include:
25+
- os: ubuntu-latest
26+
target: x86_64-unknown-linux-gnu
27+
binary-suffix: ""
28+
archive-suffix: tar.gz
29+
- os: ubuntu-latest
30+
target: x86_64-unknown-linux-musl
31+
binary-suffix: ""
32+
archive-suffix: tar.gz
33+
- os: macos-latest
34+
target: x86_64-apple-darwin
35+
binary-suffix: ""
36+
archive-suffix: tar.gz
37+
- os: macos-latest
38+
target: aarch64-apple-darwin
39+
binary-suffix: ""
40+
archive-suffix: tar.gz
41+
- os: windows-latest
42+
target: x86_64-pc-windows-msvc
43+
binary-suffix: .exe
44+
archive-suffix: zip
45+
46+
runs-on: ${{ matrix.os }}
47+
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- name: Install Rust
52+
uses: dtolnay/rust-toolchain@stable
53+
with:
54+
targets: ${{ matrix.target }}
55+
56+
- name: Install musl tools
57+
if: matrix.target == 'x86_64-unknown-linux-musl'
58+
run: |
59+
sudo apt-get update
60+
sudo apt-get install -y musl-tools musl-dev
61+
62+
- name: Cache cargo registry
63+
uses: actions/cache@v4
64+
with:
65+
path: ~/.cargo/registry
66+
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
67+
68+
- name: Cache cargo index
69+
uses: actions/cache@v4
70+
with:
71+
path: ~/.cargo/git
72+
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
73+
74+
- name: Cache cargo build
75+
uses: actions/cache@v4
76+
with:
77+
path: cli/target
78+
key: ${{ runner.os }}-${{ matrix.target }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
79+
80+
- name: Update version in Cargo.toml
81+
shell: bash
82+
run: |
83+
cd cli
84+
if [ "${{ github.event_name }}" = "release" ]; then
85+
# For releases, use the tag name as version (remove 'v' prefix if present)
86+
VERSION="${{ github.event.release.tag_name }}"
87+
VERSION="${VERSION#v}" # Remove 'v' prefix if present
88+
else
89+
# For development builds, use dev version with SHA
90+
HEX_SHA="${GITHUB_SHA:0:8}"
91+
DECIMAL_SHA=$(printf "%d" 0x$HEX_SHA)
92+
VERSION="1.0.0-dev.$DECIMAL_SHA"
93+
fi
94+
sed -i.bak "s/^version = .*/version = \"$VERSION\"/" Cargo.toml
95+
echo "Updated version to: $VERSION"
96+
cat Cargo.toml | grep version
97+
98+
- name: Build
99+
run: |
100+
cd cli
101+
cargo build --release --target ${{ matrix.target }}
102+
103+
- name: Run tests
104+
if: matrix.target == 'x86_64-unknown-linux-gnu'
105+
run: |
106+
cd cli
107+
cargo test --release --target ${{ matrix.target }}
108+
109+
- name: Prepare binary
110+
shell: bash
111+
run: |
112+
cd cli
113+
mkdir -p dist
114+
cp target/${{ matrix.target }}/release/entry-cli${{ matrix.binary-suffix }} dist/
115+
116+
# Create archive
117+
if [ "${{ matrix.archive-suffix }}" = "zip" ]; then
118+
cd dist && zip ../entry-cli-${{ matrix.target }}.${{ matrix.archive-suffix }} entry-cli${{ matrix.binary-suffix }}
119+
else
120+
cd dist && tar czf ../entry-cli-${{ matrix.target }}.${{ matrix.archive-suffix }} entry-cli${{ matrix.binary-suffix }}
121+
fi
122+
123+
- name: Upload artifact
124+
uses: actions/upload-artifact@v4
125+
with:
126+
name: entry-cli-${{ matrix.target }}
127+
path: cli/entry-cli-${{ matrix.target }}.${{ matrix.archive-suffix }}
128+
129+
- name: Upload to release
130+
if: github.event_name == 'release'
131+
uses: actions/upload-release-asset@v1
132+
env:
133+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
134+
with:
135+
upload_url: ${{ github.event.release.upload_url }}
136+
asset_path: cli/entry-cli-${{ matrix.target }}.${{ matrix.archive-suffix }}
137+
asset_name: entry-cli-${{ matrix.target }}.${{ matrix.archive-suffix }}
138+
asset_content_type: application/octet-stream
139+
140+
# Job to create a development release with all artifacts
141+
dev-release:
142+
needs: build
143+
runs-on: ubuntu-latest
144+
if: github.event_name != 'release'
145+
146+
steps:
147+
- uses: actions/checkout@v4
148+
149+
- name: Download all artifacts
150+
uses: actions/download-artifact@v4
151+
with:
152+
path: ./artifacts
153+
154+
- name: Display structure of downloaded files
155+
run: ls -laR ./artifacts
156+
157+
- name: Create development release
158+
uses: pyTooling/Actions/releaser@r0
159+
with:
160+
token: ${{ secrets.GITHUB_TOKEN }}
161+
tag: dev-latest
162+
rm: true # Remove old dev-latest release
163+
files: |
164+
./artifacts/entry-cli-x86_64-unknown-linux-gnu/entry-cli-x86_64-unknown-linux-gnu.tar.gz
165+
./artifacts/entry-cli-x86_64-unknown-linux-musl/entry-cli-x86_64-unknown-linux-musl.tar.gz
166+
./artifacts/entry-cli-x86_64-apple-darwin/entry-cli-x86_64-apple-darwin.tar.gz
167+
./artifacts/entry-cli-aarch64-apple-darwin/entry-cli-aarch64-apple-darwin.tar.gz
168+
./artifacts/entry-cli-x86_64-pc-windows-msvc/entry-cli-x86_64-pc-windows-msvc.zip

cli/.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Rust build artifacts
2+
/target/
3+
Cargo.lock
4+
5+
# IDE
6+
.idea/
7+
.vscode/
8+
*.swp
9+
*.swo
10+
*~
11+
12+
# OS
13+
.DS_Store
14+
Thumbs.db
15+
16+
# Debug
17+
*.pdb
18+
19+
# Backup files
20+
*.bak

cli/Cargo.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[package]
2+
name = "entry-cli"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["Entry API CLI Contributors"]
6+
description = "Command line interface for Entry API"
7+
license = "MIT"
8+
readme = "README.md"
9+
10+
[[bin]]
11+
name = "entry-cli"
12+
path = "src/main.rs"
13+
14+
[dependencies]
15+
anyhow = "1.0"
16+
chrono = { version = "0.4", features = ["serde"] }
17+
clap = { version = "4.5", features = ["derive", "env"] }
18+
colored = "2.1"
19+
dirs = "5.0"
20+
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
21+
serde = { version = "1.0", features = ["derive"] }
22+
serde_json = "1.0"
23+
tabled = "0.16"
24+
tempfile = "3.13"
25+
thiserror = "2.0"
26+
tokio = { version = "1.41", features = ["full"] }
27+
toml = "0.8"
28+
29+
[dev-dependencies]
30+
mockito = "1.5"

0 commit comments

Comments
 (0)