@ondeinference / cli / commits / d024f01

Add GitHub Actions workflows for release and Homebrew tap

- Add release-github.yml for building and releasing binaries - Add release-homebrew.yml for updating Homebrew tap on release - Update README with install instructions for Homebrew, pip, binaries, and cargo - Update PyPI description for onde-cli

keypair34 committed Apr 22, 2026 at 14:31 UTC d024f01aca7c21b059755446be927a888cdb3a11
4 files changed +356 -4
.github/workflows/release-github.yml new
+191
@@ -0,0 +1,191 @@
1 +name: GitHub Release
2 +
3 +on:
4 + push:
5 + tags:
6 + - "v*.*.*"
7 + workflow_dispatch:
8 + inputs:
9 + tag:
10 + description: "Release tag (e.g. v0.1.1)"
11 + required: true
12 +
13 +permissions:
14 + contents: write
15 + actions: write
16 +
17 +env:
18 + PROJECT_NAME: onde
19 + CARGO_TERM_COLOR: always
20 + ONDE_APP_ID: ${{ secrets.ONDE_APP_ID }}
21 + ONDE_APP_SECRET: ${{ secrets.ONDE_APP_SECRET }}
22 + GRESIQ_API_KEY: ${{ secrets.GRESIQ_API_KEY }}
23 + GRESIQ_API_SECRET: ${{ secrets.GRESIQ_API_SECRET }}
24 +
25 +jobs:
26 + build:
27 + name: Build binary (${{ matrix.name }})
28 + runs-on: ${{ matrix.runner }}
29 +
30 + strategy:
31 + fail-fast: false
32 + matrix:
33 + include:
34 + - name: linux-amd64
35 + runner: ubuntu-latest
36 + target: x86_64-unknown-linux-gnu
37 + - name: linux-arm64
38 + runner: ubuntu-24.04-arm
39 + target: aarch64-unknown-linux-gnu
40 + - name: win-amd64
41 + runner: windows-latest
42 + target: x86_64-pc-windows-msvc
43 + - name: win-arm64
44 + runner: windows-latest
45 + target: aarch64-pc-windows-msvc
46 + - name: macos-amd64
47 + runner: macos-15-intel
48 + target: x86_64-apple-darwin
49 + - name: macos-arm64
50 + runner: macos-latest
51 + target: aarch64-apple-darwin
52 +
53 + steps:
54 + - name: Checkout
55 + uses: actions/checkout@v4
56 + with:
57 + ref: ${{ github.event.inputs.tag || github.ref }}
58 +
59 + - name: Set the release version
60 + shell: bash
61 + run: |
62 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
63 + release_version="${GITHUB_REF_NAME#v}"
64 + else
65 + release_version="${{ github.event.inputs.tag }}"
66 + release_version="${release_version#v}"
67 + fi
68 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
69 +
70 + - name: Read Rust toolchain
71 + shell: bash
72 + run: |
73 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
74 + if [ -z "$rust_toolchain" ]; then
75 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
76 + exit 1
77 + fi
78 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
79 +
80 + - name: Install Rust toolchain
81 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
82 + with:
83 + toolchain: ${{ env.RUST_TOOLCHAIN }}
84 + targets: ${{ matrix.target }}
85 +
86 + - name: Setup Rust cache
87 + uses: Swatinem/rust-cache@v2
88 + with:
89 + key: github-${{ matrix.target }}
90 +
91 + - name: Build binary
92 + shell: bash
93 + run: cargo build --locked --release --target ${{ matrix.target }}
94 +
95 + - name: Package binary
96 + shell: bash
97 + run: |
98 + BIN_SUFFIX=""
99 + if [[ "${{ matrix.runner }}" == "windows-latest" ]]; then
100 + BIN_SUFFIX=".exe"
101 + fi
102 +
103 + BIN_OUTPUT="target/${{ matrix.target }}/release/${PROJECT_NAME}${BIN_SUFFIX}"
104 + BIN_RELEASE="${PROJECT_NAME}-${{ matrix.name }}${BIN_SUFFIX}"
105 +
106 + mkdir -p ./release
107 + mv "${BIN_OUTPUT}" "./release/${BIN_RELEASE}"
108 +
109 + - name: Package macOS tarball for Homebrew
110 + if: contains(matrix.target, 'apple-darwin')
111 + shell: bash
112 + run: |
113 + ARCHIVE_NAME="${PROJECT_NAME}-${{ matrix.name }}.tar.gz"
114 +
115 + mkdir -p staging-brew
116 + cp "./release/${PROJECT_NAME}-${{ matrix.name }}" "staging-brew/${PROJECT_NAME}"
117 + strip "staging-brew/${PROJECT_NAME}"
118 +
119 + tar -C staging-brew -czf "${ARCHIVE_NAME}" "${PROJECT_NAME}"
120 +
121 + shasum -a 256 "${ARCHIVE_NAME}" | awk '{print $1}' > "${ARCHIVE_NAME}.sha256"
122 +
123 + echo "Archive: ${ARCHIVE_NAME}"
124 + echo "SHA256: $(cat "${ARCHIVE_NAME}.sha256")"
125 +
126 + - name: Upload binary artifact
127 + uses: actions/upload-artifact@v4
128 + with:
129 + name: binary-${{ matrix.name }}
130 + path: release/*
131 +
132 + - name: Upload macOS Homebrew artifacts
133 + if: contains(matrix.target, 'apple-darwin')
134 + uses: actions/upload-artifact@v4
135 + with:
136 + name: homebrew-${{ matrix.name }}
137 + path: |
138 + ${{ env.PROJECT_NAME }}-${{ matrix.name }}.tar.gz
139 + ${{ env.PROJECT_NAME }}-${{ matrix.name }}.tar.gz.sha256
140 +
141 + release:
142 + name: Create GitHub Release
143 + needs: build
144 + runs-on: ubuntu-latest
145 + if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
146 +
147 + steps:
148 + - name: Resolve tag
149 + id: tag
150 + shell: bash
151 + run: |
152 + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
153 + echo "tag=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
154 + else
155 + echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
156 + fi
157 +
158 + - name: Download binary artifacts
159 + uses: actions/download-artifact@v4
160 + with:
161 + pattern: "binary-*"
162 + path: release
163 + merge-multiple: true
164 +
165 + - name: Download Homebrew artifacts
166 + uses: actions/download-artifact@v4
167 + with:
168 + pattern: "homebrew-*"
169 + path: release
170 + merge-multiple: true
171 +
172 + - name: Release
173 + uses: softprops/action-gh-release@v2
174 + with:
175 + tag_name: ${{ steps.tag.outputs.tag }}
176 + files: release/*
177 +
178 + - name: Trigger Homebrew release
179 + uses: actions/github-script@v7
180 + with:
181 + script: |
182 + await github.rest.actions.createWorkflowDispatch({
183 + owner: context.repo.owner,
184 + repo: context.repo.repo,
185 + workflow_id: 'release-homebrew.yml',
186 + ref: 'main',
187 + inputs: {
188 + tag: '${{ steps.tag.outputs.tag }}'
189 + }
190 + })
191 + console.log('Dispatched release-homebrew.yml for tag ${{ steps.tag.outputs.tag }}')
.github/workflows/release-homebrew.yml new
+116
@@ -0,0 +1,116 @@
1 +name: Homebrew CLI Release
2 +
3 +on:
4 + workflow_dispatch:
5 + inputs:
6 + tag:
7 + description: "Release tag (e.g. v0.1.1)"
8 + required: true
9 +
10 +permissions:
11 + contents: read
12 +
13 +env:
14 + REPO: ondeinference/onde-cli
15 +
16 +jobs:
17 + update-homebrew-tap:
18 + name: Update Homebrew tap
19 + runs-on: ubuntu-latest
20 +
21 + steps:
22 + - name: Resolve tag and version
23 + id: release
24 + shell: bash
25 + run: |
26 + TAG="${{ github.event.inputs.tag }}"
27 + VERSION="${TAG#v}"
28 +
29 + echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
30 + echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
31 +
32 + - name: Read SHA256 checksums from release
33 + id: sha
34 + env:
35 + GH_TOKEN: ${{ github.token }}
36 + shell: bash
37 + run: |
38 + mkdir -p artifacts
39 +
40 + gh release download "${{ steps.release.outputs.tag }}" \
41 + --repo "${{ env.REPO }}" \
42 + --pattern "onde-macos-*.tar.gz.sha256" \
43 + --dir artifacts/
44 +
45 + ARM64_SHA=$(cat artifacts/onde-macos-arm64.tar.gz.sha256)
46 + AMD64_SHA=$(cat artifacts/onde-macos-amd64.tar.gz.sha256)
47 +
48 + echo "arm64=${ARM64_SHA}" >> "$GITHUB_OUTPUT"
49 + echo "amd64=${AMD64_SHA}" >> "$GITHUB_OUTPUT"
50 +
51 + echo "ARM64 SHA256: ${ARM64_SHA}"
52 + echo "AMD64 SHA256: ${AMD64_SHA}"
53 +
54 + - name: Checkout Homebrew tap
55 + uses: actions/checkout@v4
56 + with:
57 + repository: ondeinference/homebrew-tap
58 + token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
59 + path: homebrew-tap
60 +
61 + - name: Generate formula
62 + shell: bash
63 + run: |
64 + VERSION="${{ steps.release.outputs.version }}"
65 + TAG="${{ steps.release.outputs.tag }}"
66 + ARM64_SHA="${{ steps.sha.outputs.arm64 }}"
67 + AMD64_SHA="${{ steps.sha.outputs.amd64 }}"
68 +
69 + mkdir -p homebrew-tap/Formula
70 +
71 + cat > homebrew-tap/Formula/onde.rb <<FORMULA
72 + # frozen_string_literal: true
73 +
74 + # Homebrew formula for the Onde Inference CLI (\`onde\` binary).
75 + class Onde < Formula
76 + desc 'Command-line interface for Onde Inference'
77 + homepage 'https://ondeinference.com'
78 + version '${VERSION}'
79 + license 'MIT OR Apache-2.0'
80 +
81 + on_macos do
82 + on_arm do
83 + url 'https://github.com/${REPO}/releases/download/${TAG}/onde-macos-arm64.tar.gz'
84 + sha256 '${ARM64_SHA}'
85 + end
86 + on_intel do
87 + url 'https://github.com/${REPO}/releases/download/${TAG}/onde-macos-amd64.tar.gz'
88 + sha256 '${AMD64_SHA}'
89 + end
90 + end
91 +
92 + def install
93 + bin.install 'onde'
94 + end
95 +
96 + test do
97 + assert_match version.to_s, shell_output("#{bin}/onde --version", 1)
98 + end
99 + end
100 + FORMULA
101 +
102 + echo "Generated formula:"
103 + cat homebrew-tap/Formula/onde.rb
104 +
105 + - name: Commit and push
106 + shell: bash
107 + run: |
108 + VERSION="${{ steps.release.outputs.version }}"
109 +
110 + cd homebrew-tap
111 + git config user.name "github-actions[bot]"
112 + git config user.email "github-actions[bot]@users.noreply.github.com"
113 + git add Formula/onde.rb
114 + git diff --cached --quiet && echo "No changes to commit" && exit 0
115 + git commit -m "Update onde to ${VERSION}"
116 + git push
README.md
+48 -3
@@ -11,6 +11,8 @@
11 <p align="center">
12 <a href="https://ondeinference.com"><img src="https://img.shields.io/badge/ondeinference.com-235843?style=flat-square&labelColor=17211D" alt="Website"></a>
13 <a href="https://apps.apple.com/se/developer/splitfire-ab/id1831430993"><img src="https://img.shields.io/badge/App%20Store-live-235843?style=flat-square&labelColor=17211D" alt="App Store"></a>
14 + <a href="https://pypi.org/project/onde-cli/"><img src="https://img.shields.io/pypi/v/onde-cli?style=flat-square&labelColor=17211D&color=235843" alt="PyPI"></a>
15 + <a href="https://crates.io/crates/onde-cli"><img src="https://img.shields.io/crates/v/onde-cli?style=flat-square&labelColor=17211D&color=235843" alt="Crates.io"></a>
16 </p>
17
18 <p align="center">
@@ -21,15 +23,56 @@
23
24 Manage your Onde Inference account from the terminal. Sign up, sign in, and access the service.
25
24 -More commands are coming.
25 -
26 ## Install
27
28 +### Homebrew (macOS)
29 +
30 +```sh
31 +brew tap ondeinference/homebrew-tap
32 +brew install onde
33 +```
34 +
35 +### pip
36 +
37 +```sh
38 +pip install onde-cli
39 +```
40 +
41 +### uv
42 +
43 +```sh
44 +uv tool install onde-cli
45 +```
46 +
47 +### Pre-built binary (macOS, Linux, Windows)
48 +
49 +Download the latest binary for your platform from the
50 +[GitHub Releases](https://github.com/ondeinference/onde-cli/releases) page,
51 +make it executable, and move it onto your `PATH`:
52 +
53 +```sh
54 +# macOS arm64 example
55 +curl -Lo onde https://github.com/ondeinference/onde-cli/releases/latest/download/onde-macos-arm64
56 +chmod +x onde
57 +mv onde /usr/local/bin/onde
58 +```
59 +
60 +| Platform | File |
61 +|---|---|
62 +| macOS Apple silicon | `onde-macos-arm64` |
63 +| macOS Intel | `onde-macos-amd64` |
64 +| Linux x64 | `onde-linux-amd64` |
65 +| Linux arm64 | `onde-linux-arm64` |
66 +| Windows x64 | `onde-win-amd64.exe` |
67 +| Windows arm64 | `onde-win-arm64.exe` |
68 +
69 +### cargo
70 +
71 ```sh
72 cargo install onde-cli
73 ```
74
32 -Or build locally:
75 +### Build from source
76
77 ```sh
78 git clone https://github.com/ondeinference/onde-cli
@@ -38,6 +81,8 @@ cargo build --release
81 ./target/release/onde
82 ```
83
84 +---
85 +
86 ## Usage
87
88 ```sh
pypi/pyproject.toml
+1 -1
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
5 [project]
6 name = "onde-cli"
7 -description = "Terminal UI for signing up, signing in, and managing your Onde Inference account."
7 +description = "Terminal UI for Onde Inference models, apps, and account management."
8 readme = "README.md"
9 requires-python = ">=3.8"
10 dynamic = ["version"]