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

Первая публикация Flutter-приложения почти никогда не срывается из-за «большой» ошибки в коде. Чаще все упирается в мелочи, которые всплывают только на сборке или на проверке в Google Play и App Store. Из-за этого команда делает лишние билды, тратит дни на переписку с ревью и нервничает перед дедлайном.
Обычно забывают не что-то одно, а цепочку вещей, которые должны совпасть в один день: подпись, версии, тексты, ассеты, диагностика. Сборка уже готова, но keystore лежит у одного человека на ноутбуке, номер версии не увеличен, в описании нет упоминания про доступ к геолокации, а скриншоты сделаны со старым дизайном.
Чаще всего релиз «ломают» пять зон:
Часть задач лучше закрыть заранее: подпись, flavors для dev и prod, подключение краш-репортинга, шаблоны текстов для разрешений. В день релиза должны остаться «чистые» операции: финальная сборка, прогон по шагам, загрузка в консоль и отправка на ревью.
Сначала решите простое: куда именно вы выпускаетесь. Android, iOS или обе платформы. От этого зависят сроки (особенно из-за ревью), набор ассетов и список доступов, которые стоит проверить уже сегодня.
Зафиксируйте дату релиза и заложите окно на ревью. Даже если приложение выглядит стабильно, первая отправка часто возвращается с вопросами: про разрешения, контент, описание функций. Планируйте так, чтобы у вас был хотя бы один рабочий день на правки и повторную отправку.
Проверьте доступы заранее, пока никто не собирает релиз в последний час. У команды должны быть роли в аккаунтах разработчика, права на публикацию, доступ к сертификатам и к почте, на которую придут письма от стора. Отдельно договоритесь, кто отвечает на вопросы модерации и кто сможет быстро обновить описание или скриншоты.
Дальше составьте список окружений и зафиксируйте, что в них различается: dev, stage, prod. Важно, чтобы все понимали, какие ключи, адреса API, флаги аналитики и режим логирования должны быть в каждом окружении. Это заметно снижает путаницу, когда появляются flavors и разные конфиги.
Чтобы релиз не превратился в переписку по чатам, заранее назначьте владельцев: кто собирает билды и проверяет их на устройстве, кто готовит тексты разрешений и описание в сторе, кто делает скриншоты и иконки, и кто ведет коммуникацию с ревью и фиксит замечания.
Если вы делаете приложение через TakProsto, полезно заранее договориться, кто подтверждает финальные изменения в чате и кто делает экспорт исходников или деплой. Это помогает не тормозить релиз в день отправки.
Начните с вещей, которые стор проверяет молча, но строго: версии, идентификаторы и базовый внешний вид сборки.
С версиями договоритесь заранее. Для Android это связка versionName и versionCode, для iOS - номер версии и build number. Удобное правило: versionName отражает релиз для пользователей (например, 1.2.0), а build number растет на каждую новую сборку, даже если вы просто пересобрали тот же релиз.
Идентификаторы должны быть уникальными и стабильными. На Android это applicationId, на iOS - bundle id. Если поменять их перед публикацией или между окружениями, стор воспримет приложение как другое, а обновление может не пройти. Это часто случается после переносов проекта или генерации «с нуля» (в том числе после экспорта исходников).
Быстрая проверка «упаковки» перед первой отправкой:
Еще одна мелочь, которая экономит время: держите короткие release notes и историю изменений в одном месте. Тогда не придется вспоминать, что именно попало в сборку, когда нужно заполнять поля в сторе или отвечать на вопросы коллег.
Подпись релиза на Android часто всплывает в последний момент, а потом оказывается, что ключ потерян или релиз подписан debug-сертификатом. Этот пункт лучше закрыть одним из первых.
Keystore создается один раз и живет годами. Потеря keystore или паролей означает, что вы не сможете обновлять приложение под тем же пакетом. Не пересылайте ключ и пароли в чатах и не храните их в публичных репозиториях. Держите файл keystore в защищенном месте, а секреты - в менеджере паролей или в закрытых переменных CI.
Проверьте, что релиз действительно собирается как release: в build.gradle должна быть настроена signingConfig для release, а в сборку не попадают debug-ключи. Отдельно убедитесь, что вы не выкладываете APK, если по плану релиза нужен AAB.
С Play App Signing легко запутаться: есть ключ загрузки (upload key) и ключ подписи приложения в Google Play. В консоль вы загружаете AAB, подписанный upload key. Дальше Google подписывает приложение своим ключом. Зафиксируйте, какой ключ используется, и кто имеет к нему доступ.
Короткая проверка перед отправкой:
Если вы получаете исходники из конструкторов или vibe-coding платформ, подпись все равно остается вашей ответственностью. Решите это до того, как дедлайн начнет давить.
Flavors нужны, когда одному приложению мало одного набора настроек: разные окружения (dev/stage/prod), разные API, отдельная сборка для тестировщиков, иногда брендинг под клиентов. Если это не про вас, не усложняйте: лишний flavor легко превращается в путаницу.
Сразу решите, что именно отличается между flavors. Различия должны быть явными и проверяемыми, а не «где-то в коде есть условие».
Обычно достаточно развести конфиги:
Если нужен отдельный package name (applicationId / bundle id), делайте его только для тестовых сборок, чтобы они не перетирали прод на устройстве и не смешивали данные.
Перед релизом прогоните каждый flavor, который реально используется, и откройте приложение на реальном устройстве. Проверьте три вещи: правильный сервер, нет тестовых экранов, логи не «шумят». Если flavor давно не используется, лучше удалить его сейчас, а не после очередного ночного фикса.
Если приложение упало у пользователя, у вас есть два варианта: гадать по отзывам или видеть точный стек и шаги перед падением. Для Flutter часто выбирают Firebase Crashlytics, но подойдут и Sentry, Bugsnag или аналоги. Важно не только подключить сервис, но и договориться, что именно вы собираете и кто смотрит алерты.
Частая ловушка: краши идут из debug, а в релизе тишина. Перед первой публикацией сделайте пробную release-сборку, установите ее как обычный пользователь и вызовите тестовый крэш. Проверьте, что событие появилось в панели и привязалось к правильной версии.
Чтобы стеки были читаемыми, нужны символы. На iOS это dSYM, на Android - mapping для R8/Proguard. Без них вы увидите набор непонятных адресов и потратите время впустую. Введите правило: каждый релиз сопровождается загрузкой символов.
Добавьте минимум контекста для воспроизведения: версия, build number, flavor (prod/stage) и 2-3 ключевых события (логин, покупка, открытие экрана). Метки лучше делать короткими и одинаковыми во всех сборках.
И проверьте приватность. Не отправляйте в логи номера телефонов, почту, точные адреса и содержимое сообщений. Если нужен идентификатор, используйте обезличенный userId или хэш.
Разрешения часто «валят» первый релиз не из-за кода, а из-за непонятного объяснения. Выпишите все разрешения, которые реально запрашивает приложение, и честно ответьте: что сломается, если пользователь откажет. Если ответа нет, разрешение лишнее.
Минимум перед сабмитом:
Текст важнее, чем кажется. Если вы просите геолокацию только для выбора ближайшего города, так и пишите. Не пишите «для улучшения сервиса» или «для безопасности», если это не правда. На такие формулировки плохо реагируют и ревью, и пользователи.
Прогоните сценарии на чистой установке: где показывается объяснение, когда появляется системный запрос, что видит человек при отказе, не спамит ли приложение повторными попапами, как ведет себя после выдачи разрешения в настройках, и нет ли обрезанных строк на разных языках.
Если вы собираете приложение через TakProsto, удобно согласовать эти тексты заранее в режиме планирования, чтобы они не всплыли в последний вечер.
Листинг в сторе часто тормозит релиз сильнее, чем сборка. Даже если билд готов, без иконки, скриншотов и нормального текста первая отправка превращается в гонку.
Начните с графики. Подготовьте иконку в нужных размерах и обязательные изображения для каждого стора (например, feature graphic для Google Play). Со скриншотами проще: сделайте 4-6 кадров, каждый про одну мысль, а не просто «экран 1, экран 2». Подписи на самих скриншотах делайте короткими и читабельными.
Тексты листинга должны обещать только то, что реально есть. Хорошая схема: короткое описание на 1-2 предложения и полное описание, где вы объясняете пользу и ограничения. Добавьте несколько преимуществ простыми словами, одну фразу «для кого», базовые требования (нужен ли интернет, нужен ли аккаунт). Если есть важные ограничения, лучше сказать о них сразу.
Категорию и ключевые слова выбирайте аккуратно: лучше точные и понятные, чем десяток общих.
Перед сабмитом проверьте поля в консоли: контактный email, возрастной рейтинг и политику конфиденциальности по факту (какие данные собираете и зачем). Если аналитики и аккаунтов нет, так и пишите, это снижает количество вопросов.
Перед сабмитом сделайте короткий, но честный прогон. Он спасает от ситуации, когда сборка уже загружена, а вы внезапно вспоминаете про неверную версию или неработающий логин.
Соберите clean release для prod-окружения и проверьте базовое: номер версии и build number, applicationId/bundleId, имя приложения, иконку, и что сборка действительно release (без debug-баннеров и тестовых ключей).
Быстро проверьте приложение руками на нескольких устройствах. Идеально 2-3 девайса, где один послабее. Пройдите 3-5 критических сценариев (онбординг, главный экран, ключевое действие), проверьте повороты экрана, сворачивание и возврат, а также «первый запуск без интернета».
Отдельно проверьте сеть: медленный интернет, короткий офлайн, таймаут. Приложение должно не зависать, а показывать статус, кнопку повторить и корректно восстанавливаться.
Если есть логин, платежи или пуши, проверьте их по одному: вход-выход, восстановление сессии, покупка в песочнице, получение уведомления и переход по нему.
После этого загрузите сборку в консоль, заполните листинг, отправьте на ревью и зафиксируйте: какая версия ушла, когда, и что именно вы проверяли.
Самая дорогая ошибка в релизе - не баг в UI, а мелочь, из-за которой приложение нельзя обновить или стор отклоняет сборку.
Окружение перепутали: релиз ушел на тестовый сервер. В коде остался тестовый endpoint или ключи песочницы, и пользователи видят пустую базу, чужие данные или неработающие оплаты. Почти всегда это про конфигурацию: переменные окружения, flavor, сборочный скрипт.
Релизный билд ведет себя как debug. В релиз случайно попадают debug-логи, тестовые флаги (вроде "showDevMenu"), или аналитика отключена и вы не видите, что происходит после публикации.
Самый болезненный кейс на Android - подпись. Если keystore потерян или подпись настроена неправильно, новую версию невозможно выкатить как обновление.
Отказы и жалобы часто связаны не с самим разрешением, а с тем, как вы его просите. Когда приложение запрашивает геолокацию или фото без нормального объяснения, люди жмут «Запретить», пишут негатив и повышают шанс дополнительных проверок.
И, наконец, листинг. Скриншоты и тексты должны соответствовать текущей версии и локали. Старые экраны на скриншотах или русский текст в английской локали выглядят как неаккуратность и легко приводят к отклонению.
Собираете prod-окружение (нужный flavor), а номера версии и build-номер увеличены. Установите сборку на чистое устройство или эмулятор: приложение запускается без «красных экранов», логин и первый экран открываются.
Проверьте, что Android keystore лежит там, где ожидает сборка, и пароли/алиасы подходят. Соберите AAB и убедитесь, что он загружается в консоль и проходит базовую проверку. Обновление должно быть возможно: подпись совпадает с предыдущей (или корректно включен Play App Signing).
Сделайте тестовый краш в релизной сборке (в отдельной ветке/фиче), чтобы убедиться, что отчеты приходят и стеки читаемы. Если все выглядит как набор "unknown", поправьте символы/обфускацию до отправки.
Откройте каждый экран, где запрашиваются разрешения. Текст объясняет, зачем это нужно. Отказ не ломает сценарий. Лишних разрешений нет.
Проверьте обязательные поля: иконка, скриншоты, короткое и полное описание, контакты поддержки, категория и возрастной рейтинг. Частая мелочь, которая тормозит релиз: скриншоты не того размера или описание не совпадает с тем, что реально есть в приложении.
Представьте небольшое Flutter-приложение: логин по номеру, экран с картой и пуш-уведомления. Команда маленькая, срок на первый релиз - неделя, хочется отправить в стор без нервов.
Заранее закрыли базовые вещи: сгенерировали Android keystore, договорились, где он хранится и кто имеет доступ. Настроили flavors: dev для тестов и prod для релиза, чтобы не перепутать ключи и конфиги. Для разрешений подготовили понятные тексты: зачем нужна геолокация для карты и зачем уведомления для пушей.
В последний момент всплыли два сюрприза. Скриншоты для листинга оказались сделаны на старой версии, где еще не было экрана с согласием на геолокацию. И второе: в prod-сборку случайно попал dev endpoint, потому что один параметр был захардкожен в коде, а не в конфиге.
Спас простой прогон по чеклисту:
Релиз ушел со второй попытки, но без серии повторных сабмитов. А когда ревью задавало вопросы, ответы уже были готовы: где и зачем запрашиваются разрешения, что делает приложение, и почему данные нужны именно так.
Первый релиз обычно получается «ручным». Дальше важнее не запомнить все нюансы, а превратить их в маршрут, который повторяется каждый раз.
Начните с простого шаблона: один файл чеклиста рядом с репозиторием и привычка обновлять его после каждого релиза. Тогда список будет отражать реальность проекта, а не общие советы.
Потом убирайте ручные действия из критичных мест. Версии, номера сборок, выбор окружения и тип сборки проще доверить автоматике, чем перепроверять в последний вечер. Даже без сложного CI можно договориться, что сборка «на прод» всегда делается одним и тем же способом.
Полезно завести отдельную папку для ассетов листинга и относиться к ней как к части продукта. Меняете ключевой экран или добавляете важную функцию - обновляете скриншоты и короткое описание сразу, а не «перед релизом».
Если нужно быстрее собирать прототипы и получать Flutter-проект, который можно дальше вести обычным релизным процессом, TakProsto (takprosto.ai) позволяет создать приложение через чат, а затем экспортировать исходники и продолжить работу в привычном темпе.