मुख्य सामग्री पर जाएं

Mac Mini M4 पर CircleCI सेल्फ-होस्टेड रनर कैसे सेट करें

एक समर्पित Mac mini M4 पर CircleCI सेल्फ-होस्टेड मशीन रनर को इंस्टॉल और कॉन्फ़िगर करने की संपूर्ण चरण-दर-चरण गाइड। नेटिव Apple Silicon प्रदर्शन, स्थायी कैशिंग, और CircleCI क्लाउड macOS संसाधनों की तुलना में 90% तक सस्ता।

CI/CD 35 मिनट का पठन अक्टूबर 2026 में अपडेट किया गया

Mac पर सेल्फ-होस्टेड CircleCI रनर क्यों उपयोग करें?

CircleCI क्लाउड-आधारित macOS एक्ज़ीक्यूशन वातावरण प्रदान करता है, लेकिन ये महत्वपूर्ण लागतों और सीमाओं के साथ आते हैं। CircleCI macOS जॉब्स का बिल क्रेडिट में बनाता है: m4pro.medium रिसोर्स क्लास प्रति मिनट 200 क्रेडिट (लगभग $0.12) और m4pro.large 400 क्रेडिट (लगभग $0.24) खपत करती है, अक्टूबर 2026 तक। अक्सर iOS बिल्ड चलाने वाली टीमों के लिए, यह जल्दी ही प्रति माह $300-$500 या उससे अधिक तक पहुँच सकता है।

MyRemoteMac के एक समर्पित Mac Mini M4 पर एक सेल्फ-होस्टेड रनर प्रति-मिनट बिलिंग को पूरी तरह समाप्त कर देता है। आपको स्थायी स्टोरेज, वार्म कैश, और पूर्ण रूट एक्सेस वाली एक समर्पित Apple Silicon मशीन एक फ्लैट मासिक शुल्क पर मिलती है, जो $85/माह से शुरू होता है। यहाँ एक विस्तृत तुलना है:

Mac पर सेल्फ-होस्टेड CircleCI रनर क्यों उपयोग करें?
MyRemoteMac सेल्फ-होस्टेड CircleCI क्लाउड macOS
लागत मॉडल $85/माह फ्लैट (असीमित मिनट) m4pro.medium पर 200 क्रेडिट/मिनट (~$0.12/मिनट)
आर्किटेक्चर 1:1 आवंटित भौतिक Apple M4 Mac M4 Pro वर्चुअल मशीन (6 vCPU, 28 GB)
बिल्ड गति ~5 मिनट (समान प्रोजेक्ट) ~14 मिनट (मध्यम iOS प्रोजेक्ट)
कैश परसिस्टेंस डिस्क पर स्थायी (तत्काल) एफ़ेमरल (हर जॉब में रिस्टोर करना ज़रूरी)
कतार प्रतीक्षा समय 0 सेकंड (समर्पित हार्डवेयर) 30 सेकंड - 5 मिनट (प्लान के अनुसार भिन्न)
गोपनीयता / डेटा नियंत्रण समर्पित मशीन, पूर्ण नियंत्रण साझा इन्फ्रास्ट्रक्चर
कस्टम सॉफ़्टवेयर पूर्ण रूट एक्सेस, कोई भी सॉफ़्टवेयर केवल पूर्व-इंस्टॉल की गई इमेज

My Remote Mac की कीमतें USD में, कर अतिरिक्त।

मुख्य लाभ: एक स्थायी सेल्फ-होस्टेड रनर के साथ, DerivedData, Swift Package Manager कैश, और CocoaPods बिल्ड के बीच संरक्षित रहते हैं। अकेले यही बिल्ड समय को CircleCI के एफ़ेमरल क्लाउड macOS वातावरणों की तुलना में 50-70% तक कम कर सकता है, जो हर बार शून्य से शुरू होते हैं। M4 चिप के श्रेष्ठ सिंगल-थ्रेडेड प्रदर्शन के साथ मिलकर, आपके iOS बिल्ड नाटकीय रूप से तेज़ होंगे।

पूर्वापेक्षाएँ

शुरू करने से पहले, सुनिश्चित करें कि आपके पास निम्नलिखित हैं:

  • My Remote Mac से एक समर्पित Mac mini M4 बिल्ड सर्वर ($85/माह से, USD, कर अतिरिक्त)
  • एक CircleCI संगठन जिसमें आप एडमिन हों (सेल्फ-होस्टेड रनर हर प्लान में उपलब्ध हैं, Free सहित, जिसमें अक्टूबर 2026 तक 5 सेल्फ-होस्टेड टास्क एक साथ चल सकते हैं)
  • आपके Mac Mini तक SSH एक्सेस (आपकी MyRemoteMac सदस्यता के साथ प्रदान किया गया)
  • एक Apple Developer खाता (कोड साइनिंग और प्रोविज़निंग प्रोफ़ाइल के लिए)
  • YAML, CircleCI कॉन्फ़िगरेशन, और टर्मिनल कमांड से बुनियादी परिचय

