DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Implementing Infrastructure as Code (IaC) for Data Center Management
  • Ansible Event-Driven Automation for Real-Time Operations
  • Fast Deployments of Microservices Using Ansible and Kubernetes
  • How To Use HashiCorp Tools To Create a Secured Edge Infrastructure

Trending

  • Medallion Architecture: Why You Need It and How To Implement It With ClickHouse
  • How to Convert XLS to XLSX in Java
  • AI-Driven Test Automation Techniques for Multimodal Systems
  • Beyond Simple Responses: Building Truly Conversational LLM Chatbots
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Xcode Server + Ansible: Scalable and Programmable iOS CI/CD Infrastructure

Xcode Server + Ansible: Scalable and Programmable iOS CI/CD Infrastructure

Learn how you can achieve scalability with Xcode Server using DevOps tools like Ansible, for continuous integration and delivery in your iOS projects.

By 
Shashikant Jagtap user avatar
Shashikant Jagtap
·
Dec. 19, 17 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
7.3K Views

Join the DZone community and get the full member experience.

Join For Free

One of the complaints about Xcode Server is it's not scalable to be used at a large-scale or enterprise level. However, if you have the skills to understand and manage an infrastructure for iOS deployment, then scalability can be easily achieved for small, medium, or large iOS teams using a mixture of iOS and DevOps toolkits. We have achieved it in the past in my previous role at Photobox Group using the combination of tools Ansible + Fastlane + TeamCity. You can read my blog post on the Moonpig Engineering blog here to learn how we achieved this.

In this post, we will see how learning a little bit of DevOps tools like Ansible and Apple's CI solution Xcode Server can help to manage large-scale iOS CI/CD infrastructure without any pain.

Background

Continuous Integration practices for iOS development aren't great as compared to the web world because of some unique challenges specific to iOS development. It's essential to understand the entire iOS ecosystem to setup and manage CI/CD infrastructure for the team. Some Senior/Lead iOS developers or iOS Tech Architects/Lead are great at the understanding whole stack of Apple developer tools, technologies, and infrastructure and implementing it in their projects, but most of the iOS developers in the industry at the moment are just iOS developers. They are good at writing Swift or Objective-C to build UI for applications inside Xcode; however, when it comes to understanding the infrastructure, they suck. They don't properly understand the underlying tools and technologies used by Xcode under the hood and that's why they became totally incapable of setting up or managing CI/CD practices for iOS apps. As an effect of this, they always have to depend on local Xcode or someone from the DevOps team to manage the infrastructure stack for them, or CI/CD is handled by highly expensive third-party services. It means developers are not full-stack and do not understand their own tools and technologies. Unfortunately, the world of iOS development is full of these kinds of amateurs and half-arsed developers. Continuous Integration won't be successful without skilled engineers on the team. In my previous post, I wrote about the top five reasons for CI failures. Those are wrong selection of CI server, CI amature engineers, lack of Infrastructure as Code, poor quality build servers, and lack of support from the team.

iOS Infrastructure Automation Challenges

On top of iOS engineers' inability to understand the entire iOS ecosystem, there are some traditional challenges in automation of iOS ecosystem. Some of them are imposed by Apple's proprietary software, and others are due to lack of tooling to automate iOS and macOS infrastructure. Some of the common challenges are

  • Lack of a configuration management tool that can be used to automate the infrastructure. Chef, Ansible, and Puppet are not designed to work with macOS servers.
  • Lack of an official package management system to provision and automate software installation. We have to use third-party solutions like HomeBrew
  • Lack of an official dependency management tools. We have to use Carthage or Cocoapods to manage dependencies. Swift Package Manager is not ready to use with iOS.
  • Lack of an official build tool. We have to use tools like Fastlane to automate iOS development tasks.

As a result of these challenges, nobody wanted to spend the time to explore a clean and automated solution to set up iOS infrastructure for smooth Continuous Delivery, which results in the following situations:

  • Manual setup of CI servers, which takes days for engineers to get things working on all build servers.
  • Flaky build automation, which produces inconsistent results.
  • The software configuration on local and build machines is different.
  • Continuous Integration is managed by a third-party provider and they need to be contacted them in case of build errors.
  • The team loses trust in CI and start using the local machine for testing and release.

These symptoms are obstacles to the best application development practices. We can solve some of these issues by knowing a little bit about configuration management tools and proper continuous integration tools. Now, we will see how the combination of Xcode Server and Ansible can help to set up large-scale continuous integration and manage it effectively.

Xcode Server

