# DevOps 2: Fastlane Chuqur Amaliyot — Match, Gym, Pilot va Multi-Flavor Pipeline

> **Holat:** 2026-yil sentabr. Fastlane — iOS va Android ilovalarini avtomatlashtirilgan tarzda yig'ish, imzolash va App Store Connect'ga yuklash bo'yicha sanoat standarti hisoblanadi. Ushbu darsda ko'p muhitli (multi-flavor/multi-target) haqiqiy production darajasidagi Fastlane pipeline'ini noldan qanday loyihalash tushuntiriladi.

## Mundarija

1. [Fastlane arxitekturasi va fayllar ierarxiyasi](#arxitektura)
2. [Appfile va Matchfile: Ko'p muhitli konfiguratsiya](#appfile-matchfile)
3. [fastlane match: Sertifikatlarni markazlashtirilgan sinxronlash](#match)
4. [fastlane scan: Barqaror va parallel testlash](#scan)
5. [fastlane gym: Deterministik arxivlash va eksport](#gym)
6. [fastlane pilot va deliver: TestFlight va App Store avtomatizatsiyasi](#pilot-deliver)
7. [To'liq ishlab chiqarish Fastfile: Multi-flavor lane'lar](#fastfile)
8. [Custom Actions: O'z vositalaringizni yaratish](#custom-actions)
9. [Xulosa](#xulosa)
10. [Manbalar](#manbalar)

---

## 1. Fastlane arxitekturasi va fayllar ierarxiyasi {#arxitektura}

Professional loyihada `fastlane/` katalogi quyidagi tartibda saqlanadi:

```text
my-ios-app/
├── Gemfile               # fastlane va plaginlar versiyasi qat'iy qulflanadi
├── Gemfile.lock
├── fastlane/
│   ├── Appfile           # Apple ID, Team ID, Bundle ID ta'riflari
│   ├── Matchfile         # Sertifikatlar ombori sozlamalari
│   ├── Fastfile          # Asosiy pipeline lane'lari
│   ├── actions/          # Maxsus ruby action'lari
│   └── metadata/         # App Store tavsiflari va skrinshotlari
```

`Gemfile` deterministik bo'lishi shart:

```ruby
# frozen_string_literal: true

source "https://rubygems.org"

gem "fastlane", ">= 2.225.0"
gem "cocoapods", require: false
```

---

## 2. Appfile va Matchfile: Ko'p muhitli konfiguratsiya {#appfile-matchfile}

Bitta ilovaning Dev, Staging va Production muhitlari turli xil Bundle Identifier'larga ega bo'ladi (`uz.azimjondev.app.dev`, `uz.azimjondev.app.staging`, `uz.azimjondev.app`):

### `fastlane/Appfile`
```ruby
# Appfile — muhitlar bo'yicha dinamik konfiguratsiya
apple_id(ENV["APPLE_ID"] || "dev@azimjondev.uz")
team_id("ABCDE12345")
itc_team_id("987654321")

for_lane :beta_staging do
  app_identifier("uz.azimjondev.app.staging")
end

for_lane :release_prod do
  app_identifier("uz.azimjondev.app")
end
```

### `fastlane/Matchfile`
```ruby
# Matchfile — Git yoki S3 orqali sertifikatlarni saqlash
git_url("git@github.com:my-company/ios-certificates.git")
storage_mode("git")
type("appstore") # development, adhoc, appstore, enterprise

# CI serverda yangi sertifikat yaratishni taqiqlash (faqat o'qish):
readonly(ENV["CI"] == "true")
```

---

## 3. fastlane match: Sertifikatlarni markazlashtirilgan sinxronlash {#match}

`match` vositasining asosiy g'oyasi — "Code Signing kimningdir kompyuterida tasodifan yaratilmasin". Barcha sertifikatlar va provisioning profile'lar Git omborida (yoki AWS S3 / Google Cloud Storage'da) OpenSSL AES-256 bilan shifrlangan holda saqlanadi:

```bash
# Yangi dasturchi qo'shilganda parolni kiritadi va profilni oladi:
bundle exec fastlane match appstore --readonly

# Yangi sertifikat va profile generatsiya qilish (faqat Lead):
bundle exec fastlane match appstore -a uz.azimjondev.app
```

CI serverda parol `MATCH_PASSWORD` environment variable orqali uzatiladi.

---

## 4. fastlane scan: Barqaror va parallel testlash {#scan}

Testlar flakiness (beqarorlik) tufayli yiqilmasligi uchun `scan` sozlamalari:

```ruby
lane :test do
  scan(
    workspace: "AzimjonDev.xcworkspace",
    scheme: "AzimjonDev",
    devices: ["iPhone 16 Pro"],
    clean: false,
    number_of_retries: 2, # Yiqilgan testni 2 martagacha qayta tekshirish
    fail_build: true,
    output_types: "html,junit",
    output_directory: "./build/reports",
    xcargs: "-parallel-testing-enabled YES -maximum-concurrent-test-simulator-destinations 4"
  )
end
```

---

## 5. fastlane gym: Deterministik arxivlash va eksport {#gym}

`gym` (`xcodebuild archive` va `xcodebuild -exportArchive`) ustiga qurilgan qulay wrapper bo'lib, uning yordamida to'g'ri imzolangan `.ipa` hosil qilinadi:

```ruby
lane :build_ipa do |options|
  environment = options[:env] || "staging"
  scheme = environment == "prod" ? "AzimjonDev-Prod" : "AzimjonDev-Staging"

  gym(
    workspace: "AzimjonDev.xcworkspace",
    scheme: scheme,
    clean: true,
    output_directory: "./build/artifacts",
    output_name: "AzimjonDev-#{environment}.ipa",
    export_method: "app-store",
    export_options: {
      compileBitcode: false,
      stripSwiftSymbols: true,
      manageAppVersionAndBuildNumber: false
    }
  )
end
```

---

## 6. fastlane pilot va deliver: TestFlight va App Store avtomatizatsiyasi {#pilot-deliver}

### TestFlight'ga yuklash (`pilot`)
```ruby
lane :upload_testflight do |options|
  api_key = app_store_connect_api_key(
    key_id: ENV["ASC_KEY_ID"],
    issuer_id: ENV["ASC_ISSUER_ID"],
    key_content: ENV["ASC_KEY_CONTENT"],
    is_key_content_base64: true
  )

  pilot(
    api_key: api_key,
    ipa: "./build/artifacts/AzimjonDev-staging.ipa",
    skip_waiting_for_build_processing: true, # CI oqimini 20 daqiqa ushlab turmaslik
    changelog: "Staging build ##{ENV['BUILD_NUMBER']}: yangi o'zgarishlar va bug fixlar."
  )
end
```

---

## 7. To'liq ishlab chiqarish Fastfile: Multi-flavor lane'lar {#fastfile}

Quyida real loyihalarda ishlatiladigan to'liq `Fastfile` namunasi keltirilgan:

```ruby
default_platform(:ios)

platform :ios do
  before_all do
    ensure_git_status_clean unless ENV["CI"]
  end

  desc "PR uchun testlarni ishga tushirish"
  lane :ci_pr do
    scan(
      scheme: "AzimjonDev-Staging",
      devices: ["iPhone 16 Pro"],
      fail_build: true
    )
  end

  desc "Staging versiyani yig'ish va TestFlight'ga jo'natish"
  lane :beta_staging do
    api_key = app_store_connect_api_key(
      key_id: ENV["ASC_KEY_ID"],
      issuer_id: ENV["ASC_ISSUER_ID"],
      key_content: ENV["ASC_KEY_CONTENT"],
      is_key_content_base64: true
    )

    match(type: "appstore", app_identifier: "uz.azimjondev.app.staging", readonly: true)

    gym(
      scheme: "AzimjonDev-Staging",
      output_name: "AzimjonDev-Staging.ipa"
    )

    pilot(
      api_key: api_key,
      ipa: "./build/artifacts/AzimjonDev-Staging.ipa",
      skip_waiting_for_build_processing: true
    )
  end

  desc "Production versiyani App Store Connect'ga yuklash"
  lane :release_prod do
    api_key = app_store_connect_api_key(
      key_id: ENV["ASC_KEY_ID"],
      issuer_id: ENV["ASC_ISSUER_ID"],
      key_content: ENV["ASC_KEY_CONTENT"],
      is_key_content_base64: true
    )

    match(type: "appstore", app_identifier: "uz.azimjondev.app", readonly: true)

    gym(
      scheme: "AzimjonDev-Prod",
      output_name: "AzimjonDev-Prod.ipa"
    )

    deliver(
      api_key: api_key,
      ipa: "./build/artifacts/AzimjonDev-Prod.ipa",
      skip_screenshots: true,
      skip_metadata: true,
      submit_for_review: false
    )
  end

  after_all do |lane|
    UI.success("Lane #{lane} muvaffaqiyatli yakunlandi! 🚀")
  end

  error do |lane, exception|
    UI.error("Lane #{lane}da xatolik: #{exception.message}")
  end
end
```

---

## 8. Custom Actions: O'z vositalaringizni yaratish {#custom-actions}

Agar mavjud Fastlane action'lari yetarli bo'lmasa (masalan, ichki Telegram chatga xabar yuborish), `fastlane/actions/notify_telegram.rb` yaratiladi:

```ruby
module Fastlane
  module Actions
    class NotifyTelegramAction < Action
      def self.run(params)
        message = params[:message]
        UI.message("Telegram xabari: #{message}")
        # Faraday yoki HTTP orqali bot API'ga so'rov yuborish mumkin
      end

      def self.description
        "Telegram guruhiga build holatini xabar qiladi"
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(key: :message, description: "Xabar matni")
        ]
      end

      def self.is_supported?(platform)
        platform == :ios
      end
    end
  end
end
```

---

## 9. Xulosa {#xulosa}

- `Fastfile` yordamida barcha murakkab `xcodebuild` buyruqlari bitta o'qilishi oson buyruqqa aylanadi (`bundle exec fastlane beta_staging`).
- `match` orqali "Certificates expired" yoki "Provisioning Profile mismatch" muammosi 100% yechiladi.
- App Store Connect API Key yordamida SMS va 2FA kodlarisiz xavfsiz CI deploy amalga oshiriladi.

---

## 10. Manbalar {#manbalar}

1. [Fastlane Docs — Code Signing with match](https://docs.fastlane.tools/actions/match/)
2. [Fastlane Docs — Building with gym](https://docs.fastlane.tools/actions/gym/)
3. [App Store Connect API Key integration in Fastlane](https://docs.fastlane.tools/app-store-connect-api/)
