Чому збірка ламається на змінних середовища
Застосунок стабільно працює на машині розробника, а на збірці падає з порожнім екраном або відмовою авторизації — майже завжди причина в змінних середовища мобільного застосунку. Локально значення підтягуються з незакоміченого файлу, який є лише в автора коду.
У збірці ios android цей файл відсутній, підставляється порожній рядок або значення за замовчуванням — і конфігурація розвалюється на етапі запуску, а не компіляції.
Класичний сценарій: адреса сервісу та ключі прописані прямо у вихідниках під конкретне середовище. Варто переключитися з розробки на тестовий контур — застосунок ходить на бойовий сервер або отримує відмову через невідповідний ідентифікатор. Помилки конфігурації спливають уже після релізу, коли відтворити їх поза пристроєм майже неможливо.
Окрема й дорожча проблема — секрети в репозиторії. Ключі платіжних систем, доступи до аналітики та push-сервісів лежать в історії комітів відкритим текстом. Утеча виявляється постфактум, а зміна ключа вимагає перезбірки та повторної публікації в усіх магазинах.
Корінь у тому, що різні середовища — розробка, тест, передпродакшн, продакшн — не розділені на рівні збірки. Значення підставляються вручну, залежать від того, хто і з якої машини запускає збірку, і не перевіряються перед викладкою.
Розбираємо, як це закривається: єдине джерело значень, автоматична підстановка під кожне середовище та захист секретів від потрапляння в репозиторій.
Що дає керована конфігурація середовищ
Керування конфігурацією усуває найдорожчий клас помилок у мобільній розробці — коли застосунок виходить у стор з адресою тестового стенда або ключем від чужого середовища.
Коли значення винесені з коду в окремі профілі, збірка перестає залежати від того, що розробник пам'ятав у момент коміту: конфігурація версіонується разом з кодом, перевіряється на етапі збірки і не може «просочитися» між середовищами.
Швидкість збірки зростає завдяки тому, що перемикання між середовищами — це зміна профілю, а не правка вихідного коду і повторна компіляція. Той самий артефакт збирається з різними наборами параметрів, кеш не скидається, а час на підготовку релізної гілки скорочується в рази.
Відтворюваність дає передбачуваний результат: збірка, зібрана сьогодні, повториться завтра без «а в мене локально працює».
Зниження відмов іде звідти ж — через відсутність ручних правок перед публікацією. Прозорість релізів з'являється, коли видно, які значення пішли в конкретну версію і хто їх змінював: розбір інциденту займає хвилини, а не години пошуку по історії комітів.
Окремий виграш — онбординг: новий інженер піднімає середовище однією командою, не випрошуючи доступи і не збираючи конфіг по чатах.
У сумі керована конфігурація середовищ дає вимірюваний ефект: менше зірваних публікацій, коротший цикл від коміту до стору, передбачувана поведінка застосунку на кожному контурі. Це не разове налаштування, а частина релізного процесу, яку ми закладаємо з першого спринту.
Підходи до зберігання та підстановки значень
Значення потрапляють у збірку трьома принципово різними шляхами, і вибір між ними визначає, що станеться при витоку репозиторію, зміні стенду або відкаті релізу.
На практиці їх комбінують: частина параметрів лежить відкрито у файлах конфігурації, частина підставляється на етапі збірки, а секрети винесені в захищені сховища.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Файли конфігурації в репозиторії | Публічні параметри: адреси стендів, флаги функціональності, ідентифікатори застосунків | Секрети в історії системи контролю версій залишаються назавжди; зміна значення вимагає правки та нового коміту |
| Змінні системи збірки | Різні середовища розробки з однієї гілки коду, параметри, що залежать від контуру | Значення видно в логах збірки; при ручній збірці легко підставити не той контур |
| Захищені сховища | Ключі підпису, токени зовнішніх сервісів, облікові дані платіжних інтеграцій | Потрібен доступ до сховища у складального агента; локальна збірка вимагає окремого налаштування |
Ключове правило — секрети не потрапляють в артефакт застосунку. Усе, що зашите в збірку, витягується з неї зворотною розробкою, тому токени, що дають доступ до серверних ресурсів, тримають на стороні сервісу, а в застосунку залишають лише публічні ідентифікатори.
Підстановка значень прив'язана до контуру: складальний агент отримує набір параметрів для конкретного середовища і вшиває їх на етапі компіляції.
Тоді одна гілка коду дає збірки для розробки, тестування та продакшену без ручного редагування файлів — а розбіжність між стендами перестає бути джерелом помилок.
Окремо вирішується відкат: якщо значення змінюється без перезбірки, його виносять у віддалену конфігурацію, яку застосунок читає при запуску.
Це прискорює реакцію на інцидент, але додає залежність від доступності конфігураційного сервісу — і цей компроміс варто закладати заздалегідь.
Як ми налаштовуємо змінні середовища мобільного застосунку
Налаштування змінних середовища — це не одноразове редагування файлів, а керований процес із перевірюваним результатом. Нижче — як ми ведемо його від аудиту до передачі, щоб конфігурація не розходилася між збірками й не ламала реліз.
- Аудит конфігурації. Збираємо всі місця, де зараз зашиті адреси серверів, ключі та прапорці: файли збірки, схеми, нативні модулі, скрипти CI. Фіксуємо, які значення дублюються, де залишилися жорстко прописані рядки, а які гілки вже розходяться між собою.
- Схема середовищ. Визначаємо набір середовищ — розробка, тестування, передпродакшн, продакшн — і єдиний список змінних для кожного. Домовляємося про правила: що можна змінювати без перезбирання, що потребує нової версії, які значення секретні й не потрапляють у репозиторій.
- Налаштування змінних. Заводимо єдине джерело значень і підключаємо його до кожної платформи — iOS, Android, React Native, Flutter. Секрети виносимо в захищене сховище, а в коді залишаємо лише посилання на них, щоб ключі не витікали через історію комітів.
- Перевірка збірки. Проганяємо збірку на кожному середовищі й звіряємо, що застосунок піднімається з потрібними адресами та прапорцями. Окремо перевіряємо перемикання між середовищами без ручного редагування файлів і відкат на попередню конфігурацію.
- Передача документації. Віддаємо схему середовищ, перелік змінних із призначенням, інструкцію з додавання нових значень і порядок дій при інциденті. Команда замовника далі веде конфігурацію самостійно.
Такий порядок прибирає клас помилок, коли тестова збірка йде в продакшн із чужими ключами. Опишіть вашу задачу — повернемося з оцінкою та планом робіт.
Артефакти конфігурації та регламенти
Конфігурація середовищ живе не в листуванні й не в голові реліз-інженера, а в наборі файлів, які можна відкрити, порівняти та передати іншій команді.
Нижче — типовий комплект, який замовник отримує на руки після налаштування змінних середовища для iOS, Android, React Native і Flutter.
- Файли конфігурації за середовищами — окремі набори значень для розробки, тестування та промислового контуру: адреси сервісів, ключі доступу до зовнішніх систем, прапорці вмикання функцій. Секрети не лежать у репозиторії: вони підставляються на етапі збірки із захищеного сховища.
- Схема середовищ — карта, де видно, який стенд до якого контуру належить, які сервіси він використовує і як значення перетікають з одного середовища в інше. За нею новий інженер розбирається за годину, а не за тиждень.
- Політики доступу — хто з команди та які середовища може змінювати, які дії потребують підтвердження другого інженера, як видаються та відкликаються доступи до секретів. Права розмежовані за ролями, а не видані «всім, кому треба».
- Регламент випуску — покроковий порядок: як додати нову змінну, як перевірити її на тестовому контурі, як викотити на промисловий без зупинки сервісу. Окремо описано, що робити під час відкату.
- Документація щодо змінних — таблиця з усіма параметрами: призначення, допустимі значення, середовище, де застосовується, хто відповідає за актуальність. Розбіжності між кодом і документацією ловляться на етапі перевірки.
- Скрипти перевірки конфігурації — автоматичні перевірки, які не дають зібрати застосунок із порожнім або невірним значенням. Помилка спливає до релізу, а не в користувача.
- Інструкція з передачі — що і в якому порядку потрібно зробити, щоб команда замовника далі вела конфігурацію самостійно: доступи, точки входу, порядок змін.
Комплект залишається робочим при зміні підрядника або розширенні команди: значення не зашиті в код, а середовища описані так, що їх можна відтворити з нуля. Опишіть вашу задачу — повернемося з оцінкою та планом щодо складу артефактів під ваш проєкт.
Кейс: прискорення збірки та зниження відмов
До нас звернувся проєкт на React Native: дві збірки під iOS і Android, чотири середовища — розробка, тестування, передпродакшн і продакшн. Конфігурація лежала в одному .env, який вручну правили перед кожною збіркою, а ключі доступу до сервісів були вписані прямо у вихідний код.
Помилка в одному ключі означала, що застосунок вирушав до магазину з налаштуваннями тестового стенда — а відкат займав години ручної роботи.
Що змінили
Розвели конфігурацію за середовищами та винесли її з коду: кожна збірка отримує свій набір значень на етапі компіляції, а не підмінюється вручну. Секрети прибрали в захищене сховище та підключили до процесу збірки — у репозиторії залишилися тільки посилання на них, не самі ключі.
Додали перевірку: якщо для вибраного середовища не вистачає обов'язкової змінної, збірка зупиняється одразу, а не падає на пристрої у тестувальника.
Результат у цифрах
| Метрика | До | Після |
|---|---|---|
| Час повної збірки | ~18 хвилин | ~7 хвилин |
| Відмови через невірну конфігурацію | 3-4 на місяць | 0 за квартал |
| Правки конфігурації вручну | перед кожною збіркою | не потрібні |
Збірка прискорилася завдяки кешуванню залежностей і відмові від повторної підстановки значень. Клас відмов, пов'язаний з людським фактором при перемиканні середовищ, зник повністю — тепер середовище визначається автоматично за гілкою.
Схожий підхід ми застосовували на Flutter-проєкті: там розвели конфігурацію через окремі схеми збірки, і команда перестала тримати в голові, який файл правити перед релізом.
Чим відрізняються змінні середовища для iOS і Android?
Відмінності починаються з того, де значення взагалі може лежати. В iOS конфігурація традиційно живе в Info.plist і в налаштуваннях схеми збірки: той самий код збирається під різні середовища перемиканням схеми, а значення підставляються на етапі збірки. В Android аналог — BuildConfig і ресурси res/values, де варіант збірки задає свій набір констант.
Звідси перша практична розбіжність: на iOS секрети зручніше тримати поза репозиторієм і підставляти під час збірки, на Android частина значень історично потрапляє прямо в артефакт і залишається читабельною після розпакування.
Друга відмінність — момент підстановки. iOS тяжіє до значень, зашитих на етапі компіляції: змінити середовище без перезбірки не можна, зате поведінка релізу передбачувана і не залежить від того, що лежить на пристрої.
Android допускає читання конфігурації під час виконання — з ресурсів, системних властивостей або віддаленого джерела. Це гнучкіше для поетапного вмикання функцій, але додає клас відмов: застосунок стартує з порожнім або застарілим значенням і падає вже в рантаймі, а не на збірці.
Третє — керування секретами. Ні Info.plist, ні BuildConfig не захищають ключі: обидва формати розбираються з готового пакета. Тому на обох платформах секрети виносять на серверну сторону, а в застосунку залишають лише публічні ідентифікатори.
Різниця лише в тому, куди дивиться розробник за звичкою, і наскільки легко ця звичка призводить до витоку.
Кросплатформенні рішення згладжують синтаксис, але не скасовують відмінностей: шар конфігурації все одно компілюється в нативні механізми кожної платформи.
Тому конфігурацію проєктують один раз — з єдиним набором імен змінних і явним розділенням на публічні та серверні, — а далі розкладають за нативними сховищами. Так збірка під ios і android залишається передбачуваною, а зміна середовища не перетворюється на правку коду.
Часті технічні сумніви
Змінні середовища — та зона, де найчастіше ламається або безпека, або збірка. Нижче — питання, які ставлять майже на кожному проєкті: де зберігати значення, як перейти на нову схему без простою і хто відповідає за конфігурацію після релізу.
Секрети у змінних середовища — це безпечно?
Змінні середовища — транспорт, а не сховище. Ключі та токени тримаємо в захищеному сховищі, а у збірку та на пристрій потрапляють лише короткоживучі значення, видані під конкретне середовище.
Плюс розділяємо контури: тестові та робочі секрети не перетинаються, у кожного своя область доступу. Тоді витік збірки не відкриває робочий контур.
Як перейти на нову схему без зупинки релізів?
Міграцію ведемо паралельно: нова схема змінних піднімається поряд зі старою, застосунок читає обидві й поступово перемикається. Відкат — повернення попереднього набору значень, без перезбірки та повторної публікації в магазинах. Так перехід займає дні, а не квартал, і не блокує поточні випуски.
Що з конфігурацією після релізу — хто її підтримує?
Конфігурація живе як код: зміни проходять перевірку, версіонуються й розкочуються по середовищах автоматично. Додавання нового середовища або зміна адреси сервісу — правка одного файлу, а не ручна збірка під кожну платформу. Ми передаємо схему, правила та інструкції вашій команді, щоб підтримка не залежала від нас.
Чи спрацює це на iOS, Android, React Native і Flutter однаково?
Так, схема спільна: єдиний набір середовищ і правил, а відмінності платформ закриті на рівні збірки. Розробник описує значення один раз, а збирач сам підставляє потрібні для конкретної платформи та середовища. Це прибирає розбіжності, коли на тесті все працює, а в магазині застосунок звертається не туди.
Якщо ваш сценарій не потрапив до списку — опишіть задачу, повернемося з оцінкою та планом.
Обговоримо ваше завдання
Обговорення починається не з прайсу, а з вашого проєкту: які платформи в периметрі, скільки середовищ потрібно розвести, як зараз влаштоване складання. За цими вхідними нашими інженерами готується оцінка та план робіт — з етапами, термінами та зонами відповідальності. Далі ви вирішуєте, рухаємося ми разом чи ні.
Щоб розмова була предметною, корисно одразу мати під рукою кілька речей:
- список платформ і цільових середовищ — де застосунок уже живе, а де лише планується;
- як зараз зберігаються ключі та параметри складання: у репозиторії, в CI-системі або передаються вручну;
- доступи до репозиторіїв, систем складання та панелей магазинів застосунків;
- опис поточного процесу релізу — хто і як збирає збірку, скільки це займає;
- відомі обмеження: вимоги безпеки, погодження, робота з підрядниками;
- контакт людини, яка відповідає за мобільний напрям з боку бізнесу.
За цими даними ми повертаємося з оцінкою та планом: які змінні середовища потрібно завести, як розмежувати конфігурації між середовищами, що піде в захищене сховище, а що залишиться у відкритому вигляді.
Окремо проговорюємо, як буде влаштовано відкат і що станеться, якщо конфігурація розійдеться між платформами.
Якщо у вас уже є напрацювання — конфіги, скрипти складання, чернетка схеми середовищ — приносьте, розберемо їх на місці. Так оцінка буде точнішою, а план — реалістичнішим. Опишіть завдання у зручному форматі: коротке повідомлення, документ або дзвінок на 30 хвилин.







