Тема
Gitea CI/CD для Android
Цель
Pipeline должен воспроизводимо проверить web и Android, сформировать артефакты, а затем отдельным доверенным job опубликовать уже проверенный AAB.
Gitea Actions доступен как встроенный CI/CD, а задания выполняет отдельный runner. Gitea Actions.
Контуры
text
Pull request/push
→ unprivileged CI: npm, web tests, Gradle lint/test, debug APK
Release tag
→ signing job: verified source → signed AAB
→ publish job: signed AAB → Play internal track
→ manual approval → promote track
Optional Codex job
→ read-only logs/diff → report or patch artifactCodex, signing и publication не объединяются в одном job.
Runner
Используйте доверенный self-hosted runner с закреплённым образом, содержащим:
- Node.js 22;
- Android command-line tools;
- platform 36/build tools/platform tools;
- совместимый JDK;
- Ruby/Bundler/Fastlane;
- Git и
unzip; - без постоянных release credentials внутри образа.
Закрепляйте image tag или digest. Не назначайте host label, похожий на ubuntu-latest: это снижает риск случайного выполнения чужого workflow прямо на хосте. Runner labels.
CI workflow — логическая спецификация
.gitea/workflows/ci.yml должен выполнять:
- Checkout без write credentials.
- Проверку Node/Java/SDK versions.
npm ci.- Web lint/unit/E2E.
npm run build.npx cap sync android../gradlew lint test assembleDebug.- При доступном emulator/device — smoke test.
- Upload test reports, lint report и APK.
Ни один шаг PR workflow не получает signing/Play secrets.
Release workflow
Trigger: защищённый tag вида vX.Y.Z или ручной dispatch.
Gates:
- commit входит в защищённую main branch;
- CI того же commit зелёный;
- version code больше последнего опубликованного;
- store metadata и policy docs актуальны;
- release notes присутствуют;
- нет uncommitted/generated drift.
Затем:
- Восстановить upload keystore во временный файл.
- Собрать release AAB.
- Проверить подпись и SHA-256.
- Удалить временный keystore независимо от результата.
- Передать AAB в отдельный publish job.
- Fastlane загружает AAB в
internal. - Production promotion выполняется отдельным ручным действием.
Fastlane
После ручного создания приложения и первой загрузки:
bash
bundle exec fastlane supply initПример lane:
ruby
platform :android do
desc "Upload a verified AAB to the internal track"
lane :internal do
upload_to_play_store(
track: "internal",
aab: ENV.fetch("ANDROID_AAB"),
json_key: ENV.fetch("PLAY_SERVICE_ACCOUNT_FILE"),
release_status: "completed",
skip_upload_screenshots: false
)
end
endFastlane Supply загружает AAB, metadata, localized descriptions, screenshots и умеет продвигать releases между tracks. Supply.
Автоматизация store assets
- Browser/device automation создаёт детерминированные screenshots ключевых экранов; для игр это gameplay, для других apps — основной пользовательский flow.
- Fastlane Screengrab применяется, если screenshots снимаются нативными tests.
- Image generation помогает делать черновые icon/feature graphics.
- Человек проверяет, что изображения показывают реальное приложение, не нарушают чужие права и не содержат вводящие в заблуждение обещания.
Cache
Можно кэшировать npm и Gradle download cache, но нельзя:
- кэшировать keystore/service-account JSON;
- переносить signing workspace между недоверенными jobs;
- считать cache воспроизводимым источником артефакта;
- публиковать AAB, собранный из PR fork/untrusted branch.
Codex в Gitea
Официальный Codex GitHub Action не переносится в Gitea автоматически. Для Gitea используйте codex exec в отдельном изолированном runner/job:
- read-only checkout;
- без Git write token;
- без signing и marketplace secrets;
- final report/patch только как artifact;
- применение patch и commit — отдельным проверяемым процессом.