Рубрики
Uncategorized

Как мы автоматизируем наш рабочий процесс iOS в Instabug с помощью Circleci

Строительство SDK часто означает, что мы должны разработать наши собственные пользовательские решения. Узнайте, как мы автоматизируем наш процесс выпуска с непрерывной интеграцией и доверием с уверенностью. Теги с iOS, SDK, CICD, CI.

Написано HESHAM ABD-ELMEGID

В Instabug мы создаем SDK для мобильных приложений. Строительство SDK часто означает, что большинство инструментов, созданных для автоматизации задач вокруг разработки и развертывания приложений iOS, не работают для нас, поэтому нам обычно нужно развивать свои собственные решения.

Чтобы увеличить нашу производительность и держать вещи быстро двигаться, нам нравится автоматизировать вещи. Одним из важных компонентов автоматизации многих частей нашего рабочего процесса является непрерывной интеграцией.

Этот пост проходит через то, что наш рабочий процесс и как мы автоматизируем его, используя Circleci .

Обзор

С Circleci 2.0 , мы можем создавать несколько рабочих мест под одним рабочим процессом, с возможностью определять зависимости между заданиями и запускать некоторые из них параллельно, что отлично.

workflows:
  version: 2
  build-test-and-generate-binary:
    jobs:
      - unit-tests
      - uitests-analyzer:
          filters:
            branches:
              only: 
                - master
                - /fix\/.*/
                - /release\/.*/
                - /Release\/.*/
      - hold:
          type: approval
          requires:
            - unit-tests
            - uitests-analyzer
      - generate-binary:
          requires:
            - hold
      - release:
          requires:
            - generate-binary
          filters:
            branches:
              only: 
                - master

Наш рабочий процесс имеет 4 рабочих места:

  1. Проходные тесты, тесты интеграции и опасность
  2. Запуск пользовательских тестов и статический анализатор
  3. Генерация двоичного
  4. Выпуская SDK

Давайте пройдемся по каждому подробно.

1. Проходные тесты, тесты интеграции и опасность

unit-tests:
  macos:
    xcode: "9.3.1"
  working_directory: /Users/distiller/project
  environment:
    BUNDLE_PATH: vendor/bundle  # path to install gems and use for caching
    ARTIFACTS_DIRECTORY: /Users/distiller/project/artifacts
  steps:
    - checkout
    - restore_cache:
        keys:
        - gems-{{ checksum "Gemfile.lock" }}
        # Fall back to using the latest cache if no exact match is found.
        # - v1-gems-
    - run: 
        name: Create artifacts directory
        command: mkdir $ARTIFACTS_DIRECTORY
    # Install gems.
    - run:
        name: Bundle install
        command: bundle check || bundle install
        environment:
          BUNDLE_JOBS: 4
          BUNDLE_RETRY: 3
    - save_cache:
        key: gems-{{ checksum "Gemfile.lock" }}
        paths:
          - vendor/bundle
    - run:
        name: Pre-start simulator
        command: xcrun instruments -w "iPhone 8 (11.3) [" || true
    - run:
        name: Run Instabug unit tests
        command: set -o pipefail && xcodebuild -workspace Instabug/Instabug.xcworkspace -scheme AllUnitTests -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=11.3,name=iPhone 8' -enableCodeCoverage YES test | xcpretty --color --report junit --output $ARTIFACTS_DIRECTORY/AllTests_unittest_results.xml
    - run:
        name: Run Danger
        command: bundle exec Danger
    - run: 
        name: Run integration tests
        command: set -o pipefail && xcodebuild -workspace Instabug/Instabug.xcworkspace -scheme InstabugIntegrationTests -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=11.3,name=iPhone 8' -enableCodeCoverage YES test | xcpretty --color --report junit --output $ARTIFACTS_DIRECTORY/InstabugIntegrationTests_unittest_results.xml

Во-первых, мы устанавливаем все драгоценные камни, используемые нашим проектом, как Опасность и Fastlane. Либо путем восстановления кеша предыдущей установки или выполняя новую установку.

Затем мы запустим наши модульные тесты. Из-за того, как наш проект структурирован, у нас есть около 15 целей Framework, с отдельной тестовой целью для каждого. Чтобы запустить все наши модульные тесты одновременно, у нас есть Allinittests Схема, которая управляет всеми тестовыми целями.

После запуска наших модульных тестов мы запускаем опасность, что является отличным инструментом для автоматизации некоторых по дому Code Code Reviews. Вот что мы используем это прямо сейчас.

  1. Enforce имеет описание и ссылку на проблему JIRA для всех запросов на тягу
  2. Убедитесь, что все запросы на тягу, которые добавляют новые струны, обращенные к пользователям, добавляют локализованные версии этих строк.
  3. Беги XCOV Чтобы создать отчет о наших тестах охвата, и опубликовать его в качестве комментариев на запрос на потяжку
  4. Убедитесь, что все запросы на тягу, которые изменяют любые тесты пользовательских интерфейсов для файлов пользовательского интерфейса, прежде чем объединить запрос на тягу.
