# Xcode Cloud

### How it Works

When configuring our workflow, we select a branch to indicate where Xcode Cloud will listen for changes. Depending on how we configured it, a commit or merge request will trigger Xcode Cloud to begin making the build.

The process begins by creating the environment in which our repository gets cloned. After the repository is cloned, a **Post Clone Script** that we create is used to install dependencies such as CocoaPods as well as download any secrets to the directory. After this step, build actions are ran. We can also create a **Pre Build Script** as well as a **Post Build Script**. Finally, post-build actions are ran such as notifying to a Slack channel, pushing to TestFlight, etc.

In addition to configuring our flow to just archiving, we can set it to do other things such as running UI or Unit Tests.

### Creating the Scripts

If our app requires dependencies, we will first need to create a custom build script to be executed.

1. Create a branch called `release` in the GitHub repository.
2. Inside of the workspace, create a **Group** called `ci_scripts`. This folder must be located in the root directory.
3. There are three scripts possible scripts to make in here. See [this link](https://developer.apple.com/documentation/xcode/writing-custom-build-scripts). Note that we may not need all of them.
   1. Make sure to make these scripts executable by running `chmod +x <file_name.sh>`.
   2. **If our app contains secrets, we will most likely have to use environment variables for security reasons since these scripts must be published in the GitHub repository.**
   3. [This link](https://developer.apple.com/documentation/xcode/making-dependencies-available-to-xcode-cloud#Use-a-custom-build-script-to-install-a-third-party-dependency-or-tool) may also be helpful.
4. Push all of these changes to the `release` branch.

### Configure the Workflow

1. In Xcode, go to **Integrate > Xcode Cloud > Create Workflow**.
2. Select the Product.
3. Select `Edit Workflow`.
4. Under **General**, make sure that the correct **Primary Repository** is selected. Change the **Name** to `Release` and give it a description such as “Shipping new updates to the AppStore.”
5. Under **Environment**, select `Clean`.
6. Add any environment variables used by our scripts. Make sure to check `Secret` if they are secretive.
7. Under **Branch Changes**, remove `master` and add `release`. We want to use `master` for development only and then merge the `master` branch to `release` when ready for production.
8. Under **Archive - iOS** choose `iOS` and make sure the proper scheme is selected (e.g. a production environment scheme)
   1. Check `App Store`.
9. Click **Save** and enable Xcode cloud to have access to the GitHub repository.
   1. This will redirect us to GitHub. Make sure to choose `Only select repositories` and select the correct repository.
10. Go back to Xcode and make sure a green checkmark appears indicating that Xcode cloud has access, then click **Next > Complete**.
11. Create a first build for the `release` branch. Note that this will default to Build 1, but we can change this later.
12. We can view all builds under the Xcode Cloud tab in AppStore Connect.
    1. If there is already a build version, select the next build number in settings.
13. Under **Post Actions** we can configure it to notify Slack channels, upload to TestFlight, etc.

### Development Workflow

It’s often the standard that we follow this approach when developing.

1. Create a branch off of `master` and work on that branch.
2. Create a PR to merge the branch to `master` or `main`. Note that these changes are only meant for development.
3. When we are ready to release changes to the AppStore, we can then merge `master` or `main` to `release`.
   1. In the case that there are merge conflicts, create a branch off of `release` (call it `release-copy`) and merge our `master` or `main` branch to resolve merge conflicts. Make sure to change the app version as well as the build version (even though the build version should automatically be incremented by Xcode Cloud). When done, submit a PR to merge `release-copy` to `release`.

Now, there are times when we want to make changes to the AppStore version without interfering with the development side.

1. In this case, you want to create a working branch off of `release`.
2. Then, increment the build version as well as the app version.
3. Submit a PR to merge that working branch to `release`. If there are merge conflicts, follow the same process mentioned above.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ios-course.cornellappdev.com/resources/textbook/ci-cd/xcode-cloud.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
