Loading .github/workflows/daily_builds.yml +2 −0 Original line number Diff line number Diff line Loading @@ -9,3 +9,5 @@ jobs: trigger_daily_build: uses: ./.github/workflows/shippable_builds.yml secrets: inherit permissions: contents: write .github/workflows/shippable_builds.yml +230 −22 Original line number Diff line number Diff line Loading @@ -10,6 +10,9 @@ on: skipK9Mail: type: boolean description: Skip building K-9 Mail skipTests: type: boolean description: Skip running tests skipBetaBump: type: boolean description: Skip version bump (beta) Loading Loading @@ -62,6 +65,10 @@ jobs: releaseType: ${{ vars.RELEASE_TYPE }} skipThunderbird: ${{ inputs.skipThunderbird }} skipK9Mail: ${{ inputs.skipK9Mail }} skipTests: ${{ inputs.skipTests }} skipBetaBump: ${{ inputs.skipBetaBump }} skipGooglePlay: ${{ inputs.skipGooglePlay }} draftGooglePlay: ${{ inputs.draftGooglePlay }} with: script: | let matrix = JSON.parse(process.env.matrixInclude); Loading Loading @@ -105,13 +112,60 @@ jobs: .write(); if (skipThunderbird) { await core.summary.addList(["Thunderbird is being skipped in this build"]).write(); await core.summary.addList(["Thunderbird build is being skipped"]).write(); } if (skipK9Mail) { await core.summary.addList(["K-9 Mail is being skipped in this build"]).write(); await core.summary.addList(["K-9 Mail build is being skipped"]).write(); } if (process.env.skipTests == "true") { await core.summary.addList(["Tests are being skipped"]).write(); } if (process.env.skipBetaBump == "true" && process.env.releaseType == "beta") { await core.summary.addList(["Beta bump is being skipped"]).write(); } if (process.env.skipGooglePlay == "true") { await core.summary.addList(["Play Store upload is being skipped"]).write(); } if (process.env.skipGooglePlay != "true" && process.env.draftGooglePlay == "true") { await core.summary.addList(["Play Store upload is being kept in the draft state"]).write(); } notify_build_start: name: Notify Build Start runs-on: ubuntu-latest needs: [dump_config] if: ${{ needs.dump_config.outputs.releaseType == 'beta' || needs.dump_config.outputs.releaseType == 'release' }} environment: notify_matrix outputs: actorLink: ${{ steps.actorLink.outputs.actorLink }} steps: - name: Triggering Actor Link id: actorLink uses: actions/github-script@v7 env: userMap: ${{ vars.MATRIX_NOTIFY_USER_MAP }} with: script: | let userMap = JSON.parse(process.env.userMap || "{}"); if (Object.hasOwn(userMap, context.actor)) { let mxid = userMap[context.actor]; core.setOutput("actorLink", `[${mxid}](https://matrix.to/#/${mxid})`); } else { core.setOutput("actorLink", `[@${context.actor}](https://github.com/${context.actor})`); } - name: Notify Build Start if: ${{ vars.MATRIX_NOTIFY_ROOM }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🔵 [${{ vars.RELEASE_TYPE }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) was started by ${{ steps.actorLink.outputs.actorLink }} release_commit: name: Release Bumps runs-on: ubuntu-latest Loading @@ -126,6 +180,8 @@ jobs: outputs: k9mail_sha: ${{ steps.commit.outputs.k9mail_sha }} thunderbird_sha: ${{ steps.commit.outputs.thunderbird_sha }} k9mail_github_notes: ${{ steps.render_notes.outputs.k9mail_github_notes }} thunderbird_github_notes: ${{ steps.render_notes.outputs.thunderbird_github_notes }} steps: - name: Checkout repository if: ${{ contains(matrix.releaseTarget, 'github') }} Loading Loading @@ -203,18 +259,30 @@ jobs: cat $GITHUB_OUTPUT - name: Render Release Notes id: render_notes if: ${{ contains(matrix.releaseTarget, 'github') }} shell: bash env: APP_NAME: ${{ matrix.appName }} APPLICATION_ID: ${{ steps.appinfo.outputs.APPLICATION_ID }} APPLICATION_LABEL: ${{ steps.appinfo.outputs.APPLICATION_LABEL }} VERSION_CODE: ${{ steps.bump_version_code.outputs.CODE }} FULL_VERSION_NAME: ${{ steps.appinfo.outputs.VERSION_NAME }}${{ steps.bump_version_suffix.outputs.SUFFIX || steps.appinfo.outputs.VERSION_NAME_SUFFIX }} run: | echo "<h2>${APPLICATION_LABEL} ${FULL_VERSION_NAME} Release Notes (${VERSION_CODE})</h2><pre>" | tee -a $GITHUB_STEP_SUMMARY mkdir -p ./app-metadata/${APPLICATION_ID}/en-US/changelogs python ./scripts/render-notes.py ${APPLICATION_ID} ${FULL_VERSION_NAME} ${VERSION_CODE} | tee -a $GITHUB_STEP_SUMMARY echo "</pre>" | tee -a $GITHUB_STEP_SUMMARY GITHUB_NOTES_FILE="$(mktemp -d)/long-notes.txt" python ./scripts/render-notes.py ${APPLICATION_ID} ${FULL_VERSION_NAME} ${VERSION_CODE} ${GITHUB_NOTES_FILE} echo "${APP_NAME}_github_notes<<EOF" >> $GITHUB_OUTPUT cat $GITHUB_NOTES_FILE >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "<h2>${APPLICATION_LABEL} ${FULL_VERSION_NAME} Release Notes (${VERSION_CODE})</h2>" | tee -a $GITHUB_STEP_SUMMARY echo -e "Summarized Version Notes\n\n\`\`\`" | tee -a $GITHUB_STEP_SUMMARY cat ./app-metadata/${APPLICATION_ID}/en-US/changelogs/${VERSION_CODE}.txt | tee -a $GITHUB_STEP_SUMMARY echo -e "\n\`\`\`\n\nLong Version Notes\n\n\`\`\`" | tee -a $GITHUB_STEP_SUMMARY cat $GITHUB_NOTES_FILE | tee -a $GITHUB_STEP_SUMMARY echo -e "\`\`\`" | tee -a $GITHUB_STEP_SUMMARY - name: Validate Release Notes Length if: ${{ contains(matrix.releaseTarget, 'github') }} Loading Loading @@ -299,6 +367,7 @@ jobs: name: Build Unsigned runs-on: ubuntu-latest timeout-minutes: 90 if: ${{ !failure() && !cancelled() }} # Run if release_commit is skipped needs: [dump_config, get_environment, release_commit] strategy: matrix: Loading @@ -316,6 +385,7 @@ jobs: case "${APP_NAME}" in thunderbird) APP_SHA=$THUNDERBIRD_SHA ;; k9mail) APP_SHA=$K9MAIL_SHA ;; *) APP_SHA=$GITHUB_SHA ;; esac echo "app_sha=$APP_SHA" >> $GITHUB_OUTPUT Loading Loading @@ -361,6 +431,11 @@ jobs: ./gradlew clean :app-${APP_NAME}:${BUILD_COMMAND} --no-build-cache --no-configuration-cache echo "Status: $?" - name: Test It if: ${{ !inputs.skipTests }} shell: bash run: ./gradlew testsOnCi - name: Move apps to upload directory shell: bash env: Loading Loading @@ -413,11 +488,12 @@ jobs: sign_mobile: name: Sign Packages runs-on: ubuntu-latest if: ${{ !failure() && !cancelled() }} # Run if previous step is skipped needs: [build_unsigned, dump_config] strategy: matrix: include: "${{ fromJSON(needs.dump_config.outputs.matrixInclude) }}" environment: ${{ matrix.appName }}_${{ needs.dump_config.outputs.releaseType }}_${{ matrix.packageFlavor || 'default' }} needs: [build_unsigned, dump_config] env: RELEASE_TYPE: ${{ needs.dump_config.outputs.releaseType }} steps: Loading Loading @@ -458,6 +534,22 @@ jobs: uploads/*.apk uploads/*.aab notify_pre_publish: name: Notify Publish Approval needs: [dump_config, sign_mobile, notify_build_start] if: ${{ needs.dump_config.outputs.releaseType == 'beta' || needs.dump_config.outputs.releaseType == 'release' }} runs-on: ubuntu-latest environment: notify_matrix steps: - uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🟡 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) waiting for publish approval (triggered by ${{ needs.notify_build_start.outputs.actorLink }}) pre_publish: # This is a holding job meant to require approval before proceeding with the publishing jobs below # The environment has a deployment protection rule requiring approval from a set of named reviewers Loading @@ -482,6 +574,11 @@ jobs: matrix: include: "${{ fromJSON(needs.dump_config.outputs.matrixInclude) }}" environment: publish_release outputs: thunderbird_release_url: ${{ steps.summary.outputs.thunderbird_release_url }} k9mail_release_url: ${{ steps.summary.outputs.k9mail_release_url }} thunderbird_full_version_name: ${{ steps.summary.outputs.thunderbird_full_version_name }} k9mail_full_version_name: ${{ steps.summary.outputs.k9mail_full_version_name }} env: RELEASE_TYPE: ${{ needs.dump_config.outputs.releaseType }} APP_NAME: ${{ matrix.appName }} Loading Loading @@ -556,20 +653,24 @@ jobs: app-id: ${{ vars.RELEASER_APP_CLIENT_ID }} private-key: ${{ secrets.RELEASER_APP_PRIVATE_KEY }} - name: Get release sha id: sha - name: Get release sha and notes id: shanotes shell: bash env: THUNDERBIRD_GITHUB_NOTES: ${{ needs.release_commit.outputs.thunderbird_github_notes }} K9MAIL_GITHUB_NOTES: ${{ needs.release_commit.outputs.k9mail_github_notes }} THUNDERBIRD_SHA: ${{ needs.release_commit.outputs.thunderbird_sha }} K9MAIL_SHA: ${{ needs.release_commit.outputs.k9mail_sha }} APP_NAME: ${{ matrix.appName }} run: | case "${APP_NAME}" in thunderbird) APP_SHA=$THUNDERBIRD_SHA ;; k9mail) APP_SHA=$K9MAIL_SHA ;; esac app_sha_name=${APP_NAME^^}_SHA echo "app_sha=${!app_sha_name}" >> $GITHUB_OUTPUT app_relnotes_name=${APP_NAME^^}_GITHUB_NOTES echo "app_github_notes<<EOF" >> $GITHUB_OUTPUT echo "${!app_relnotes_name}" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "app_sha=$APP_SHA" >> $GITHUB_OUTPUT cat $GITHUB_OUTPUT - name: Publish to GitHub Releases Loading @@ -578,9 +679,10 @@ jobs: uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 with: token: ${{ steps.app-token.outputs.token || github.token }} target_commitish: ${{ steps.sha.outputs.app_sha }} target_commitish: ${{ steps.shanotes.outputs.app_sha }} tag_name: ${{ steps.pkginfo.outputs.TAG_NAME }} name: ${{ steps.pkginfo.outputs.FULL_VERSION_NAME }} body: ${{ steps.shanotes.outputs.app_github_notes }} prerelease: ${{ env.RELEASE_TYPE != 'release' }} fail_on_unmatched_files: true files: | Loading @@ -593,7 +695,7 @@ jobs: VERSION_CODE: ${{ steps.pkginfo.outputs.VERSION_CODE }} APPLICATION_ID: ${{ steps.pkginfo.outputs.APPLICATION_ID }} REPO: ${{ github.repository }} APP_SHA: ${{ steps.sha.outputs.app_sha }} APP_SHA: ${{ steps.shanotes.outputs.app_sha }} run: | # r0adkll/upload-google-play expects the release notes in a different structure FILEPATH=app-metadata/${APPLICATION_ID}/en-US/changelogs/${VERSION_CODE}.txt Loading @@ -617,30 +719,136 @@ jobs: - name: Summary uses: actions/github-script@v7 id: summary env: tagName: ${{ steps.pkginfo.outputs.TAG_NAME }} fullVersionName: ${{ steps.pkginfo.outputs.FULL_VERSION_NAME }} ghReleaseUrl: ${{ steps.publish_gh.outputs.url }} playTargetTrack: ${{ matrix.playTargetTrack }} applicationId: ${{ steps.pkginfo.outputs.APPLICATION_ID }} app_sha: ${{ steps.sha.outputs.app_sha }} releaseTarget: ${{ matrix.releaseTarget }} appSha: ${{ steps.shanotes.outputs.app_sha }} appName: ${{ matrix.appName }} skipGooglePlay: ${{ inputs.skipGooglePlay }} with: script: | await core.summary .addHeading(`${process.env.fullVersionName} (${process.env.applicationId})`, 2) .addRaw(`Tag ${process.env.tagName} at `) .addLink(process.env.app_sha, `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.app_sha}`) .addEOL() .write(); core.setOutput(`${process.env.appName}_full_version_name`, process.env.fullVersionName); if (process.env.ghReleaseUrl) { if (!process.env.releaseTarget) { await core.summary .addRaw(`Artifact-only build at `) .addLink(process.env.appSha, `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.appSha}`) .addEOL() .write(); } else if (process.env.ghReleaseUrl) { await core.summary .addRaw(`Tag ${process.env.tagName} at `) .addLink(process.env.appSha, `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.appSha}`) .addEOL() .addRaw(`Released to Github at `) .addLink(process.env.ghReleaseUrl, process.env.ghReleaseUrl) .addEOL() .write(); core.setOutput(`${process.env.appName}_release_url`, process.env.ghReleaseUrl); } if (process.env.playTargetTrack) { if (process.env.skipGooglePlay != "true" && process.env.playTargetTrack && process.env.releaseTarget.includes("play")) { await core.summary.addRaw(`Released to the <b>${process.env.playTargetTrack}</b> track on Google Play`, true).write(); } notify_build_result: name: Notify Build Result if: ${{ always() }} needs: [dump_config, release_commit, build_unsigned, sign_mobile, publish_release, notify_build_start] runs-on: ubuntu-latest environment: notify_matrix steps: - name: Get previous workflow status uses: Mercymeilya/last-workflow-status@3418710aefe8556d73b6f173a0564d38bcfd9a43 id: last_status with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Info uses: actions/github-script@v7 id: info env: needs: ${{ toJSON(needs) }} with: script: | let needs = JSON.parse(process.env.needs); let failures = []; for (let [job, need] of Object.entries(needs)) { if (need.result == 'failure') { failures.push(job.replace(/([-_])/g, "\\$1")); } } core.setOutput("fail_steps", failures.join(`, `)); - name: Notify Failure if: ${{ vars.MATRIX_NOTIFY_ROOM && contains(needs.*.result, 'failure') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🔴 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) has failed at step ${{ steps.info.outputs.fail_steps }} (triggered by ${{ needs.notify_build_start.outputs.actorLink }}) - name: Notify Cancelled if: ${{ vars.MATRIX_NOTIFY_ROOM && !contains(needs.*.result, 'failure') && contains(needs.*.result, 'cancelled') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- ⚪ [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) was cancelled - name: Notify Success (Beta/Release) if: ${{ vars.MATRIX_NOTIFY_ROOM && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && (needs.dump_config.outputs.releaseType == 'beta' || needs.dump_config.outputs.releaseType == 'release') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🟢 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) has succeeded (triggered by ${{ needs.notify_build_start.outputs.actorLink }}) - name: Thunderbird Publish URL (Beta/Release) if: ${{ vars.MATRIX_NOTIFY_ROOM && needs.publish_release.outputs.thunderbird_release_url && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- ${{ needs.publish_release.outputs.thunderbird_full_version_name }} [is available](${{ needs.publish_release.outputs.thunderbird_release_url }}) - name: K-9 Mail Publish URL (Beta/Release) if: ${{ vars.MATRIX_NOTIFY_ROOM && needs.publish_release.outputs.k9mail_release_url && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- ${{ needs.publish_release.k9mail_full_version_name }} [is available](${{ needs.publish_release.outputs.k9mail_release_url }}) - name: Notify Success (Daily) if: ${{ vars.MATRIX_NOTIFY_ROOM && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && needs.dump_config.outputs.releaseType == 'daily' && steps.last_status.outputs.last_status == 'failure' }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🟢 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) has recovered .gitignore +0 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ out/ # IDEA/Android Studio includes !.idea/icon.png !.idea/codeStyles/ !.idea/inspectionProfiles/ !.idea/fileTemplates/ # Android Studio captures folder Loading README.md +45 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes app-k9mail/badging/release-badging.txt +2 −3 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ uses-permission: name='android.permission.WAKE_LOCK' uses-permission: name='android.permission.FOREGROUND_SERVICE' uses-permission: name='android.permission.FOREGROUND_SERVICE_DATA_SYNC' uses-permission: name='android.permission.SCHEDULE_EXACT_ALARM' uses-permission: name='android.permission.CAMERA' uses-permission: name='android.permission.USE_BIOMETRIC' uses-permission: name='android.permission.USE_FINGERPRINT' uses-permission: name='com.fsck.k9.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION' Loading Loading @@ -54,6 +53,7 @@ application-label-lv:'K-9 pasts' application-label-ml:'K-9 Mail' application-label-nb:'K-9 e-post' application-label-nl:'K-9 Mail' application-label-nn:'K-9 e-post' application-label-pl:'K-9 Mail' application-label-pt:'K-9 Mail' application-label-pt-BR:'K-9 Mail' Loading Loading @@ -84,7 +84,6 @@ launchable-activity: name='com.fsck.k9.activity.MessageList' label='' icon='' uses-library-not-required:'androidx.window.extensions' uses-library-not-required:'androidx.window.sidecar' feature-group: label='' uses-feature-not-required: name='android.hardware.camera' uses-feature-not-required: name='android.hardware.touchscreen' provides-component:'app-widget' main Loading @@ -93,6 +92,6 @@ other-receivers other-services supports-screens: 'small' 'normal' 'large' 'xlarge' supports-any-density: 'true' locales: '--_--' 'ar' 'be' 'bg' 'br' 'ca' 'co' 'cs' 'cy' 'da' 'de' 'el' 'en' 'en-GB' 'eo' 'es' 'et' 'eu' 'fa' 'fi' 'fr' 'fy' 'gd' 'gl' 'hr' 'hu' 'in' 'is' 'it' 'iw' 'ja' 'ko' 'lt' 'lv' 'ml' 'nb' 'nl' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'sk' 'sl' 'sq' 'sr' 'sv' 'tr' 'uk' 'vi' 'zh' 'zh-CN' 'zh-TW' locales: '--_--' 'ar' 'be' 'bg' 'br' 'ca' 'co' 'cs' 'cy' 'da' 'de' 'el' 'en' 'en-GB' 'eo' 'es' 'et' 'eu' 'fa' 'fi' 'fr' 'fy' 'gd' 'gl' 'hr' 'hu' 'in' 'is' 'it' 'iw' 'ja' 'ko' 'lt' 'lv' 'ml' 'nb' 'nl' 'nn' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'sk' 'sl' 'sq' 'sr' 'sv' 'tr' 'uk' 'vi' 'zh' 'zh-CN' 'zh-TW' densities: '120' '160' '240' '320' '480' '640' '65534' native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64' Loading
.github/workflows/daily_builds.yml +2 −0 Original line number Diff line number Diff line Loading @@ -9,3 +9,5 @@ jobs: trigger_daily_build: uses: ./.github/workflows/shippable_builds.yml secrets: inherit permissions: contents: write
.github/workflows/shippable_builds.yml +230 −22 Original line number Diff line number Diff line Loading @@ -10,6 +10,9 @@ on: skipK9Mail: type: boolean description: Skip building K-9 Mail skipTests: type: boolean description: Skip running tests skipBetaBump: type: boolean description: Skip version bump (beta) Loading Loading @@ -62,6 +65,10 @@ jobs: releaseType: ${{ vars.RELEASE_TYPE }} skipThunderbird: ${{ inputs.skipThunderbird }} skipK9Mail: ${{ inputs.skipK9Mail }} skipTests: ${{ inputs.skipTests }} skipBetaBump: ${{ inputs.skipBetaBump }} skipGooglePlay: ${{ inputs.skipGooglePlay }} draftGooglePlay: ${{ inputs.draftGooglePlay }} with: script: | let matrix = JSON.parse(process.env.matrixInclude); Loading Loading @@ -105,13 +112,60 @@ jobs: .write(); if (skipThunderbird) { await core.summary.addList(["Thunderbird is being skipped in this build"]).write(); await core.summary.addList(["Thunderbird build is being skipped"]).write(); } if (skipK9Mail) { await core.summary.addList(["K-9 Mail is being skipped in this build"]).write(); await core.summary.addList(["K-9 Mail build is being skipped"]).write(); } if (process.env.skipTests == "true") { await core.summary.addList(["Tests are being skipped"]).write(); } if (process.env.skipBetaBump == "true" && process.env.releaseType == "beta") { await core.summary.addList(["Beta bump is being skipped"]).write(); } if (process.env.skipGooglePlay == "true") { await core.summary.addList(["Play Store upload is being skipped"]).write(); } if (process.env.skipGooglePlay != "true" && process.env.draftGooglePlay == "true") { await core.summary.addList(["Play Store upload is being kept in the draft state"]).write(); } notify_build_start: name: Notify Build Start runs-on: ubuntu-latest needs: [dump_config] if: ${{ needs.dump_config.outputs.releaseType == 'beta' || needs.dump_config.outputs.releaseType == 'release' }} environment: notify_matrix outputs: actorLink: ${{ steps.actorLink.outputs.actorLink }} steps: - name: Triggering Actor Link id: actorLink uses: actions/github-script@v7 env: userMap: ${{ vars.MATRIX_NOTIFY_USER_MAP }} with: script: | let userMap = JSON.parse(process.env.userMap || "{}"); if (Object.hasOwn(userMap, context.actor)) { let mxid = userMap[context.actor]; core.setOutput("actorLink", `[${mxid}](https://matrix.to/#/${mxid})`); } else { core.setOutput("actorLink", `[@${context.actor}](https://github.com/${context.actor})`); } - name: Notify Build Start if: ${{ vars.MATRIX_NOTIFY_ROOM }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🔵 [${{ vars.RELEASE_TYPE }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) was started by ${{ steps.actorLink.outputs.actorLink }} release_commit: name: Release Bumps runs-on: ubuntu-latest Loading @@ -126,6 +180,8 @@ jobs: outputs: k9mail_sha: ${{ steps.commit.outputs.k9mail_sha }} thunderbird_sha: ${{ steps.commit.outputs.thunderbird_sha }} k9mail_github_notes: ${{ steps.render_notes.outputs.k9mail_github_notes }} thunderbird_github_notes: ${{ steps.render_notes.outputs.thunderbird_github_notes }} steps: - name: Checkout repository if: ${{ contains(matrix.releaseTarget, 'github') }} Loading Loading @@ -203,18 +259,30 @@ jobs: cat $GITHUB_OUTPUT - name: Render Release Notes id: render_notes if: ${{ contains(matrix.releaseTarget, 'github') }} shell: bash env: APP_NAME: ${{ matrix.appName }} APPLICATION_ID: ${{ steps.appinfo.outputs.APPLICATION_ID }} APPLICATION_LABEL: ${{ steps.appinfo.outputs.APPLICATION_LABEL }} VERSION_CODE: ${{ steps.bump_version_code.outputs.CODE }} FULL_VERSION_NAME: ${{ steps.appinfo.outputs.VERSION_NAME }}${{ steps.bump_version_suffix.outputs.SUFFIX || steps.appinfo.outputs.VERSION_NAME_SUFFIX }} run: | echo "<h2>${APPLICATION_LABEL} ${FULL_VERSION_NAME} Release Notes (${VERSION_CODE})</h2><pre>" | tee -a $GITHUB_STEP_SUMMARY mkdir -p ./app-metadata/${APPLICATION_ID}/en-US/changelogs python ./scripts/render-notes.py ${APPLICATION_ID} ${FULL_VERSION_NAME} ${VERSION_CODE} | tee -a $GITHUB_STEP_SUMMARY echo "</pre>" | tee -a $GITHUB_STEP_SUMMARY GITHUB_NOTES_FILE="$(mktemp -d)/long-notes.txt" python ./scripts/render-notes.py ${APPLICATION_ID} ${FULL_VERSION_NAME} ${VERSION_CODE} ${GITHUB_NOTES_FILE} echo "${APP_NAME}_github_notes<<EOF" >> $GITHUB_OUTPUT cat $GITHUB_NOTES_FILE >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "<h2>${APPLICATION_LABEL} ${FULL_VERSION_NAME} Release Notes (${VERSION_CODE})</h2>" | tee -a $GITHUB_STEP_SUMMARY echo -e "Summarized Version Notes\n\n\`\`\`" | tee -a $GITHUB_STEP_SUMMARY cat ./app-metadata/${APPLICATION_ID}/en-US/changelogs/${VERSION_CODE}.txt | tee -a $GITHUB_STEP_SUMMARY echo -e "\n\`\`\`\n\nLong Version Notes\n\n\`\`\`" | tee -a $GITHUB_STEP_SUMMARY cat $GITHUB_NOTES_FILE | tee -a $GITHUB_STEP_SUMMARY echo -e "\`\`\`" | tee -a $GITHUB_STEP_SUMMARY - name: Validate Release Notes Length if: ${{ contains(matrix.releaseTarget, 'github') }} Loading Loading @@ -299,6 +367,7 @@ jobs: name: Build Unsigned runs-on: ubuntu-latest timeout-minutes: 90 if: ${{ !failure() && !cancelled() }} # Run if release_commit is skipped needs: [dump_config, get_environment, release_commit] strategy: matrix: Loading @@ -316,6 +385,7 @@ jobs: case "${APP_NAME}" in thunderbird) APP_SHA=$THUNDERBIRD_SHA ;; k9mail) APP_SHA=$K9MAIL_SHA ;; *) APP_SHA=$GITHUB_SHA ;; esac echo "app_sha=$APP_SHA" >> $GITHUB_OUTPUT Loading Loading @@ -361,6 +431,11 @@ jobs: ./gradlew clean :app-${APP_NAME}:${BUILD_COMMAND} --no-build-cache --no-configuration-cache echo "Status: $?" - name: Test It if: ${{ !inputs.skipTests }} shell: bash run: ./gradlew testsOnCi - name: Move apps to upload directory shell: bash env: Loading Loading @@ -413,11 +488,12 @@ jobs: sign_mobile: name: Sign Packages runs-on: ubuntu-latest if: ${{ !failure() && !cancelled() }} # Run if previous step is skipped needs: [build_unsigned, dump_config] strategy: matrix: include: "${{ fromJSON(needs.dump_config.outputs.matrixInclude) }}" environment: ${{ matrix.appName }}_${{ needs.dump_config.outputs.releaseType }}_${{ matrix.packageFlavor || 'default' }} needs: [build_unsigned, dump_config] env: RELEASE_TYPE: ${{ needs.dump_config.outputs.releaseType }} steps: Loading Loading @@ -458,6 +534,22 @@ jobs: uploads/*.apk uploads/*.aab notify_pre_publish: name: Notify Publish Approval needs: [dump_config, sign_mobile, notify_build_start] if: ${{ needs.dump_config.outputs.releaseType == 'beta' || needs.dump_config.outputs.releaseType == 'release' }} runs-on: ubuntu-latest environment: notify_matrix steps: - uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🟡 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) waiting for publish approval (triggered by ${{ needs.notify_build_start.outputs.actorLink }}) pre_publish: # This is a holding job meant to require approval before proceeding with the publishing jobs below # The environment has a deployment protection rule requiring approval from a set of named reviewers Loading @@ -482,6 +574,11 @@ jobs: matrix: include: "${{ fromJSON(needs.dump_config.outputs.matrixInclude) }}" environment: publish_release outputs: thunderbird_release_url: ${{ steps.summary.outputs.thunderbird_release_url }} k9mail_release_url: ${{ steps.summary.outputs.k9mail_release_url }} thunderbird_full_version_name: ${{ steps.summary.outputs.thunderbird_full_version_name }} k9mail_full_version_name: ${{ steps.summary.outputs.k9mail_full_version_name }} env: RELEASE_TYPE: ${{ needs.dump_config.outputs.releaseType }} APP_NAME: ${{ matrix.appName }} Loading Loading @@ -556,20 +653,24 @@ jobs: app-id: ${{ vars.RELEASER_APP_CLIENT_ID }} private-key: ${{ secrets.RELEASER_APP_PRIVATE_KEY }} - name: Get release sha id: sha - name: Get release sha and notes id: shanotes shell: bash env: THUNDERBIRD_GITHUB_NOTES: ${{ needs.release_commit.outputs.thunderbird_github_notes }} K9MAIL_GITHUB_NOTES: ${{ needs.release_commit.outputs.k9mail_github_notes }} THUNDERBIRD_SHA: ${{ needs.release_commit.outputs.thunderbird_sha }} K9MAIL_SHA: ${{ needs.release_commit.outputs.k9mail_sha }} APP_NAME: ${{ matrix.appName }} run: | case "${APP_NAME}" in thunderbird) APP_SHA=$THUNDERBIRD_SHA ;; k9mail) APP_SHA=$K9MAIL_SHA ;; esac app_sha_name=${APP_NAME^^}_SHA echo "app_sha=${!app_sha_name}" >> $GITHUB_OUTPUT app_relnotes_name=${APP_NAME^^}_GITHUB_NOTES echo "app_github_notes<<EOF" >> $GITHUB_OUTPUT echo "${!app_relnotes_name}" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "app_sha=$APP_SHA" >> $GITHUB_OUTPUT cat $GITHUB_OUTPUT - name: Publish to GitHub Releases Loading @@ -578,9 +679,10 @@ jobs: uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 with: token: ${{ steps.app-token.outputs.token || github.token }} target_commitish: ${{ steps.sha.outputs.app_sha }} target_commitish: ${{ steps.shanotes.outputs.app_sha }} tag_name: ${{ steps.pkginfo.outputs.TAG_NAME }} name: ${{ steps.pkginfo.outputs.FULL_VERSION_NAME }} body: ${{ steps.shanotes.outputs.app_github_notes }} prerelease: ${{ env.RELEASE_TYPE != 'release' }} fail_on_unmatched_files: true files: | Loading @@ -593,7 +695,7 @@ jobs: VERSION_CODE: ${{ steps.pkginfo.outputs.VERSION_CODE }} APPLICATION_ID: ${{ steps.pkginfo.outputs.APPLICATION_ID }} REPO: ${{ github.repository }} APP_SHA: ${{ steps.sha.outputs.app_sha }} APP_SHA: ${{ steps.shanotes.outputs.app_sha }} run: | # r0adkll/upload-google-play expects the release notes in a different structure FILEPATH=app-metadata/${APPLICATION_ID}/en-US/changelogs/${VERSION_CODE}.txt Loading @@ -617,30 +719,136 @@ jobs: - name: Summary uses: actions/github-script@v7 id: summary env: tagName: ${{ steps.pkginfo.outputs.TAG_NAME }} fullVersionName: ${{ steps.pkginfo.outputs.FULL_VERSION_NAME }} ghReleaseUrl: ${{ steps.publish_gh.outputs.url }} playTargetTrack: ${{ matrix.playTargetTrack }} applicationId: ${{ steps.pkginfo.outputs.APPLICATION_ID }} app_sha: ${{ steps.sha.outputs.app_sha }} releaseTarget: ${{ matrix.releaseTarget }} appSha: ${{ steps.shanotes.outputs.app_sha }} appName: ${{ matrix.appName }} skipGooglePlay: ${{ inputs.skipGooglePlay }} with: script: | await core.summary .addHeading(`${process.env.fullVersionName} (${process.env.applicationId})`, 2) .addRaw(`Tag ${process.env.tagName} at `) .addLink(process.env.app_sha, `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.app_sha}`) .addEOL() .write(); core.setOutput(`${process.env.appName}_full_version_name`, process.env.fullVersionName); if (process.env.ghReleaseUrl) { if (!process.env.releaseTarget) { await core.summary .addRaw(`Artifact-only build at `) .addLink(process.env.appSha, `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.appSha}`) .addEOL() .write(); } else if (process.env.ghReleaseUrl) { await core.summary .addRaw(`Tag ${process.env.tagName} at `) .addLink(process.env.appSha, `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${process.env.appSha}`) .addEOL() .addRaw(`Released to Github at `) .addLink(process.env.ghReleaseUrl, process.env.ghReleaseUrl) .addEOL() .write(); core.setOutput(`${process.env.appName}_release_url`, process.env.ghReleaseUrl); } if (process.env.playTargetTrack) { if (process.env.skipGooglePlay != "true" && process.env.playTargetTrack && process.env.releaseTarget.includes("play")) { await core.summary.addRaw(`Released to the <b>${process.env.playTargetTrack}</b> track on Google Play`, true).write(); } notify_build_result: name: Notify Build Result if: ${{ always() }} needs: [dump_config, release_commit, build_unsigned, sign_mobile, publish_release, notify_build_start] runs-on: ubuntu-latest environment: notify_matrix steps: - name: Get previous workflow status uses: Mercymeilya/last-workflow-status@3418710aefe8556d73b6f173a0564d38bcfd9a43 id: last_status with: github_token: ${{ secrets.GITHUB_TOKEN }} - name: Info uses: actions/github-script@v7 id: info env: needs: ${{ toJSON(needs) }} with: script: | let needs = JSON.parse(process.env.needs); let failures = []; for (let [job, need] of Object.entries(needs)) { if (need.result == 'failure') { failures.push(job.replace(/([-_])/g, "\\$1")); } } core.setOutput("fail_steps", failures.join(`, `)); - name: Notify Failure if: ${{ vars.MATRIX_NOTIFY_ROOM && contains(needs.*.result, 'failure') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🔴 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) has failed at step ${{ steps.info.outputs.fail_steps }} (triggered by ${{ needs.notify_build_start.outputs.actorLink }}) - name: Notify Cancelled if: ${{ vars.MATRIX_NOTIFY_ROOM && !contains(needs.*.result, 'failure') && contains(needs.*.result, 'cancelled') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- ⚪ [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) was cancelled - name: Notify Success (Beta/Release) if: ${{ vars.MATRIX_NOTIFY_ROOM && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && (needs.dump_config.outputs.releaseType == 'beta' || needs.dump_config.outputs.releaseType == 'release') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🟢 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) has succeeded (triggered by ${{ needs.notify_build_start.outputs.actorLink }}) - name: Thunderbird Publish URL (Beta/Release) if: ${{ vars.MATRIX_NOTIFY_ROOM && needs.publish_release.outputs.thunderbird_release_url && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- ${{ needs.publish_release.outputs.thunderbird_full_version_name }} [is available](${{ needs.publish_release.outputs.thunderbird_release_url }}) - name: K-9 Mail Publish URL (Beta/Release) if: ${{ vars.MATRIX_NOTIFY_ROOM && needs.publish_release.outputs.k9mail_release_url && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- ${{ needs.publish_release.k9mail_full_version_name }} [is available](${{ needs.publish_release.outputs.k9mail_release_url }}) - name: Notify Success (Daily) if: ${{ vars.MATRIX_NOTIFY_ROOM && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && needs.dump_config.outputs.releaseType == 'daily' && steps.last_status.outputs.last_status == 'failure' }} uses: kewisch/action-matrix-notify@v1 with: matrixHomeserver: ${{ vars.MATRIX_NOTIFY_HOMESERVER }} matrixRoomId: ${{ vars.MATRIX_NOTIFY_ROOM }} matrixToken: ${{ secrets.MATRIX_NOTIFY_TOKEN }} message: >- 🟢 [${{ needs.dump_config.outputs.releaseType }} build ${{ github.run_number}}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) has recovered
.gitignore +0 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ out/ # IDEA/Android Studio includes !.idea/icon.png !.idea/codeStyles/ !.idea/inspectionProfiles/ !.idea/fileTemplates/ # Android Studio captures folder Loading
app-k9mail/badging/release-badging.txt +2 −3 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ uses-permission: name='android.permission.WAKE_LOCK' uses-permission: name='android.permission.FOREGROUND_SERVICE' uses-permission: name='android.permission.FOREGROUND_SERVICE_DATA_SYNC' uses-permission: name='android.permission.SCHEDULE_EXACT_ALARM' uses-permission: name='android.permission.CAMERA' uses-permission: name='android.permission.USE_BIOMETRIC' uses-permission: name='android.permission.USE_FINGERPRINT' uses-permission: name='com.fsck.k9.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION' Loading Loading @@ -54,6 +53,7 @@ application-label-lv:'K-9 pasts' application-label-ml:'K-9 Mail' application-label-nb:'K-9 e-post' application-label-nl:'K-9 Mail' application-label-nn:'K-9 e-post' application-label-pl:'K-9 Mail' application-label-pt:'K-9 Mail' application-label-pt-BR:'K-9 Mail' Loading Loading @@ -84,7 +84,6 @@ launchable-activity: name='com.fsck.k9.activity.MessageList' label='' icon='' uses-library-not-required:'androidx.window.extensions' uses-library-not-required:'androidx.window.sidecar' feature-group: label='' uses-feature-not-required: name='android.hardware.camera' uses-feature-not-required: name='android.hardware.touchscreen' provides-component:'app-widget' main Loading @@ -93,6 +92,6 @@ other-receivers other-services supports-screens: 'small' 'normal' 'large' 'xlarge' supports-any-density: 'true' locales: '--_--' 'ar' 'be' 'bg' 'br' 'ca' 'co' 'cs' 'cy' 'da' 'de' 'el' 'en' 'en-GB' 'eo' 'es' 'et' 'eu' 'fa' 'fi' 'fr' 'fy' 'gd' 'gl' 'hr' 'hu' 'in' 'is' 'it' 'iw' 'ja' 'ko' 'lt' 'lv' 'ml' 'nb' 'nl' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'sk' 'sl' 'sq' 'sr' 'sv' 'tr' 'uk' 'vi' 'zh' 'zh-CN' 'zh-TW' locales: '--_--' 'ar' 'be' 'bg' 'br' 'ca' 'co' 'cs' 'cy' 'da' 'de' 'el' 'en' 'en-GB' 'eo' 'es' 'et' 'eu' 'fa' 'fi' 'fr' 'fy' 'gd' 'gl' 'hr' 'hu' 'in' 'is' 'it' 'iw' 'ja' 'ko' 'lt' 'lv' 'ml' 'nb' 'nl' 'nn' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'sk' 'sl' 'sq' 'sr' 'sv' 'tr' 'uk' 'vi' 'zh' 'zh-CN' 'zh-TW' densities: '120' '160' '240' '320' '480' '640' '65534' native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64'