चरण 1: अपने Mac Mini में SSH करें और डिपेंडेंसी इंस्टॉल करें

सबसे पहले, SSH के ज़रिए अपने Mac Mini M4 से कनेक्ट करें। जब आपने अपना MyRemoteMac सर्वर सेट किया था तब आपको अपने क्रेडेंशियल मिले होंगे। CircleCI रनर सेट करने से पहले हमें Xcode और iOS बिल्ड के लिए आवश्यक टूल इंस्टॉल करने होंगे।

SSH के ज़रिए कनेक्ट करें

# Connect to your Mac mini M4
ssh admin@your-server-ip

# Verify you're on Apple Silicon
uname -m
# Expected output: arm64

# Show the macOS version
sw_vers

Homebrew और Xcode Command Line Tools इंस्टॉल करें

# Install Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Add Homebrew to PATH: zsh for your sessions, bash for CircleCI job steps
# (CircleCI runs macOS steps in a bash login shell)
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.bash_profile
eval "$(/opt/homebrew/bin/brew shellenv)"

# Install Xcode Command Line Tools
xcode-select --install

# Accept the license agreement
sudo xcodebuild -license accept

Xcode इंस्टॉल करें (पूर्ण संस्करण)

iOS बिल्ड के लिए, आपको पूर्ण Xcode एप्लिकेशन की आवश्यकता होती है। 28 अप्रैल 2026 से App Store Connect केवल Xcode 26 या उससे नए वर्ज़न से बने बिल्ड स्वीकार करता है, इसलिए हेडलेस सर्वर पर सबसे तेज़ तरीके xcodes से मौजूदा रिलीज़ इंस्टॉल करें:

# Install the xcodes CLI tool
brew install xcodes

# Install the latest release of Xcode (asks for your Apple Account)
xcodes install --latest

# Show where it was installed, then make it the default Xcode
xcodes installed
# e.g. 27.0 (27A266a)  /Applications/Xcode-27.0.0.app
sudo xcode-select -s /Applications/Xcode-27.0.0.app/Contents/Developer

# Verify installation
xcodebuild -version

iOS सिम्युलेटर और बिल्ड टूल इंस्टॉल करें

# Install the current iOS simulator runtime
xcodebuild -downloadPlatform iOS

# Verify simulator availability
xcrun simctl list runtimes

# Install additional build tools
brew install xcbeautify fastlane swiftlint

चरण 2: CircleCI रनर एजेंट इंस्टॉल करें

CircleCI का मशीन रनर 3 आपके Mac mini को CircleCI से जोड़ता है: यह जॉब्स प्राप्त करता है और उन्हें सीधे आपके macOS होस्ट पर चलाता है। macOS पर CircleCI इसे अपने Homebrew पैकेज से इंस्टॉल करने की सलाह देता है। यह कंटेनर रनर से अलग है (जो केवल Linux पर काम करता है)।

वह उपयोगकर्ता चुनें जो आपके जॉब्स चलाएगा

मशीन रनर 3 हर जॉब को उसी macOS उपयोगकर्ता के रूप में चलाता है जिसने उसे शुरू किया, उसी उपयोगकर्ता के Homebrew, कीचेन और Xcode के साथ। इसे अपने एडमिन उपयोगकर्ता से इंस्टॉल और शुरू करें, जिसके पास Homebrew है, root से नहीं: Homebrew root के रूप में चलने से मना करता है।

# Run the steps below as the user that will run CI jobs, not with sudo
whoami

# Homebrew must work for this user (prints /opt/homebrew)
brew --prefix

Homebrew से मशीन रनर 3 इंस्टॉल करें

# Add CircleCI's Homebrew tap and install machine runner 3
brew tap circleci-public/circleci
brew install circleci-runner

# Check that macOS accepts the binary notarized by CircleCI
spctl -a -vvv -t install "$(brew --prefix)/bin/circleci-runner"
# Expected: accepted, source=Notarized Developer ID,
# origin=Developer ID Application: Circle Internet Services Inc.

# Remove the quarantine attribute (asks for your macOS password)
sudo xattr -r -d com.apple.quarantine "$(brew --prefix)/bin/circleci-runner"

रनर एजेंट कॉन्फ़िगर करें

Homebrew पैकेज कॉन्फ़िगरेशन फ़ाइल बनाता है। आपको CircleCI वेब ऐप से अपने रनर प्रमाणीकरण टोकन की आवश्यकता होगी (चरण 3 में शामिल)। अभी के लिए, रनर का नाम सेट करें और टोकन की जगह एक प्लेसहोल्डर रखें:

# Open the configuration file created by the Homebrew package
nano "$HOME/Library/Preferences/com.circleci.runner/config.yaml"

# Contents (the token comes in Step 3):
runner:
  name: "mac-mini-m4-runner"
  working_directory: "/Users/$USER/Library/com.circleci.runner/workdir"
  cleanup_working_directory: true
api:
  auth_token: "YOUR_RUNNER_TOKEN_HERE"

