No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-17 12:48:47 +00:00
.forgejo/workflows Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
lib Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
tests Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
tooling/gate Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
.gitignore Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
install.sh Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
README.md Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
status.sh Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00
uninstall.sh Add native Forgejo runner installer for the Apple Silicon Mac (#1000) 2026-10-17 06:39:49 -05:00

mac-runner

A pull-and-run installer for a native Forgejo Actions runner on an Apple Silicon Mac. It builds forgejo-runner, registers it with https://git.zeinestone.me for the ZSDev/connor-ios repository only, and keeps it running in the background with a launchd LaunchAgent. Jobs run directly on the Mac with the host executor (no Docker), so workflows can call xcodebuild with the selected Xcode.

Jobs reach it with:

runs-on: macos-arm64      # or: xcode-27.1

What you need

  • An Apple Silicon Mac running macOS Tahoe 26.6 or later.
  • Xcode 27.1, selected with xcode-select and with its licence accepted:
    sudo xcode-select -s /Applications/Xcode-27.1.app   # wherever Xcode 27.1 lives
    sudo xcodebuild -license accept
    
  • Network access to git.zeinestone.me, code.forgejo.org, go.dev and proxy.golang.org (the last two only while building).

The installer checks the first two and stops with a message saying what to fix.

One-time setup

  1. Get a registration token for the iOS repository. On the forge, open ZSDev/connor-ios → Settings → Actions → Runners and click Show registration token. Using the repository's own token, not the organisation's, means this runner serves only connor-ios.
  2. Clone this repository and run the installer:
    git clone https://git.zeinestone.me/ZSDev/mac-runner.git
    cd mac-runner
    ./install.sh
    
  3. When asked, paste the token. It is not shown as you paste, and is never written to this checkout. The runner keeps its own credential in ~/Library/Application Support/forgejo-runner/.runner, readable only by you.

The first run downloads Go and the runner's source, builds the runner (a few minutes), registers it and starts it. The runner then appears on the Runners page as idle.

Check on it any time with:

./status.sh

status.sh shows the binary, the registration, whether the LaunchAgent is loaded and running, and whether the runner is online. It reads "online" from the runner's log. To ask the forge directly, give it a token that can see the repository's runners for that one command; the token is read from the environment and never stored:

FORGEJO_TOKEN=... ./status.sh

It exits 0 when the runner is running and online, and 1 otherwise.

Where things live

What Where
Runner binary ~/Library/Application Support/forgejo-runner/bin/forgejo-runner
Config and registration ~/Library/Application Support/forgejo-runner/
LaunchAgent ~/Library/LaunchAgents/me.zeinestone.forgejo-runner.plist
Logs ~/Library/Logs/forgejo-runner/runner.log
Build caches and job workspaces ~/Library/Caches/forgejo-runner/

The LaunchAgent starts the runner when you log in and starts it again whenever it exits. It runs as you, inside your login session, so jobs can use your keychain for code signing.

Builds only run while the Mac is awake

The runner lives on this Mac, so it can only take jobs while the Mac is awake, logged in and online. Anything pushed while the lid is closed or the Mac is asleep waits in the forge's queue and starts once the Mac wakes. To keep it available during a long session, leave it plugged in and prevent sleep (for example caffeinate -s in a terminal).

Updating

lib/pins.sh names the runner version and the Go version to build it with, each with its SHA-256. The installer refuses any download that does not match. When a new runner release comes out, ./install.sh prints a notice.

To move to a new release:

  1. In lib/pins.sh, set RUNNER_VERSION to the new release and RUNNER_SRC_SHA256 to the SHA-256 of https://code.forgejo.org/forgejo/runner/archive/vX.Y.Z.tar.gz. Check it against a second source, such as Homebrew's forgejo-runner formula (https://formulae.brew.sh/formula/forgejo-runner).
  2. If the release needs a newer Go (see the go line in its go.mod), update GO_VERSION and GO_SHA256 from https://go.dev/dl/ (the darwin-arm64.tar.gz row).
  3. Merge that change, then on the Mac:
    git pull
    ./install.sh
    
    The installer rebuilds the runner, keeps the existing registration and restarts the agent.

To register again from scratch (for example, after deleting the runner on the forge), run ./install.sh --reregister.

Uninstalling

./uninstall.sh          # unload the agent; remove binary, config, registration and caches
./uninstall.sh --logs   # the same, and remove the logs too

The forge keeps listing the runner until you delete it under ZSDev/connor-ios → Settings → Actions → Runners.

Development

The scripts are written for macOS's own /bin/bash 3.2. The gate, tooling/gate/run.sh, checks syntax and flags bash 4 features. It also runs shellcheck and the behaviour tests in tests/run.sh, which stand in stubs for the macOS tools and the network so they run on Linux too. CI runs the same gate on the Linux runner (.forgejo/workflows/gate.yml).