.. _xcode_cloud_api: ================================== Xcode Cloud API Configuration Tool ================================== This tool allows you to programmatically export and create Xcode Cloud workflow configurations using the App Store Connect REST API. The script lives at ``~/dev-peek/dev-peek-workspace/workspace-common/`` and uses Python 3.12 with Twisted. -------------------- Getting API Credentials -------------------- You need an App Store Connect API key to authenticate. **Step 1 — Create the API key** 1. Go to `App Store Connect `_ 2. Navigate to **Users and Access → Integrations → App Store Connect API** 3. Click **Generate API Key** (or use an existing one) 4. Download the ``.p8`` private key file — Apple only lets you download it once 5. Note your **Key ID** (shown in the table, also in the filename: ``AuthKey_.p8``) **Step 2 — Get the Issuer ID** The **Issuer ID** is shown at the top of the same **Users and Access → Integrations → App Store Connect API** page. It is a UUID like ``69a6de79-d6e1-47e3-e053-5b8c7c11a4d1``. **Step 3 — Set environment variables** .. code-block:: bash export ASC_KEY_ID="966L93C63C" export ASC_ISSUER_ID="69a6de79-d6e1-47e3-e053-5b8c7c11a4d1" export ASC_PRIVATE_KEY_PATH="/path/to/AuthKey_966L93C63C.p8" -------------------- Setup -------------------- Create a virtual environment using the Peek Python installation: .. code-block:: bash cd ~/dev-peek/dev-peek-workspace/workspace-common ~/dev-peek/opt/python/bin/python -m venv .venv .venv/bin/pip install twisted click "PyJWT[crypto]" pyopenssl service_identity certifi -------------------- Interactive Setup Wizard -------------------- The wizard walks through adding a new app by copying an existing workflow. It handles exporting the source workflow, updating the new product's default workflow, creating a GitLab access token, and printing the manual steps that cannot be done via API. .. code-block:: bash cd ~/dev-peek/dev-peek-workspace/workspace-common export ASC_KEY_ID="..." ASC_ISSUER_ID="..." ASC_PRIVATE_KEY_PATH="..." .venv/bin/python bin/pd_setup_xcode_cloud_app.py -------------------- Usage — Individual Commands -------------------- These commands are available from the ``xcode-cloud`` CLI if the package is installed from ``~/Downloads/xcode-cloud``, or by calling the modules directly. List all Xcode Cloud products (apps): .. code-block:: bash .venv/bin/xcode-cloud list-products List workflows for a product: .. code-block:: bash .venv/bin/xcode-cloud list-workflows Export all workflows for a product to JSON files: .. code-block:: bash .venv/bin/xcode-cloud export-workflows -o ./exported List available Xcode and macOS versions: .. code-block:: bash .venv/bin/xcode-cloud list-xcode-versions .venv/bin/xcode-cloud list-macos-versions List connected repositories: .. code-block:: bash .venv/bin/xcode-cloud list-repositories List registered bundle IDs: .. code-block:: bash .venv/bin/xcode-cloud list-bundle-ids Create a workflow from an exported JSON file: .. code-block:: bash .venv/bin/xcode-cloud create-workflow ./exported/.json \ --xcode-version-id \ --macos-version-id Update an existing workflow from a JSON file: .. code-block:: bash .venv/bin/xcode-cloud update-workflow ./exported/.json \ --xcode-version-id \ --macos-version-id -------------------- Adding a New App -------------------- Apple's public API requires a GitLab project bot to be present in the repository before a product can be registered with Xcode Cloud. This bot is created automatically by Apple's servers during the initial Xcode setup flow — it cannot be triggered via the public API. This one step must be done manually; everything after it is fully API-driven. **Step 1 — One-time Xcode setup (creates the GitLab bot and product)** 1. In the target app's repo, open the Xcode workspace:: cd peek_field_app/ios/App open App.xcworkspace 2. In Xcode: **Integrate → Create Workflow** 3. Click through all the *Next* prompts and set the app name 4. On the final screen, choose **Don't Start Build** — the default workflow Xcode creates will be replaced in the next step This registers the GitLab repo with Xcode Cloud (creating a project-scoped bot account), creates the bundle ID, and creates an initial ``ciProduct``. **Step 2 — Run the interactive setup wizard** .. code-block:: bash cd ~/dev-peek/dev-peek-workspace/workspace-common .venv/bin/python bin/pd_setup_xcode_cloud_app.py The wizard will: - Copy the workflow configuration from an existing product - Update the new product's default workflow - Create a GitLab project access token (reads ``~/.gitlabtoken``) - Print the environment variables to add in App Store Connect - Prompt for the TestFlight and Slack post-action steps **Step 3 — Add outbound network access to the workflow** Xcode Cloud sandboxes outbound network connections from custom build scripts. The CI scripts upload build artefacts to ``gitlab.synerty.com``, so that host must be explicitly allowed in the workflow. In App Store Connect → *product* → **Workflows** → *workflow* → **Edit** → **Environment** → scroll to **Custom Build Script Network Access** → add: .. code-block:: text gitlab.synerty.com Without this, ``ci_post_xcodebuild.sh`` will fail with ``Could not resolve host: gitlab.synerty.com`` (curl exit code 6). .. note:: This setting is not exposed in the App Store Connect API, so the setup wizard cannot configure it automatically. It must be added manually once per workflow. **Step 4 — Add environment variables in App Store Connect** The wizard prints the values — add them under **Workflows → Environment**: .. list-table:: :header-rows: 1 :widths: 30 50 20 * - Name - Value - Secret * - ``GITLAB_PROJECT_ID`` - GitLab numeric project ID (e.g. ``3372``) - No * - ``GITLAB_ACCESS_TOKEN`` - Project access token created by the wizard - Yes **Step 5 — Add post-actions** Under **Workflows → Post-Actions → Add**: 1. **TestFlight Internal Testing - iOS** - Artifact: Archive - iOS - Groups: select or create the relevant internal tester group 2. **Notify - Successes and Failures** - Slack: select the relevant channel -------------------- Xcode and macOS Version IDs -------------------- The Xcode and macOS version resource IDs are paired — the same UUID is used for both ``--xcode-version-id`` and ``--macos-version-id``. .. list-table:: :header-rows: 1 :widths: 45 30 25 * - UUID - Xcode - macOS * - ``31ce63a2-a54f-3e25-b883-dc13290abb7f`` - Xcode 17E202 - macOS 25E246 To find current IDs: .. code-block:: bash .venv/bin/xcode-cloud list-xcode-versions .venv/bin/xcode-cloud list-macos-versions -------------------- Exported Workflow JSON Schema -------------------- Exported JSON files can be edited before re-importing. Fields: .. code-block:: json { "name": "Default", "description": "", "isEnabled": true, "clean": false, "containerFilePath": "peek_field_app/ios/App/App.xcworkspace", "actions": [ { "name": "Archive - iOS", "actionType": "ARCHIVE", "destination": null, "buildDistributionAudience": "APP_STORE_ELIGIBLE", "testConfiguration": null, "scheme": "App", "platform": "IOS", "isRequiredToPass": true } ] }