Post

CI/CD Explained: Boost iOS App Development Stability and Efficiency|Tool Selection Guide

iOS app teams struggle with unstable builds and slow releases; discover how implementing CI/CD improves development speed and reliability, and learn which tools optimize your workflow for consistent delivery.

CI/CD Explained: Boost iOS App Development Stability and Efficiency|Tool Selection Guide

点击这里查看本文章简体中文版本。

點擊這裡查看本文章正體中文版本。

This post was translated with AI assistance — let me know if anything sounds off!


Practical Guide to CI/CD (Part 1): What is CI/CD? How to Build a Stable and Efficient Development Team with CI/CD? Tool Selection?

Using the App (iOS) Team as an example, this will guide you from zero to understanding CI/CD and the tangible value it brings after implementation.

Photo by [Leif Christoph Gottwald](https://unsplash.com/@project2204?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash){:target="_blank"}

Photo by Leif Christoph Gottwald

Preface

After experiencing building App CI/CD with two different development teams, I finally have time to organize the journey from “why to do it” to “how to do it.” I can’t guarantee this is the most standard CI/CD workflow, but it is definitely a valuable starting point to help your team begin implementation, improve product stability, and enhance overall development efficiency.

Chapter

This series will start with “What is CI/CD and what value it brings,” then move on to a hands-on guide on “How to set up a CI/CD environment using GitHub Actions + self-hosted Runner.” Using app development as an example, it will demonstrate how to implement CI and CD in practice. Finally, it will introduce how to “use Google Apps Script Web App combined with GitHub Actions to create a convenient app packaging platform for cross-team use.” I hope this series will be helpful to you.

Final Outcome

No more nonsense, here is the final result.

[Demo PR](https://github.com/ZhgChgLi/github-actions-ci-cd-demo/pull/11){:target="_blank"}

Demo PR

[Demo Web App](https://script.google.com/macros/s/AKfycbxk1nYhzfBzqny34rvBlxmcWMEQbWTL5a28mBmYId0NDaCZd0S-U3ytpBoTi2wZp0d6cg/exec){:target="_blank"}

Demo Web App

CI/CD — Entirely developed using GitHub Actions, easy to maintain and extend.

CI:

  • Trigger Unit Tests Automatically on PR Submission

  • Run corresponding tests based on the scope of the changed files

  • Merge PR only after the test has passed.

CD:

  • Google Apps Script Web App (CD Packaging Interface) allows engineers, QA, and PMs to package apps on computers or mobile devices through this website.

  • GitHub Actions Self-hosted Runner: Using Your Own Machine for Unlimited CI/CD Usage

  • Integrate Firebase App Distribution API to Directly Obtain the Packaged Beta Download Link

Automation :

  • Auto-Assign Self on PR Submission

  • Assign Reviewers Automatically and Randomly When Creating a PR

  • Mark PR Size Label

Demo Web App/Project

Sign in Edit description script.google.com

What is CI/CD?

Story — Development Process Without CI/CD

Before discussing what CI/CD actually is, let’s set aside the term “CI/CD” and first recall how a startup development team without any workflow implemented would operate. The general process can be roughly summarized in the diagram below:

  1. The product has a bug. Developer T created a branch fix/bug-c from the main branch to fix it. After the fix, the branch was merged back into the main branch.

  2. Next, Developer Z branched off feature/a from the main branch to work on requirement A. Halfway through, they noticed the feature was acting strange. After checking, they found the current feature was broken, and the tests were failing. They then informed Developer T to fix it.

  3. After all development is complete, Developer Z uses his computer to package the version for QA testing, repeatedly fixing and packaging. Once there are no issues, the feature is merged back into the main branch.

  4. The sprint quickly came to an end, and it was time to package and release to users; Developer Z put aside current tasks to help package from the main branch for QA to perform regression testing, similarly going back and forth fixing issues and repackaging, then finally packaged and submitted the app for review.

  5. After Apple/Google review is complete, release it to users.

Question

In the above story, we can summarize two major issues.

Question 1: There is no unified inspection mechanism for current correct functional changes.

  • Code That Does Not Meet the Coding Style Can Also Be Merged

  • Even if the build fails, I can still merge.

  • After changes, basic Unit Tests and important checkpoints failed but still merged

  • My environment functions correctly, but it may not work properly for others.

  • Affecting other developers currently working on the project

Question 2: A lot of manpower and time are spent on packing work.

  • Packaging requires engineers’ manpower, interrupting ongoing development work.

  • Switching between packaging and development causes high cognitive switching costs.

  • Waiting for packaging delays other development tasks.

  • Engineers’ time costs money.

  • Manual operations can lead to errors.

  • QA must ask engineers to package, causing back-and-forth communication.

CI — Continuous Integration

For Question 1, “Continuous Integration” aims to ensure that all changes automatically undergo Build & Test in a unified environment, guaranteeing that all modifications pass every test case and meet team standards before entering the production environment — “continuously and automatically ensuring correct code integration into production.”

You can also add Nightly Build and more automated testing stages to ensure stability.

CD — Continuous Delivery / Deployment Continuous Delivery / Deployment

Corresponding to Question 2, “Continuous Deployment” aims to automatically complete the packaging and deployment process of code changes after passing the CI stage without errors, delivering them to internal testing (QA, Debug, Staging, Beta…) or external release (Production, Release…).

  • Continuous Deployment: Fully automated direct deployment to the Production environment

  • Continuous Delivery: Automatically deploy only to Staging/Debug environments; manual verification is required before deploying to Production environment.

In the context of app development, it leans more towards Continuous Delivery, where we want a manual check to confirm everything is perfect before the app is officially released, ensuring the release timing and functionality are accurate.

Story — Building a Stable and Efficient Development Team Through CI/CD

Looking back at our story, after implementing CI/CD:

  • CI
    All adjustments must pass automated testing verification before merging into the main branch. Add a Nightly Build scheduled automated testing phase to improve stability.

  • CD
    Using CD packaging consistently allows Developer T and Developer Z to fully focus on business development, reducing manual communication and operational errors.

Team Work Efficiency and Product Stability 🚀🚀🚀🚀🚀

The Value of CI/CD

Combining the core Agile development principle of “small steps, fast iteration,” CI/CD provides the foundation for stability and efficiency during frequent continuous feature iterations.

Automated Unified Verification of Iteration Results

  • Ensure all adjustments meet the expected results, do not affect other functions, and do not impact other team members.

Automate Tedious Deployment Processes

  • Enable team members to focus on core business development and reduce manual operation errors

The Effectiveness of CI/CD

Looking back at the 2021 Pinkoi talk “2021 Pinkoi Tech Career Talk — Secrets of High-Efficiency Engineering Teams,” the content was essentially the same: focusing on “automation, reducing dependence on people, and concentrating on core business.” Implementing CI/CD perfectly aligns with these three goals, allowing us to use the same approach to estimate its effectiveness.

Another point that needs to be highlighted again is the cost of flow switching:

After working continuously for a period, we enter a “flow” state, where our thoughts and productivity peak, allowing us to produce the most effective output. However, if interrupted, it takes time to return to this flow state—here, we use 30 minutes as an example.

In scenarios without CI/CD, it might be: spending a lot of time only to find out something was broken and then going back to communicate and adjust (CI), QA/PM asking engineers to help package the test version of the app (CD).

CI/CD Effectiveness Estimation

Team size: 6 people Calculated over one month

Team size: 6 people / calculated per month

Here, we use a monthly basis. Assuming no CI/CD process, there are 4 unexpected breaks in the main branch each month, causing about 720 minutes of repair and communication costs. Adding the time for packaging test and official versions and errors from manual operations, the total is about 1,010 minutes. With an engineer’s monthly salary of 80,000, this results in a monthly cost waste of about 13,000.

CI/CD Build Costs

  • Labor Cost:
    Based on this series of articles, it is estimated that 1 person needs 10 days = 4,800 minutes to complete the work. (~= NT$36,384)

  • Equipment and Execution Costs:
    Using GitHub Actions self-hosted Runner only requires purchasing 1–2 Mac Minis initially or directly using existing retired MacBook Pros as CI/CD Runners to provide services.
    For example, a 6-person team purchasing a brand new Mac Mini: 32G RAM M4 Mini (= NT$40,900)

The total cost is about NT$80,000, and benefits can be enjoyed starting around six months later.

Disclaimer: This is just one method to calculate benefits and may not be the most accurate; it is intended to provide a concept for everyone to expand on, enabling management to understand the benefits of CI/CD and thus approve the promotion and completion of the entire workflow.

Tool Selection for CI/CD

Cloud Services Bitrise / XCode Cloud

  • Bitrise: One of the earliest cloud services focused on App CI/CD. My first experience with CI/CD was using Bitrise. It offers a user-friendly and intuitive step editor, allowing quick setup of App CI/CD workflows.
    Drawback: Initially, it was $99 for unlimited usage. When Apple M-series processors first came out, they switched to usage-based billing (lock-in strategy), and our team’s monthly cost was at least $500. So we migrated to GitHub Actions.
    However, recently on their official site, they now offer 1 App / 1 Concurrent / unlimited usage / $89 per month.

  • XCode Cloud: 100 hours / 1 month / $50, advantage is high integration with XCode and app development; however, the downside is it does not support Android and customizing some steps can be difficult. For small pure iOS apps, I would consider using it again.

Really worried about cloud services being a trap, so I prefer to keep control in my own hands and consider on-premise services instead.

On-Premises Services Jenkins / GitHub Actions / Gitlab CI/CD

  • Gitlab CI/CD:
    It was launched earlier and has more complete features than GitHub Actions, but since our project is hosted on GitHub, we won’t consider using Gitlab CI/CD. However, both have similar functions, and this series will use GitHub Actions as an example.

  • GitHub Actions
    GitHub launched its CI/CD service in 2018, directly integrated with GitHub projects. It has continuously improved over the years, offering many pre-built steps (Marketplace) ready to use. It supports self-hosted runners, allowing unlimited use of your own machines (effectively a hybrid cloud).

  • Jenkins:
    An open-source, free tool specialized in CI/CD, old but powerful; it covers everything from application-level task design and permission management to backend service dispatch and execution. Jenkins is all-inclusive. It also offers Plugins for direct integration and is an essential tool for early DevOps CI/CD.

Jenkins v.s. GitHub Actions

TL;DR

In app teams without dedicated DevOps, expecting app developers to set up and maintain a Jenkins environment from scratch is too challenging. Few know how to do it, and it can lead to network security issues. Choosing GitHub Actions allows app developers to focus solely on designing the CI/CD process. By briefly reviewing the official documentation on writing workflows and starting runners, they can quickly build a free, stable, and secure CI/CD service.

The following comparison is based solely on setting up App CI/CD and does not apply to all technical scenarios.

Setup and Maintenance Difficulty Jenkins »> GitHub Actions

Here is a simple layered diagram to explain the difference between the two. As mentioned before, Jenkins covers all functions from top to bottom, making self-hosting much more complex. In contrast, GitHub Actions only requires writing YAML workflows on GitHub. On the local machine, you just need to register the GitHub self-hosted Runner (completed with 5 commands), and GitHub will automatically dispatch tasks to the local machine. Other issues, such as GitHub Actions/Runner version upgrades or task dispatch problems, are maintained by GitHub, so we don’t need to handle them.

Another more troublesome point is that Jenkins is a service independent of Git, and communication between them must be done through APIs (e.g., GitHub API/WebHook), making the setup even more complex.

I previously surveyed about 30 iOS developers around me. Only a few (2) understood Jenkins, while more than 10 were using GitHub Actions. After all, writing a bit of YAML can complete CI/CD tasks.

Learning Difficulty Jenkins »> GitHub Actions

Just refer to the official documentation to learn the available YAML commands for GitHub Actions and how to set up your own Runner locally.

Stability: GitHub Actions > Jenkins

I think GitHub Actions slightly outperforms Jenkins in this aspect.

Jenkins may crash due to system upgrades or conflicting plugins (however, if it’s running smoothly, it generally has no issues as long as you don’t interfere).

GitHub Actions depends on GitHub Service Status (if GitHub is down, it will be down too), but outages are rare, with an average uptime of 99.9%. If a problem occurs, just wait for it to be fixed.

Security: GitHub Actions > Jenkins

Considering that GitHub Actions/Runner is maintained and automatically updated by GitHub itself, it may be safer than Jenkins, which requires manual updates.

Additionally, opening API/WebHook ports for communication between Jenkins and GitHub is relatively risky. GitHub and GitHub Actions integrate seamlessly, and the relationship between GitHub Actions and the self-hosted Runner is observer-based. The self-hosted Runner requests tasks from GitHub, so the Runner itself does not need to expose any external interfaces.

But in a fully closed network environment, Jenkins is more secure than GitHub Actions.

Permission Control Jenkins »> GitHub Actions

This point needs special comparison: Jenkins allows setting up account login permissions for control; GitHub Actions is directly tied to the GitHub Repo, so only those with Repo permissions can use it.

Therefore, the following article uses GAS Web App to build a cross-team operation platform.

Using Jenkins Extensively »> GitHub Actions

For teams with a full DevOps team, Jenkins is undoubtedly the preferred choice. After all, in other fields (such as Web, backend, Java…), Jenkins has been running the longest, offers the most useful plugins, and allows building a unified CI/CD system for all teams, making management easier. It also supports complex CI/CD scenarios like deploying the backend first and then automatically deploying the frontend.

GitHub Actions later also supports cross-repo Actions/Runners.

Richness of Third-Party Plugins Jenkins > GitHub Actions

In terms of quantity, GitHub Actions outnumbers Jenkins, but Jenkins offers deeper and more powerful CI/CD capabilities. Many features of GitHub Actions are primarily automation functions.

Feature Depth Jenkins »> GitHub Actions

This aspect is unmatched. Jenkins has been around for nearly 20 years, while GitHub Actions still needs to add many features; for example: permission management, secret management (currently only supports plain text, key files must be converted to plain text first), cache/artifact support is currently limited to the cloud, and so on.

Additionally, GitHub Self-hosted Runner also supports Docker or k8s.

Customized Deep Jenkins »> GitHub Actions

Jenkins is fully controlled by yourself, offering greater customization of permissions that can affect the entire system. GitHub Actions can only customize different steps at the application level.

For example, since the built-in Artifacts in GitHub Actions do not support self-hosted runners, you can only change the step to use sh to copy files to another directory, and cannot customize your own Artifacts implementation.

App CI/CD scenarios do not require very advanced features.

Usability GitHub Actions »> Jenkins

On the interface, GitHub Actions is a newer tool and is easier to use than Jenkins;
In terms of script configuration, Jenkins uses Pipeline Scripts stored on Jenkins, while GitHub Actions uses YAML files managed with the project’s Git, making it easier to set up than Jenkins.

Cost Risk Jenkins > GitHub Actions

Jenkins is fully open-source and free to use, while GitHub Actions is partially open-source but its task dispatching and execution are part of GitHub’s closed SAAS service. Currently, GitHub Actions is completely free; you only pay for using GitHub Runners (Private Repo), but self-hosted runners are free.

Uses of Google Apps Script Web App and Why Choose It

Another tool option is Google Apps Script Web App. The reason for needing this is that GitHub Actions’ built-in form feature is too basic (the interface is too technical and static) and its execution permissions are tied to the GitHub repo. This makes it very inconvenient if we want to provide access to other functional partners.

As follows:

CD packaging often requires the operator to fill in some information, such as Release Notes.

Therefore, we need an “interface” tool for other partners to use or even for our own engineers to use more conveniently.

Required Scenario:

Fill in the required information on this more user-friendly “interface,” connect to project management tools (e.g., Jira, Asana) to fetch Tasks, or directly retrieve the PR list from GitHub. Then select from the dropdown menu and submit, triggering GitHub Actions through the GitHub API to perform packaging.

Slack

When we first implemented CI/CD, we chose to integrate the Slack API to achieve an effect like the following:

<https://slack.com/intl/zh-tw/blog/productivity/workflow-builder-tools-automation-examples>{:target="_blank"}

https://slack.com/intl/zh-tw/blog/productivity/workflow-builder-tools-automation-examples

  • Partners can fill out forms directly in Slack to submit information, trigger CD packaging, and receive Slack notifications.

The operation is smooth and unified within daily office tools (SSOT), requiring no relearning; however, the underlying issue is that development and maintenance costs are very high. One reason is that the Slack Outgoing-Webhook API demands a very fast response (within 3 seconds), which basically rules out using FAAS services for simple integration (e.g., Cloud Functions, GAS, Lambda…).

Previously, a team member interested in automation and backend development created a complete backend service using Kotlin+ktor, then deployed the server on GCP for Slack integration.

Development and maintenance costs are extremely high, and handover is very difficult.

Google Apps Script — Web App

Previously shared “Using Google Apps Script Web App Form to Integrate with Github Action CI/CD Workflow”:

[Demo Web App Form URL](https://script.google.com/macros/s/AKfycbw8SuK7lLLMdY86y3jxMJyzXqa5tdxJryRnteOnNi-lK--j6CmKYXj7UuU58DiS0NSVvA/exec){:target="_blank"}

Demo Web App Form URL

Advantages of Using Google Apps Script — Web App:

  • Website Web

  • Similar to Google Workspace enterprise account permission management, you can set access so that only Google accounts within the organization are allowed.

  • Completely Free

  • Function as a Service Does Not Require Setting Up or Maintaining Servers

  • Easier to maintain and hand over

  • Can be operated on a mobile phone

  • AI Can Help!
    Whether it’s ChatGPT or other AI tools, they are very familiar with GAS and can directly help us create packaged forms and connect to the GitHub API.

  • Can also integrate with Jira, Asana, Slack notification APIs

For the second promotion, I switched to using a GAS Web App for the team, which also received great feedback. The only difference from Slack is that you need to bookmark an additional URL. When packaging is needed, open the URL and operate the packaging through the web form.

Complete App CI/CD Tool Workflow

Here is the complete workflow. In the next article, I will gradually explain how to use and integrate each tool.

Tool Role:

  • GitHub Actions: CI/CD logic script code

  • GitHub Actions — Self-hosted Runner: The actual environment where CI/CD runs. Using your own hosted runner means you only pay for the machine, enabling unlimited task executions.

  • Google Apps Script Web App: Since packaging is not always done by engineers, a platform is needed for cross-functional partners; GAS Web App can quickly create a web tool and share the URL for others to use.

  • Asana/Jira: Project management tools that integrate with GAS Web App, allowing QA/PM to directly select tasks for packaging.

  • Slack: Handles receiving execution result notifications

Scenario:

  • End-User (QA/PM/PD/Developer): Use GAS Web App to submit the packaging form (fetch the Branch corresponding to the Jira or Asana task) -> GAS calls GitHub API -> trigger CD packaging GitHub Actions <- GitHub self-hosted runner listens to the task and pulls it to the machine for execution -> upon completion, send Slack notification and update the packaging status in GAS Web App.

  • End-User (Developer): Open PR, push new commit to PR -> trigger CI test process <- GitHub self-hosted runner listens for task, pulls it to the machine for execution -> after completion, comment test results and update Checks.

Summary

This article mainly provides an introduction to what CI/CD is and its benefits. The next article will dive into the technical aspects, guiding you step-by-step to understand and implement GitHub Actions CI/CD, leading to the final outcome discussed earlier.

Series Articles:

Buy me a coffee

This series of articles took a lot of time and effort to write. If the content helps you or improves your team’s work efficiency and product quality, please consider buying me a coffee. Thank you for your support!

[Buy me a coffee](https://www.buymeacoffee.com/zhgchgli){:target="_blank"}

Buy me a coffee

If you have any questions or feedback, feel free to contact me.


Buy me a beer

This post was originally published on Medium (View original post), and automatically converted and synced by ZMediumToMarkdown.

Improve this page on Github.

This post is licensed under CC BY 4.0 by the author.