Skip to content

Conversation

Copy link

Copilot AI commented Dec 18, 2025

Implements the design doc's secure signing architecture with key isolation between untrusted PR builds and production releases. Renames package to org.joefang.webdav and adds fork attribution.

Signing Architecture

  • build.yml: Unsigned builder, no secrets access
  • sign-test.yml: Signs PR builds via ci:test environment (test key)
  • sign-release.yml: Signs main/tags via ci:release environment (release key)
  • Deprecated legacy workflows (build-release.yaml, ci-build.yml, release.yml)

Package & Flavors

  • Renamed dev.rocli.android.webdavorg.joefang.webdav
  • Added product flavors:
    • prodorg.joefang.webdav
    • untrustedorg.joefang.webdav.test (side-by-side installation)

Version Naming

Build Type Format Example
Release v{M}.{m}.{p} v5.4.3
Pre-release v{M}.{m}.{p}-dev.{count}+{sha} v5.4.4-dev.42+a1b2c3d
Test ci-test-untrusted-{M}.{m}.{p}-dev.{count}+{sha} ci-test-untrusted-5.4.4-dev.42+a1b2c3d

Documentation

  • README: Fork attribution to alexbakker/webdav-provider, no compatibility guarantee
  • VERSIONING.md: Complete signing architecture, key generation, environment setup
Original prompt

Your task is to ensure the CI/CD binary signing flow completely conforms to the new standard. Note that the current CI/CD flow already conforms to the standard reasonably well and handles the major.minor.patch+commit_since logic correctly, but there are still some discrepencies in details (e.g. how the version names are formatted). I want you to work on the conformace to bring this CI/CD pipeline in line with the best practices. Please follow best practices and write idiomatic code, and ensure the signing keys for untrusted test binaries are completely separate from the signing keys for pre-releases and releases. Please also ensure you upload untrusted but signed test binaries to Actions artifacts so our testers can download and install them to test out. Note that since we have implemented this isolation, the untrusted binaries can be signed without maintainer's approval and automatically generated for every PR so we can more efficiently test out, but please make it very clear in the docs/ that thest ".test" variants are untrusted by us and are signed for convenience of tests using a separate keypair.

In the meantime, since we have made significant changes to the original project that we don't intend to maintain any kind of compatibility with the original project, I want you to rename the android package name to org.joefang.webdav (and org.joefang.webdav.test for the untrusted test binaries) and revamp the current Gradle scripts to bring them in line with best practices and idiomatic configurations. Also make the documentation very clear that we have forked from where, and attribute the original author (keep a link to the original repo) while making it very clear we are a separate project with a different package name with no compatibility guaranteed.

Design Doc: Secure Android CI/CD Signing & Versioning Architecture

1. Objective

Establish a unified, secure signing pipeline across Android projects that:

  1. Protects Signing Keys: Isolates keys in protected GitHub Environments (ci:test, ci:release) so untrusted PR code never accesses them.
  2. Differentiates Builds: clearly distinguishes Test (PRs), Pre-release (Main), and Release (Tags) via specific package names and versioning strings.
  3. Ensures Co-installation: Allows Test APKs (.test) to exist alongside Production APKs.

2. Infrastructure & Key Management

2.1. GitHub Environments

Create two environments per repository to segregate access:

Environment Purpose Key Usage Protection Rules
ci:test Signing untrusted PR builds. Test Key Branches: No restriction.
Reviewers: None (Automated).
ci:release Signing Main/Tags builds. Release Key Branches: main, v*.
Reviewers: Recommended.

2.2. Key Generation Standard

To ensure alignment, generate keys for each environment using the exact commands below.

  • Variables: ANDROID_KEYSTORE_B64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS.
  • Validity: 1,048,576 days (~2800 years) as requested.
# 1. Generate Keypair (Run locally, DO NOT commit .jks)
# Replace 'test' with 'release' for the production key
export ANDROID_KEY_ALIAS="test" 
export ANDROID_KEYSTORE_PASSWORD="<your-strong-password>"
export KEYSTORE_FILE="project-test.jks"

keytool -genkeypair -v \
  -keystore "$KEYSTORE_FILE" \
  -storetype JKS \
  -alias "$ANDROID_KEY_ALIAS" \
  -keyalg RSA \
  -keysize 4096 \
  -validity 1048576 \
  -storepass "$ANDROID_KEYSTORE_PASSWORD" \
  -keypass "$ANDROID_KEYSTORE_PASSWORD" \
  -dname "CN=$ANDROID_KEY_ALIAS,O=YourOrg,OU=Mobile,L=Toronto,ST=Ontario,C=CA"

# 2. Base64 Encode for GitHub Secret
base64 -w 0 "$KEYSTORE_FILE" > "${KEYSTORE_FILE}.b64"

3. Project Configuration (Gradle)

3.1. Build Variants (Co-installation)

In app/build.gradle.kts, define flavors so the test app has a distinct applicationId.

android {
    namespace = "org.joefang.letterbox" // Canonical Namespace
    defaultConfig {
        applicationId = "org.joefang.letterbox"
    }

    flavorDimensions += "env"
    productFlavors {
        create("prod") {
            dimension = "env"
            // Installs as: org.joefang.letterbox
        }
        create("test") {
            dimension = "env"
            // Installs as: org.joefang.letterbox.test
            applicationIdSuffix = ".test"
        }
    }
}

3.2. Versioning Strategy

Implement dynamic versioning in app/build.gradle.kts. This enforces the "untrusted" naming convention for test builds.

// Load base version from file
val versionProps = Properties().apply {
    load(file("../version.properties").reader()) // Contains MAJOR=1, MINOR=2, PATCH=3
}
val major = versionProps["MAJOR"]
val minor = versionProps["MINOR"]
val patch = versionProps["PATCH"]

// Determine context from Env Var set by CI
val ciBuildType = System.getenv("CI_BUILD_TYPE") ?: "local"

// H...

</details>



<!-- START COPILOT CODING AGENT TIPS -->
---Let Copilot coding agent [set things up for you](https://github.com/BTreeMap/WebDAV/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Ensure CI/CD binary signing flow conforms to new standard Implement secure CI/CD signing architecture with separate test/release environments Dec 18, 2025
Copilot AI requested a review from MinecraftFuns December 18, 2025 03:32
@MinecraftFuns MinecraftFuns marked this pull request as ready for review December 18, 2025 03:42
@MinecraftFuns MinecraftFuns merged commit 42c1b11 into master Dec 18, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants