#android #docker #continuous-integration #gitlab #fastlane
# #Android #docker #непрерывная интеграция #gitlab #fastlane
Вопрос:
Я использую Gitlab CI для создания своего приложения для Android с использованием fastlane внутри контейнера Docker. В моем приложении есть два «варианта», которые я хочу создать в отдельных заданиях CI. Вот соответствующая часть .gitlab-ci.yml
:
default:
image: registry.example.com/group/project:29-android-fastlane-debian
tags:
- docker
before_script:
- ruby -v # Print out ruby version for debugging
- bundle install
build_flavor1_debug:
stage: build
script:
- bundle exec fastlane build release:"false" --env flavor1
artifacts:
paths:
- app/build/outputs/bundle/
rules:
- if: '$CI_COMMIT_TAG amp;amp; $CI_COMMIT_REF_PROTECTED == "true"'
when: never
- when: on_success
build_flavor2_debug:
stage: build
script:
- bundle exec fastlane build release:"false" --env flavor2
artifacts:
paths:
- app/build/outputs/bundle/
rules:
- if: '$CI_COMMIT_TAG amp;amp; $CI_COMMIT_REF_PROTECTED == "true"'
when: never
- when: on_success
(Другие задания в этом конвейере выполняют сборки релизов для тегов git и загружают их в Play Store, но они не имеют отношения к этой проблеме.)
Вот соответствующие части Fastfile
:
# All flavors we know about. If one is not specified, run them all
flavors = {
"flavor1" => "com.example.flavor1.app",
"flavor2" => "com.example.flavor2.app"
}
# If set to a single flavor, make it the only one in the array
if ENV["FLAVOR_NAME"]
flavors = flavors.slice(ENV["FLAVOR_NAME"])
end
UI.user_error!("Unknown flavor '#{ENV["FLAVOR_NAME"]}' selected") if flavors.empty?
platform :android do
desc "Build the application"
lane :build do |options|
setup(options)
flavors.each { |flavor_name, flavor_package|
build_flavor(
flavor: flavor_name,
release: options[:release]
)
}
end
end
Использование --env
флага загружает .env
файл с соответствующей FLAVOR_NAME
переменной, установленной для одновременного запуска только одного варианта.
Это работало нормально, когда я запускал сборки последовательно, но это занимает слишком много времени. Я изменил конфигурацию Gitlab Runner, чтобы разрешить одновременное выполнение до 8 заданий, и теперь я получаю следующую ошибку:
The message received from the daemon indicates that the daemon has disappeared.
Build request sent: Build{id=111291aa-90bc-45c3-8fb4-9a271d4663f4, currentDir=/builds/group/project}
Attempting to read last messages from the daemon log...
Daemon pid: 1100
log file: /root/.gradle/daemon/6.5/daemon-1100.out.log
----- Last 20 lines from daemon log file - daemon-1100.out.log -----
[SNIP] - No useful logs here...
----- End of the daemon log -----
FAILURE: Build failed with an exception.
* What went wrong:
Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed)
Иногда это происходит на задании одного варианта, а иногда и на другом. Если я вручную повторно запускаю неудачное задание, оно всегда выполняется успешно.
Я считаю, что происходит то, что два задания сборки выполняются внутри одного и того же контейнера Docker вместо того, чтобы каждое из них имело свое собственное. Тот, который сначала завершает использование Gradle, завершает работу демона Gradle, что приводит к сбою другого.
Как я могу заставить эти задания выполняться параллельно?
Комментарии:
1. Проверьте свою идею о том, что они выполняются в одном контейнере, изменив изображение для одного из них и посмотрев, решает ли это проблему.
2. Попробуйте выполнить сборку с
--no-daemon
помощью, режим демона бесполезен в контейнере.3. @Xiaofeng Я попробую, но, согласно документации Gradle, этот флаг больше не имеет никакого значения. Также смотрите github.com/gradle/gradle/issues/2824#issuecomment-326282674
4. Достаточно ли у вас ресурсов для одновременных запусков? Особенно проблемой может быть память.
5. @JanGaraj У меня на компьютере 32 ГБ, и Docker разрешено использовать до 24 ГБ.
Ответ №1:
Достаточно ли у вас ресурсов для одновременных запусков? Особенно это может быть проблемой с памятью, поэтому ОС будет уничтожать другие контейнеры из-за нехватки памяти.