Написано 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 рабочих места:
- Проходные тесты, тесты интеграции и опасность
- Запуск пользовательских тестов и статический анализатор
- Генерация двоичного
- Выпуская 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. Вот что мы используем это прямо сейчас.
- Enforce имеет описание и ссылку на проблему JIRA для всех запросов на тягу
- Убедитесь, что все запросы на тягу, которые добавляют новые струны, обращенные к пользователям, добавляют локализованные версии этих строк.
- Беги XCOV Чтобы создать отчет о наших тестах охвата, и опубликовать его в качестве комментариев на запрос на потяжку
- Убедитесь, что все запросы на тягу, которые изменяют любые тесты пользовательских интерфейсов для файлов пользовательского интерфейса, прежде чем объединить запрос на тягу.
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.
Развязывайте следующее:
- Создайте и нажмите новый тег на наш частный репозиторий
- Нажмите обновленную рамку в https://github.com/instabug/instabug-ios/ . и создать выпуск GitHub
- Опубликовать структуру к какаоподам
- Обновите наш картаге JSON File.
- Загрузите освобождение в нашу собственную 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»