# The file will hold a secret: make it readable by you only
chmod 600 "$HOME/Library/Preferences/com.circleci.runner/config.yaml"

हेडलेस Mac के लिए launchd सेवा तैयार करें

Homebrew पैकेज एक launchd एजेंट, com.circleci.runner, भी इंस्टॉल करता है। एजेंट आम तौर पर आपके उपयोगकर्ता के लॉग इन करने पर शुरू होता है; जिस Mac तक आप केवल SSH से पहुँचते हैं, उस पर CircleCI का हेडलेस सेटअप इसे /Library/LaunchAgents में ले जाता है ताकि यह रीबूट के बाद लोड हो। टोकन लगाने के बाद इसे चरण 3 में शुरू करें:

# The launchd agent installed by the Homebrew package
ls ~/Library/LaunchAgents/com.circleci.runner.plist

# Headless Mac reached over SSH only: move it to the per-user agents
# folder so it loads after a reboot (CircleCI's headless setup)
sudo mv ~/Library/LaunchAgents/com.circleci.runner.plist /Library/LaunchAgents/

महत्वपूर्ण: जब तक config.yaml में एक वैध प्रमाणीकरण टोकन नहीं होता, रनर कनेक्ट नहीं होगा। चरण 3 में टोकन जनरेट करें, उसे फ़ाइल में जोड़ें, फिर सेवा शुरू करें।

चरण 3: CircleCI डैशबोर्ड में रनर कॉन्फ़िगर करें

अब आपको CircleCI वेब इंटरफ़ेस में अपना रनर पंजीकृत करना होगा और एक प्रमाणीकरण टोकन जनरेट करना होगा। यह आपके Mac Mini को आपके CircleCI संगठन से जोड़ता है।

एक रिसोर्स क्लास बनाएं

CircleCI में, सेल्फ-होस्टेड रनर रिसोर्स क्लास द्वारा व्यवस्थित होते हैं। एक रिसोर्स क्लास एक लेबल है जो आपके .circleci/config.yml को रनर के एक विशिष्ट सेट से मैप करता है।

  1. CircleCI वेब ऐप में साइडबार से Runners खोलें (आपको संगठन का एडमिन होना चाहिए)
  2. "Create Resource Class" पर क्लिक करें
  3. Namespace को अपने संगठन के नाम पर सेट करें (उदाहरण: your-org)
  4. Resource Class नाम को कुछ वर्णनात्मक पर सेट करें (उदाहरण: mac-runner)
  5. इससे एक रिसोर्स क्लास पहचानकर्ता बनता है: your-org/mac-runner

एक रनर प्रमाणीकरण टोकन जनरेट करें

  1. "Save and continue" पर क्लिक करें: CircleCI रिसोर्स क्लास बनाता है और उसका प्रमाणीकरण टोकन दिखाता है
  2. टोकन को तुरंत कॉपी करें और सुरक्षित रखें: यह केवल एक बार दिखाया जाता है
  3. खो गया? CircleCI CLI से नया बनाएं: circleci runner token create your-org/mac-runner mac-mini-m4

अपना टोकन जोड़ें और रनर शुरू करें

# SSH back into your Mac mini
ssh admin@your-server-ip

# Replace YOUR_RUNNER_TOKEN_HERE with the resource class token
nano "$HOME/Library/Preferences/com.circleci.runner/config.yaml"

# Start the service. Headless Mac (plist moved to /Library/LaunchAgents):
launchctl bootstrap user/$(id -u) /Library/LaunchAgents/com.circleci.runner.plist
launchctl enable user/$(id -u)/com.circleci.runner
launchctl kickstart -k user/$(id -u)/com.circleci.runner

# Or, from a desktop session (VNC), with the plist left in ~/Library/LaunchAgents:
# launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.circleci.runner.plist
# launchctl enable gui/$(id -u)/com.circleci.runner
# launchctl kickstart -k gui/$(id -u)/com.circleci.runner

# Verify the service, then read the runner log
launchctl print user/$(id -u)/com.circleci.runner
tail -20 "$HOME/Library/Logs/com.circleci.runner/runner.log"

कनेक्ट होने के बाद रनर CircleCI वेब ऐप में Runners के अंतर्गत दिखता है, और circleci runner instance list your-org/mac-runner भी इसे दिखाता है। यदि यह 60 सेकंड के भीतर नहीं दिखता, तो त्रुटि संदेशों के लिए लॉग फ़ाइल जाँचें।

CircleCI CLI का उपयोग करना (वैकल्पिक)

आप CircleCI CLI के ज़रिए भी रनर प्रबंधित कर सकते हैं:

# Install the CircleCI CLI
brew install circleci

# Authenticate with CircleCI
circleci setup

# Create the namespace (once per organization)
circleci namespace create your-org --org-id YOUR_ORGANIZATION_ID

# Create the resource class and print its token
circleci runner resource-class create your-org/mac-runner \
  "Mac mini M4 runner" --generate-token

# List the runners connected to this resource class
circleci runner instance list your-org/mac-runner

चरण 4: iOS बिल्ड के लिए अपना .circleci/config.yml बनाएं