has_ui_changes = !git.modified_files.grep(/View Controllers/).empty? || !git.modified_files.grep(/Views/).empty?

if !ENV['RUN_UI_TESTS'] && has_ui_changes
    fail("UI has been changed but UI tests were not run. Please make sure to run them before merging the PR.")
end

# Make sure PR has a description.
if github.pr_body.length < 3 && git.lines_of_code > 10
    fail "Please provide a summary of the changes in the Pull Request description."
end

# Check if PR title has reference to a Jira issue.
if !github.pr_title[/\[[a-zA-Z]*-[0-9]*\]/]
    fail("Pull request should include Jira card number in the name. For example: [IBGProj-123]")
end

Последние шаги этой работы — запускать наши интеграционные тесты, что является просто тестовой целью с аналогичной конфигурацией для наших тестовых целей.

Эта работа работает на каждом запросе на тягу, поэтому мы должны убедиться, что он содержит все необходимые проверки/тесты, и что он также работает в разумном времени. В настоящее время он работает около 8 минут, причем большинство времени собирается сделать чистую сборку SDK для пробогов.

2. Запуск пользовательских тестов и статический анализатор

uitests-analyzer:
  macos:
    xcode: "9.3.1"
  working_directory: /Users/distiller/project
  environment:
    BUNDLE_PATH: vendor/bundle  # path to install gems and use for caching
    ARTIFACTS_DIRECTORY: /Users/distiller/project/artifacts
  steps:
    - checkout
    - restore_cache:
        keys:
        - gems-{{ checksum "Gemfile.lock" }}
        # Fall back to using the latest cache if no exact match is found.
        # - v1-gems-
    - run: 
        name: Create artifacts directory
        command: mkdir $ARTIFACTS_DIRECTORY
    # Install gems.
    - run:
        name: Bundle install
        command: bundle check || bundle install
        environment:
          BUNDLE_JOBS: 4
          BUNDLE_RETRY: 3
    - run:
        name: Pre-start simulator
        command: xcrun instruments -w "iPhone 8 (11.3) [" || true
    - run:
        name: Run UI tests
        command: |
          if [[ -n "${RUN_UI_TESTS}" || $CIRCLE_BRANCH = 'master' ]]; then
            set -o pipefail && xcodebuild -workspace Instabug/Instabug.xcworkspace -scheme InstabugDemoUITests -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=11.3,name=iPhone 8' -only-testing:InstabugDemoUITests/AlertsUITests -only-testing:InstabugDemoUITests/BugReportingDisabledAttachmentsUITests -only-testing:InstabugDemoUITests/BugReportingUITests -only-testing:InstabugDemoUITests/IBGAnnotationUITests -only-testing:InstabugDemoUITests/IBGChatBasicUITests -only-testing:InstabugDemoUITests/IBGPromptVCUITests -only-testing:InstabugDemoUITests/IBGStatusBarTests test | xcpretty --color --report junit --output $ARTIFACTS_DIRECTORY/xcode/uitest_results_1.xml
            set -o pipefail && xcodebuild -workspace Instabug/Instabug.xcworkspace -scheme InstabugDemoUITests -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=11.3,name=iPhone 8' -only-testing:InstabugDemoUITests/IBGSurveysFlowUITests -only-testing:InstabugDemoUITests/IBGSurveysUITests -only-testing:InstabugDemoUITests/InstabugUITests -only-testing:InstabugDemoUITests/IBGFeatureRequestUITests test | xcpretty --color --report junit --output $ARTIFACTS_DIRECTORY/xcode/uitest_results_2.xml
          else
            echo 'Skipping running UI Tests.'
          fi
        no_output_timeout: 15m

    - run:
        name: Run static analyzer on other frameworks
        command: sh ./Scripts/analyze_Instabug.sh

Эта работа очень похожа на то, что мы делаем на первой работе, но вместо этого запускает цель пользовательских пользователей и статическим анализатором, использующим XCodeBuild анализировать Отказ

Эта работа работает только на мастере и исправлена/выпускает ветви, поэтому мы в порядке, чтобы забрать немного дольше, чтобы запустить. В настоящее время он заканчивается около 40 минут и работает параллельно с первой работой. Также может быть проведена по требованию на любой запрос на тягу независимо от его филиала, упомянув простым ботом GitHub, который мы написали, что использует API Circleci для запуска определенной работы.

