Guia

Como configurar o GitLab Runner em um Mac para builds de iOS

Para rodar jobs do GitLab CI em um Mac, instale o binário oficial gitlab-runner e registre com o shell executor. Antes, crie o runner nas configurações de CI/CD do seu projeto. Isso gera um token glrt-. Depois instale como LaunchAgent de usuário e ative o login automático, para que ele volte depois de reinicializar. Faça a instalação em um terminal na área de trabalho do Mac, não por SSH, como a documentação do GitLab exige.

O que você precisa antes

  • Um Mac com Apple silicon, acesso de administrador e Xcode instalado.
  • A primeira abertura do Xcode concluída. Rode sudo xcodebuild -runFirstLaunch uma vez se não tiver certeza.
  • Permissão para gerenciar runners no seu projeto ou grupo do GitLab.
  • Uma sessão na área de trabalho do Mac, por compartilhamento de tela ou com um monitor. A página de instalação do GitLab para macOS diz para usar um terminal gráfico local, não uma sessão SSH.
  • A conta do macOS que vai rodar os jobs. Entre na área de trabalho com esse usuário.

1. Baixe o binário do runner

O GitLab diz que não mantém a fórmula do Homebrew e recomenda o binário oficial. No Apple silicon, use a versão arm64. Um Mac recém instalado pode ainda não ter /usr/local/bin, então crie essa pasta primeiro.

sudo mkdir -p /usr/local/bin
sudo curl --output /usr/local/bin/gitlab-runner \
  "https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/latest/binaries/gitlab-runner-darwin-arm64"
sudo chmod +x /usr/local/bin/gitlab-runner
gitlab-runner --version

2. Crie o runner no GitLab

Os tokens de registro de runner estão obsoletos. O GitLab planeja removê-los no GitLab 20.0. O fluxo atual cria o runner primeiro na interface e depois entrega um token de autenticação do runner. Esse token começa com glrt-.

  • No seu projeto, abra Settings, depois CI/CD, e expanda Runners.
  • Selecione Create project runner e escolha macOS.
  • Em Tags, digite macos, xcode. Deixe Run untagged jobs desligado, para que só cheguem aqui os jobs que pedem um Mac.
  • Selecione Create runner e copie o token. Ele aparece só por um instante.

Agora as tags ficam no runner, dentro do GitLab. A documentação do GitLab diz que opções como --tag-list e --run-untagged só podem ser definidas quando o runner é criado, na interface ou pela API. Para mudar as tags depois, use a página Edit do runner.

3. Registre com o shell executor

A página de instalação do GitLab para macOS indica o shell executor para builds de iOS e macOS. Os jobs rodam direto no Mac, com o seu usuário, com o Xcode e os simuladores. Registre sem perguntas assim:

export RUNNER_TOKEN="glrt-paste-your-token-here"
gitlab-runner register \
  --non-interactive \
  --url "https://gitlab.com/" \
  --token "$RUNNER_TOKEN" \
  --executor "shell" \
  --description "mac-mini-m6"

No GitLab autogerenciado, use a URL da sua instância. As configurações ficam em ~/.gitlab-runner/config.toml. O GitLab avisa que o shell executor está em modo de manutenção. Ele ainda recebe correções de segurança e continua sendo o que a página de macOS recomenda para trabalho com Xcode.

4. Instale e inicie o serviço

cd ~
gitlab-runner install
gitlab-runner start
gitlab-runner status

Isso cria ~/Library/LaunchAgents/gitlab-runner.plist. No macOS o runner é um LaunchAgent de usuário, e o GitLab diz que esse é o único modo suportado. Ele roda com o seu usuário, não como root. Ele acessa o seu keychain e a sua sessão de login, que o Simulador do iOS e a assinatura de código precisam. Os logs vão para ~/Library/Logs/gitlab-runner.out.log e gitlab-runner.err.log.

5. Faça ele sobreviver a uma reinicialização

Um LaunchAgent inicia quando o usuário entra e para no logout. Então o runner só volta depois de reinicializar se esse usuário entrar sozinho. Por isso a documentação do GitLab manda ativar o login automático. Faça isso em System Settings, em Users and Groups. Depois impeça o Mac de entrar em repouso e teste com uma reinicialização de verdade.

sudo pmset -a sleep 0
sudo shutdown -r now
# after it comes back, over SSH:
gitlab-runner status