अपने रिपॉज़िटरी के रूट में एक .circleci/config.yml फ़ाइल बनाएं। एक मानक CircleCI कॉन्फ़िग से मुख्य अंतर यह है कि अपने सेल्फ-होस्टेड रनर को टारगेट करने के लिए अपने कस्टम resource_class के साथ machine: true का उपयोग किया जाता है।

version: 2.1

jobs:
  build-and-test:
    machine: true
    resource_class: your-org/mac-runner

    environment:
      # Xcode for this job, without sudo (path from `xcodes installed`)
      DEVELOPER_DIR: "/Applications/Xcode-27.0.0.app/Contents/Developer"
      SCHEME: "MyApp"
      # Any device listed by: xcrun simctl list devices available
      DESTINATION: "platform=iOS Simulator,name=iPhone 17,OS=latest"

    steps:
      - checkout

      - run:
          name: Show the Xcode version
          command: xcodebuild -version

      # Caches live in $HOME, outside the job's working directory,
      # so they survive cleanup_working_directory between jobs
      - run:
          name: Resolve Swift Package Dependencies
          command: |
            xcodebuild -resolvePackageDependencies \
              -scheme "$SCHEME" \
              -clonedSourcePackagesDirPath "$HOME/spm-cache"

      - run:
          name: Build the app
          command: |
            xcodebuild build \
              -scheme "$SCHEME" \
              -destination "generic/platform=iOS Simulator" \
              -clonedSourcePackagesDirPath "$HOME/spm-cache" \
              -derivedDataPath "$HOME/DerivedData/$SCHEME" \
              | xcbeautify

      # store_test_results needs JUnit XML: xcbeautify writes test-results/junit.xml
      - run:
          name: Run unit tests
          command: |
            xcodebuild test \
              -scheme "$SCHEME" \
              -destination "$DESTINATION" \
              -clonedSourcePackagesDirPath "$HOME/spm-cache" \
              -derivedDataPath "$HOME/DerivedData/$SCHEME" \
              -resultBundlePath TestResults.xcresult \
              | xcbeautify --report junit --report-path test-results

      - store_test_results:
          path: test-results

      - store_artifacts:
          path: TestResults.xcresult
          destination: test-results

workflows:
  ios-pipeline:
    jobs:
      - build-and-test:
          filters:
            branches:
              only:
                - main
                - develop

ध्यान दें: resource_class: your-org/mac-runner मान बिल्कुल उसी रिसोर्स क्लास से मेल खाना चाहिए जो आपने CircleCI डैशबोर्ड में बनाई थी। यदि यह मेल नहीं खाता, तो जॉब्स अनिश्चित काल तक कतार में रहेंगे।

चरण 5: कैशिंग और पैरेललिज़्म के साथ ऑप्टिमाइज़ करें

सेल्फ-होस्टेड रनर के सबसे बड़े लाभों में से एक स्थायी कैशिंग है। चूँकि रनर का फ़ाइलसिस्टम स्थायी होता है, आपको CircleCI क्लाउड संसाधनों की तरह कैश अपलोड और डाउनलोड करने की आवश्यकता नहीं होती। हालाँकि, अपनी बिल्ड गति को अधिकतम करने के लिए अतिरिक्त ऑप्टिमाइज़ेशन मौजूद हैं।

स्थायी DerivedData का लाभ उठाएं

चूँकि रनर डिस्क बिल्ड के बीच बनी रहती है, DerivedData पहले से ही स्वचालित रूप से कैश हो जाता है। एक सुसंगत पथ का उपयोग करें:

# In your config.yml steps, always use a consistent DerivedData path:
- run:
    name: Build with persistent cache
    command: |
      xcodebuild build \
        -scheme "$SCHEME" \
        -destination "$DESTINATION" \
        -derivedDataPath ~/DerivedData/"$SCHEME" \
        -clonedSourcePackagesDirPath ~/spm-cache \
        | xcbeautify

# Periodically clean old DerivedData on the runner (cron job):
# 0 3 * * 0 find ~/DerivedData -mindepth 1 -maxdepth 1 -mtime +7 -exec rm -rf {} +

जॉब्स के बीच वर्कस्पेस परसिस्टेंस

बने हुए प्रोडक्ट्स को टेस्ट जॉब तक पहुँचाने के लिए CircleCI वर्कस्पेस का उपयोग करें; यह जॉब उसी रिसोर्स क्लास के किसी दूसरे Mac पर भी चल सकता है:

jobs:
  build:
    machine: true
    resource_class: your-org/mac-runner
    steps:
      - checkout
      - run:
          name: Build for testing
          command: |
            xcodebuild build-for-testing \
              -scheme "MyApp" \
              -destination "generic/platform=iOS Simulator" \
              -derivedDataPath DerivedData \
              | xcbeautify
      # Pass only the built products, not the whole DerivedData
      - persist_to_workspace:
          root: .
          paths:
            - DerivedData/Build/Products

  test:
    machine: true
    resource_class: your-org/mac-runner
    steps:
      - attach_workspace:
          at: .
      - run:
          name: Run the tests built by the previous job
          command: |
            xcodebuild test-without-building \
              -xctestrun "$(ls DerivedData/Build/Products/*.xctestrun | head -n 1)" \
              -destination "platform=iOS Simulator,name=iPhone 17,OS=latest" \
              | xcbeautify --report junit --report-path test-results
      - store_test_results:
          path: test-results

