From cbb66ea1887f692b5e74b0ed686b64a0f6f28aab Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Thu, 24 Sep 2026 19:38:04 -0400 Subject: [PATCH] chore: harden release signing boundaries --- .github/workflows/build.yml | 11 +++++------ .github/workflows/release.yml | 4 ++-- .github/workflows/sign.yml | 6 ++---- tools/release/make-release-key.sh | 8 ++++---- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b2377bf6d..607cd6d49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,6 +55,7 @@ env: jobs: build: + name: Build APK if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }} runs-on: ubuntu-24.04 timeout-minutes: 45 @@ -498,20 +499,18 @@ jobs: # An apk is a zip already; compressing it again buys nothing and costs seconds. compression-level: 0 - # The apk signed with DroidDeck's own key (tools/release), so a test build installs over a release - # and keeps its data. Main's builds sign straight away (signing-main); any other branch's wait for - # the owner's approval (signing-branch). A pull request's never: its code is not ours to sign, and - # the job that would hold the key never runs for it. The testkey apk above is unaffected. + # Only main is signed with DroidDeck's private key. Pull requests and other branches keep the + # public AOSP testkey build, so unreviewed branch code never gets access to the release key. sign: needs: build - if: github.event_name != 'pull_request' + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' # What sign.yml asks for; a called workflow never gets more than its caller gives it. permissions: contents: read actions: read uses: ./.github/workflows/sign.yml with: - environment: ${{ github.ref == 'refs/heads/main' && 'signing-main' || 'signing-branch' }} + environment: signing-main variants: '["standard"]' # The key is an environment secret; a called workflow sees secrets only when they are passed on. secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2106659c8..f9d705aed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,8 +4,8 @@ run-name: release ${{ inputs.version }} from main ${{ github.sha }} # Every package of a release, signed with DroidDeck's own key: the standard app and the named ones # in tools/release/variants.txt, one matrix job each. Nothing is rebuilt - the apk is the one the # Build APK run of this exact main commit made (with its caches) and that was tested, so the -# release is those bytes. Waits for the owner's approval (the release environment); publishing the -# GitHub release stays a separate, manual step. +# release is those bytes. This workflow is manually dispatched from main; publishing the GitHub +# release stays a separate, manual step. on: workflow_dispatch: diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index e1e649869..8f98ecc1e 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -4,10 +4,8 @@ name: Sign APKs # one matrix job per package in tools/release/variants.txt (tools/release/sign-apk.sh does the work # and checks it). The key lives only in the GitHub environment named by the caller: # signing-main builds of main -# signing-branch builds of any other branch - waits for the owner's approval -# release release.yml - main only, waits for the owner's approval -# Pull requests never get here (build.yml skips this for pull_request), so code from a pull -# request can never be signed with the key or come near it. +# release manually dispatched release.yml from main +# Pull requests and other branches never call this workflow with the release key. on: workflow_call: diff --git a/tools/release/make-release-key.sh b/tools/release/make-release-key.sh index 96d423ae1..cc1c24123 100755 --- a/tools/release/make-release-key.sh +++ b/tools/release/make-release-key.sh @@ -3,8 +3,8 @@ # # - The key is made on this device, in ~/droiddeck-release-key (outside the repo), with a long # random password written beside it. Nothing secret is printed. -# - The key and password go to GitHub as secrets of the three signing environments -# (signing-main, signing-branch, release). GitHub never shows a secret again. +# - The key and password go to GitHub as secrets of the two signing environments +# (signing-main and release). Branch builds and pull requests keep using the public test key. # - The key's certificate digest - public, not a secret - goes to keystore/release-signer.sha256, # which CI checks every signed apk against. That file is the only thing to commit. # @@ -12,8 +12,8 @@ # Without it no update can ever be signed for the people who installed a signed build. set -euo pipefail -REPO=The412Banner/DroidDeck -ENVIRONMENTS=(signing-main signing-branch release) +REPO=Droid-Deck/DroidDeck +ENVIRONMENTS=(signing-main release) ALIAS=droiddeck OUT=${DROIDDECK_KEY_DIR:-$HOME/droiddeck-release-key} here=$(cd "$(dirname "$0")" && pwd)