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
83 changes: 83 additions & 0 deletions .github/workflows/update-cask.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Update Cask on Release

on:
release:
types: [published]

jobs:
update-cask:
runs-on: ubuntu-latest
permissions:
contents: write
if: startsWith(github.event.release.tag_name, 'v') && endsWith(github.event.release.tag_name, '-tauri')
steps:
- name: Checkout tap repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
Comment on lines +15 to +17
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Check out a branch before pushing cask updates

When this workflow runs from release.published, GitHub documents GITHUB_REF as the release tag (refs/tags/<tag_name>), and actions/checkout defaults to the event ref; this leaves the job on a detached tag checkout. The later git commit succeeds, but git push without a refspec then fails with “You are not currently on a branch”, so every release that needs a cask checksum bump will leave Casks/openless.rb stale unless the checkout targets the tap branch (or the push uses an explicit HEAD:<branch> refspec).

Useful? React with 👍 / 👎.


- name: Extract version from tag
id: version
run: |
TAG="${{ github.event.release.tag_name }}"
VERSION="${TAG#v}"
VERSION="${VERSION%-tauri}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Detected version: $VERSION"

- name: Fetch release assets SHA256
id: sha256
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
REPO="${{ github.repository }}"

# Fetch release assets info
RESPONSE=$(gh api "repos/$REPO/releases/tags/v${VERSION}-tauri")

# Extract SHA256 for aarch64 DMG
ARM64_SHA=$(echo "$RESPONSE" | jq -r '.assets[] | select(.name | contains("aarch64.dmg")) | .digest' | sed 's/sha256://')

# Extract SHA256 for x64 DMG
X64_SHA=$(echo "$RESPONSE" | jq -r '.assets[] | select(.name | contains("_x64.dmg")) | .digest' | sed 's/sha256://')
Comment thread
Kiruno-lz marked this conversation as resolved.

echo "arm64_sha=$ARM64_SHA" >> "$GITHUB_OUTPUT"
echo "x64_sha=$X64_SHA" >> "$GITHUB_OUTPUT"

echo "aarch64 DMG SHA256: $ARM64_SHA"
echo "x64 DMG SHA256: $X64_SHA"

- name: Update Cask file
run: |
VERSION="${{ steps.version.outputs.version }}"
ARM64_SHA="${{ steps.sha256.outputs.arm64_sha }}"
X64_SHA="${{ steps.sha256.outputs.x64_sha }}"
CASK_FILE="Casks/openless.rb"

# Update version
sed -i "s/version \"[^\"]*\"/version \"$VERSION\"/" "$CASK_FILE"

# Update SHA256 values
sed -i "s/sha256 arm: \"[^\"]*\"/sha256 arm: \"$ARM64_SHA\"/" "$CASK_FILE"
sed -i "s/intel: \"[^\"]*\"/intel: \"$X64_SHA\"/" "$CASK_FILE"

echo "Updated $CASK_FILE:"
cat "$CASK_FILE"

- name: Commit and push changes
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"

VERSION="${{ steps.version.outputs.version }}"

git add Casks/openless.rb

if git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi

git commit -m "[cask] Update openless to $VERSION"
git push
29 changes: 29 additions & 0 deletions Casks/openless.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
cask "openless" do
arch arm: "aarch64", intel: "x64"

version "1.2.22"
sha256 arm: "8e65729eb671f5fec3ce392d4f8dfd33303f1c84f8f4533683f8d3a3afd1e21d",
intel: "6d97fb7cab173b4f3241aa18b3db0f51a03a03d6b2bdea48cab8fe761440df7b"

url "https://github.com/appergb/openless/releases/download/v#{version}-tauri/OpenLess_#{version}_#{arch}.dmg"
name "OpenLess"
desc "Menu-bar voice input layer for macOS"
homepage "https://github.com/appergb/openless"

livecheck do
url :url
regex(/^v?(\d+(?:\.\d+)+)[._-]tauri$/i)
end