workflows:
  build-test:
    jobs:
      - build
      - test:
          requires:
            - build

पैरेलल टेस्ट एक्ज़ीक्यूशन

- run:
    name: Run tests in parallel
    command: |
      # Xcode clones the simulator and runs test classes on up to 4 clones
      xcodebuild test \
        -scheme "MyApp" \
        -destination "platform=iOS Simulator,name=iPhone 17,OS=latest" \
        -parallel-testing-enabled YES \
        -maximum-parallel-testing-workers 4 \
        -derivedDataPath ~/DerivedData/MyApp \
        | xcbeautify

CircleCI टेस्ट स्प्लिटिंग

बड़े टेस्ट सूट के लिए, CircleCI की टेस्ट स्प्लिटिंग टेस्ट क्लासेज़ को पैरेलल टास्क में बाँटती है। हर टास्क को अपना रनर चाहिए, इसलिए parallelism: 3 के लिए रिसोर्स क्लास में तीन Mac चाहिए; एक ही Mac पर टास्क एक के बाद एक चलते हैं:

jobs:
  test:
    machine: true
    resource_class: your-org/mac-runner
    # One task per runner: 3 tasks need 3 Macs in this resource class
    parallelism: 3
    steps:
      - checkout
      - run:
          name: Split test classes and run this task's share
          command: |
            # One XCTest class per file, named like the file (LoginTests.swift)
            CLASSES=$(circleci tests glob "MyAppTests/**/*Tests.swift" \
              | xargs -n1 basename | sed 's/\.swift$//' \
              | circleci tests split)

            # -only-testing takes Target/Class identifiers, not file paths
            ONLY_TESTING=""
            for CLASS in $CLASSES; do
              ONLY_TESTING="$ONLY_TESTING -only-testing:MyAppTests/$CLASS"
            done

            xcodebuild test \
              -scheme "MyApp" \
              -destination "platform=iOS Simulator,name=iPhone 17,OS=latest" \
              $ONLY_TESTING \
              | xcbeautify --report junit --report-path test-results
      - store_test_results:
          path: test-results

वर्कफ़्लो उदाहरण

सामान्य iOS CI/CD परिदृश्यों के लिए यहाँ संपूर्ण, प्रोडक्शन-रेडी वर्कफ़्लो उदाहरण दिए गए हैं।

संपूर्ण iOS बिल्ड, टेस्ट, और डिप्लॉय पाइपलाइन

version: 2.1

jobs:
  lint:
    machine: true
    resource_class: your-org/mac-runner
    steps:
      - checkout
      - run:
          name: Run SwiftLint
          command: swiftlint lint --reporter json > swiftlint-results.json || true
      - store_artifacts:
          path: swiftlint-results.json

  build-and-test:
    machine: true
    resource_class: your-org/mac-runner
    environment:
      # Xcode for this job, without sudo (path from `xcodes installed`)
      DEVELOPER_DIR: "/Applications/Xcode-27.0.0.app/Contents/Developer"
    steps:
      - checkout
      - run:
          name: Resolve dependencies
          command: |
            xcodebuild -resolvePackageDependencies \
              -scheme "MyApp" \
              -clonedSourcePackagesDirPath ~/spm-cache
      - run:
          name: Build and test
          command: |
            xcodebuild test \
              -scheme "MyApp" \
              -destination "platform=iOS Simulator,name=iPhone 17,OS=latest" \
              -clonedSourcePackagesDirPath ~/spm-cache \
              -derivedDataPath ~/DerivedData/MyApp \
              -resultBundlePath TestResults.xcresult \
              -parallel-testing-enabled YES \
              | xcbeautify --report junit --report-path test-results
      - store_test_results:
          path: test-results
      - store_artifacts:
          path: TestResults.xcresult

  deploy-testflight:
    machine: true
    resource_class: your-org/mac-runner
    environment:
      DEVELOPER_DIR: "/Applications/Xcode-27.0.0.app/Contents/Developer"
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: bundle install
      # MATCH_PASSWORD and the App Store Connect API key variables
      # (ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_CONTENT) come from a CircleCI
      # context or the project's environment variables
      - run:
          name: Build and upload to TestFlight
          command: bundle exec fastlane beta

workflows:
  ios-pipeline:
    jobs:
      - lint
      - build-and-test:
          requires:
            - lint
      - deploy-testflight:
          requires:
            - build-and-test
          filters:
            branches:
              only: main

Fastlane एकीकरण उदाहरण

यदि आप अपने बिल्ड ऑटोमेशन के लिए Fastlane का उपयोग करते हैं, तो इसे अपने CircleCI सेल्फ-होस्टेड रनर के साथ एकीकृत करने का तरीका यहाँ दिया गया है:

