{"id":29687266,"url":"https://github.com/thepalaceproject/android-ci","last_synced_at":"2026-04-07T13:32:15.759Z","repository":{"id":44869306,"uuid":"367082212","full_name":"ThePalaceProject/android-ci","owner":"ThePalaceProject","description":"Helper scripts for Android App CI Builds","archived":false,"fork":false,"pushed_at":"2025-07-02T14:37:33.000Z","size":329,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-07-23T04:44:31.982Z","etag":null,"topics":["android","ci","mobile"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThePalaceProject.png","metadata":{"files":{"readme":"README-implementation.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-05-13T14:54:49.000Z","updated_at":"2025-07-02T14:37:37.000Z","dependencies_parsed_at":"2024-05-03T21:30:07.612Z","dependency_job_id":"f060f2a2-7b4c-4f85-b3fb-e39166198938","html_url":"https://github.com/ThePalaceProject/android-ci","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ThePalaceProject/android-ci","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThePalaceProject%2Fandroid-ci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThePalaceProject%2Fandroid-ci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThePalaceProject%2Fandroid-ci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThePalaceProject%2Fandroid-ci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThePalaceProject","download_url":"https://codeload.github.com/ThePalaceProject/android-ci/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThePalaceProject%2Fandroid-ci/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31515144,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","ci","mobile"],"created_at":"2025-07-23T04:36:30.894Z","updated_at":"2026-04-07T13:32:15.740Z","avatar_url":"https://github.com/ThePalaceProject.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# From Commits To Android Builds\n\n## Overview\n\nThis document attempts to describe the _continuous integration_ processes\nthat produce Android builds of the Palace application.\n\n## CI Scripts\n\nThe CI process is implemented entirely in plain [Bash](https://www.gnu.org/software/bash/),\nwith a strong emphasis on allowing developers to run the scripts on their local\nmachines for testing purposes. The scripts are maintained in a single\n[source repository](https://www.github.com/ThePalaceProject/android-ci) and are imported by all projects\nwishing to use them as a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules).\n\nThe main entry point into the script is the `ci-main.sh` script, and this\nis typically executed by a [GitHub Action](https://github.com/features/actions).\nCurrently, each repository defines an action to be executed on each authenticated\ncommit, and a separate action to be executed on pull requests.\n\n## CI Execution\n\nThe execution of the CI scripts can be divided into two phases: _building_\nand _deploying_. The _build_ phase compiles all of the code and runs the\ntest suite, and the _deploy_ phase uploads the produced binaries to various \ndifferent locations depending on the project-specific configuration.\nThe _deploy_ phase _only_ executes for authenticated commits (and not pull \nrequests), because deploying usually requires access to credentials and other \nsecrets, and a malicious pull request from a third party could steal those \nsecrets. GitHub actions have built-in protections against this, but the CI\nscripts are written in an CI-independent manner, and therefore keep \n\"executing with credentials\" and \"executing without credentials\" strictly\nseparated. Given that the execution of a build for a pull request is just\na subset of the execution of a build for an authenticated commit, this\ndocument only goes into detail for the authenticated case.\n\nThe full execution of the CI workflow is described by the following graph:\n\n![flow.png](flow.png)\n\n## Build\n\nThe _build_ phase requires little explanation: It simply executes a\nconventional `./gradlew clean assemble test` command to build the code\nand execute the test suite. A _credentials_ step is executed that is\nactually controlled by a small project-specific script; it's the responsibility\nof this script to copy credentials from an external credentials repository\nin to any required locations in the project sources before the build can\nproceed.\n\n## Deploy\n\nThe _deploy_ phase of the build is more complex and is explained over \nthe following sections.\n\n### -SNAPSHOT Versioning\n\nThe CI scripts expect projects to follow the Maven convention of having version\nnumbers that end in `-SNAPSHOT` denote volatile snapshot versions of\npackages. The artifacts for a snapshot version of a package can be updated\nand/or removed at any time. Snapshot versions are convenient during development,\nbut release versions should always be using non-snapshot versions (and, ideally,\nbe only using non-snapshot versions of any dependencies too).\n\nThe CI scripts read the _gradle.properties_ file in the root of the project\nbeing built, and extract a `VERSION_NAME` attribute from the properties. If\nthis version name ends with `-SNAPSHOT`, the build assumes that the package\nbeing built is a snapshot version, and adjusts the _deploy_ behaviour \naccordingly.\n\n### Tagged Commits\n\nIf the contents of the current commit are not a [snapshot version](#-snapshot-versioning),\nand the commit is [tagged](https://git-scm.com/book/en/v2/Git-Basics-Tagging),\nthen the CI scripts assume that the package being built should be _released_ \nformally, and adjusts the _deploy_ behaviour accordingly.\n\n### Neither -SNAPSHOT Nor Tag!\n\nIf the contents of the current commit are not a [snapshot version](#-snapshot-versioning),\nand the commit isn't [tagged](#tagged-commits), then the CI scripts assume \nthat someone made a mistake when committing and forgot to change the version\nnumber from the previous release. The CI scripts adjust their behaviour to\nonly perform a very minimal deployment.\n\n### Error Handling\n\nThe _deploy_ phase defers errors to the end of the build. If an individual\nstep (such as deploying to Maven Central) fails, then all of the steps that\nfollow will still be executed, but the build as a whole will be marked as failed\nat the end of the _deploy_ phase. The reason for this is that deployment\nnecessarily involves talking to a lot of external systems, and any of those\nsystems can fail at any time. If the build is allowed to continue in the\nface of errors, then this means that the build can be retried manually \nuntil all of the steps have succeeded.\n\nIn practice, it seems to be quite rare for any of the deploy steps to fail,\nas all of the external systems seem to be generally reliable.\n\n### Maven Central\n\nIff all the following are true:\n\n  * The contents of the current commit are a [snapshot version](#-snapshot-versioning)\n  * The project is configured to publish artifacts to Maven Central.\n\n... Then then the produced build artifacts are published to the Sonatype Snapshots \nrepository. This is a repository hosted in the same place as Maven Central, \nbut exclusively holds snapshot artifacts. This is node `S1` on the flow chart.\n\nIff all the following are true:\n\n  * The contents of the current commit are _not_ a [snapshot version](#-snapshot-versioning).\n  * The current commit is [tagged](#tagged-commits).\n  * The project is configured to publish artifacts to Maven Central.\n\n... Then the CI scripts use [brooklime](https://www.io7m.com/software/brooklime) \nto perform a full release staging process to Maven Central. This is node `S3` \non the flow chart.\n\n### Git Binaries\n\nThe CI scripts are able to (optionally) deploy binaries to a Git repository.\n\nIff all the following are true:\n\n  * The contents of the current commit are a [snapshot version](#-snapshot-versioning).\n  * The project is configured to publish artifacts to a Git repository. \n\n... Then the produced artifacts are published to the configured repository. This is\nnode `S2` on the flow chart.\n\nIff all the following are true:\n\n  * The contents of the current commit are _not_ a [snapshot version](#-snapshot-versioning).\n  * The current commit is [tagged](#tagged-commits).\n  * The project is configured to publish artifacts to a Git repository.\n\n... Then the produced artifacts are published to the configured repository. This is\nnode `S4` on the flow chart.\n\n### Fastlane (Play Store)\n\nThe CI process optionally uses [Fastlane](https://fastlane.tools/) to deploy\napplication builds to the [Play Store](https://play.google.com/store).\n\nIff all the following are true:\n\n  * The contents of the current commit are _not_ a [snapshot version](#-snapshot-versioning).\n  * The current commit is [tagged](#tagged-commits).\n  * The project is configured to publish one or more applications using Fastlane.\n\n... Then the CI scripts will install Fastlane locally, and use it to stage a\nrelease of the application to the Play Store. Specifically, the scripts will\nupload to the _alpha_ (closed testing) track. This requires a developer to\ngo into the [Play Console](https://play.google.com/console) and manually\nclick \"Deploy To Production\". This is node `S5` on the flow chart.\n\nDeploying an application to the Play Store requires including _release notes_.\nThe current applications use [changelog](https://www.io7m.com/software/changelog/)\nto maintain a `README-CHANGES.xml` file in each project. The build system\nautomatically generates release notes for the store from this file.\n\nDeploying an application to the Play Store using Fastlane requires a private\nkey in JSON format, obtained from the Play Console. It also requires API\nAccess to be enabled in the Play Console. Only the owner of the Play Store\naccount is able to enable/disable API access. See the\n[Fastlane setup documentation](https://docs.fastlane.tools/getting-started/android/setup/)\nfor information on how these credentials are received. The CI process automates\nall the setup steps except for the credentials retrieval. Projects are\nexpected to copy the required JSON key into the correct location at the\n[start of the build](#build).\n\n### Firebase\n\nThe CI process optionally uses [Firebase](https://firebase.google.com/) to deploy\napplication builds to an online repository for testing and QA.\n\nIff all of the following are true:\n\n  * The project is configured to publish one or more applications using Firebase.\n\n... Then the CI scripts will install Firebase locally, and use it to publish APK\nand/or AAB files. Note that this is the only deployment step that doesn't\ncare about whether a build is a snapshot version, a tagged commit, or something\nelse. This is node `S6` on the flow chart.\n\nDeploying an application to Firebase requires including _release notes_.\nThe current applications use [changelog](https://www.io7m.com/software/changelog/)\nto maintain a `README-CHANGES.xml` file in each project. The build system\nautomatically generates release notes from this file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthepalaceproject%2Fandroid-ci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthepalaceproject%2Fandroid-ci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthepalaceproject%2Fandroid-ci/lists"}