# DevOps 1: iOS CI/CD 2026 — Xcode Cloud, GitHub Actions va kalitsiz imzolash

> **Holat:** 2026-yil sentabr (Xcode 26.x, Xcode 27, iOS 27). Narxlar, runner nomlari va versiyalar tez o'zgaradi — har bir raqam yonida manba bor, ishlatishdan oldin rasmiy sahifani tekshiring.
>
> Kursdagi [CI/CD — Fastlane](/ios-lessons/ci-cd) darsi asoslarni (Fastfile, match, gym, pilot) o'rgatadi. Bu dars bir qadam chuqurroq: 2026-yildagi haqiqiy pipeline qanday quriladi.

## Mundarija

1. [Pipeline anatomiyasi](#pipeline)
2. [Xcode Cloud — chuqurroq](#xcode-cloud)
3. [GitHub Actions macOS runner'lari (2026)](#github-actions)
4. [Kalitsiz code signing: App Store Connect API key](#signing)
5. [Build'ni yuklash: `xcodebuild -exportArchive`](#upload)
6. [fastlane 2026-yilda](#fastlane)
7. [TestFlight chegaralari](#testflight)
8. [Privacy Manifest — CI'ni to'xtatadigan darvoza](#privacy-manifest)
9. [To'liq workflow: PR'da test, tag'da TestFlight](#workflow)
10. [Qaysi CI qachon?](#tanlash)
11. [Xulosa](#xulosa)
12. [Manbalar](#manbalar)

---

## 1. Pipeline anatomiyasi {#pipeline}

iOS uchun CI/CD — bu bir xil bosqichlarni har safar, bir xil tartibda, odam aralashmasdan bajarish:

```text
push / PR  →  lint  →  build  →  test  →  archive  →  sign  →  upload  →  TestFlight / App Store
```

- **CI (Continuous Integration)** — har bir PR'da lint + build + test. Maqsad: `main` doim yig'iladigan (buildable) holatda bo'lsin.
- **CD (Continuous Delivery)** — tag yoki release branch'da archive + imzolash + App Store Connect'ga yuklash.

Qoida: pipeline **deterministik** bo'lishi kerak — bir xil commit har doim bir xil natija beradi. Buning uchun Xcode versiyasi, dependency versiyalari (`Package.resolved`, `Gemfile.lock`) va tool versiyalari qat'iy belgilab qo'yiladi.

---

## 2. Xcode Cloud — chuqurroq {#xcode-cloud}

**Xcode Cloud** — Apple'ning App Store Connect'ga ulangan CI/CD xizmati. Workflow to'rt qismdan iborat:

| Qism                 | Nima qiladi                                                                                                |
| -------------------- | ---------------------------------------------------------------------------------------------------------- |
| **Environment**      | Xcode va macOS versiyasi, environment variable'lar (secret sifatida belgilash mumkin — log'da yashiriladi) |
| **Start Conditions** | Qachon ishga tushadi: branch o'zgarishi, pull request, tag, jadval (schedule) yoki qo'lda                  |
| **Actions**          | Build, Test, Analyze, Archive                                                                              |
| **Post-Actions**     | TestFlight'ga tarqatish, xabarnoma yuborish                                                                |

### Narx (2026)

Apple Developer Program a'zoligi bilan **oyiga 25 compute-soat bepul**. Undan ko'pi obuna bilan:

| Oylik soat | Narx           |
| ---------- | -------------- |
| 100        | $49.99 / oy    |
| 250        | $99.99 / oy    |
| 1 000      | $399.99 / oy   |
| 10 000     | $3 999.99 / oy |

Ishlatilmagan soat keyingi oyga **o'tmaydi**. Manba: [Apple — Get started with Xcode Cloud](https://developer.apple.com/xcode-cloud/get-started).

### Custom build script'lar: `ci_scripts/`

Loyiha (yoki workspace) turgan papkada `ci_scripts` papkasini yarating. Xcode Cloud uch nomdagi script'ni o'zi taniydi:

| Fayl                    | Qachon ishlaydi                                                        |
| ----------------------- | ---------------------------------------------------------------------- |
| `ci_post_clone.sh`      | repo klonlangandan keyin, dependency'lar (SPM) yechilishidan **oldin** |
| `ci_pre_xcodebuild.sh`  | har bir `xcodebuild` chaqiruvidan oldin                                |
| `ci_post_xcodebuild.sh` | `xcodebuild` tugagandan keyin (build yiqilsa ham)                      |

Script bajariladigan bo'lishi shart:

```bash
chmod +x ci_scripts/ci_post_clone.sh
```

Namuna — lint'ni build'dan oldin "darvoza" qilish:

```bash
#!/bin/sh
# ci_scripts/ci_post_clone.sh
# Xcode Cloud bu faylni repo klonlangandan keyin ishga tushiradi.
set -eu

# Script ci_scripts papkasidan ishga tushadi — loyiha ildiziga o'tamiz.
cd "$(dirname "$0")/.."

echo "Xcode Cloud build #${CI_BUILD_NUMBER:-local}"

# Lint xatosi bo'lsa build shu yerda to'xtaydi.
brew install swiftlint
swiftlint lint --strict
```

**Muhim:** `CI_BUILD_NUMBER`, `CI_XCODEBUILD_ACTION`, `CI_BRANCH`, `CI_TAG` kabi o'zgaruvchilarni Xcode Cloud o'zi beradi. To'liq ro'yxat: [Environment variable reference](https://developer.apple.com/documentation/xcode/environment-variable-reference). Script ichida `sudo` ishlatib bo'lmaydi.

### Cheklovlar

- Faqat Apple platformalari (iOS, macOS, tvOS, watchOS, visionOS) — backend yoki Android uchun emas.
- O'z serveringizda (self-hosted) ishlatib bo'lmaydi, build mashinasiga SSH yo'q.
- Kuchli tomoni: signing va TestFlight'ga tarqatish App Store Connect ichida, deyarli sozlashsiz.

---

## 3. GitHub Actions macOS runner'lari (2026) {#github-actions}

| Label                              | Holat                                                                   |
| ---------------------------------- | ----------------------------------------------------------------------- |
| `macos-15`                         | Apple Silicon, faol                                                     |
| `macos-26`                         | Apple Silicon, **2026-02-26 dan GA**                                    |
| `macos-15-intel`, `macos-26-intel` | Intel varianti ham bor                                                  |
| `macos-13`                         | **2025-12-04 da butunlay o'chirilgan** — eski workflow'larni ko'chiring |

Standart Apple Silicon runner: 3 core (M1), 7 GB RAM, 14 GB SSD. Manba: [GitHub-hosted runners](https://docs.github.com/en/actions/reference/runners/github-hosted-runners), [macOS 26 GA](https://github.blog/changelog/2026-02-26-macos-26-is-now-generally-available-for-github-hosted-runners/), [macOS 13 retirement](https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/).

### Narx: macOS daqiqasi ~10 barobar qimmat

| Runner         | Narx (1 daqiqa) |
| -------------- | --------------- |
| Linux 2-core   | $0.006          |
| Windows 2-core | $0.010          |
| macOS          | $0.062          |

Manba: [About billing for GitHub Actions](https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions). Amaliy xulosa: Linux'da bajarsa bo'ladigan ishni (masalan backend testlari, markdown lint) macOS runner'ga qo'ymang.

### Xcode versiyasini tanlash

Har bir runner image'da bir nechta Xcode o'rnatilgan. Qaysilari borligini image'ning README faylidan ko'ring ([runner-images](https://github.com/actions/runner-images/tree/main/images/macos)) va aniq versiyani tanlang:

```bash
sudo xcode-select -s /Applications/Xcode_26.4.app
xcodebuild -version
```

### Cache

`actions/cache` bilan SPM paketlarini saqlash build'ni tezlashtiradi. Bitta repo uchun standart limit **10 GB**, 7 kun ishlatilmagan cache o'chiriladi ([cache limitlari](https://github.blog/changelog/2025-11-20-github-actions-cache-size-can-now-exceed-10-gb-per-repository/)). To'liq `DerivedData` odatda bir necha GB bo'lgani uchun faqat SPM paketlarini cache qilish ko'proq foyda beradi.

---

## 4. Kalitsiz code signing: App Store Connect API key {#signing}

Eski usul — CI'da Apple ID + parol + 2FA sessiyasi. Bu mo'rt: sessiya muddati tugaydi, 2FA kodi so'raladi. Zamonaviy usul — **App Store Connect API key** (`.p8` fayl):

1. App Store Connect → **Users and Access → Integrations → App Store Connect API** → yangi _Team Key_. Kalitni faqat Account Holder yoki Admin yarata oladi.
2. Kalitga eng kichik yetarli rolni bering: TestFlight'ga yuklash uchun odatda **App Manager** yetarli.
3. Uch qiymatni CI secret sifatida saqlang: `ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_KEY_P8_BASE64` (`.p8` faylning base64 ko'rinishi). `.p8` fayl faqat bir marta yuklab olinadi — uni xavfsiz joyda saqlang.

Shundan keyin `xcodebuild` o'zi sertifikat va profillarni yaratadi yoki yangilaydi:

```bash
xcodebuild archive \
  -project MyApp.xcodeproj -scheme MyApp -configuration Release \
  -archivePath "$RUNNER_TEMP/MyApp.xcarchive" \
  -allowProvisioningUpdates \
  -authenticationKeyPath "$HOME/private_keys/AuthKey_${ASC_KEY_ID}.p8" \
  -authenticationKeyID "$ASC_KEY_ID" \
  -authenticationKeyIssuerID "$ASC_ISSUER_ID"
```

`-allowProvisioningUpdates` — `xcodebuild`ga Apple Developer sayti bilan gaplashishga ruxsat beradi. **Automatic signing** target'larida profil, App ID va sertifikatni yaratadi yoki yangilaydi; **manual signing**'da esa yetishmayotgan profillarni yuklab oladi. Bu ma'lumot `xcodebuild -help` chiqishidan olingan (Xcode 26.5).

### Qo'lda boshqariladigan sertifikat bo'lsa: vaqtinchalik keychain

Agar jamoa `.p12` sertifikatni o'zi boshqarsa, CI'da uni **vaqtinchalik keychain**'ga import qilib, ish tugagach o'chiriladi:

```bash
#!/bin/bash
# CI: .p12 sertifikatni vaqtinchalik keychain'ga import qilish
set -euo pipefail

KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
CERT_PATH="$RUNNER_TEMP/cert.p12"

echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o "$CERT_PATH"

security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security import "$CERT_PATH" -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH"
```

Ish oxirida (xato bo'lsa ham) keychain'ni o'chiring: `security delete-keychain "$KEYCHAIN_PATH"`.

---

## 5. Build'ni yuklash: `xcodebuild -exportArchive` {#upload}

`ExportOptions.plist`da `destination` = `upload` bo'lsa, `xcodebuild -exportArchive` archive'ni eksport qiladi **va** App Store Connect'ga yuklaydi. Alohida Transporter chaqirish shart emas.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>method</key>
    <string>app-store-connect</string>
    <key>destination</key>
    <string>upload</string>
    <key>manageAppVersionAndBuildNumber</key>
    <true/>
</dict>
</plist>
```

Xcode 15.3'dan boshlab `method` qiymatlari yangilandi. `app-store` → **`app-store-connect`**, `ad-hoc` → **`release-testing`**, `development` → **`debugging`**. Eskilari hali ishlaydi, lekin _deprecated_. Qo'shimcha foydali kalitlar:

- `manageAppVersionAndBuildNumber` — standart qiymati `YES`: yuklashda build raqamini Xcode o'zi boshqaradi.
- `testFlightInternalTestingOnly` — `YES` bo'lsa, bu build'ni external TestFlight yoki App Store'ga chiqarib bo'lmaydi. PR va dev branch build'lari uchun qulay.

Barcha kalitlarni o'zingiz ko'rishingiz mumkin: `xcodebuild -help` → _"Available keys for -exportOptionsPlist"_.

> **altool haqida:** `xcrun altool --notarize-app` **2023-11-01 da o'chirilgan** — bu faqat macOS **notarizatsiya** funksiyasi, uning o'rniga `notarytool` ishlatiladi. App Store Connect'ga yuklash uchun `xcodebuild -exportArchive` (yoki Transporter) — eng sodda yo'l. Manba: [Apple — notarization tool deprecation](https://developer.apple.com/news/upcoming-requirements/?id=11012023a).

---

## 6. fastlane 2026-yilda {#fastlane}

- 2021-yil oxirida Google homiyligi to'xtadi. Loyiha **2023-10-27 dan Mobile Native Foundation (MNF)** qaramog'ida. Hamjamiyat uni faol qo'llab-quvvatlaydi. Manba: [MNF discussion #194](https://github.com/MobileNativeFoundation/discussions/discussions/194).
- CI'da autentifikatsiya uchun `app_store_connect_api_key` action ishlatiladi — Apple ID/2FA kerak emas:

```ruby
# fastlane/Fastfile
default_platform(:ios)

platform :ios do
  desc "Build yig'ib TestFlight'ga yuklash"
  lane :beta do
    api_key = app_store_connect_api_key(
      key_id: ENV.fetch("ASC_KEY_ID"),
      issuer_id: ENV.fetch("ASC_ISSUER_ID"),
      key_content: ENV.fetch("ASC_KEY_P8_BASE64"),
      is_key_content_base64: true
    )
    build_app(scheme: "MyApp", export_method: "app-store")
    upload_to_testflight(api_key: api_key, skip_waiting_for_build_processing: true)
  end
end
```

- **Xavfsizlik darsi (2026):** rubyzip kutubxonasida path-traversal zaifligi topilgan (**CVE-2026-85396**, HIGH). Uning tuzatilgan versiyasi fastlane'ning dependency cheklovi bilan to'qnashadi. 2026-sentabr holatiga ko'ra muammo [issue #30175](https://github.com/fastlane/fastlane/issues/30175)da hali ochiq. Xulosa: fastlane'ni doim **Bundler** orqali, versiyasi `Gemfile.lock`da qotirilgan holda ishga tushiring (`bundle exec fastlane beta`) va dependency yangilanishlarini kuzatib boring.

Qachon fastlane kerak? Screenshot generatsiyasi (`snapshot`), metadata yuklash (`deliver`) yoki ko'p lane'li murakkab jarayonlar bo'lsa — foydali. Faqat "archive + upload" kerak bo'lsa, fastlane'siz `xcodebuild` yetarli (4–5 bo'limlar).

---

## 7. TestFlight chegaralari {#testflight}

| Parametr            | Qiymat                                                                              |
| ------------------- | ----------------------------------------------------------------------------------- |
| Internal tester'lar | 100 tagacha (App Store Connect jamoa a'zolari), har biri 30 tagacha qurilmada       |
| External tester'lar | 10 000 tagacha, 100 tagacha guruhga bo'linadi                                       |
| Beta App Review     | External tester'larga versiyaning birinchi build'ini berishdan oldin talab qilinadi |
| Build muddati       | Yuklangandan **90 kun** keyin build ishlamay qoladi                                 |

Manbalar: [TestFlight limits 2026](https://ptkd.com/journal/testflight-external-tester-limit-2026), [TestFlight overview](https://developer.apple.com/testflight/).

---

## 8. Privacy Manifest — CI'ni to'xtatadigan darvoza {#privacy-manifest}

**2024-yil 1-maydan** App Store Connect quyidagi holatlardagi yuklashni rad etadi:

- ilova yoki SDK **Required Reason API** ishlatib, sababini `PrivacyInfo.xcprivacy`da ko'rsatmagan bo'lsa (masalan `UserDefaults`, fayl timestamp'lari, disk hajmi, system boot time);
- Apple'ning "keng tarqalgan uchinchi tomon SDK'lari" ro'yxatidagi kutubxona o'z privacy manifest'i va imzosisiz qo'shilgan bo'lsa.

Manba: [Apple — Privacy manifest requirements](https://developer.apple.com/news/upcoming-requirements/?id=3d8a9yyh).

Minimal namuna — ilova `UserDefaults`dan faqat o'z ma'lumotlari uchun foydalanadi (sabab kodi `CA92.1`):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSPrivacyTracking</key>
    <false/>
    <key>NSPrivacyTrackingDomains</key>
    <array/>
    <key>NSPrivacyCollectedDataTypes</key>
    <array/>
    <key>NSPrivacyAccessedAPITypes</key>
    <array>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>CA92.1</string>
            </array>
        </dict>
    </array>
</dict>
</plist>
```

CI uchun amaliy qoida: yangi SDK qo'shadigan PR'da manifest'ni ham ko'rib chiqing. Xcode Organizer'da archive'ni o'ng tugma bilan bosib **Generate Privacy Report** tanlasangiz, barcha manifest'lar jamlangan hisobot chiqadi.

---

## 9. To'liq workflow: PR'da test, tag'da TestFlight {#workflow}

Fayl: `.github/workflows/ios.yml`. Kerakli secret'lar: `ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_KEY_P8_BASE64`. Loyiha **automatic signing**da bo'lsin va repo'da `ExportOptions.plist` (5-bo'lim) tursin.

```yaml
name: iOS CI

on:
  pull_request:
    branches: [main]
  push:
    tags: ["v*"]

concurrency:
  group: ios-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    if: github.event_name == 'pull_request'
    runs-on: macos-26
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4

      - name: Select Xcode
        run: sudo xcode-select -s /Applications/Xcode_26.4.app

      - name: Cache SPM packages
        uses: actions/cache@v4
        with:
          path: ~/Library/Developer/Xcode/DerivedData/**/SourcePackages
          key: spm-${{ runner.os }}-${{ hashFiles('**/Package.resolved') }}
          restore-keys: spm-${{ runner.os }}-

      - name: Test
        run: |
          set -o pipefail
          xcodebuild test \
            -project MyApp.xcodeproj -scheme MyApp \
            -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \
            -resultBundlePath TestResults.xcresult

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: TestResults.xcresult

  testflight:
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: macos-26
    timeout-minutes: 45
    env:
      ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
      ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
    steps:
      - uses: actions/checkout@v4

      - name: Select Xcode
        run: sudo xcode-select -s /Applications/Xcode_26.4.app

      - name: Write App Store Connect API key
        env:
          ASC_KEY_P8_BASE64: ${{ secrets.ASC_KEY_P8_BASE64 }}
        run: |
          mkdir -p "$HOME/private_keys"
          echo -n "$ASC_KEY_P8_BASE64" | base64 --decode -o "$HOME/private_keys/AuthKey_${ASC_KEY_ID}.p8"

      - name: Archive
        run: |
          set -o pipefail
          xcodebuild archive \
            -project MyApp.xcodeproj -scheme MyApp -configuration Release \
            -archivePath "$RUNNER_TEMP/MyApp.xcarchive" \
            -allowProvisioningUpdates \
            -authenticationKeyPath "$HOME/private_keys/AuthKey_${ASC_KEY_ID}.p8" \
            -authenticationKeyID "$ASC_KEY_ID" \
            -authenticationKeyIssuerID "$ASC_ISSUER_ID"

      - name: Export and upload to App Store Connect
        run: |
          xcodebuild -exportArchive \
            -archivePath "$RUNNER_TEMP/MyApp.xcarchive" \
            -exportOptionsPlist ExportOptions.plist \
            -exportPath "$RUNNER_TEMP/export" \
            -allowProvisioningUpdates \
            -authenticationKeyPath "$HOME/private_keys/AuthKey_${ASC_KEY_ID}.p8" \
            -authenticationKeyID "$ASC_KEY_ID" \
            -authenticationKeyIssuerID "$ASC_ISSUER_ID"

      - name: Remove API key
        if: always()
        run: rm -f "$HOME/private_keys/AuthKey_${ASC_KEY_ID}.p8"
```

Tekshiruv ro'yxati:

- `Xcode_26.4.app` va `iPhone 17` nomlari runner image'da borligini README'dan tekshiring. Kerak bo'lsa bitta qadam qo'shib, `xcrun simctl list devices available` chiqishini ko'ring.
- `concurrency` — bitta branch'da yangi push kelsa, eski ish bekor qilinadi (pul tejaydi).
- Tag push qilish: `git tag v1.4.0 && git push origin v1.4.0`.

---

## 10. Qaysi CI qachon? {#tanlash}

| Vaziyat                                                        | Tavsiya                                                                                                                                                      |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Kichik jamoa, faqat Apple platformalari, oyiga ≤ 25 soat build | **Xcode Cloud** — sozlash eng kam                                                                                                                            |
| Backend/web ham GitHub'da, bitta joyda boshqarmoqchisiz        | **GitHub Actions**                                                                                                                                           |
| Faqat mobil, tayyor "step"lar va avtomatik signing kerak       | **Codemagic** (500 bepul M2 daqiqa/oy) yoki **Bitrise** (Hobby: 300 kredit/oy) — narxni rasmiy sahifada tekshiring                                           |
| Juda ko'p build, macOS daqiqalari qimmatga tushyapti           | O'z Mac mini'laringiz + virtualizatsiya (masalan, ochiq manbali **Tart**). Loyiha jamoasi 2026-yilda OpenAI'ga o'tgani uchun uning kelajagini kuzatib boring |

Manbalar: [Codemagic pricing](https://codemagic.io/pricing/), [Bitrise pricing](https://www.bitrise.io/pricing), [Tart](https://tart.run/).

---

## 11. Xulosa {#xulosa}

- Pipeline bosqichlari: lint → build → test → archive → sign → upload. Har birining versiyasini qotiring.
- **App Store Connect API key + `-allowProvisioningUpdates`** — 2026-yilda CI'da imzolashning eng sodda yo'li.
- `ExportOptions.plist`da `app-store-connect` + `destination: upload` — eksport va yuklash bitta qadamda.
- macOS runner daqiqasi Linux'dan ~10 barobar qimmat. `macos-13` yo'q; `macos-15`/`macos-26` ishlating.
- Privacy manifest'siz SDK butun release'ni to'xtatadi. Uni PR darajasida tekshiring.

---

## Manbalar {#manbalar}

1. [Apple — Get started with Xcode Cloud](https://developer.apple.com/xcode-cloud/get-started)
2. [Apple — Xcode Cloud environment variable reference](https://developer.apple.com/documentation/xcode/environment-variable-reference)
3. [GitHub — GitHub-hosted runners](https://docs.github.com/en/actions/reference/runners/github-hosted-runners)
4. [GitHub — About billing for GitHub Actions](https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions)
5. [GitHub changelog — macOS 13 runner closing down](https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/)
6. [GitHub changelog — macOS 26 GA](https://github.blog/changelog/2026-02-26-macos-26-is-now-generally-available-for-github-hosted-runners/)
7. [Apple — altool notarization deprecation](https://developer.apple.com/news/upcoming-requirements/?id=11012023a)
8. [Apple — Privacy manifest requirements](https://developer.apple.com/news/upcoming-requirements/?id=3d8a9yyh)
9. [fastlane — App Store Connect API](https://docs.fastlane.tools/app-store-connect-api/)
10. [Mobile Native Foundation — fastlane transfer](https://github.com/MobileNativeFoundation/discussions/discussions/194)