# Fastfile (fastlane/Fastfile)
default_platform(:ios)

platform :ios do
  desc "Run tests"
  lane :test do
    scan(
      scheme: "MyApp",
      device: "iPhone 17",
      derived_data_path: File.expand_path("~/DerivedData/MyApp"),
      result_bundle: true,
      output_directory: "./test_output",
      # store_test_results reads JUnit XML
      output_types: "junit",
      output_files: "junit.xml"
    )
  end

  desc "Build and push to TestFlight"
  lane :beta do
    # App Store Connect API key: no Apple ID password or 2FA on the runner
    app_store_connect_api_key(
      key_id: ENV["ASC_KEY_ID"],
      issuer_id: ENV["ASC_ISSUER_ID"],
      key_content: ENV["ASC_KEY_CONTENT"]
    )
    match(type: "appstore", readonly: true)
    increment_build_number(
      build_number: ENV["CIRCLE_BUILD_NUM"]
    )
    gym(
      scheme: "MyApp",
      export_method: "app-store",
      derived_data_path: File.expand_path("~/DerivedData/MyApp")
    )
    pilot(skip_waiting_for_build_processing: true)
  end
end
# .circleci/config.yml using Fastlane
version: 2.1

jobs:
  fastlane-test:
    machine: true
    resource_class: your-org/mac-runner
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: bundle install
      - run:
          name: Run Fastlane tests
          command: bundle exec fastlane test
      - store_test_results:
          path: ./test_output
      - store_artifacts:
          path: ./test_output

  fastlane-deploy:
    machine: true
    resource_class: your-org/mac-runner
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: bundle install
      - run:
          name: Deploy to TestFlight
          command: bundle exec fastlane beta

workflows:
  ios-workflow:
    jobs:
      - fastlane-test
      - fastlane-deploy:
          requires:
            - fastlane-test
          filters:
            branches:
              only: main

प्रदर्शन तुलना

CircleCI क्लाउड macOS संसाधनों और MyRemoteMac के एक सेल्फ-होस्टेड Mac Mini M4 के बीच यहाँ एक विस्तृत प्रदर्शन और लागत तुलना दी गई है:

बिल्ड समय बेंचमार्क

बिल्ड समय बेंचमार्क
सेल्फ-होस्टेड Mac Mini M4 CircleCI क्लाउड macOS सुधार
क्लीन बिल्ड (मध्यम ऐप) 5 मिनट 14 मिनट 2.8 गुना तेज़
इंक्रीमेंटल बिल्ड 1.5 मिनट 14 मिनट (कोई कैश नहीं) 9.3 गुना तेज़
SPM डिपेंडेंसी रिज़ॉल्यूशन 5 सेकंड (डिस्क पर कैश) 3-5 मिनट (हर बार डाउनलोड) ~60 गुना तेज़
यूनिट टेस्ट सूट (500 टेस्ट) 2.5 मिनट 8 मिनट 3.2 गुना तेज़
कतार प्रतीक्षा समय 0 सेकंड 30 सेकंड - 5 मिनट तत्काल

मासिक लागत विश्लेषण

मासिक लागत विश्लेषण
टीम का आकार MyRemoteMac लागत बिल्ड/माह CircleCI क्लाउड लागत मासिक बचत
एकल डेवलपर $85/माह 100 बिल्ड (औसतन 10 मिनट) $120/माह $35/माह
छोटी टीम (5) $85/माह 500 बिल्ड (औसतन 10 मिनट) $600/माह $515/माह
मध्यम टीम (15) $229/माह (M4 Pro) 1500 बिल्ड (औसतन 10 मिनट) $1,800/माह $1,571/माह
एंटरप्राइज़ (50+) $458/माह (2x M4 Pro) 5000+ बिल्ड $6,000+/माह $5,542+/माह

My Remote Mac की कीमतें USD में, कर अतिरिक्त।

निष्कर्ष: CircleCI की m4pro.medium क्लास की दर पर (200 क्रेडिट, लगभग $0.12 प्रति मिनट, अक्टूबर 2026 तक) 10 मिनट का एक बिल्ड लगभग $1.20 का पड़ता है, इसलिए $85/माह (USD, कर अतिरिक्त) वाला समर्पित Mac mini M4 लगभग 71 बिल्ड प्रति माह से सस्ता पड़ता है। स्थायी Mac के वार्म कैश हर बिल्ड पर आपकी टीम का इंतज़ार भी घटाते हैं।

सामान्य समस्याओं का निवारण

रनर डिस्कनेक्ट हो जाता है या "Offline" दिखाता है

नेटवर्क समस्या, क्रैश या रीबूट के बाद रनर का कनेक्शन टूट सकता है। gui डोमेन में शुरू किया गया रनर तभी लौटता है जब उसका उपयोगकर्ता लॉग इन करे; चरण 2 का हेडलेस सेटअप इससे बचाता है। सेवा और उसका लॉग जाँचें:

# Check the service (use gui/ instead of user/ if you started it
# from a desktop session)
launchctl print user/$(id -u)/com.circleci.runner

# View the runner log
tail -50 "$HOME/Library/Logs/com.circleci.runner/runner.log"

# Restart the service
launchctl kickstart -k user/$(id -u)/com.circleci.runner

# If the token was revoked, create a new one, put it in
# ~/Library/Preferences/com.circleci.runner/config.yaml and restart
circleci runner token create your-org/mac-runner mac-mini-m4

resource_class नहीं मिला या जॉब्स कतार में अटके हुए

यदि जॉब्स "No matching runner found" के साथ कतार में रहते हैं, तो आपके कॉन्फ़िग में रिसोर्स क्लास डैशबोर्ड से मेल नहीं खाती:

# Verify the exact resource class name in the CircleCI web app:
# Runners (sidebar) lists your resource classes

# The resource_class in .circleci/config.yml must match exactly:
# resource_class: your-org/mac-runner  (case-sensitive!)

# Check your runner is online:
circleci runner instance list your-org/mac-runner

# Common mistakes:
# - Wrong namespace (org name vs personal namespace)
# - Typo in resource class name
# - Runner is offline or token is invalid
# - Using 'docker' executor instead of 'machine: true'

Xcode कोड साइनिंग त्रुटियाँ

एक CI मशीन पर कोड साइनिंग के लिए सावधानीपूर्वक कीचेन प्रबंधन की आवश्यकता होती है। रनर प्रक्रिया के पास लॉगिन कीचेन तक पहुँच नहीं हो सकती:

# Option 1: Use Fastlane Match (recommended)
# In your Fastfile:
match(type: "appstore", readonly: true)

# Option 2: Manual keychain management in your job steps
- run:
    name: Setup code signing
    command: |
      # Decode and import the certificate
      echo "$BUILD_CERTIFICATE_BASE64" | base64 --decode > /tmp/cert.p12

      # Create a temporary keychain
      security create-keychain -p "ci" /tmp/ci.keychain
      security set-keychain-settings -lut 21600 /tmp/ci.keychain
      security unlock-keychain -p "ci" /tmp/ci.keychain

      # Import the certificate
      security import /tmp/cert.p12 -P "$P12_PASSWORD" \
        -A -t cert -f pkcs12 -k /tmp/ci.keychain
      # Let codesign use the key without a GUI prompt
      security set-key-partition-list -S apple-tool:,apple:,codesign: \
        -s -k "ci" /tmp/ci.keychain
      security list-keychain -d user -s /tmp/ci.keychain

      # Install the provisioning profile (Xcode 16 and later location)
      PROFILES=~/Library/Developer/Xcode/UserData/Provisioning\ Profiles
      mkdir -p "$PROFILES"
      echo "$PROVISIONING_PROFILE_BASE64" | base64 --decode \
        > "$PROFILES/profile.mobileprovision"

सिम्युलेटर बूट होने में विफल या टाइम आउट हो जाता है

लंबे समय तक चलने वाली CI मशीनों पर सिम्युलेटर खराब स्थिति में आ सकते हैं। उन्हें बिल्ड के बीच रीसेट करें:

# Add a pre-build step to clean simulators
- run:
    name: Reset simulators
    command: |
      xcrun simctl shutdown all 2>/dev/null || true
      xcrun simctl erase all 2>/dev/null || true

# If a specific runtime is missing, reinstall it:
xcodebuild -downloadPlatform iOS

# List available simulators
xcrun simctl list devices available

डिस्क स्थान कम हो रहा है

Xcode बिल्ड बड़ी मात्रा में डेटा उत्पन्न करते हैं। अपने रनर पर स्वचालित सफ़ाई सेट करें:

# Check available disk space
df -h /

# Clean DerivedData folders unused for a week
find ~/DerivedData ~/Library/Developer/Xcode/DerivedData \
  -mindepth 1 -maxdepth 1 -mtime +7 -exec rm -rf {} +

# Delete simulators the current Xcode no longer supports
xcrun simctl delete unavailable

# List simulator runtimes, then delete the ones you no longer test on
xcrun simctl runtime list
# xcrun simctl runtime delete <runtime-identifier>

# Clean Homebrew cache
brew cleanup --prune=7

# Set up a weekly cron job for automatic cleanup
(crontab -l 2>/dev/null; echo "0 4 * * 0 find ~/DerivedData -mindepth 1 -maxdepth 1 -mtime +7 -exec rm -rf {} + ; /opt/homebrew/bin/brew cleanup --prune=7") | crontab -

अक्सर पूछे जाने वाले प्रश्न

Mac Mini M4 पर CircleCI सेल्फ-होस्टेड रनर की लागत कितनी है?
My Remote Mac का एक समर्पित Mac mini M4 असीमित बिल्ड मिनटों के साथ $85/माह (USD, कर अतिरिक्त) से शुरू होता है, और CircleCI सेल्फ-होस्टेड रनर पर प्रति बिल्ड मिनट शुल्क नहीं लेता। CircleCI के क्लाउड macOS जॉब्स m4pro.medium क्लास पर लगभग $0.12 प्रति मिनट के पड़ते हैं (200 क्रेडिट, हर क्रेडिट $0.0006, अक्टूबर 2026 तक), यानी सक्रिय टीमों के लिए मोटे तौर पर $300-500/माह। अपने रनर के साथ, बिल्ड की मात्रा चाहे जो हो, लागत पूर्वानुमेय रहती है।
क्या मैं iOS और macOS बिल्ड के लिए CircleCI सेल्फ-होस्टेड रनर का उपयोग कर सकता हूँ?
हाँ। Mac Mini M4 पर एक सेल्फ-होस्टेड रनर किसी भी macOS वर्कलोड को चला सकता है, जिसमें iOS बिल्ड, macOS ऐप बिल्ड, Swift पैकेज टेस्टिंग, Xcode UI टेस्ट, और Fastlane ऑटोमेशन शामिल हैं। चूँकि यह Apple Silicon पर नेटिव रूप से चलता है, बिल्ड एमुलेटेड या Intel-आधारित क्लाउड रनर की तुलना में तेज़ होते हैं।
CircleCI मशीन रनर और कंटेनर रनर में क्या अंतर है?
CircleCI मशीन रनर जॉब्स को सीधे होस्ट मशीन के ऑपरेटिंग सिस्टम पर एक्ज़ीक्यूट करता है, जो उन macOS/iOS बिल्ड के लिए आवश्यक है जिन्हें Xcode, सिम्युलेटर, और Apple फ्रेमवर्क की ज़रूरत होती है। कंटेनर रनर जॉब्स को Docker कंटेनरों के अंदर एक्ज़ीक्यूट करता है और केवल Linux पर उपलब्ध है। Mac बिल्ड के लिए, आपको मशीन रनर का उपयोग करना होगा।
मैं अपने CircleCI सेल्फ-होस्टेड रनर को अपडेटेड कैसे रखूँ?
मशीन रनर 3 खुद अपडेट नहीं होता: Homebrew पैकेज के साथ आप तय करते हैं कि brew upgrade circleci-runner कब चलाना है, फिर सेवा को पुनः शुरू करें। हर महीने रनर का चेंजलॉग देखें और Xcode तथा macOS को भी अपडेटेड रखें।
क्या एक सेल्फ-होस्टेड रनर CircleCI क्लाउड macOS की तुलना में तेज़ है?
हाँ, क्लीन बिल्ड के लिए आमतौर पर 2-3 गुना तेज़ और इंक्रीमेंटल बिल्ड के लिए 9 गुना तक तेज़। CircleCI हर क्लाउड macOS जॉब को एक नई M4 Pro वर्चुअल मशीन में चलाता है, इसलिए DerivedData और पैकेज कैश हर बार रिस्टोर करने पड़ते हैं। एक सेल्फ-होस्टेड Mac mini M4 केवल आपके लिए समर्पित भौतिक मशीन है, जिसमें DerivedData और SPM कैश बने रहते हैं और किसी क्लाउड मशीन के शुरू होने का इंतज़ार नहीं करना पड़ता।
क्या मैं एक Mac Mini पर एक साथ कई CircleCI जॉब्स चला सकता हूँ?
एक रनर के साथ नहीं। CircleCI प्रति मशीन एक ही मशीन रनर सपोर्ट करता है, और हर रनर एक समय में एक जॉब लेता है, इसलिए एक ही रिसोर्स क्लास में भेजे गए जॉब्स Mac के खाली होने तक इंतज़ार करते हैं। जॉब्स को पैरेलल चलाने के लिए, हर अतिरिक्त एक साथ चलने वाले जॉब के लिए एक Mac जोड़ें और उसे उसी रिसोर्स क्लास में रजिस्टर करें: CircleCI कतार में लगे हर जॉब को किसी खाली रनर को भेजता है, आपके प्लान की एक साथ चलने वाले सेल्फ-होस्टेड टास्क की सीमा के भीतर (Free पर 5, Performance पर 20, अक्टूबर 2026 तक)। एक जॉब के भीतर Xcode अब भी कई सिम्युलेटर पर टेस्ट पैरेलल चला सकता है। भारी जॉब्स के लिए Mac mini M4 Pro (12-कोर CPU, 24 GB, $229/माह से, USD, कर अतिरिक्त) ज़्यादा गुंजाइश देता है।

अपनी CircleCI पाइपलाइनों के लिए एक Mac Mini M4 से शुरुआत करें

अपने CircleCI सेल्फ-होस्टेड रनर के रूप में एक समर्पित Mac Mini M4 डिप्लॉय करें। असीमित बिल्ड मिनट $85/माह से शुरू।

My Remote Mac की कीमतें USD में, कर अतिरिक्त।

और जानकारी चाहिए?

चरण-दर-चरण सेटअप, कॉन्फ़िगरेशन संदर्भ और समस्या-निवारण के लिए संपूर्ण दस्तावेज़ देखें।

दस्तावेज़ खोलें →