O login automático em um Mac sem monitor tem algumas falhas silenciosas, incluindo uma nova no macOS 27. Explicamos todas em login automático em um Mac sem monitor.

6. Um .gitlab-ci.yml para um app iOS

Um job só roda em um runner se o runner tiver todas as tags que o job lista. Este job pede macos, roda os testes e guarda o result bundle mesmo quando os testes falham.

stages:
  - test

ios_tests:
  stage: test
  tags:
    - macos
  script:
    - xcodebuild -version
    - rm -rf build/TestResults.xcresult
    - xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' -resultBundlePath build/TestResults.xcresult
  artifacts:
    when: always
    paths:
      - build/TestResults.xcresult
    expire_in: 1 week

A linha rm -rf é importante em uma máquina que mantém a cópia de trabalho. O xcodebuild se recusa a sobrescrever um result bundle que já existe. Conferimos isso no Xcode 26.6.

Erros comuns e soluções

Estes vêm da seção de solução de problemas do GitLab para macOS.

  • "launchctl" failed: Could not find domain for. Você rodou install ou start por SSH. Abra o Terminal na área de trabalho do Mac e rode os comandos lá.
  • FATAL: Failed to start gitlab-runner: exit status 134. O serviço não foi instalado direito. Rode gitlab-runner uninstall, depois install, depois start, na área de trabalho.
  • killed: 9 no Apple silicon. As pastas de log citadas no plist precisam existir e permitir escrita pelo seu usuário.
  • Failed to authorize rights (0x1) with status: -60007. Rode DevToolsSecurity -enable e sudo security authorizationdb remove system.privilege.taskport is-developer.
  • O git fetch trava. Um Git do Homebrew pode adicionar um credential helper do keychain. Rode git config --global --add credential.helper '' com o usuário do runner.
  • Um job fica parado. As tags dele não batem com as do runner, ou o job não tem tags e o runner não aceita jobs sem tag.

Por que um Mac dedicado ajuda

O shell executor usa a mesma máquina para todos os jobs. O DerivedData do Xcode, os checkouts de pacotes Swift e os caches do CocoaPods ficam no disco entre pipelines. É aí que está o tempo. No nosso benchmark com o app iOS da Wikipedia no Xcode 26.6, medimos um job típico depois de uma pequena mudança. Ele levou 27 segundos em um M6 aquecido. O mesmo job levou 269 segundos em um runner macos-26 novo hospedado pelo GitHub. Um build limpo levou 86 segundos contra 183.

Quando os runners Mac hospedados pelo GitLab bastam

O GitLab tem seus próprios runners macOS. A documentação, lida em outubro de 2026, lista esses runners como beta. Eles são para clientes Premium e Ultimate e para programas de código aberto. Os tamanhos são um M1 com 4 vCPUs e 8 GB e um M2 Pro com 6 vCPUs e 16 GB. Se você está em um desses planos e roda poucos pipelines por dia, os runners hospedados poupam todos os passos acima.

Não escolha um Mac dedicado com shell executor para um projeto público que roda merge requests não confiáveis. O GitLab avisa que jobs de shell podem ler o código de outros projetos na mesma máquina. Também não escolha a MacRun se você precisa de um IP fixo para lista de permissões, de um SLA ou de mais de uma região. Não oferecemos nada disso.

Quer testar no nosso hardware? Nossa página de outros sistemas de CI cobre o lado da MacRun, e a página de preços lista todos os planos.

Perguntas frequentes

Devo instalar o GitLab Runner no macOS com Homebrew?

+

O GitLab recomenda o binário oficial. A documentação diz que o GitLab não mantém a fórmula do Homebrew.

Por que o gitlab-runner install falha por SSH?

+

O runner é um LaunchAgent de usuário e precisa de uma sessão de login gráfica. Rode install e start em um terminal na área de trabalho do Mac.

O GitLab Runner pode rodar como LaunchDaemon no macOS?

+

Não. O GitLab diz que o LaunchAgent em modo de usuário é o único modo suportado, porque os jobs precisam do keychain e da sessão do usuário para assinar e para o Simulador.

Onde defino as tags do runner no novo fluxo de token?

+

No GitLab, na página de criação ou edição do runner. A documentação do GitLab diz que as tags só podem ser definidas quando o runner é criado na interface ou pela API, não pelo comando register.

Guias relacionados