Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/build-apps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
on:
workflow_call:
secrets:
PLAYSTORE_SECRET_PASSPHRASE:
required: true
KEYSTORE_PASSWORD:
required: true
KEYSTORE_KEY_PASSWORD:
required: true

jobs:
build:
name: 🔨 Build
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- name: 📱 Android App
gradle_module: tasks-app-android
- name: 🖥️ Desktop App
gradle_module: tasks-app-desktop
permissions:
contents: write
checks: write
id-token: write
pull-requests: write

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

- name: 🔓 Decrypt secrets
env:
PLAYSTORE_SECRET_PASSPHRASE: ${{ secrets.PLAYSTORE_SECRET_PASSPHRASE }}
run: ./_ci/decrypt_secrets.sh

- name: ${{ matrix.name }}
env:
PLAYSTORE_SECRET_PASSPHRASE: ${{ secrets.PLAYSTORE_SECRET_PASSPHRASE }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
run: |
gradle_module="${{ matrix.gradle_module }}"
if [ "${gradle_module}" = "tasks-app-desktop" ]; then
./gradlew --no-daemon --parallel ":${gradle_module}:assemble"
elif [ "${gradle_module}" = "tasks-app-android" ]; then
./gradlew --no-daemon --parallel :tasks-app-android:assembleStoreRelease \
-Pci=true \
-Pplaystore.keystore.file="${PWD}/_ci/tasksApp.keystore" \
-Pplaystore.keystore.password="${KEYSTORE_PASSWORD}" \
-Pplaystore.keystore.key_password="${KEYSTORE_KEY_PASSWORD}"
fi
173 changes: 10 additions & 163 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,171 +14,18 @@ on:
- main

jobs:
build:
name: 🔨 Build
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- name: 📱 Android App
gradle_module: tasks-app-android
- name: 🖥️ Desktop App
gradle_module: tasks-app-desktop
permissions:
contents: write
checks: write
id-token: write
pull-requests: write
build-apps:
uses: ./.github/workflows/build-apps.yml
secrets:
PLAYSTORE_SECRET_PASSPHRASE: ${{ secrets.PLAYSTORE_SECRET_PASSPHRASE }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

- name: 🔓 Decrypt secrets
env:
PLAYSTORE_SECRET_PASSPHRASE: ${{ secrets.PLAYSTORE_SECRET_PASSPHRASE }}
run: ./_ci/decrypt_secrets.sh

- name: ${{ matrix.name }}
env:
PLAYSTORE_SECRET_PASSPHRASE: ${{ secrets.PLAYSTORE_SECRET_PASSPHRASE }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
run: |
gradle_module="${{ matrix.gradle_module }}"
if [ "${gradle_module}" = "tasks-app-desktop" ]; then
./gradlew --no-daemon ":${gradle_module}:assemble"
elif [ "${gradle_module}" = "tasks-app-android" ]; then
./gradlew --no-daemon :tasks-app-android:assembleStoreRelease \
-Pci=true \
-Pplaystore.keystore.file="${PWD}/_ci/tasksApp.keystore" \
-Pplaystore.keystore.password="${KEYSTORE_PASSWORD}" \
-Pplaystore.keystore.key_password="${KEYSTORE_KEY_PASSWORD}"
fi

test:
name: ✅ Tests
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

# `test` to trigger as much Jvm tests as possible
# `:tasks-app-android:testStoreReleaseUnitTest` to restrict to only specific flavor(store)+variant(release) for `:tasks-app-android` module.
# `jvmTest` to execute Compose UI tests on Jvm
# `-x :tasks-app-android:test` to remove all tests from `:tasks-app-android` module not being covered by `:tasks-app-android:testStoreReleaseUnitTest`.
# `-x testDebugUnitTest` to avoid triggering tests both in debug & release build.
# `-x :tasks-app-android:build` to avoid triggering useless build tasks (typically for unused flavors).
# Only rely on dependencies of `:tasks-app-android:testStoreReleaseUnitTest`.
- name: ✅ Unit tests
run: |
jq '(.client[0].client_info.android_client_info.package_name) = "net.opatry.tasks.app"' \
tasks-app-android/src/dev/google-services.json > tasks-app-android/google-services.json
./gradlew --no-daemon test :tasks-app-android:testStoreReleaseUnitTest jvmTest \
-x :tasks-app-android:test -x testDebugUnitTest -x :tasks-app-android:build

- name: 🗒️ Publish Test Reports
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
detailed_summary: true
require_passed_tests: true
require_tests: true
report_paths: '**/build/test-results/**/TEST-*.xml'
unit-tests:
uses: ./.github/workflows/unit-tests.yml

coverage:
name: 📊 Coverage
runs-on: ubuntu-24.04
permissions:
contents: write

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

- name: 📊 Check coverage
if: github.event_name == 'pull_request'
run: |
./gradlew koverLogCoverage koverVerifyCoverage

- name: 📊 Check coverage & update badge
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
sudo apt -y install libxml2-utils
./gradlew koverXmlReportCoverage koverLogCoverage koverVerifyCoverage
./_ci/replace_coverage_badge.sh build/reports/kover/reportCoverage.xml
if [[ $(git status --porcelain README.md) ]]; then
git config user.name 'Github Actions'
git config user.email 'opatry-tasks-app@users.noreply.github.com'
git add README.md
git commit -m "Update coverage badge in README.md"
git push
fi
uses: ./.github/workflows/coverage.yml

licenses-check:
name: ©️ Check licenses
# run on macOS to use Skiko mac for credits checks
runs-on: macos-15
strategy:
fail-fast: false
matrix:
include:
- gradle_module: tasks-app-android
license_path: src/main/assets/licenses_android.json
- gradle_module: tasks-app-desktop
license_path: src/main/resources/licenses_desktop.json
permissions:
checks: write
id-token: write
pull-requests: write

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

- name: ©️ Generate credits for ':${{ matrix.gradle_module }}'
id: check_credits
run: |
gradle_module="${{ matrix.gradle_module }}"
license_file="${gradle_module}/${{ matrix.license_path }}"

./gradlew --no-daemon ":${gradle_module}:exportLibraryDefinitions" -Pci=true
stale_credits=$(git diff "${license_file}")

if [ -n "${stale_credits}" ]; then
{
echo "## ©️ Stale credits for \`:${gradle_module}\`"
echo '```diff'
echo "${stale_credits}"
echo '```'
} >> "${GITHUB_STEP_SUMMARY}"

{
echo "credits_diff_comment<<EOF"
echo "## ©️ Stale credits for \\\`:${gradle_module}\\\`\n\n"
echo "\\\`\\\`\\\`diff\n"
echo "${stale_credits}\n"
echo "\\\`\\\`\\\`\n\n"
echo Run \\\`./gradlew :${gradle_module}:exportLibraryDefinitions -Pci=true\\\` and commit resulting diff to fix the issue.
echo "EOF"
} >> "$GITHUB_OUTPUT"
else
echo "credits_diff_comment=" >> "$GITHUB_OUTPUT"
fi

- name: 🛎️ Notify stale credits for ':${{ matrix.gradle_module }}'
if: github.event_name == 'pull_request' && steps.check_credits.outputs.credits_diff_comment != ''
uses: actions/github-script@v7
env:
GRADLE_MODULE: ${{ matrix.gradle_module }}
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `${{ steps.check_credits.outputs.credits_diff_comment }}`
})
core.setFailed(`Stale credits detected in module ':${process.env.GRADLE_MODULE}:'`)
uses: ./.github/workflows/licenses-check.yml
34 changes: 34 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
on:
workflow_call:

jobs:
coverage:
name: 📊 Coverage
runs-on: ubuntu-24.04
permissions:
contents: write

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

# Avoid using --parallel for coverage reporting, seems unreliable when doing it
- name: 📊 Check coverage
if: github.event_name == 'pull_request'
run: |
./gradlew --no-daemon koverLogCoverage koverVerifyCoverage

# Avoid using --parallel for coverage reporting, seems unreliable when doing it
- name: 📊 Check coverage & update badge
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
sudo apt -y install libxml2-utils
./gradlew --no-daemon koverXmlReportCoverage koverLogCoverage koverVerifyCoverage
./_ci/replace_coverage_badge.sh build/reports/kover/reportCoverage.xml
if [[ $(git status --porcelain README.md) ]]; then
git config user.name 'Github Actions'
git config user.email 'opatry-tasks-app@users.noreply.github.com'
git add README.md
git commit -m "Update coverage badge in README.md"
git push
fi
69 changes: 69 additions & 0 deletions .github/workflows/licenses-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
on:
workflow_call:

jobs:
licenses-check:
name: ©️ Check licenses
# run on macOS to use Skiko mac for credits checks
runs-on: macos-15
strategy:
fail-fast: false
matrix:
include:
- gradle_module: tasks-app-android
license_path: src/main/assets/licenses_android.json
- gradle_module: tasks-app-desktop
license_path: src/main/resources/licenses_desktop.json
permissions:
checks: write
id-token: write
pull-requests: write

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

- name: ©️ Generate credits for ':${{ matrix.gradle_module }}'
id: check_credits
run: |
gradle_module="${{ matrix.gradle_module }}"
license_file="${gradle_module}/${{ matrix.license_path }}"

./gradlew --no-daemon --parallel ":${gradle_module}:exportLibraryDefinitions" -Pci=true
stale_credits=$(git diff "${license_file}")

if [ -n "${stale_credits}" ]; then
{
echo "## ©️ Stale credits for \`:${gradle_module}\`"
echo '```diff'
echo "${stale_credits}"
echo '```'
} >> "${GITHUB_STEP_SUMMARY}"

{
echo "credits_diff_comment<<EOF"
echo "## ©️ Stale credits for \\\`:${gradle_module}\\\`\n\n"
echo "\\\`\\\`\\\`diff\n"
echo "${stale_credits}\n"
echo "\\\`\\\`\\\`\n\n"
echo Run \\\`./gradlew :${gradle_module}:exportLibraryDefinitions -Pci=true\\\` and commit resulting diff to fix the issue.
echo "EOF"
} >> "$GITHUB_OUTPUT"
else
echo "credits_diff_comment=" >> "$GITHUB_OUTPUT"
fi

- name: 🛎️ Notify stale credits for ':${{ matrix.gradle_module }}'
if: github.event_name == 'pull_request' && steps.check_credits.outputs.credits_diff_comment != ''
uses: actions/github-script@v7
env:
GRADLE_MODULE: ${{ matrix.gradle_module }}
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `${{ steps.check_credits.outputs.credits_diff_comment }}`
})
core.setFailed(`Stale credits detected in module ':${process.env.GRADLE_MODULE}:'`)
2 changes: 1 addition & 1 deletion .github/workflows/play-store-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
CI_BUILD_NUMBER: ${{ github.run_number }}
run: |
./gradlew --no-daemon :tasks-app-android:bundleStoreRelease \
./gradlew --no-daemon --parallel :tasks-app-android:bundleStoreRelease \
-Pci=true \
-Pplaystore.keystore.file="${PWD}/_ci/tasksApp.keystore" \
-Pplaystore.keystore.password="${KEYSTORE_PASSWORD}" \
Expand Down
37 changes: 37 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
on:
workflow_call:

jobs:
unit-tests:
name: ✅ Tests
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-jdk-gradle

- name: Prepare google-services.json
run: |
jq '(.client[0].client_info.android_client_info.package_name) = "net.opatry.tasks.app"' \
tasks-app-android/src/dev/google-services.json > tasks-app-android/google-services.json

# `test` to trigger as much Jvm tests as possible
# `:tasks-app-android:testStoreReleaseUnitTest` to restrict to only specific flavor(store)+variant(release) for `:tasks-app-android` module.
# `jvmTest` to execute Compose UI tests on Jvm
# `-x :tasks-app-android:test` to remove all tests from `:tasks-app-android` module not being covered by `:tasks-app-android:testStoreReleaseUnitTest`.
# `-x testDebugUnitTest` to avoid triggering tests both in debug & release build.
# `-x :tasks-app-android:build` to avoid triggering useless build tasks (typically for unused flavors).
# Only rely on dependencies of `:tasks-app-android:testStoreReleaseUnitTest`.
- name: ✅ Unit tests
run: |
./gradlew --no-daemon --parallel test :tasks-app-android:testStoreReleaseUnitTest jvmTest \
-x :tasks-app-android:test -x testDebugUnitTest -x :tasks-app-android:build

- name: 🗒️ Publish Test Reports
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
detailed_summary: true
require_passed_tests: true
require_tests: true
report_paths: '**/build/test-results/**/TEST-*.xml'