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
98 changes: 80 additions & 18 deletions .github/workflows/macos-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,96 @@ on:
branches: [ main ]
pull_request:

concurrency:
group: macos-build-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

jobs:
build-macos:
lint:
name: Lint
runs-on: macos-latest
strategy:
matrix:
python: [3.14]
timeout-minutes: 5
steps:
- uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
python-version: '3.14'
cache: 'pip'
cache-dependency-path: |
requirements.txt
pyproject.toml
setup.py
- name: Install ruff
run: python -m pip install --upgrade ruff
- name: Ruff lint
# Informational for now: surfaces style issues without blocking the build.
# Tighten to blocking once the existing code is ruff-clean.
continue-on-error: true
run: ruff check . --output-format=github
- name: Ruff format check
continue-on-error: true
run: ruff format --check . --output-format=github

build:
name: Build
needs: lint
runs-on: macos-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: '3.14'
cache: 'pip'
cache-dependency-path: |
requirements.txt
pyproject.toml
setup.py
- name: Upgrade packaging tools
run: python -m pip install --upgrade pip "setuptools>=61,<79" wheel py2app rumps

- name: Install runtime dependencies
run: python -m pip install -r requirements.txt

- name: Install project
run: python -m pip install .

- name: Build macOS .app with py2app
- name: Build .app with py2app
run: python setup.py py2app

- name: Upload build artifact
uses: actions/upload-artifact@v4
- name: Verify .app structure
run: |
if [ ! -d "dist/XMManager.app" ]; then
echo "::error::dist/XMManager.app was not produced"
ls -laR dist/ 2>/dev/null || true
exit 1
fi
{
echo "### Build output"
echo ""
echo "- App bundle: \`dist/XMManager.app\`"
echo "- Total size: \`$(du -sh dist/XMManager.app | cut -f1)\`"
echo "- Main binary: \`$(file dist/XMManager.app/Contents/MacOS/* | sed 's/.*: //')\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Package as DMG
run: |
# hdiutil is built into macOS, no install needed.
# UDZO = compressed read-only, the standard "drag to Applications" DMG.
hdiutil create -volname "XMManager" \
-srcfolder dist/XMManager.app \
-ov -format UDZO \
XMManager.dmg
echo "DMG created:"
ls -la XMManager.dmg
{
echo "- DMG: \`XMManager.dmg\`"
echo "- DMG size: \`$(du -sh XMManager.dmg | cut -f1)\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload DMG
uses: actions/upload-artifact@v7
with:
name: macos-app
path: dist/
name: XMManager
path: XMManager.dmg
archive: false
# archive: false is the v7 feature for uploading a single file
# without zipping. DMGs are a single file, so the user gets
# XMManager.dmg directly instead of XMManager.dmg.zip.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# XMManager

[![macOS build](https://github.com/numycode/xmmanager/actions/workflows/macos-build.yml/badge.svg)](https://github.com/numycode/xmmanager/actions/workflows/macos-build.yml)

XMManager is an easy way to manage XMRig on your Mac. It currently allows you to toggle XMRig for easy use of the miner.

# Install
### Using prebuilt:
1. Download from releases
2. Download [XMRig](https://xmrig.com/download) and extract it to the same folder as XMManager
1. Download from releases and drag `XMManager.app` to `/Applications`
2. Install [XMRig](https://xmrig.com/download) somewhere XMManager can find it. The easiest way is `brew install xmrig`, which puts it at `/opt/homebrew/bin/xmrig` (Apple Silicon) or `/usr/local/bin/xmrig` (Intel). Other places XMManager checks automatically:
- `$XMRIG_PATH` environment variable (highest priority, useful for custom installs)
- `/opt/homebrew/bin/xmrig`, `/usr/local/bin/xmrig`, `/opt/local/bin/xmrig` (Homebrew / MacPorts)
- `~/bin/xmrig`, `~/.local/bin/xmrig`
- The same folder as `XMManager.app` (legacy "sidecar" install)
- Warning - XMRig can get flagged by your antivirus due to malicious programs using it to mine without permission. XMRig is a safe program.
3. Create a [config.json](https://xmrig.com/docs/miner/config) file and put it in the same folder as the rest. (command line arguments are not yet supported)
3. Create a [config.json](https://xmrig.com/docs/miner/config) and save it as `~/.xmrig.json` (in your home directory). XMManager passes `--config=$HOME/.xmrig.json` to xmrig automatically, since a menu bar app can't ship a config inside the `.app` bundle. (Other command line arguments are not yet supported.)
4. Run XMManager and have fun mining!

If XMManager can't find xmrig at startup, it shows a notification and quits instead of staying open with a dead toggle. Set `XMRIG_PATH=/full/path/to/xmrig` in your shell profile if you installed it somewhere unusual.
### From source:

I don't even remember at this point, too much debugging. I'll add CI soon so I'll update this part once I understand how I built it.
Expand All @@ -30,7 +39,7 @@ Watch the video [here](https://cdn.hackclub.com/019df076-974f-7d73-9d7f-e3ed8fa1
And that is it! Have fun mining!

## AI Notice
AI was used in this repository only to make the GitHub Actions runner, a function in the code I'll replace later, and debugging CI. The rest is human-written.
AI was used in this repository for the GitHub Actions runner, a function flagged for later replacement, CI debugging, and the `mining_controller` refactor that fixed the toggle race and replaced `pkill` with proper PID handling. The rest is human-written.

## Contributors
- [@rocklake](https://codeberg.org/rocklake/) ([rocklake's GitHub](https://github.com/rocklake/)) - Helped get the code into a usable state since the whole codebase was crumbling
Loading
Loading