Xcode Server is a native Continuous Integration service developed by Apple. Xcode Server is one of the easiest ways to get started with Continuous Integration for iOS applications. It just needs Xcode installation and permission to access the Apple developer portal on macOS servers. If you use other solutions like Jenkins or TeamCity, you will need to install other dependencies like Java and other related software which have nothing to do with iOS development. Apple still has old documentation for Xcode Server at the time of writing this post, but I wrote the setup instructions in my previous blog post here. In order to set up the Continuous Integration server, we just need to install the following on the build machines:

  • Xcode
  • Xcode Command Line tools
  • macOS default settings
  • Ruby and Homebrew (optional)

We can manually install that software on each machine, but it will time-consuming if we have multiple macOS machines. We need to make sure that Xcode and other tool versions are consistent on all the servers. Now, we need to have configuration management to manage servers and software versions on those servers.

Provisioning Xcode Server With Ansible

There are various configuration management tools on the market, like Chef, Puppet, and Salt, but Ansible is very easy to learn and use. Although Ansible is designed for Linux, there are enough modules that can be used with macOS as well. This is not an Ansible tutorial, but you need to read a bit of documentation to get started with Ansible here.

In order to provision Xcode Server, we need the following things:

  • Xcode.xip file downloaded from Apple Developer Portal
  • Ansible installed on a remote macOS machine; Ansible will then ssh into a different macOS and install all available software.

Additionally, we can install other tools like Ruby and Homebrew using Ansible, if needed.

Provisioning Xcode Installation

In order to install Xcode, we need to have the .xip file downloaded from Apple Developer Portal and put it on the Ansible remote machine to copy over to ssh machines. There are various other things to be installed as part of the Xcode installation:

  • Archive XIP file and move Xcode app to /Applications
  • Accept Licence agreement
  • Install Xcode Command Line tools and other mobile development packages
  • Enable developer tools and install additional components
  • Set Xcode Developer directory

We can achieve all these tasks using Ansible.

---
- name: Check if Xcode is already installed
  stat: path=~/Library/Developer/Xcode/
  register: xcode_dir

- name: test whether xcode was uploaded earlier
  stat: path=/Users/{{ ansible_ssh_user }}/{{ xcode_src }}
  register: xcode_dl_path

- name: upload xcode
  copy: src={{ xcode_src }} dest=/Users/{{ ansible_ssh_user }}/
  when: xcode_dl_path.stat.exists == False

- name: check that the xcode archive is valid
  command: "pkgutil --check-signature ~/{{ xcode_src }} | grep \"Status: signed Apple Software\""
  when: xcode_dir.stat.exists == False

- name: Install Xcode from XIP file Location
  command: bash -c 'open -FWga "Archive Utility" --args /Users/{{ ansible_ssh_user }}/{{ xcode_src }}'
  when: xcode_dir.stat.exists == False

- name: Move Xcode To Application
  command: bash -c 'mv ~/Xcode*.app /Applications/'
  when: xcode_dir.stat.exists == False


- name: accept license agreement
  command: bash -c "sudo /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -license accept"

- name: install mobile device package
  command: bash -c " sudo installer -pkg /Applications/Xcode.app/Contents/Resources/Packages/MobileDevice.pkg -target /"

- name: install mobile device development package
  command: bash -c "sudo installer -pkg /Applications/Xcode.app/Contents/Resources/Packages/MobileDeviceDevelopment.pkg -target /"

- name: install Xcode System Resources package
  command: bash -c "sudo installer -pkg /Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg -target /"

- name: install additional xcode components
  command: bash -c "sudo installer -pkg /Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg -target /"

- name: check on the status of developer mode
  command: DevToolsSecurity -status
  become: yes
  become_method: sudo
  register: dev_tools_security_status


- name: enable developer mode
  command: DevToolsSecurity -enable
  become: yes
  become_method: sudo
  when:
    - "'disabled' in dev_tools_security_status.stdout"
    - xcode_dir.stat.exists == False

- name: Set Xcode Developer Directory
  command: bash -c "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer/"

Note that the code above is the example of an Ansible task; we have to set up some variables to configure users and directories.

Provisioning Xcode Server

Now we can install Xcode as part of the task mentioned above. The next thing is to control the Xcode Server using Ansible. Xcode Server has command line tools, xcscontrol, to manage the Xcode Server. We can start, stop, reset, and restart Xcode Server using this utility. We can write an Ansible task like this:

