# How the CI Build Script (`ci-build-and-tests.sh`) Automates iOS Building and Testing in HallelujahIM

> Discover how the ci-build-and-tests.sh script in HallelujahIM automates iOS CI by cleaning dependencies, running xcodebuild tests, and building the app. Learn more now

- Repository: [dongyuwei/hallelujahim](https://github.com/dongyuwei/hallelujahim)
- Tags: how-to-guide
- Published: 2026-02-28

---

**The [`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh) script in the `dongyuwei/hallelujahim` repository automates iOS continuous integration by sequentially cleaning CocoaPods dependencies, executing unit tests via `xcodebuild`, and building the application only after tests pass.**

This shell script serves as the central orchestration point for the HallelujahIM project's CI pipeline. By encapsulating dependency management, test execution, and build steps into a single executable file, the repository ensures that both local developers and remote CI servers follow identical, reproducible workflows.

## Overview of the CI Build Script Automation

The [`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh) script implements a three-phase automation strategy designed to guarantee code quality before producing distributable artifacts. Each phase addresses a specific concern: dependency isolation, test validation, and artifact generation. The script delegates technical details to specialized sub-scripts ([`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh) and [`build.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/build.sh)) while maintaining high-level control over execution order and environment preparation.

## Step-by-Step Breakdown of [`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh)

### Step 1: Clean and Reinstall CocoaPods Dependencies

The script begins by forcing a pristine dependency state to eliminate version conflicts or corrupted pod installations. It removes the lock file and existing pods directory before triggering a fresh install:

```bash
rm Podfile.lock
rm -rf Pods
pod install

```

This sequence guarantees that the CI environment uses the exact library versions specified in the `Podfile`. By discarding `Podfile.lock`, the script ensures that dependency resolution occurs dynamically, catching any upstream changes or incompatibilities immediately. The subsequent `pod install` regenerates the `Pods` directory and updates the `hallelujah.xcworkspace` file, creating a consistent foundation for compilation.

### Step 2: Execute Unit Tests via [`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh)

After dependency preparation, the script prints a visual delimiter and delegates test execution to [`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh):

```bash
echo "===================tests===================="
sh unit-tests.sh

```

The [`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh) file contains the precise `xcodebuild` commands required to compile and test the project without manual intervention:

```bash
xcodebuild clean -workspace hallelujah.xcworkspace/ -scheme Tests
xcodebuild test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO \
    -workspace hallelujah.xcworkspace/ -scheme Tests

```

The initial `clean` command purges build artifacts from previous runs, preventing incremental build inconsistencies from affecting test outcomes. The `test` command executes the `Tests` scheme within the CocoaPods-managed workspace. Critically, the script disables code signing by setting `CODE_SIGN_IDENTITY` to an empty string and `CODE_SIGNING_REQUIRED` to `NO`, allowing the CI environment to run tests without provisioning profiles or developer certificates.

### Step 3: Build the Application with [`build.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/build.sh)

Upon successful test completion, the script proceeds to the final build phase:

```bash
echo "=================build App=================="
sh build.sh

```

This invocation triggers [`build.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/build.sh), which typically contains an `xcodebuild` command configured to generate the final application bundle or IPA file for distribution. By isolating the build step from the test step, the CI pipeline implements a **fail-fast** strategy: if unit tests fail, the script exits before consuming resources on compilation, providing immediate feedback to developers.

## Running the CI Build Script Locally

Developers can reproduce the exact CI environment on their local machines by executing the script directly from the repository root:

```bash
chmod +x ci-build-and-tests.sh
./ci-build-and-tests.sh

```

This command sequence ensures the script has execute permissions and then runs the full pipeline—dependency refresh, test execution, and application build—mirroring the behavior of remote CI servers.

## Integrating with GitHub Actions

The script integrates seamlessly with modern CI platforms. A typical GitHub Actions workflow configuration invokes the script after setting up the required environment:

```yaml
steps:
  - name: Checkout repository
    uses: actions/checkout@v3

  - name: Set up Ruby (for CocoaPods)
    uses: ruby/setup-ruby@v1
    with:
      ruby-version: '2.7'

  - name: Install CocoaPods
    run: sudo gem install cocoapods

  - name: Run CI build and tests
    run: ./ci-build-and-tests.sh

```

This configuration delegates all build logic to the shell script, keeping the YAML configuration concise and ensuring consistency between local and cloud-based builds.

## Summary

- **[`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh)** serves as the central automation hub for the HallelujahIM iOS project, orchestrating dependency management, testing, and building.
- The script enforces a **clean dependency state** by removing `Podfile.lock` and the `Pods` directory before running `pod install`, ensuring reproducible builds.
- Unit tests execute via **[`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh)**, which uses `xcodebuild` with code signing disabled (`CODE_SIGN_IDENTITY=""`) to run the `Tests` scheme in CI environments without certificates.
- The **fail-fast** architecture stops the pipeline if tests fail, preventing unnecessary resource consumption during the final application build step.
- The script is **environment-agnostic**, running identically on local developer machines and remote CI platforms like GitHub Actions.

## Frequently Asked Questions

### What does [`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh) do in the HallelujahIM project?

The [`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh) script automates the entire continuous integration workflow for the HallelujahIM iOS application. It sequentially cleans and reinstalls CocoaPods dependencies, executes the unit test suite via [`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh), and triggers the final application build through [`build.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/build.sh). This automation ensures that every code change is validated against a clean, reproducible environment before producing distributable artifacts.

### Why does the script delete `Podfile.lock` and the `Pods` directory?

The script removes `Podfile.lock` and the `Pods` directory to force a **deterministic dependency resolution** from scratch. Deleting these files eliminates the risk of stale, corrupted, or version-mismatched libraries that might exist from previous builds. The subsequent `pod install` command regenerates these files based on the current `Podfile`, guaranteeing that the CI environment uses the exact versions of third-party libraries intended by the developers, which prevents nondeterministic build and test failures.

### How does the script handle code signing during testing?

The script disables code signing entirely during the test phase to accommodate CI environments that lack Apple Developer certificates and provisioning profiles. Inside [`unit-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/unit-tests.sh), the `xcodebuild test` command includes the flags `CODE_SIGN_IDENTITY=""` and `CODE_SIGNING_REQUIRED=NO`, which instructs Xcode to skip signing operations while compiling and running the test target. This configuration allows the unit tests to execute on any machine, including cloud-based CI runners, without requiring access to secure signing assets.

### Can I run [`ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/ci-build-and-tests.sh) on my local machine?

Yes, you can execute the script locally to reproduce the exact same build and test process used by remote CI servers. Simply navigate to the repository root, ensure the script has execute permissions with `chmod +x ci-build-and-tests.sh`, and run [`./ci-build-and-tests.sh`](https://github.com/dongyuwei/hallelujahim/blob/main/./ci-build-and-tests.sh). This will perform a fresh CocoaPods installation, run all unit tests, and build the application on your local machine, providing immediate feedback during development and ensuring that your changes will pass CI validation before being pushed.