Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy

- name: Cache Rust build
uses: Swatinem/rust-cache@v2
Expand All @@ -48,6 +50,9 @@ jobs:
- name: Build frontend
run: pnpm -C apps/desktop build

- name: Run clippy
run: cargo clippy --workspace --all-targets -- -D warnings

- name: Run Rust tests
run: cargo test --workspace

Expand Down Expand Up @@ -162,3 +167,36 @@ jobs:

- name: Run desktop E2E
run: pnpm test:e2e

fmt:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Check formatting
run: cargo fmt --all -- --check

audit:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install cargo-audit
uses: taiki-e/install-action@v2
with:
tool: cargo-audit

# Fails on security vulnerabilities. Unmaintained/unsound advisories
# (e.g. the GTK3 bindings Tauri requires on Linux) surface as warnings
# without failing the build.
- name: Run cargo audit
run: cargo audit
106 changes: 94 additions & 12 deletions .github/workflows/release-linux.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
name: Release (Linux)

# Builds the OpenCherry desktop app as a Debian package (.deb).
# Builds the OpenCherry desktop app as Linux packages: Debian (.deb), AppImage,
# and RPM, each with a SHA-256 checksum.
#
# Triggers:
# - Push of a tag matching `v*` (e.g. v0.0.1) — attaches the .deb to the
# matching GitHub Release.
# - Manual `workflow_dispatch` — uploads the .deb as a build artifact only
# - Push of a tag matching `v*` (e.g. v0.0.1) — attaches the packages and
# checksums to the matching GitHub Release, sets the release notes from
# CHANGELOG.md, and (when enabled) publishes the AUR package.
# - Manual `workflow_dispatch` — uploads the packages as build artifacts only
# (no release).

on:
Expand Down Expand Up @@ -33,7 +35,8 @@ jobs:
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf
patchelf \
rpm

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
Expand All @@ -59,19 +62,98 @@ jobs:
run: pnpm install --frozen-lockfile
working-directory: apps/desktop

- name: Build .deb package
run: pnpm tauri build --bundles deb
- name: Build Linux bundles (.deb, .AppImage, .rpm)
run: pnpm tauri build --bundles deb,appimage,rpm
working-directory: apps/desktop
env:
# Stripping can corrupt the AppImage runtime on some toolchains.
NO_STRIP: "true"

- name: Upload .deb artifact
- name: Generate SHA-256 checksums
run: |
set -euo pipefail
for f in \
target/release/bundle/deb/*.deb \
target/release/bundle/appimage/*.AppImage \
target/release/bundle/rpm/*.rpm; do
[ -e "$f" ] || continue
( cd "$(dirname "$f")" && sha256sum "$(basename "$f")" > "$(basename "$f").sha256" )
done

- name: Upload Linux artifacts
uses: actions/upload-artifact@v4
with:
name: opencherry-linux-deb
path: target/release/bundle/deb/*.deb
name: opencherry-linux-packages
path: |
target/release/bundle/deb/*.deb
target/release/bundle/deb/*.deb.sha256
target/release/bundle/appimage/*.AppImage
target/release/bundle/appimage/*.AppImage.sha256
target/release/bundle/rpm/*.rpm
target/release/bundle/rpm/*.rpm.sha256
if-no-files-found: error

- name: Attach .deb to release
- name: Extract release notes from CHANGELOG
if: startsWith(github.ref, 'refs/tags/v')
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#v}"
awk -v ver="$version" '
$0 ~ "^## \\[" ver "\\]" { capture=1; next }
capture && /^## \[/ { exit }
capture && /^\[[^]]+\]: / { exit }
capture { print }
' CHANGELOG.md > changelog_section.md
if [ ! -s changelog_section.md ]; then
echo "Release ${GITHUB_REF_NAME}" > changelog_section.md
fi

# The Linux workflow uniquely owns the release body; macOS/Windows attach
# files only. action-gh-release@v2 preserves an existing body when called
# without one, so this is race-safe across the three parallel workflows.
- name: Attach Linux assets to release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: target/release/bundle/deb/*.deb
body_path: changelog_section.md
files: |
target/release/bundle/deb/*.deb
target/release/bundle/deb/*.deb.sha256
target/release/bundle/appimage/*.AppImage
target/release/bundle/appimage/*.AppImage.sha256
target/release/bundle/rpm/*.rpm
target/release/bundle/rpm/*.rpm.sha256

# Publishes the AUR package `opencherry-bin`. Dormant until configured: set the
# repo variable PUBLISH_AUR=true and provide the AUR_SSH_PRIVATE_KEY secret plus
# AUR_COMMIT_USERNAME / AUR_COMMIT_EMAIL variables. See packaging/aur/README.md.
publish-aur:
needs: build-linux
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && vars.PUBLISH_AUR == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Inject version and checksum into PKGBUILD
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#v}"
base="https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}"
sum_x86="$(curl -fsSL "${base}/opencherry_${version}_amd64.AppImage.sha256" | cut -d' ' -f1)"
[ -n "$sum_x86" ] || { echo "missing x86_64 AppImage checksum"; exit 1; }
sed -i \
-e "s/^pkgver=.*/pkgver=${version}/" \
-e "s/REPLACE_WITH_SHA256_X86_64/${sum_x86}/" \
packaging/aur/PKGBUILD

- name: Publish to AUR
uses: KSXGitHub/github-actions-deploy-aur@v4.1.3
with:
pkgname: opencherry-bin
pkgbuild: packaging/aur/PKGBUILD
commit_username: ${{ vars.AUR_COMMIT_USERNAME }}
commit_email: ${{ vars.AUR_COMMIT_EMAIL }}
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: "Update to ${{ github.ref_name }}"
updpkgsums: false
68 changes: 63 additions & 5 deletions .github/workflows/release-macos.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
name: Release (macOS)

# Builds the OpenCherry desktop app as a macOS disk image (.dmg), for both
# Apple Silicon (aarch64) and Intel (x86_64).
# Apple Silicon (aarch64) and Intel (x86_64), each with a SHA-256 checksum.
#
# Triggers:
# - Push of a tag matching `v*` (e.g. v0.0.1) — attaches the .dmg files to the
# matching GitHub Release.
# - Push of a tag matching `v*` (e.g. v0.0.1) — attaches the .dmg files and
# checksums to the matching GitHub Release.
# - Manual `workflow_dispatch` — uploads the .dmg files as build artifacts
# only (no release), useful for contributors without a Mac.
#
# The images are unsigned and not notarized: on first launch macOS Gatekeeper
# may block the app (right-click → Open to bypass).
#
# This workflow attaches files only; the Linux release workflow owns the release
# notes body (action-gh-release@v2 preserves an existing body when not set here).

on:
push:
Expand Down Expand Up @@ -68,15 +71,70 @@ jobs:
run: pnpm tauri build --bundles dmg --target ${{ matrix.target }}
working-directory: apps/desktop

- name: Generate SHA-256 checksum
run: |
set -euo pipefail
for f in target/${{ matrix.target }}/release/bundle/dmg/*.dmg; do
[ -e "$f" ] || continue
( cd "$(dirname "$f")" && shasum -a 256 "$(basename "$f")" > "$(basename "$f").sha256" )
done

- name: Upload .dmg artifact
uses: actions/upload-artifact@v4
with:
name: opencherry-macos-${{ matrix.arch }}-dmg
path: target/${{ matrix.target }}/release/bundle/dmg/*.dmg
path: |
target/${{ matrix.target }}/release/bundle/dmg/*.dmg
target/${{ matrix.target }}/release/bundle/dmg/*.dmg.sha256
if-no-files-found: error

- name: Attach .dmg to release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: target/${{ matrix.target }}/release/bundle/dmg/*.dmg
files: |
target/${{ matrix.target }}/release/bundle/dmg/*.dmg
target/${{ matrix.target }}/release/bundle/dmg/*.dmg.sha256

# Publishes the Homebrew cask to the tap. Dormant until configured: set the
# repo variable PUBLISH_HOMEBREW=true and provide the HOMEBREW_TAP_TOKEN secret.
# See packaging/homebrew/README.md.
publish-homebrew:
needs: build-macos
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && vars.PUBLISH_HOMEBREW == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Render cask from release checksums
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#v}"
base="https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}"
arm="$(curl -fsSL "${base}/opencherry_${version}_aarch64.dmg.sha256" | cut -d' ' -f1)"
intel="$(curl -fsSL "${base}/opencherry_${version}_x64.dmg.sha256" | cut -d' ' -f1)"
[ -n "$arm" ] && [ -n "$intel" ] || { echo "missing dmg checksum(s)"; exit 1; }
sed -e "s/^ version .*/ version \"${version}\"/" \
-e "s/REPLACE_WITH_SHA256_ARM/${arm}/" \
-e "s/REPLACE_WITH_SHA256_INTEL/${intel}/" \
packaging/homebrew/opencherry.rb > opencherry.rb

- name: Push cask to tap
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
set -euo pipefail
git clone "https://x-access-token:${GH_TOKEN}@github.com/4nrry/homebrew-tap.git" tap
mkdir -p tap/Casks
cp opencherry.rb tap/Casks/opencherry.rb
cd tap
git config user.name "opencherry-release-bot"
git config user.email "noreply@opencherry.ai"
git add Casks/opencherry.rb
if git diff --cached --quiet; then
echo "cask unchanged; nothing to push"
else
git commit -m "opencherry ${GITHUB_REF_NAME}"
git push
fi
35 changes: 33 additions & 2 deletions .github/workflows/release-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,46 @@ jobs:
run: pnpm tauri build --bundles nsis
working-directory: apps/desktop

- name: Generate SHA-256 checksum
shell: pwsh
run: |
Get-ChildItem target/release/bundle/nsis/*-setup.exe | ForEach-Object {
$hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLower()
"$hash $($_.Name)" | Out-File -NoNewline -Encoding ascii "$($_.FullName).sha256"
}

- name: Upload installer artifact
uses: actions/upload-artifact@v4
with:
name: opencherry-windows-installer
path: target/release/bundle/nsis/*-setup.exe
path: |
target/release/bundle/nsis/*-setup.exe
target/release/bundle/nsis/*-setup.exe.sha256
if-no-files-found: error

- name: Attach installer to release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: target/release/bundle/nsis/*-setup.exe
files: |
target/release/bundle/nsis/*-setup.exe
target/release/bundle/nsis/*-setup.exe.sha256

# Publishes to the Windows Package Manager (winget). Dormant until configured:
# set the repo variable PUBLISH_WINGET=true and provide the WINGET_TOKEN secret
# (a CLASSIC PAT with public_repo scope; fine-grained tokens are not supported).
# A fork of microsoft/winget-pkgs must exist under the repo owner, and the
# package's first version must already be in winget (submitted once manually).
# See packaging/winget/README.md.
publish-winget:
needs: build-windows
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && vars.PUBLISH_WINGET == 'true'
steps:
- name: Publish to winget
uses: vedantmgoyal9/winget-releaser@v2
with:
identifier: 4nrry.OpenCherryDesktop
installers-regex: '\.exe$'
release-tag: ${{ github.ref_name }}
token: ${{ secrets.WINGET_TOKEN }}
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.0.1] - 2026-06-22

### Added

- Initial public alpha of OpenCherry: an Ubuntu/GNOME-first, multi-repo ×
multi-agent control tower for AI-assisted coding, built on Tauri 2.
- Multi-repo sidebar with per-repo Git status, grouped diffs (conflicted,
staged, unstaged, untracked), stage/unstage, commit, publish, and sync.
- Running-agent detection (Claude Code, OpenCode, Codex, Gemini CLI, Aider, …).
- Linux packages: `.deb`, `.AppImage`, and `.rpm`.
- macOS disk images (`.dmg`) for Apple Silicon and Intel.
- Windows NSIS installer (`.exe`).
- One-command Linux install script (`scripts/install.sh`) and SHA-256 checksums
attached to every release artifact.

[Unreleased]: https://github.com/4nrry/opencherry/compare/v0.0.1...HEAD
[0.0.1]: https://github.com/4nrry/opencherry/releases/tag/v0.0.1
Loading
Loading