---

  - name:  Start Xcode Server with given user
    command: bash -c 'sudo xcrun xcscontrol --initialize --build-service-user {{xcode_server_user}}'

  - name:  COnfigure Xcode Server Certificate
    command: bash -c 'sudo xcrun xcscontrol --configure-ota-certificate'

  - name:  Configure Xcode Server timeout
    command: bash -c 'sudo xcrun xcscontrol --configure-integration-timeout 3600'

  - name:  Check Xcode Server Health
    command: bash -c 'sudo xcrun xcscontrol --health'

With this simple configuration, we can easily manage Xcode Servers on multiple macOS servers.

Xcode Server: Ansible Role

I have created an Ansible role for Xcode Server and published to Ansible Galaxy. You can find this role here.

This role is very configurable and can be used for setting up multiple macOS servers as per your needs. You can find detailed information in the README file.

You can see all the variables used for this role and turn them ON/OFF or set them as per your needs. You can optionally set up Ruby and Homebrew if needed.

vars:
    clean_xcode: yes
    clean_rvm: no
    clean_homebrew: no

    configure_xcode: yes
    configure_xcodeserver: yes
    configure_macos_defaults: yes
    configure_ruby_rvm: no
    configure_homebrew: no

    xcode_src: Xcode_9.1.xip

    xcode_server_user: shashi
    ansible_ssh_user: shashi

How to Use an Xcode Server Ansible Role

Imagine, you have a fresh Mac with fresh macOS installed. You can set up all your Xcode Server for CI by creating a Playbook for this role. You can set up config variables as per your needs. Assuming you have installed Ansible, we can download the role by running this command:

$ ansible-galaxy install Shashikant86.XcodeServer

Now we have to create our own playbook for this role by setting variables. We can use the default variables here. Now make a new directory called xcode_server and create a files directory and xcs_playbook.yml file.

$ mkdir xcode_server
$ mkdir XcodeServer/files
$ touch xcs_playbook.yml

Now place your Xcode_9.x.xip file inside the files directory and insert the following into the playbook file:

---
- hosts: localhost
  connection: local

  vars:
    clean_xcode: yes
    clean_rvm: no
    clean_homebrew: no

    configure_xcode: yes
    configure_xcodeserver: yes
    configure_macos_defaults: yes
    configure_ruby_rvm: no
    configure_homebrew: no

    xcode_src: Xcode_9.1.xip

    xcode_server_user: shashi
    ansible_ssh_user: shashi

  roles:
    - Shashikant86.XcodeServer

Change ansible_ssh_user and xcode_server_user to your username and Feel free to set variables as per your need. You can also specify your inventory to enable this playbook to run on multiple hosts. Now execute this playbook using the following command:

$ ansible-playbook xcs_playbook.yml

Watch your Mac Mini servers getting set up with Xcode Server for iOS Continuous Integration.

When to Use Xcode Server and Ansible

There are situations when we want to run Ansible playbook on servers; some common situations are:

  • New Xcode Versions to be installed
  • Resetting the Rebuild CI environment at regular intervals
  • Cleaning up the environment to fix code signing issues
  • Resetting the server to save disk space

Ideally, we should run the Ansible playbook regularly to check if anything has changed.

Benefits

Some of the benefits of using configuration management tools with Xcode Server are

  • Consistent setup all across the servers
  • Infrastructure as a code
  • Destroy and build CI servers whenever needed
  • Save hours of engineers manually setting up CI server machines
  • Eliminate the cost of expensive third-party CI services
  • No need to have dedicated DevOps resources to manage iOS CI/CD infrastructure
  • Understanding of the iOS ecosystem and the confidence to deal with any issues
  • No need to use third-party build automation tools like Fastlane as Xcode Server can handle almost everything needed for CI/CD

You might see several other benefits and increased confidence and trust in Continuous Integration.

Conclusion

Using the combination of DevOps tools and Apple's native CI/CD tools, we can achieve scalable and programmable infrastructure for our iOS apps. The Xcode Server and Ansible combination can work well together to achieve Continuous Delivery of iOS apps without any pain. Are you using any configuration management tools for iOS CI/CD infrastructure? What are your experiences with Xcode Server? Please let me know what you think about this approach- any ideas or suggestions would be great.

Continuous Integration/Deployment XCode Ansible (software) Infrastructure

Published at DZone with permission of Shashikant Jagtap, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Implementing Infrastructure as Code (IaC) for Data Center Management
  • Ansible Event-Driven Automation for Real-Time Operations
  • Fast Deployments of Microservices Using Ansible and Kubernetes
  • How To Use HashiCorp Tools To Create a Secured Edge Infrastructure

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: