Add GitHub Actions release build workflow#3592
Conversation
Migrate the release build pipeline from Jenkins to GitHub Actions. The workflow triggers on commcare_* tags and runs tests, builds release variants (CommCare, LTS, CCC Staging), submits the build to CommCareHQ, runs BrowserStack tests, and uploads build artifacts. Co-Authored-By: Claude Code <noreply@anthropic.com>
These variables were carried over from the Jenkins config but are not used by scripts/submit_build.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracts the version from the tag name and creates a draft release with commcare_X.Y.Z.apk and commcare_X.Y.Z.aab attached. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parses commcare_X.Y.Z tag to set VERSION=X.Y.Z and CCCORE_BRANCH=commcare_X.Y, with validation that the tag matches the expected format. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows triggering the release build manually with a VERSION parameter. Version parsing now handles both tag push and dispatch events, and release steps use VERSION from env instead of re-parsing GITHUB_REF. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removes assembleCommcareReleaseAndroidTest gradle task, encryption step, and artifact upload for the test APK. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restores the keystore from a base64-encoded secret and writes signing properties to gradle.properties using a quoted heredoc to safely handle special characters in secret values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Write full gradle.properties to ~/.gradle/ with JVM args, signing config, and service API keys, matching the PR workflow configuration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update shared steps to match PR workflow conventions so that differences between the two files reflect actual behavioral differences only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move Python setup right after checkout (version 3.9) - Move Gradle properties before JDK/Gradle setup - Move Restore Keystore after tests, before build - Reorder artifact uploads to match PR sequence - Remove extra blank lines between steps to match PR style Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consistently use format "Action Product release FORMAT" for build and upload step names (e.g. "Upload CommCare release APK"). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These settings were already partially in gradle.properties (org.gradle.parallel=false). Move the remaining flags (no-daemon, max-workers) there too and simplify the gradle command lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each gradle build step is now immediately followed by its artifact upload, matching the PR workflow structure for minimal diff. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add androidTest APK build and upload to the build job - Add browserstack-tests job matching the PR workflow - Move submit_build.py to a separate job that runs after BrowserStack tests pass - Expose VERSION as a job output for cross-job access Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Combine draft release and submit build into a single "release" job that runs after BrowserStack tests pass. Downloads artifacts from the build job to attach to the GitHub release. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow Gradle to use default daemon and parallelism settings for faster builds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move versionCode into the main Gradle properties block. Safe for PR builds since computeVersionCode() only applies it to release variant outputs and defaults to 1 when absent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Encrypt the instrumentation test APK before uploading as an artifact and decrypt it in the BrowserStack job before use. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create browserstack-tests.yml as a reusable workflow called by both PR and release workflows. Accepts an optional pr-number input and required secrets for decryption and BrowserStack authentication. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis change introduces a new GitHub Actions release build workflow and refactors CI/CD automation by extracting BrowserStack testing into a reusable workflow. The Sequence Diagram(s)sequenceDiagram
actor Trigger as Tag/Dispatch Event
participant GH as GitHub Actions
participant Repo as Repository
participant Build as Build System
participant BS as BrowserStack
participant API as GitHub API
Trigger->>GH: Trigger release-build workflow
GH->>Repo: Checkout commcare-android & commcare-core
Repo-->>GH: Source code
GH->>Build: Validate version & build
Build->>Build: Compile, sign, create APK/AAB
Build-->>GH: Build artifacts
GH->>BS: Download artifacts & run tests
BS-->>GH: Test results
GH->>API: Create draft GitHub release
API-->>GH: Release created
GH->>GH: Submit build with credentials
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.Add a .trivyignore file to your project to customize which findings Trivy reports. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release-build.yml:
- Around line 157-162: The release job's needs array incorrectly lists `build`;
update the `release` job's needs to include `build-test-assemble` (so it reads
needs: [build-test-assemble, browserstack-tests]) so that the `release` job can
access `needs.build-test-assemble.outputs.version`; modify the `release` job's
`needs` entry accordingly in the workflow to ensure the output reference
`needs.build-test-assemble.outputs.version` is valid.
- Around line 135-147: The workflow currently runs the Gradle task
bundleLtsRelease (step "Bundle LTS release AAB") but never runs
assembleLtsRelease, so the "Upload LTS release APK" artifact path will not
exist; add a new job step that runs ./gradlew assembleLtsRelease in the
commcare-android working-directory (before the "Upload LTS release APK" step) so
the APK at app/build/outputs/apk/lts/release/app-lts-release.apk is produced,
keeping the existing artifact upload steps unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7721612c-009c-41f0-b2ff-1881a932e28a
📒 Files selected for processing (3)
.github/workflows/browserstack-tests.yml.github/workflows/commcare-android-pr-workflow.yml.github/workflows/release-build.yml
| - name: Bundle LTS release AAB | ||
| run: ./gradlew bundleLtsRelease | ||
| working-directory: commcare-android | ||
| - name: Upload LTS release APK | ||
| uses: actions/upload-artifact@v6 | ||
| with: | ||
| name: app-lts-release-apk | ||
| path: commcare-android/app/build/outputs/apk/lts/release/app-lts-release.apk | ||
| - name: Upload LTS release AAB | ||
| uses: actions/upload-artifact@v6 | ||
| with: | ||
| name: app-lts-release-aab | ||
| path: commcare-android/app/build/outputs/bundle/ltsRelease/app-lts-release.aab |
There was a problem hiding this comment.
Missing assembleLtsRelease step — LTS APK upload will fail.
The workflow bundles the LTS AAB (line 136) but then attempts to upload an LTS APK (lines 138-142) that was never assembled. The bundleLtsRelease Gradle task produces only the AAB, not the APK.
🐛 Proposed fix: Add LTS APK assembly step
+ - name: Assemble LTS release APK
+ run: ./gradlew assembleLtsRelease
+ working-directory: commcare-android
- name: Bundle LTS release AAB
run: ./gradlew bundleLtsRelease
working-directory: commcare-android
- name: Upload LTS release APK🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release-build.yml around lines 135 - 147, The workflow
currently runs the Gradle task bundleLtsRelease (step "Bundle LTS release AAB")
but never runs assembleLtsRelease, so the "Upload LTS release APK" artifact path
will not exist; add a new job step that runs ./gradlew assembleLtsRelease in the
commcare-android working-directory (before the "Upload LTS release APK" step) so
the APK at app/build/outputs/apk/lts/release/app-lts-release.apk is produced,
keeping the existing artifact upload steps unchanged.
| release: | ||
| needs: [build, browserstack-tests] | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| VERSION: ${{ needs.build-test-assemble.outputs.version }} |
There was a problem hiding this comment.
Fix job dependency reference: build does not exist.
The needs array references build, but the actual job name is build-test-assemble. This will cause the workflow to fail. Additionally, line 162 won't be able to access build-test-assemble.outputs.version since only jobs listed in needs expose their outputs.
🐛 Proposed fix
release:
- needs: [build, browserstack-tests]
+ needs: [build-test-assemble, browserstack-tests]
name: Release
runs-on: ubuntu-latest📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| release: | |
| needs: [build, browserstack-tests] | |
| name: Release | |
| runs-on: ubuntu-latest | |
| env: | |
| VERSION: ${{ needs.build-test-assemble.outputs.version }} | |
| release: | |
| needs: [build-test-assemble, browserstack-tests] | |
| name: Release | |
| runs-on: ubuntu-latest | |
| env: | |
| VERSION: ${{ needs.build-test-assemble.outputs.version }} |
🧰 Tools
🪛 actionlint (1.7.11)
[error] 157-157: job "release" needs job "build" which does not exist in this workflow
(job-needs)
[error] 162-162: property "build-test-assemble" is not defined in object type {browserstack-tests: {outputs: {}; result: string}}
(expression)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release-build.yml around lines 157 - 162, The release
job's needs array incorrectly lists `build`; update the `release` job's needs to
include `build-test-assemble` (so it reads needs: [build-test-assemble,
browserstack-tests]) so that the `release` job can access
`needs.build-test-assemble.outputs.version`; modify the `release` job's `needs`
entry accordingly in the workflow to ensure the output reference
`needs.build-test-assemble.outputs.version` is valid.
The build-test-assemble job only runs Gradle tasks and doesn't need Python. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change print statements to print() function calls and fix identity comparison (is) to equality (==) for integer check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
I had Claude Code do a somewhat complex rebase-like thing to get a branch based on My prompt was
and it appears to have done that. (It also correctly inferred that I wanted |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
0c2ead5 to
46670f1
Compare
|
Seems to be running from the right branch setup, but is failing https://github.com/dimagi/commcare-android/actions/runs/22978879809 with Update: I reran this build job and it passed. Ahmad also mentioned that this is a known flaky test. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Product Description
No user-facing changes. This adds CI/CD infrastructure for release builds.
Technical Summary
Adds a GitHub Actions workflow to replace the Jenkins release build job. Also refactors the existing PR workflow to share code with the new release workflow.
New release workflow (
.github/workflows/release-build.yml):commcare_*tag pushes or manual dispatch with a version parametercommcare_2.61.6→VERSION=2.61.6)CCCORE_BRANCHis autoselected based on the most up-to-date tag in commcare-core at this version or below (e.g. ifVERSION=2.61.6it will try commcare_2.61.6, then commcare_2.61.5, then commcare_2.61.4, etc. and finally commcare_2.61, but it will never try commcare_2.61.7 or higher)commcare_X.Y.Z.apkand.aabassetsShared BrowserStack workflow (
.github/workflows/browserstack-tests.yml):workflow_callworkflow used by both PR and release workflowsPR workflow changes (
.github/workflows/commcare-android-pr-workflow.yml):versionCodeto shared gradle.propertiesFeature Flag
N/A
Safety Assurance
Safety story
Automated test coverage
The workflows themselves run the existing
testCommcareDebugtest suite and BrowserStack instrumentation tests.QA Plan
Labels and Review