Почему падает Android-сборка в CI/CD?
На моей практике чаще всего проблемы возникали не из-за крупных архитектурных грехов, а из-за обычных мелочей, про которые все забывают.
Первое место в моем личном топе — кавычки.
Например, в проекте значения в gradle.properties указываются в кавычках:
API_BASE_URL="https://example.com"
И build logic завязан на этот формат: он ожидает значения с кавычками и обрабатывает их соответствующим образом. Пока сборка берет значения по умолчанию из gradle.properties, всё работает. Проблема появляется, когда значения переопределяются через GitLab CI/CD variables. В интерфейсе GitLab CI, когда вводишь переменную, ты обычно пишешь:
API_BASE_URL=https://example.com
И легко забыть, что build logic ожидает значение вместе с кавычками: В итоге локально сборка работает, а при передаче параметров через CI/CD начинает падать, потому что build logic получает значение в другом формате.
Второе место — имена артефактов.
С именами APK при разных build flavors тоже можно легко ошибиться. Сама Android-сборка проходит успешно, но следующий шаг CI/CD падает, потому что не может найти собранный артефакт. Причина в разном формате именования. В Android Gradle Plugin имя variant обычно выглядит как camelCase:
prodRelease
А в CI/CD часто удобнее использовать snake_case:
prod_release
Если build logic генерирует имя APK на основе variant.name, а CI/CD ожидает файл в формате prod_release, получается расхождение. Например, Gradle/build logic может создать файл с именем:
app_prodRelease.apk
А CI/CD будет искать:
app_prod_release.apk
APK был собран, но pipeline всё равно падает, потому что ищет его по другому имени.
После этого я стал явно нормализовать flavor/build type и всегда проверять, какой файл реально появляется после сборки. И перестал использовать кавычки в properties. Такие ошибки выглядят мелкими, но именно они часто съедают время команды: сборка вроде есть, артефакт вроде есть, а pipeline всё равно красный.