3. Генерация двоичного

generate-binary: 
  macos:
    xcode: "9.3.1"
  working_directory: /Users/distiller/project
  environment:
    BUNDLE_PATH: vendor/bundle  # path to install gems and use for caching
    ARTIFACTS_DIRECTORY: /Users/distiller/project/artifacts
  steps:
    - checkout
    - restore_cache:
        keys:
        - gems-{{ checksum "Gemfile.lock" }}
        # Fall back to using the latest cache if no exact match is found.
        # - v1-gems-
    - run: 
        name: Create artifacts directory
        command: mkdir $ARTIFACTS_DIRECTORY
    # Install gems.
    - run:
        name: Bundle install
        command: bundle check || bundle install
        environment:
          BUNDLE_JOBS: 4
          BUNDLE_RETRY: 3
    - run:
        name: Install signing identity
        command: |
          bundle exec fastlane setup_signing
    - run:
        name: Increment version number
        command: |
          ./Scripts/IncrementSDKVersion.swift
          /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CIRCLE_BUILD_NUM" "Instabug/InstabugI/Info.plist"
    - run:
        name: Generate fat binary for Instabug static
        command: |
          xcodebuild -workspace Instabug/Instabug.xcworkspace -scheme Framework -sdk iphoneos -destination generic/platform=iOS clean build | xcpretty
    - run:
        name: Link Instabug static with dynamic project
        command: |
          ruby ./Instabug-dynamic/linkInstabug.rb
    - run:
        name: Generate fat binary for Instabug dynamic
        command: |
          xcodebuild -project Instabug-dynamic/Instabug.xcodeproj -scheme Framework -sdk iphoneos -destination generic/platform=iOS clean archive | xcpretty
    - run:
        name: Generate appledoc
        command: |
          sh ./Scripts/generate_appledoc.sh
    - run:
        name: Create framework archive
        command: |
          find ./Instabug/Instabug-SDK-Static -path '*/.*' -prune -o -type f -print | zip $ARTIFACTS_DIRECTORY/Instabug-static.zip -@
          find ./Instabug-dynamic/Instabug-SDK -path '*/.*' -prune -o -type f -print | zip $ARTIFACTS_DIRECTORY/Instabug.zip -@
          find ./Instabug-Docs -path '*/.*' -prune -o -type f -print | zip $ARTIFACTS_DIRECTORY/appledoc.zip -@
    - run:
        name: Test Fat Binaries are not Corrupted
        command: |
          xcodebuild -project InstabugProductionDemo/InstabugProductionDemo.xcodeproj -scheme InstabugProductionDemoUITests -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=11.3,name=iPhone 8' test | xcpretty
    - store_artifacts:
        path: artifacts
    - persist_to_workspace:
        root: .
        paths:
          - .

После завершения первых двух заданий мы можем генерировать двоичный SDK из любой ветви. Это требует одобрения удержания от приборной панели CIRCLECI.

Эта работа будет установить наш идентификатор подписания кода, который мы делимся по всей команде, используя Fastlane. . Затем он генерирует как статические, так и динамические варианты нашей структуры. Подробнее о строительстве двоичных рамх, проверьте наш предыдущий Блог пост Отказ

Затем он связывает оба каркаса в ZIP-архиве и хранит его в каталоге артефактов, который будет доступен для загрузки.

4. Выпуская SDK

release:
  macos:
    xcode: "9.3.1"
  working_directory: /Users/distiller/project
  environment:
    ARTIFACTS_DIRECTORY: /Users/distiller/project/artifacts
  steps:
    - attach_workspace:
        at: /Users/distiller/project
    - run:
        name: Release
        command: ./release

Последняя работа выпускает SDK для общественности. Он запускает развязок, наше приложение Homegrown CLI для выпуска SDK.

Развязывайте следующее:

  1. Создайте и нажмите новый тег на наш частный репозиторий
  2. Нажмите обновленную рамку в https://github.com/instabug/instabug-ios/ . и создать выпуск GitHub
  3. Опубликовать структуру к какаоподам
  4. Обновите наш картаге JSON File.
  5. Загрузите освобождение в нашу собственную API для потребления на приборной панели Instabug и веб-сайт.

Заключение

Мы довольно довольны рабочим процессом, у нас пока. Наличие надежного процесса CI делает нас доверительным доверием, а автоматизация нашего процесса выпуска сохраняет тонну времени, поскольку мы выпускаем один раз в неделю.

Circleci был отличным инструментом для использования для нашей непрерывной интеграции, особенно с Circleci 2.0.

Узнать больше instabug.com/blog .

Оригинал: «https://dev.to/instabug/how-we-automate-our-ios-workflow-at-instabug-using-circleci-50n3»