auto_updates true

app "OpenLess.app"

zap trash: [
"~/Library/Application Support/OpenLess",
"~/Library/Caches/com.openless.app",
"~/Library/Logs/OpenLess",
"~/Library/Preferences/com.openless.app.plist",
"~/Library/WebKit/com.openless.app",
]
end
67 changes: 67 additions & 0 deletions Formula/openless.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
class Openless < Formula
desc "Menu-bar voice input layer for macOS"
homepage "https://github.com/appergb/openless"
url "https://github.com/appergb/openless/archive/refs/tags/v1.2.20-tauri.tar.gz"
sha256 "be1363f7762a42b7e932ec3cc687cfdfb5b550b6cf1c96d52a1f87c906f27863"
license "MIT"

head "https://github.com/appergb/openless.git", branch: "main"

depends_on "rust" => :build
depends_on "node" => :build
depends_on :macos
depends_on arch: :arm64

# qwen-asr submodule for local ASR engine on macOS
resource "qwen-asr" do
url "https://github.com/antirez/qwen-asr.git",
revision: "b00b789b17051aea61e9717458171100662318a4"
end

def install
# Place submodule at expected path before building
vendor_dir = "openless-all/app/src-tauri/vendor/qwen-asr"
rm_rf vendor_dir
resource("qwen-asr").stage(vendor_dir)

cd "openless-all/app" do
# Install frontend dependencies
system "npm", "ci"

# Build Tauri app with ad-hoc signing (no Developer ID required)
ENV["APPLE_SIGNING_IDENTITY"] = "-"
system "npm", "run", "tauri", "--", "build"

# Install the .app bundle
prefix.install "src-tauri/target/release/bundle/macos/OpenLess.app"
end

# Symlink binary for command-line access
bin.install_symlink prefix/"OpenLess.app/Contents/MacOS/openless"
end

def caveats
<<~EOS
OpenLess.app has been installed to:
#{prefix}/OpenLess.app

To use it, link it into /Applications:
ln -sf #{opt_prefix}/OpenLess.app /Applications/OpenLess.app

Or launch it directly:
open #{opt_prefix}/OpenLess.app

First-time setup:
- Grant Accessibility permission when prompted
- Grant Microphone permission when prompted

If Gatekeeper blocks the app (ad-hoc signed), run:
xattr -cr /Applications/OpenLess.app
EOS
end

test do
assert_path_exists prefix/"OpenLess.app"
assert_predicate prefix/"OpenLess.app/Contents/MacOS/openless", :executable?
end
end
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ OpenLess does one thing: **turn speech into usable written text (especially AI p
Go to [Releases](../../releases) and download:
- **macOS**: `OpenLess_<version>_aarch64.dmg` — open, drag to `/Applications`
- **Windows**: `OpenLess_<version>_x64-setup.exe` — run the installer
- **macOS(brew install)**:
```bash
brew tap appergb/openless https://github.com/appergb/openless
brew install --cask openless
xattr -cr /Applications/OpenLess.app

# Upgrade to the latest version
brew update && brew upgrade openless
```

On first launch, grant the permissions the app requests:

Expand Down
11 changes: 10 additions & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,17 @@ OpenLess 只做一件事:**把语音变成可用的书面文字(尤其是 AI
## 下载与安装(普通用户)

到 [Releases](../../releases) 下载对应平台的安装包:
- **macOS**:`OpenLess_<版本>_aarch64.dmg` — 打开后拖入「应用程序」
- **Windows**:`OpenLess_<版本>_x64-setup.exe` — 运行安装程序
- **macOS**:`OpenLess_<版本>_aarch64.dmg` — 打开后拖入「应用程序」
- **macOS(brew install)**:
```bash
brew tap appergb/openless https://github.com/appergb/openless
brew install --cask openless
xattr -cr /Applications/OpenLess.app

# Upgrade to the latest version
brew update && brew upgrade openless
```

首次启动需要授予权限:

Expand Down