v1.4.0: Global Hotkeys + CLI Tool + Raycast Extension #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build & Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| build: | |
| name: Build ${{ matrix.label }} | |
| runs-on: macos-15 | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: arm64 | |
| sdk_arch: arm64 | |
| label: Apple-Silicon | |
| - arch: x86_64 | |
| sdk_arch: x86_64 | |
| label: Intel | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Show Swift version | |
| run: swift --version | |
| - name: Build release binaries (GUI + CLI) | |
| run: | | |
| swift build -c release --arch ${{ matrix.arch }} | |
| - name: Package .app bundle + CLI binary | |
| env: | |
| VERSION: ${{ github.ref_name }} | |
| run: | | |
| VER="${VERSION#v}" | |
| APP_NAME="Codex Rate Watcher" | |
| GUI_EXEC="CodexRateWatcherNative" | |
| CLI_EXEC="codex-rate" | |
| APP_DIR="dist/${APP_NAME}.app" | |
| BUILD_DIR=".build/${{ matrix.arch }}-apple-macosx/release" | |
| rm -rf dist | |
| mkdir -p "${APP_DIR}/Contents/MacOS" | |
| mkdir -p "${APP_DIR}/Contents/Resources" | |
| # --- GUI app bundle --- | |
| cp "${BUILD_DIR}/${GUI_EXEC}" \ | |
| "${APP_DIR}/Contents/MacOS/${GUI_EXEC}" | |
| cat > "${APP_DIR}/Contents/Info.plist" << PLIST | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" | |
| "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>CFBundleName</key> | |
| <string>${APP_NAME}</string> | |
| <key>CFBundleDisplayName</key> | |
| <string>${APP_NAME}</string> | |
| <key>CFBundleIdentifier</key> | |
| <string>com.sinoon.codex-rate-watcher</string> | |
| <key>CFBundleVersion</key> | |
| <string>${VER}</string> | |
| <key>CFBundleShortVersionString</key> | |
| <string>${VER}</string> | |
| <key>CFBundleExecutable</key> | |
| <string>${GUI_EXEC}</string> | |
| <key>CFBundlePackageType</key> | |
| <string>APPL</string> | |
| <key>LSMinimumSystemVersion</key> | |
| <string>14.0</string> | |
| <key>LSUIElement</key> | |
| <true/> | |
| <key>NSHighResolutionCapable</key> | |
| <true/> | |
| </dict> | |
| </plist> | |
| PLIST | |
| # --- CLI binary alongside the .app --- | |
| cp "${BUILD_DIR}/${CLI_EXEC}" "dist/${CLI_EXEC}" | |
| echo "Built ${APP_NAME}.app + ${CLI_EXEC} (${VER}) for ${{ matrix.arch }}" | |
| - name: Create ZIP archive | |
| env: | |
| VERSION: ${{ github.ref_name }} | |
| run: | | |
| VER="${VERSION#v}" | |
| cd dist | |
| zip -r -y "../Codex-Rate-Watcher-${VER}-${{ matrix.label }}.zip" \ | |
| "Codex Rate Watcher.app" \ | |
| "codex-rate" | |
| cd .. | |
| echo "ASSET_PATH=Codex-Rate-Watcher-${VER}-${{ matrix.label }}.zip" >> $GITHUB_ENV | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: app-${{ matrix.arch }} | |
| path: ${{ env.ASSET_PATH }} | |
| release: | |
| name: Create GitHub Release | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: List artifacts | |
| run: ls -lhR artifacts/ | |
| - name: Generate release notes | |
| id: notes | |
| env: | |
| VERSION: ${{ github.ref_name }} | |
| run: | | |
| VER="${VERSION#v}" | |
| PREV_TAG=$(git tag --sort=-v:refname | grep '^v' | sed -n '2p' || echo "") | |
| { | |
| echo "body<<RELEASE_EOF" | |
| echo "## Codex Rate Watcher ${VERSION}" | |
| echo "" | |
| echo "### Downloads" | |
| echo "" | |
| echo "| Platform | File |" | |
| echo "|---|---|" | |
| echo "| **Apple Silicon** (M1/M2/M3/M4) | \`Codex-Rate-Watcher-${VER}-Apple-Silicon.zip\` |" | |
| echo "| **Intel** (x86_64) | \`Codex-Rate-Watcher-${VER}-Intel.zip\` |" | |
| echo "" | |
| echo "### What's Included" | |
| echo "" | |
| echo "Each ZIP contains:" | |
| echo "- **Codex Rate Watcher.app** -- Menu bar GUI" | |
| echo "- **codex-rate** -- CLI tool (copy to a directory on your PATH for terminal access)" | |
| echo "" | |
| echo "### Installation" | |
| echo "" | |
| echo "1. Download the ZIP for your Mac chip" | |
| echo "2. Unzip and drag **Codex Rate Watcher.app** to Applications" | |
| echo "3. Optionally copy codex-rate to a directory on your PATH for CLI usage" | |
| echo "4. Launch the app -- it lives in your menu bar" | |
| echo "5. Codex CLI must be logged in (~/.codex/auth.json)" | |
| echo "" | |
| echo "> **Note:** The app is not notarized. On first launch: right-click the app, select Open, or go to System Settings > Privacy & Security > Open Anyway." | |
| echo "" | |
| echo "### Key Features" | |
| echo "" | |
| echo "- Real-time 3-dimensional quota tracking (5h primary + weekly + code review)" | |
| echo "- Burn-rate estimation with linear regression" | |
| echo "- Reset countdown on every quota card" | |
| echo "- Multi-account management with weighted smart switching" | |
| echo "- Orphaned snapshot auto-reconciliation" | |
| echo "- Plus / Team plan badges" | |
| echo "- Dark-themed Linear-inspired UI" | |
| echo "- **Global Hotkey** -- Toggle the popover from anywhere" | |
| echo "- **codex-rate CLI** -- Terminal-first monitoring with JSON output" | |
| echo "- **Raycast Extension** -- Native integration via CLI bridge" | |
| echo "- Zero dependencies -- pure Apple system frameworks" | |
| echo "" | |
| if [ -n "$PREV_TAG" ]; then | |
| echo "### Changes since ${PREV_TAG}" | |
| echo "" | |
| git log --pretty=format:"- %s (%h)" "${PREV_TAG}..HEAD" -- || true | |
| else | |
| echo "### Changes" | |
| echo "" | |
| echo "Initial release!" | |
| fi | |
| echo "" | |
| echo "RELEASE_EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: "Codex Rate Watcher ${{ github.ref_name }}" | |
| body: ${{ steps.notes.outputs.body }} | |
| draft: false | |
| prerelease: false | |
| files: artifacts/*.zip |