diff options
| author | Danilo M. <danix@danix.xyz> | 2026-11-02 13:42:58 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-11-02 13:42:58 +0100 |
| commit | 36af7af9f646207dfe6774f91b53b5ccf8d288c2 (patch) | |
| tree | 6e183b3ef0efee27bb75fd087e2f1a8639180a69 | |
| parent | db49c998c7746812f78c6d7b8d2ae5cbb6bb25bc (diff) | |
| download | HardenedPass-36af7af9f646207dfe6774f91b53b5ccf8d288c2.tar.gz HardenedPass-36af7af9f646207dfe6774f91b53b5ccf8d288c2.zip | |
ci: sign and publish HardenedPass releases with the fork's own key
Add the fork's release keystore and its signing properties, encrypted
with openssl (aes-256-cbc, pbkdf2) as secrets/keystore.cipher and
secrets/props.cipher; the key is the ENCRYPT_KEY repository secret.
The plaintext files and the master copy never enter the repository.
Rewrite deploy_github_releases.yml for the single FOSS build: on a
vX.Y.Z tag it decrypts the signing secrets, builds the signed release
APK, removes the secrets, and creates a draft GitHub Release with
HardenedPass_<tag>.apk and its SHA-256 checksum using gh, replacing
the archived actions/create-release and upload-release-asset actions.
AGENTS.md records the certificate fingerprint and the procedure.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | .github/workflows/deploy_github_releases.yml | 126 | ||||
| -rw-r--r-- | AGENTS.md | 17 | ||||
| -rw-r--r-- | secrets/keystore.cipher | bin | 0 -> 4288 bytes | |||
| -rw-r--r-- | secrets/props.cipher | bin | 0 -> 176 bytes |
4 files changed, 33 insertions, 110 deletions
diff --git a/.github/workflows/deploy_github_releases.yml b/.github/workflows/deploy_github_releases.yml index 8dbdbcf5..5c5ea147 100644 --- a/.github/workflows/deploy_github_releases.yml +++ b/.github/workflows/deploy_github_releases.yml @@ -1,127 +1,41 @@ -name: Publish APS binaries to GitHub Releases +name: Publish HardenedPass to GitHub Releases on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' jobs: - build: - name: Build release binaries + release: + name: Build and publish signed release runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Setup build environment uses: danixland/Android-Password-Store/.github/reusable-workflows/setup-gradle@master - - name: Decrypt secrets + - name: Decrypt signing secrets shell: bash run: scripts/signing-setup.sh "$ENCRYPT_KEY" env: ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }} - - name: Build release binaries + - name: Build signed release APK shell: bash - run: ./gradlew :app:assembleFreeRelease :app:assembleNonFreeRelease :app:bundleNonFreeRelease - env: - SENTRY_DSN: ${{ secrets.SENTRY_DSN }} - - - name: Upload non-free release APK - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: APS Non-Free Release APK - path: app/build/outputs/apk/nonFree/release/app-nonFree-release.apk - - - name: Upload non-free release Bundle - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: APS Non-Free Release Bundle - path: app/build/outputs/bundle/nonFreeRelease/app-nonFree-release.aab + run: ./gradlew :app:assembleRelease - - name: Upload free release APK - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: APS Free Release APK - path: app/build/outputs/apk/free/release/app-free-release.apk - - - name: Clean secrets + - name: Clean signing secrets if: "${{ always() }}" run: scripts/signing-cleanup.sh - create_github_release: - name: Create GitHub Release - runs-on: ubuntu-latest - needs: build - steps: - - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - - - name: Get Non-Free Release APK - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: APS Non-Free Release APK - path: artifacts/nonFree - - - name: Get Non-Free Bundle - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: APS Non-Free Release Bundle - path: artifacts/nonFree - - - name: Get Free Release APK - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: APS Free Release APK - path: artifacts/free - - - name: Get Changelog Entry - id: changelog_reader - uses: mindsers/changelog-reader-action@32aa5b4c155d76c94e4ec883a223c947b2f02656 # v2.2.3 - with: - version: ${{ github.ref }} - path: ./CHANGELOG.md - - - name: Create Release - id: create_release - uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e # v1.1.4 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - body: ${{ steps.changelog_reader.outputs.changes }} - draft: true - prerelease: false - - - name: Get the version - id: get_version - shell: bash - run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT - - - name: Upload Non-Free Release Apk - uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./artifacts/nonFree/app-nonFree-release.apk - asset_name: APS-nonFree_${{ steps.get_version.outputs.VERSION }}.apk - asset_content_type: application/vnd.android.package-archive - - - name: Upload Non-Free Release Bundle - uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./artifacts/nonFree/app-nonFree-release.aab - asset_name: APS-nonFree_${{ steps.get_version.outputs.VERSION }}.aab - asset_content_type: application/octet-stream - - - name: Upload Free Release Apk - uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./artifacts/free/app-free-release.apk - asset_name: APS-free_${{ steps.get_version.outputs.VERSION }}.apk - asset_content_type: application/vnd.android.package-archive + - name: Create draft release + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + run: | + apk="HardenedPass_${TAG}.apk" + cp app/build/outputs/apk/release/app-release.apk "$apk" + sha256sum "$apk" > "$apk.sha256" + gh release create "$TAG" "$apk" "$apk.sha256" --draft --title "$TAG" \ + --notes "See [CHANGELOG.md](https://github.com/${GITHUB_REPOSITORY}/blob/${TAG}/CHANGELOG.md)." @@ -143,7 +143,16 @@ Last run: 2026-11-02. ## Releases -Not set up yet. Upstream's encrypted signing keystore was removed (only upstream could decrypt -it). `deploy_github_releases.yml` needs a keystore of our own, encrypted with -`scripts/encrypt-secret.sh` into `secrets/`, and the `ENCRYPT_KEY` secret. A different signing -key means the APK cannot update over upstream's install while `applicationId` is unchanged. +Signed with the maintainer's own key (certificate `CN=HardenedPass`, SHA-256 +`72:50:16:66:9E:48:2F:9A:C3:71:DE:E8:DF:19:A2:A1:B3:4F:A7:6D:1A:F0:5B:2A:23:78:47:25:B1:B4:9C:83`). +The master copy lives outside the repo, never in it. Losing it means installed copies can never +be updated again. + +- Local: `keystore.jks` and `keystore.properties` at the repo root (gitignored, `/keystore.*`) + make `./gradlew :app:assembleRelease` produce a signed `app-release.apk`. +- CI: `secrets/keystore.cipher` and `secrets/props.cipher` are those two files encrypted with + `openssl enc -aes-256-cbc -md sha256 -pbkdf2`; the key is the `ENCRYPT_KEY` repository + secret. `scripts/signing-setup.sh` decrypts them, `signing-cleanup.sh` deletes them. +- Pushing a `vX.Y.Z` tag runs `deploy_github_releases.yml`: it builds the signed APK and creates + a draft GitHub Release with `HardenedPass_vX.Y.Z.apk` and its `.sha256`. +- Never print, log or commit the keystore password or `ENCRYPT_KEY`. diff --git a/secrets/keystore.cipher b/secrets/keystore.cipher Binary files differnew file mode 100644 index 00000000..999cf521 --- /dev/null +++ b/secrets/keystore.cipher diff --git a/secrets/props.cipher b/secrets/props.cipher Binary files differnew file mode 100644 index 00000000..4afdd22b --- /dev/null +++ b/secrets/props.cipher |
