Expert capabilities for managing Upnext application releases, CI/CD pipelines, and versioning.
This skill provides a comprehensive guide for managing the release lifecycle of the Upnext Android application. It encapsulates logic for GitHub Actions, Fastlane, Semantic Versioning, and troubleshooting.
The release pipeline is fully automated via GitHub Actions, prioritizing stability and reducing noise.
Automated deployments run daily at 2:00 AM UTC via .github/workflows/deploy.yml. This batches all dependency updates and merges from the day into a single release.
Triggers:
cron: '0 2 * * *'workflow_dispatch (Run via GitHub Actions UI)Process:
VERSION_CODE and VERSION_NAME in version.properties..aab).v2025.1.4-215).Critical Implementation Detail (GitHub Releases): For scheduled builds, the workflow runs on the
mainbranch ref (refs/heads/main), not the tag ref. To ensure a GitHub Release is attached to the newly created tag:
- Fastlane updates
version.properties.- The workflow explicitly reads
VERSION_NAMEandVERSION_CODEfrom the updated file.- It constructs the tag name (
v{NAME}-{CODE}) and passes it to thesoftprops/action-gh-releaseaction. Do not rely ongithub.reffor scheduled release tagging.
Every Pull Request to main undergoes strict quality checks via .github/workflows/pull_request.yml.
Parallelized Verification Jobs:
To minimize PR feedback time to ~5 minutes, tasks are executed concurrently across parallel GitHub Actions runners with 4 GB JVM heap tuning (-Dorg.gradle.jvmargs="-Xmx4096m -XX:+UseParallelGC"):
code-quality: ktlintCheck, detekt, and testDebugUnitTest (Code Style, Static Analysis, Unit Tests).android-lint: lintDebug (Android Lint checks).build-validation: assembleDebug and assembleRelease (Build compilation and R8/ProGuard shrinking verification).ui-tests: connectedDebugAndroidTest on Android emulator.Note on Signing in Pull Requests: PR builds do not have access to production signing keys.
app/build.gradleis configured to fallback to debug signing automatically when the release keystore is missing. This allowsassembleReleaseto verify compilation and shrinking logic in CI without needing secrets.
To prevent excessive consumption of GitHub Actions minutes, especially from automated dependency bots like Renovate, the following strategies are implemented:
deploy.yml)The nightly scheduled build incorporates a check_changes pre-job.
git rev-list "${LATEST_TAG}..HEAD" --count).main since the last deployment tag, it skips the expensive deploy job entirely.workflow_dispatch) bypass this check and force a deployment.renovate.json & pull_request.yml)Dependency updates can cause massive CI fan-out. To mitigate this:
rebaseWhen: conflicted: Renovate is configured to only rebase PRs if there is a git conflict, preventing it from auto-rebasing 10+ PRs whenever a single PR is merged into main.all-minor-patch), reducing PR volume.prConcurrentLimit: 3: Restricts the maximum number of simultaneous Renovate PRs.pull_request.yml includes a concurrency block (cancel-in-progress: true). If a PR receives new commits (e.g. during a manual rebase), GitHub instantly cancels the running tests for the old commit, saving minutes.You can run the release logic locally using Fastlane to verify builds before pushing.
fastlane installed.key.properties present (or environment variables set).service-account.json for Google Play API access.screenshot-framer (Python library) installed for generating marketing screenshots (do not use fastlane frameit).Run Internal Track Deployment locally:
fastlane deploy_internal
Note: This will perform the build, signing, and upload to Google Play, and will commit/tag version bumps.
Run Specific CI Checks Locally:
# Verify Code Style
./gradlew ktlintCheck
# Verify Static Analysis
./gradlew detekt
# Verify Android Lint
./gradlew lintDebug
# Verify Release Build (Compilation + R8)
./gradlew assembleRelease
Upnext uses Calendar Versioning (CalVer): YYYY.M.Patch
File: version.properties
VERSION_CODE=214
VERSION_NAME=2025.1.4
Automated Bumping:
The Fastfile (deploy_internal lane) automatically:
VERSION_CODE for every build.VERSION_NAME to YYYY.M.1 (if new month) or YYYY.M.Patch+1 (if same month).local.properties or Secrets.TRAKT_CLIENT_ID and TRAKT_CLIENT_SECRET are set in GitHub Actions Secrets.assembleRelease fails with SigningConfig "release" is missing required property "storeFile".app/build.gradle. Ensure the buildTypes.release block contains the fallback logic:
if (signingConfigs.release.storeFile != null) { ... } else { signingConfig signingConfigs.debug }
lintDebug fails with "Missing permission" (e.g., WAKE_LOCK) or "Resource not found".core:common, core:data) often need their own AndroidManifest.xml and resource definitions to satisfy lint, even if the app module provides them.AndroidManifest.xml with <uses-permission> to the specific module (e.g., core/common/src/main/AndroidManifest.xml) or define the missing resource in that module.deploy.yml configures git user/email before tagging using github-actions[bot]..github/workflows/deploy.yml: Nightly CD workflow..github/workflows/pull_request.yml: PR CI workflow.fastlane/Fastfile: Build automation script.version.properties: App version definition.app/build.gradle: Build & signing configuration.Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer