-
Notifications
You must be signed in to change notification settings - Fork 4
chore: protect main, Homebrew install path, and PR title checks #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Default owners for review routing (optional reviews; PRs still required on main). | ||
| * @DevVig | ||
|
|
||
| /crates/ @DevVig | ||
| /apps/microbridge-ui/ @DevVig | ||
| /adapters/ @DevVig | ||
| /Formula/ @DevVig | ||
| /.github/ @DevVig |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| name: PR title | ||
|
|
||
| on: | ||
| pull_request_target: | ||
| types: [opened, edited, synchronize, reopened] | ||
|
|
||
| permissions: | ||
| pull-requests: read | ||
|
|
||
| jobs: | ||
| lint: | ||
| name: conventional title | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: amannn/action-semantic-pull-request@v5 | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| with: | ||
| types: | | ||
| feat | ||
| fix | ||
| docs | ||
| style | ||
| refactor | ||
| perf | ||
| test | ||
| build | ||
| ci | ||
| chore | ||
| adapter | ||
| revert | ||
| requireScope: false | ||
| subjectPattern: .+ | ||
| wip: true |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,6 +7,7 @@ on: | |||||||||||||||
|
|
||||||||||||||||
| permissions: | ||||||||||||||||
| contents: write | ||||||||||||||||
| pull-requests: write | ||||||||||||||||
|
|
||||||||||||||||
| jobs: | ||||||||||||||||
| build: | ||||||||||||||||
|
|
@@ -18,7 +19,7 @@ jobs: | |||||||||||||||
| include: | ||||||||||||||||
| - os: macos-latest | ||||||||||||||||
| target: aarch64-apple-darwin | ||||||||||||||||
| - os: macos-13 | ||||||||||||||||
| - os: macos-latest | ||||||||||||||||
| target: x86_64-apple-darwin | ||||||||||||||||
| - os: ubuntu-latest | ||||||||||||||||
| target: x86_64-unknown-linux-gnu | ||||||||||||||||
|
|
@@ -29,8 +30,7 @@ jobs: | |||||||||||||||
| targets: ${{ matrix.target }} | ||||||||||||||||
| - uses: Swatinem/rust-cache@v2 | ||||||||||||||||
| - name: Build | ||||||||||||||||
| run: | | ||||||||||||||||
| cargo build --release -p microbridged -p microbridgectl --target ${{ matrix.target }} | ||||||||||||||||
| run: cargo build --release -p microbridged -p microbridgectl --target ${{ matrix.target }} | ||||||||||||||||
| - name: Package | ||||||||||||||||
| run: | | ||||||||||||||||
| STAGE=microbridge-${{ github.ref_name }}-${{ matrix.target }} | ||||||||||||||||
|
|
@@ -64,10 +64,46 @@ jobs: | |||||||||||||||
| generate_release_notes: true | ||||||||||||||||
| files: release-assets/* | ||||||||||||||||
| body: | | ||||||||||||||||
| ## Install | ||||||||||||||||
| ## Install (macOS) | ||||||||||||||||
|
|
||||||||||||||||
| ```sh | ||||||||||||||||
| ./scripts/install-from-release.sh ${{ github.ref_name }} | ||||||||||||||||
| brew tap DevVig/microbridge https://github.com/DevVig/microbridge | ||||||||||||||||
| brew install microbridge | ||||||||||||||||
| brew services start microbridge | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| Or from source: see [INSTALL.md](INSTALL.md). | ||||||||||||||||
| Upgrade later: `brew update && brew upgrade microbridge` | ||||||||||||||||
|
|
||||||||||||||||
| Binary archive: `./scripts/install-from-release.sh ${{ github.ref_name }}` | ||||||||||||||||
|
|
||||||||||||||||
| Full guide: [INSTALL.md](INSTALL.md). | ||||||||||||||||
|
|
||||||||||||||||
| bump-formula: | ||||||||||||||||
| name: bump Homebrew formula | ||||||||||||||||
| needs: publish | ||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||
| steps: | ||||||||||||||||
| - uses: actions/checkout@v5 | ||||||||||||||||
| with: | ||||||||||||||||
| ref: main | ||||||||||||||||
|
Comment on lines
+86
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Disable persisted checkout credentials.
🔐 Proposed fix - uses: actions/checkout@v5
with:
ref: main
+ persist-credentials: false📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[warning] 86-88: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||
| - name: Bump Formula url + sha256 | ||||||||||||||||
| env: | ||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||
| run: | | ||||||||||||||||
| chmod +x scripts/bump-formula.sh | ||||||||||||||||
| ./scripts/bump-formula.sh "${{ github.ref_name }}" | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Do not interpolate the release tag directly into shell code.
🛡️ Proposed fix env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ RELEASE_TAG: ${{ github.ref_name }}
run: |
chmod +x scripts/bump-formula.sh
- ./scripts/bump-formula.sh "${{ github.ref_name }}"
+ ./scripts/bump-formula.sh "$RELEASE_TAG"🧰 Tools🪛 zizmor (1.26.1)[error] 94-94: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||
| - name: Open PR | ||||||||||||||||
| uses: peter-evans/create-pull-request@v7 | ||||||||||||||||
| with: | ||||||||||||||||
| token: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||
| commit-message: "chore(brew): bump formula to ${{ github.ref_name }}" | ||||||||||||||||
| title: "chore(brew): bump formula to ${{ github.ref_name }}" | ||||||||||||||||
| body: | | ||||||||||||||||
| Auto-bump `Formula/microbridge.rb` after release `${{ github.ref_name }}`. | ||||||||||||||||
|
|
||||||||||||||||
| After merge, users get the new version via: | ||||||||||||||||
| ```sh | ||||||||||||||||
| brew update && brew upgrade microbridge | ||||||||||||||||
| ``` | ||||||||||||||||
| branch: chore/brew-${{ github.ref_name }} | ||||||||||||||||
| delete-branch: true | ||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,111 +1,122 @@ | ||||||||||||||||||
| # Installing Microbridge | ||||||||||||||||||
|
|
||||||||||||||||||
| Microbridge is a local daemon plus an optional companion UI. There is **no | ||||||||||||||||||
| network** and **no cloud account** — install puts binaries on your machine and | ||||||||||||||||||
| (on macOS) a per-user launchd agent. | ||||||||||||||||||
| cloud account** — install puts binaries on your machine and runs a user-level | ||||||||||||||||||
| service. | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Requirements | ||||||||||||||||||
|
|
||||||||||||||||||
| | Piece | Need | | ||||||||||||||||||
| |---|---| | ||||||||||||||||||
| | Daemon | Rust stable (`rustup`), macOS 13+ or Linux | | ||||||||||||||||||
| | Companion UI (optional) | Node ≥ 20; full `.app` also needs Xcode CLT | | ||||||||||||||||||
| | Hardware LEDs | Codex Micro over USB (HID packing still landing — mock works without hardware) | | ||||||||||||||||||
| ## Recommended on macOS: Homebrew (with updates) | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Quick install (macOS, from source) | ||||||||||||||||||
| This is the easy path. You do **not** need to clone the repo. Homebrew owns | ||||||||||||||||||
| install, upgrades, and the launchd service. | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| git clone https://github.com/DevVig/microbridge.git | ||||||||||||||||||
| cd microbridge | ||||||||||||||||||
| ./scripts/install.sh | ||||||||||||||||||
| brew tap DevVig/microbridge https://github.com/DevVig/microbridge | ||||||||||||||||||
| brew install microbridge | ||||||||||||||||||
| brew services start microbridge | ||||||||||||||||||
| microbridgectl status | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| This will: | ||||||||||||||||||
|
|
||||||||||||||||||
| 1. `cargo build --release` for `microbridged` and `microbridgectl` | ||||||||||||||||||
| 2. Install them to `~/.local/bin` (override with `MICROBRIDGE_BIN=…`) | ||||||||||||||||||
| 3. Ensure `~/.local/bin` is on your PATH (prints a hint if not) | ||||||||||||||||||
| 4. Install and start the launchd agent `ai.microbridge.daemon` | ||||||||||||||||||
| 5. Write config defaults under `~/.microbridge/` | ||||||||||||||||||
|
|
||||||||||||||||||
| Verify: | ||||||||||||||||||
| ### Updates | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| microbridgectl status | ||||||||||||||||||
| # or: | ||||||||||||||||||
| tail -f ~/.microbridge/daemon.log | ||||||||||||||||||
| brew update && brew upgrade microbridge | ||||||||||||||||||
| brew services restart microbridge | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Optional companion UI | ||||||||||||||||||
| Optional **background** upgrades (Homebrew’s autoupdate): | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| ./scripts/install.sh --with-ui | ||||||||||||||||||
| # web preview during development: | ||||||||||||||||||
| cd apps/microbridge-ui && npm install && npm run dev | ||||||||||||||||||
| brew autoupdate start --upgrade --cleanup --immediate | ||||||||||||||||||
| # later: brew autoupdate status / brew autoupdate stop | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| `--with-ui` installs frontend deps and, when Tauri/Xcode tooling is available, | ||||||||||||||||||
| attempts `npm run tauri build`. You can always run the Vite UI against a live | ||||||||||||||||||
| daemon without bundling an `.app`. | ||||||||||||||||||
| Private tap note: if the GitHub repo is private, authenticate once | ||||||||||||||||||
| (`gh auth login` or a `HOMEBREW_GITHUB_API_TOKEN`) so `brew` can fetch the | ||||||||||||||||||
| tarball. | ||||||||||||||||||
|
Comment on lines
+33
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: set -euo pipefail
printf '\n## INSTALL.md excerpt\n'
nl -ba INSTALL.md | sed -n '1,160p'
printf '\n## Search for Homebrew/GitHub token references\n'
rg -n "HOMEBREW_GITHUB_API_TOKEN|repo-scoped|fine-grained|Contents: read|gh auth login|private repo|tarball|brew" -S .Repository: DevVig/microbridge Length of output: 219 🌐 Web query:
💡 Result: GitHub fine-grained personal access tokens (PATs) can be used to download private repository archives (tarballs) via the GitHub REST API, but they require specific configurations and permissions. Permissions: To download a repository tarball, a fine-grained PAT requires "Contents: read" repository permissions [1][2][3]. API Endpoint: While classic PATs could often access archives directly via the github.com web URL, fine-grained PATs are generally required to use the official GitHub REST API endpoint: GET /repos/{owner}/{repo}/tarball/{ref} [4][5]. Authentication Scheme: A known quirk exists where some tools using hard-coded "Bearer" authentication schemes with fine-grained PATs may fail with a 401 Unauthorized error when accessing the tarball endpoint [3]. Using the "token" authentication scheme (e.g., Authorization: token ) instead of "Bearer" is often necessary to successfully authorize the request [3]. Homebrew Context: Homebrew supports using fine-grained PATs via the HOMEBREW_GITHUB_API_TOKEN environment variable. Historically, Homebrew's internal regex for validating tokens did not recognize the github_pat_ prefix used by fine-grained PATs, but this has been updated [6][7]. Additionally, recent changes in Homebrew (as of mid-2026) have improved how the application handles environment variable scrubbing during formula/cask evaluation, ensuring that HOMEBREW_GITHUB_API_TOKEN remains available to private taps so they can resolve authenticated assets [8][9]. Users experiencing issues with private taps downloading artifacts should ensure their Homebrew installation is up to date, as these updates were specifically designed to preserve token availability during the evaluation process [9]. Citations:
🏁 Script executed: set -euo pipefail
printf '\n## INSTALL.md lines 1-170\n'
nl -ba INSTALL.md | sed -n '1,170p'
printf '\n## Token-related references in repository\n'
rg -n "HOMEBREW_GITHUB_API_TOKEN|fine-grained|repo-scoped|Contents: read|private repo|tarball" -S .Repository: DevVig/microbridge Length of output: 223 🏁 Script executed: set -euo pipefail
printf '\n## INSTALL.md excerpt\n'
sed -n '1,170p' INSTALL.md | cat -n
printf '\n## Token-related references in repository\n'
rg -n "HOMEBREW_GITHUB_API_TOKEN|fine-grained|repo-scoped|Contents: read|private repo|tarball|gh auth login" -S .Repository: DevVig/microbridge Length of output: 4601 Prefer a fine-grained PAT here 🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| ## Linux (from source) | ||||||||||||||||||
| Uninstall: | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| ./scripts/install.sh --no-launchd | ||||||||||||||||||
| # run in the foreground, or add your own systemd --user unit: | ||||||||||||||||||
| microbridged | ||||||||||||||||||
| brew services stop microbridge | ||||||||||||||||||
| brew uninstall microbridge | ||||||||||||||||||
| # optional: brew untap DevVig/microbridge | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| A sample user unit is in [`scripts/microbridge.service`](scripts/microbridge.service). | ||||||||||||||||||
| Governance / why this path: [docs/governance.md](docs/governance.md). | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Homebrew (skeleton) | ||||||||||||||||||
| --- | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Requirements | ||||||||||||||||||
|
|
||||||||||||||||||
| | Piece | Need | | ||||||||||||||||||
| |---|---| | ||||||||||||||||||
| | Daemon (Homebrew) | Homebrew; Rust pulled in as a build dependency | | ||||||||||||||||||
| | Daemon (from source) | Rust stable (`rustup`), macOS 13+ or Linux | | ||||||||||||||||||
| | Companion UI (optional) | Node ≥ 20; full `.app` also needs Xcode CLT | | ||||||||||||||||||
| | Hardware LEDs | Codex Micro over USB (HID packing still landing — mock works without hardware) | | ||||||||||||||||||
|
|
||||||||||||||||||
| ## From source (developers) | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| brew install --build-from-source ./Formula/microbridge.rb | ||||||||||||||||||
| brew services start microbridge # when using the formula's service block | ||||||||||||||||||
| git clone https://github.com/DevVig/microbridge.git | ||||||||||||||||||
| cd microbridge | ||||||||||||||||||
| ./scripts/install.sh # macOS: binaries + launchd | ||||||||||||||||||
| # ./scripts/install.sh --with-ui | ||||||||||||||||||
| # ./scripts/install-linux-systemd.sh | ||||||||||||||||||
| microbridgectl status | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| A published tap/bottle is not available yet — use `./scripts/install.sh` for | ||||||||||||||||||
| day-to-day installs. | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Install from a GitHub Release | ||||||||||||||||||
| Uninstall: `./scripts/uninstall.sh` (add `--purge` to remove `~/.microbridge`). | ||||||||||||||||||
|
|
||||||||||||||||||
| When a `v*` tag is pushed, CI attaches platform archives. Then: | ||||||||||||||||||
| ### Optional companion UI | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| ./scripts/install-from-release.sh v0.0.1 | ||||||||||||||||||
| # or latest: | ||||||||||||||||||
| ./scripts/install-from-release.sh | ||||||||||||||||||
| ./scripts/install.sh --with-ui | ||||||||||||||||||
| # or during development: | ||||||||||||||||||
| cd apps/microbridge-ui && npm install && npm run dev | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Uninstall | ||||||||||||||||||
| ## Linux | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| ./scripts/uninstall.sh | ||||||||||||||||||
| ./scripts/install-linux-systemd.sh | ||||||||||||||||||
| # or: | ||||||||||||||||||
| ./scripts/install.sh --no-launchd && microbridged | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
Comment on lines
+82
to
85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Use the installed binary path in the Linux foreground example. The layout documents the source binary at 🛠️ Proposed fix-./scripts/install.sh --no-launchd && microbridged
+./scripts/install.sh --no-launchd
+"$HOME/.local/bin/microbridged"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| Removes the launchd agent, binaries from `MICROBRIDGE_BIN` / `~/.local/bin`, | ||||||||||||||||||
| and optionally (`--purge`) `~/.microbridge/` (config, socket, logs). | ||||||||||||||||||
| Sample unit: [`scripts/microbridge.service`](scripts/microbridge.service). | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Install from a GitHub Release (binaries) | ||||||||||||||||||
|
|
||||||||||||||||||
| When a `v*` tag is published, CI attaches platform archives: | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| ./scripts/install-from-release.sh # latest | ||||||||||||||||||
| ./scripts/install-from-release.sh v0.0.1 | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Layout after install | ||||||||||||||||||
|
|
||||||||||||||||||
| | Path | Purpose | | ||||||||||||||||||
| |---|---| | ||||||||||||||||||
| | `~/.local/bin/microbridged` | Daemon | | ||||||||||||||||||
| | `~/.local/bin/microbridgectl` | CLI | | ||||||||||||||||||
| | `~/Library/LaunchAgents/ai.microbridge.daemon.plist` | macOS autostart | | ||||||||||||||||||
| | `$(brew --prefix)/bin/microbridged` | Daemon (Homebrew) | | ||||||||||||||||||
| | `~/.local/bin/microbridged` | Daemon (source install script) | | ||||||||||||||||||
|
Comment on lines
+102
to
+103
|
||||||||||||||||||
| | `~/.microbridge/microbridged.sock` | Local NDJSON socket | | ||||||||||||||||||
| | `~/.microbridge/config.toml` | Key source, lighting, appearance | | ||||||||||||||||||
| | `~/.microbridge/daemon.log` | launchd stdout/stderr | | ||||||||||||||||||
| | `~/.microbridge/daemon.log` | launchd / service logs | | ||||||||||||||||||
|
Comment on lines
98
to
+106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Document the Homebrew log location separately. The formula writes service logs to 🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| ## Troubleshooting | ||||||||||||||||||
|
|
||||||||||||||||||
| **`microbridgectl: connect …`** — daemon not running. On macOS: | ||||||||||||||||||
| `launchctl kickstart -k gui/$(id -u)/ai.microbridge.daemon`. | ||||||||||||||||||
| **`microbridgectl: connect …`** — daemon not running. | ||||||||||||||||||
|
|
||||||||||||||||||
| ```sh | ||||||||||||||||||
| brew services restart microbridge | ||||||||||||||||||
| # or: | ||||||||||||||||||
| launchctl kickstart -k "gui/$(id -u)/ai.microbridge.daemon" | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| **LEDs stay dark** — HID packing is still best-effort; ChatGPT desktop may | ||||||||||||||||||
| also own the device. Pause that app or use Settings → Pause LEDs while testing | ||||||||||||||||||
| the mock path (`microbridgectl status` still works). | ||||||||||||||||||
| also own the device. | ||||||||||||||||||
|
|
||||||||||||||||||
| **PATH** — add `export PATH="$HOME/.local/bin:$PATH"` to your shell rc if | ||||||||||||||||||
| `microbridgectl` is not found. | ||||||||||||||||||
| **Homebrew can’t fetch (private repo)** — `gh auth login`, or set | ||||||||||||||||||
| `HOMEBREW_GITHUB_API_TOKEN` to a PAT with `repo` scope. | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Scope pull-request write permission to
bump-formula.The workflow-level permission exposes PR write access to build and publish jobs that do not need it. A compromised build step could otherwise create or modify pull requests.
🧰 Tools
🪛 zizmor (1.26.1)
[error] 10-10: overly broad permissions (excessive-permissions): pull-requests: write is overly broad at the workflow level
(excessive-permissions)
🤖 Prompt for AI Agents
Source: Linters/SAST tools