Repository navigation
CI Overhaul: Separate test, build, and release workflows with least-privilege permissions - #2
Conversation
- Add ci-tests.yml for unit tests and lint on PRs/push - Add ci-build.yml for unsigned APK artifacts on PRs/push - Add release.yml for tag-triggered signed releases - Add scripts/ci_local.sh for local CI parity - Update build.gradle to make signing config optional - Mark legacy build-release.yaml as deprecated and add tests Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com>
…secret - Improve Java version detection to handle both old (1.8) and new (17.0) formats - Add validation for numeric version before comparison - Add comment explaining shared password secret pattern Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com>
|
@copilot can you resolve the following warnings in the codebase by updating them to the latest non-deprecated syntax/library function (following best practices; ensure the new code is functional and don't break things), and another CI failure regarding dependency verification
FAILURE: Build failed with an exception.
|
|
@copilot can you resolve the following warnings in the codebase by updating them to the latest non-deprecated syntax/library function (following best practices; ensure the new code is functional and don't break things), and another CI failure regarding dependency verification
FAILURE: Build failed with an exception.
|
Current CI builds and releases on every master push without running tests, uses overbroad permissions, and exposes signing secrets during build. This PR separates concerns into distinct workflows with minimal privileges.
New Workflows
ci-tests.yml— Unit tests + lint on PRs/pushes to master, parallel jobs,contents: readonlyci-build.yml— Unsigned debug APK artifact on PRs/pushes,contents: readonlyrelease.yml— Tag-triggered (v*.*.*) signed releases,contents: writescoped to signing job onlyBuild Configuration
Made signing config conditional to allow builds without keystore:
signingConfigs { if (System.getenv("ANDROID_KEYSTORE") != null) { create("multiset") { storeFile file(System.getenv("ANDROID_KEYSTORE")) // ... } } }Local CI Parity
scripts/ci_local.sh— runs full test suite locally with--skip-dockeroption1.8.x) and new (17.x) Java version formatsLegacy Workflow
build-release.yamlmarked deprecated with migration docscontents: readWarning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
jitpack.io/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.9-all/6m0mbzute7p0zdleavqlib88a/gradle-8.9/lib/gradle-daemon-main-8.9.jar -javaagent:/home/REDACTED/.gradle/wrapper/dists/gradle-8.9-all/6m0mbzute7p0zdleavqlib88a/gradle-8.9/lib/agents/gradle-instrumentation-agent-8.9.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 8.9(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
Your task is to overhaul the current CI pipeline to ensure a modern CI experience so developers can write code with confidence. You should follow best practices & write idiomatic code as you make edits to the codebase following the attached design docs.
Title
CI Overhaul: Comprehensive Test Coverage + Secure, Efficient Android Build/Release Pipelines
Author / Reviewers
Background
Our current GitHub Actions workflow (
build-release.yml) builds and publishes an Android APK but does not run tests. The repository contains unit, integration, and end-to-end (E2E) tests, but some may be outdated or inconsistent with current code.This project will (1) bring tests up to date, (2) ensure they run locally, and (3) integrate them into CI using separate workflows that enforce separation of concerns and minimal privilege.
Goals
Non-goals
Current state (as-is)
build-release.yml:master../gradlew app:assembleRelease, creates a prerelease GitHub Release, uploadsapp-release.apk.contents: writepermissions for the whole job, and accesses signing secrets during build.Key issues:
Proposed solution overview
Introduce three workflows with clear responsibility boundaries:
CI: Tests (
ci-tests.yml)Runs unit + integration + E2E tests on PRs and pushes. Minimal permissions (
contents: read). Uses service containers / Docker Compose where needed.CI: Build (Unsigned) (
ci-build.yml)Builds unsigned artifacts (debug/release) and uploads them as artifacts for downstream jobs. Minimal permissions (
contents: read). No signing secrets.Release: Sign + Publish (
release.yml)Runs only on tagged commits (or manual dispatch) and depends on tests (and optionally build artifacts). Has the narrowest elevated permissions required (e.g.,
contents: writeonly in the release job). Signing secrets are only exposed in the signing step/job, preferably behind protected environments.Detailed plan
1) Test inventory and remediation
Identify and standardize how tests are invoked:
./gradlew test(or module-specific tasks like:app:testDebugUnitTest)integrationTest,testIntegration, etc.). If these exist but are inconsistent, consolidate on a single naming scheme.connectedAndroidTest(requires emulator) orfirebaseTestLab(out of scope unless already used)../gradlew e2eTestor./scripts/e2e.sh).Remediation expectations:
2) Local validation requirements
Engineers must be able to run the full suite locally (including Docker-required tests) from a clean checkout.
Define a single “local CI parity” entrypoint, for example:
./scripts/ci_local.shrunning:./gradlew --no-daemon clean testdocker compose up -d(only if E2E/integration requires it)./gradlew --no-daemon integrationTest(or equivalent)./gradlew --no-daemon e2eTest(or equivalent)docker compose down -vDocument prerequisites:
3) CI workflow design (separation + minimal privilege)
A)
ci-tests.yml(PR gating)Triggers:
pull_requesttomasterpushtomaster(optional, but recommended to keepmasterhonest)Permissions:
contents: readonly...
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.