mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-06 00:02:48 +02:00
Compare commits
1 Commits
v1.6.6
...
michaelk/a
Author | SHA1 | Date | |
---|---|---|---|
|
14e7c71b26 |
1802
.editorconfig
1802
.editorconfig
File diff suppressed because it is too large
Load Diff
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,3 +0,0 @@
|
||||
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text
|
||||
**/src/androidTest/assets/*.realm filter=lfs diff=lfs merge=lfs -text
|
||||
**/matrix-rust-sdk-crypto.aar filter=lfs diff=lfs merge=lfs -text
|
13
.github/ISSUE_TEMPLATE/bug.yml
vendored
13
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,5 +1,5 @@
|
||||
name: Bug report for the Element Android app
|
||||
description: Report any issues that you have found with the Element app. Please check open issues first, in case it has already been reported.
|
||||
description: Report any issues that you have found with the Element app. Please [check open issues](https://github.com/vector-im/element-android/issues) first, in case it has already been reported.
|
||||
labels: [T-Defect]
|
||||
body:
|
||||
- type: markdown
|
||||
@@ -73,14 +73,3 @@ body:
|
||||
- 'No'
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: pr
|
||||
attributes:
|
||||
label: Are you willing to provide a PR?
|
||||
description: |
|
||||
Providing a PR can drastically speed up the process of fixing this bug. Don't worry, it's still OK to answer 'No' :).
|
||||
options:
|
||||
- 'Yes'
|
||||
- 'No'
|
||||
validations:
|
||||
required: true
|
||||
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Enhancement or feature request
|
||||
url: https://github.com/vector-im/element-meta/discussions/categories/ideas
|
||||
about: Do you have a suggestion or feature request?
|
||||
- name: Element Android Community Support
|
||||
url: https://matrix.to/#/#element-android:matrix.org
|
||||
about: General Element Android support questions can be asked in the app Matrix room
|
36
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
36
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Enhancement request
|
||||
description: Do you have a suggestion or feature request?
|
||||
labels: [T-Enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to propose a new feature or make a suggestion.
|
||||
- type: textarea
|
||||
id: usecase
|
||||
attributes:
|
||||
label: Your use case
|
||||
description: Please feel welcome to include screenshots or mock ups.
|
||||
placeholder: Tell us what you would like to do!
|
||||
value: |
|
||||
#### What would you like to do?
|
||||
|
||||
#### Why would you like to do it?
|
||||
|
||||
#### How would you like to achieve it?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: Have you considered any alternatives?
|
||||
placeholder: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: Is there anything else you'd like to add?
|
||||
validations:
|
||||
required: false
|
2
.github/ISSUE_TEMPLATE/matrix-sdk.yml
vendored
2
.github/ISSUE_TEMPLATE/matrix-sdk.yml
vendored
@@ -1,5 +1,5 @@
|
||||
name: Matrix SDK bug or enhancement
|
||||
description: "Report issue or ask for a feature in the Android Matrix SDK: https://github.com/matrix-org/matrix-android-sdk2"
|
||||
description: Report issue or ask for a feature in the [Android Matrix SDK](https://github.com/matrix-org/matrix-android-sdk2)
|
||||
title: "[SDK] "
|
||||
labels: [matrix-sdk]
|
||||
|
||||
|
76
.github/ISSUE_TEMPLATE/release.yml
vendored
76
.github/ISSUE_TEMPLATE/release.yml
vendored
@@ -10,6 +10,7 @@ body:
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Release checklist
|
||||
description: For the template example, we are releasing the version 1.2.3. Replace 1.2.3 with the version in the issue body.
|
||||
placeholder: |
|
||||
If you are reading this, you have deleted the content of the release template: undo the deletion or start again.
|
||||
value: |
|
||||
@@ -19,56 +20,87 @@ body:
|
||||
- [ ] Check the update of the store descriptions (using Google Translate if necessary) to ensure that the changes are acceptable to be published to the stores.
|
||||
- [ ] While Weblate is locked, and after the PR from Weblate has been merged, handle all the TODOs in the main `strings.xml` file
|
||||
- [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect.
|
||||
- [ ] Ensure all [the required PRs](https://github.com/vector-im/element-android/pulls?q=is%3Aopen+is%3Apr+label%3AZ-NextRelease) have been merged
|
||||
|
||||
### Do the release
|
||||
|
||||
- [ ] Run the script ./tools/release/releaseScript.sh and follow the steps.
|
||||
- [ ] Create release with gitflow, branch name `release/1.2.3`
|
||||
- [ ] Check the crashes from the PlayStore
|
||||
- [ ] Check the rageshake with the current dev version: https://github.com/matrix-org/element-android-rageshakes/labels/1.2.3-dev
|
||||
- [ ] Run the integration test, and especially `UiAllScreensSanityTest.allScreensTest()`
|
||||
- [ ] Create an account on matrix.org and do some smoke tests that the sanity test does not cover like: 1-1 call, 1-1 video call, Jitsi call for instance
|
||||
- [ ] Run towncrier: `towncrier --version v1.2.3 --draft` (remove `--draft` do write the file CHANGES.md)
|
||||
- [ ] Check that the folder `changelog.d` is empty. It can happen that some remaining files stay here
|
||||
- [ ] Check the file CHANGES.md consistency. It's possible to reorder items (most important changes first) or change their section if relevant. Also an opportunity to fix some typo, or rewrite things
|
||||
- [ ] Add file for fastlane under ./fastlane/metadata/android/en-US/changelogs
|
||||
- [ ] (optional) Push the branch and start a draft PR (will not be merged), to check that the CI is happy with all the changes.
|
||||
- [ ] Finish release with gitflow, delete the draft PR (if created)
|
||||
- [ ] Push `main` and the new tag `v1.2.3` to origin
|
||||
- [ ] Checkout `develop`
|
||||
- [ ] Increase version (versionPatch + 2) in `./vector/build.gradle`
|
||||
- [ ] Change the value of SDK_VERSION in the file `./matrix-sdk-android/build.gradle`
|
||||
- [ ] Commit and push `develop`
|
||||
- [ ] Wait for [Buildkite](https://buildkite.com/matrix-dot-org/element-android/builds?branch=main) to build the `main` branch.
|
||||
- [ ] Run the script `~/scripts/releaseElement.sh`. It will download the APKs from Buildkite check them and sign them.
|
||||
- [ ] Install the APK on your phone to check that the upgrade went well (no init sync, etc.)
|
||||
- [ ] Create the release on gitHub [from the tag](https://github.com/vector-im/element-android/tags), copy paste the block from the file CHANGES.md
|
||||
- [ ] Add the 4 signed APKs to the GitHub release
|
||||
- [ ] Ping the Android Internal room
|
||||
|
||||
### Once tested and validated internally
|
||||
|
||||
- [ ] Create a new open testing release on the GooglePlay console and upload the 4 signed Apks.
|
||||
- [ ] Create a new beta release on the GooglePlay console and upload the 4 signed Apks.
|
||||
- [ ] Check that the version codes are correct
|
||||
- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
|
||||
- [ ] Push the open testing release to 100% of the users
|
||||
- [ ] Notify the F-Droid team [here](https://matrix.to/#/!LAAuJLQXYHjMNWKrCK:matrix.org?via=matrix.org&via=bubu1.eu&via=lant.uk) so that they can schedule the publication on F-Droid
|
||||
- [ ] The application is available to the PlayStore testers (live). Google can take between 1 hour and up to 7 days to approve the release.
|
||||
- [ ] The application is available to the F-Droid users.
|
||||
- [ ] Push to beta release to 100% of the users
|
||||
- [ ] Notify the F-Droid team so that they can schedule the publication on F-Droid
|
||||
|
||||
### Once open testing is live on PlayStore
|
||||
### Once Live on PlayStore
|
||||
|
||||
- [ ] Ping the Android public room and update its topic
|
||||
- [ ] Add an entry in the internal diary
|
||||
|
||||
### Once Live on F-Droid
|
||||
|
||||
- [ ] Update the Android public room topic
|
||||
|
||||
### After at least 2 days (generally next Monday)
|
||||
### After at least 2 days
|
||||
|
||||
- [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
|
||||
- [ ] Check the crash reports on the GooglePlay console
|
||||
- [ ] Check the Android Element room for any reported issues on the new version
|
||||
- [ ] If all is OK, promote the open testing release to production. Generally using a 100% roll out, but can be a smaller value depending on the release content.
|
||||
- [ ] The application is available to the PlayStore users (live). Google can take (again!) between 1 hour and up to 7 days to approve the release.
|
||||
|
||||
### Once production is live on PlayStore
|
||||
|
||||
- [ ] Ping the Android public room and update its topic
|
||||
- [ ] Add an entry in the internal diary
|
||||
- [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
|
||||
- [ ] Ping the Android public room and update its topic with the new available version
|
||||
|
||||
### Android SDK2
|
||||
|
||||
The SDK2 and the sample app are released only when Element has been pushed to production.
|
||||
|
||||
- [ ] On the [SDK2 project](https://github.com/matrix-org/matrix-android-sdk2), run the script ./tools/releaseScript.sh and follow the instructions.
|
||||
- [ ] Checkout the `main` branch on Element Android project
|
||||
|
||||
Note: if the step `./gradlew closeAndReleaseRepository` fails (for instance, several repositories are waiting to be handled), you have to close and release the repository manually. Do the following steps:
|
||||
#### On the SDK2 project
|
||||
|
||||
https://github.com/matrix-org/matrix-android-sdk2
|
||||
|
||||
- [ ] Create a release with GitFlow
|
||||
- [ ] Update the value of VERSION_NAME in the file gradle.properties
|
||||
- [ ] Update the files `./build.gradle` and `./gradle/gradle-wrapper.properties` manually, to use the latest version for the dependency. You can get inspired by the same files on Element Android project.
|
||||
- [ ] Run the script `./tools/import_from_element.sh`
|
||||
- [ ] Check the diff in the file `./matrix-sdk-android/build.gradle` and restore what may have been erased (in particular the line `apply plugin: "com.vanniktech.maven.publish"` and the line about the version)
|
||||
- [ ] Let the script finish to build the library
|
||||
- [ ] Update the file `CHANGES.md`
|
||||
- [ ] Finish the release using GitFlow
|
||||
- [ ] Push the branch `main`, the new tag and the branch `develop` to origin
|
||||
|
||||
##### Release on MavenCentral
|
||||
|
||||
- [ ] Run the command `./gradlew publish --no-daemon --no-parallel`. You'll need some non-public element to do so
|
||||
- [ ] Connect to https://s01.oss.sonatype.org
|
||||
- [ ] Click on Staging Repositories and check the the files have been uploaded
|
||||
- [ ] Click on close
|
||||
- [ ] Wait (check Activity tab until step "Repository closed" is displayed)
|
||||
- [ ] Click on release. The staging repository will disappear
|
||||
- [ ] Check that the release is available in https://repo1.maven.org/maven2/org/matrix/android/matrix-android-sdk2/ (it can take a few minutes)
|
||||
|
||||
##### Release on GitHub
|
||||
|
||||
- [ ] Create the release on GitHub from [the tag](https://github.com/matrix-org/matrix-android-sdk2/tags)
|
||||
- [ ] Upload the AAR on the GitHub release
|
||||
|
||||
### Android SDK2 sample
|
||||
|
||||
|
13
.github/dependabot.yml
vendored
13
.github/dependabot.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
@@ -10,10 +10,8 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
reviewers:
|
||||
- "vector-im/element-android-reviewers"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
- dependency-name: "*github-script*"
|
||||
# Updates for Gradle dependencies used in the app
|
||||
- package-ecosystem: gradle
|
||||
directory: "/"
|
||||
@@ -21,7 +19,6 @@ updates:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 200
|
||||
reviewers:
|
||||
- "vector-im/element-android-reviewers"
|
||||
allow:
|
||||
- dependency-name: "io.element.android:wysiwyg"
|
||||
- dependency-name: "org.matrix.rustcomponents:crypto-android"
|
||||
- "bmarty"
|
||||
ignore:
|
||||
- dependency-name: com.google.zxing:core
|
||||
|
68
.github/workflows/build.yml
vendored
68
.github/workflows/build.yml
vendored
@@ -7,8 +7,9 @@ on:
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
|
||||
CI_GRADLE_ARG_PROPERTIES: >
|
||||
-Porg.gradle.jvmargs=-Xmx2g
|
||||
-Porg.gradle.parallel=false
|
||||
|
||||
jobs:
|
||||
debug:
|
||||
@@ -25,66 +26,45 @@ jobs:
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Assemble ${{ matrix.target }} debug apk
|
||||
run: ./gradlew assemble${{ matrix.target }}RustCryptoDebug $CI_GRADLE_ARG_PROPERTIES
|
||||
run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
||||
- name: Upload ${{ matrix.target }} debug APKs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: vector-${{ matrix.target }}-debug
|
||||
path: |
|
||||
vector-app/build/outputs/apk/*/debug/*.apk
|
||||
vector/build/outputs/apk/*/debug/*.apk
|
||||
|
||||
release:
|
||||
name: Build unsigned GPlay APKs
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/head/main' && format('build-release-apk-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('build-release-apk-develop-{0}', github.sha) || format('build-debug-{0}', github.ref) }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/head/main' }}
|
||||
if: github.ref == 'refs/heads/main'
|
||||
# Only runs on main, no concurrency.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
# https://github.com/actions/checkout/issues/881
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Assemble GPlay unsigned apk
|
||||
run: ./gradlew clean assembleGplayRustCryptoRelease $CI_GRADLE_ARG_PROPERTIES
|
||||
run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
||||
- name: Upload Gplay unsigned APKs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: vector-gplay-release-unsigned
|
||||
path: |
|
||||
vector-app/build/outputs/apk/*/release/*.apk
|
||||
vector/build/outputs/apk/*/release/*.apk
|
||||
|
||||
exodus:
|
||||
runs-on: ubuntu-latest
|
||||
needs: release
|
||||
steps:
|
||||
- name: Obtain apk from artifact
|
||||
id: download
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: vector-gplay-release-unsigned
|
||||
- name: Show apks in artifact
|
||||
run: ls -R ${{steps.download.outputs.download-path}}
|
||||
- name: Execute exodus-standalone
|
||||
uses: docker://exodusprivacy/exodus-standalone:latest
|
||||
with:
|
||||
args: /github/workspace/gplayRustCrypto/release/vector-gplay-rustCrypto-universal-release-unsigned.apk -j -o /github/workspace/exodus.json
|
||||
- name: Upload exodus json report
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: exodus.json
|
||||
path: |
|
||||
exodus.json
|
||||
- name: Check for trackers
|
||||
run: "jq -e '.trackers == []' exodus.json > /dev/null || { echo '::error static analysis identified user tracking library' ; exit 1; }"
|
||||
# TODO: add exodus checks
|
||||
|
20
.github/workflows/danger.yml
vendored
20
.github/workflows/danger.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Danger CI
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Danger
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: |
|
||||
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
||||
- name: Danger
|
||||
uses: danger/danger-js@11.2.6
|
||||
with:
|
||||
args: "--dangerfile ./tools/danger/dangerfile.js"
|
||||
env:
|
||||
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
|
||||
# Fallback for forks
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
22
.github/workflows/docs.yml
vendored
22
.github/workflows/docs.yml
vendored
@@ -1,22 +0,0 @@
|
||||
name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Generate and publish Android Matrix SDK documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build docs
|
||||
run: ./gradlew dokkaHtml
|
||||
|
||||
- name: Deploy docs
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./matrix-sdk-android/build/dokka/html
|
37
.github/workflows/elementr.yml
vendored
37
.github/workflows/elementr.yml
vendored
@@ -1,37 +0,0 @@
|
||||
name: ER APK Build
|
||||
|
||||
on:
|
||||
pull_request: { }
|
||||
push:
|
||||
branches: [ develop ]
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
|
||||
|
||||
jobs:
|
||||
debug:
|
||||
name: Build debug APKs ER
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref != 'refs/heads/main'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [ Gplay, Fdroid ]
|
||||
# Allow all jobs on develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/develop' && format('elementr-{0}-{1}', matrix.target, github.sha) || format('build-er-debug-{0}-{1}', matrix.target, github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Assemble ${{ matrix.target }} debug apk
|
||||
run: ./gradlew assemble${{ matrix.target }}RustCryptoDebug $CI_GRADLE_ARG_PROPERTIES
|
@@ -1,8 +1,5 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on:
|
||||
pull_request: { }
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
|
355
.github/workflows/nightly.yml
vendored
355
.github/workflows/nightly.yml
vendored
@@ -1,43 +1,338 @@
|
||||
name: Build and release nightly APK
|
||||
name: Nightly Tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ release/* ]
|
||||
schedule:
|
||||
# Every nights at 4
|
||||
- cron: "0 4 * * *"
|
||||
# At 20:00 every day UTC
|
||||
- cron: '0 20 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
|
||||
|
||||
CI_GRADLE_ARG_PROPERTIES: >
|
||||
-Porg.gradle.jvmargs=-Xmx4g
|
||||
-Porg.gradle.parallel=false
|
||||
jobs:
|
||||
nightly:
|
||||
name: Build and publish nightly Gplay APK to Firebase
|
||||
runs-on: ubuntu-latest
|
||||
# Run Android Tests
|
||||
integration-tests:
|
||||
name: Matrix SDK - Running Integration Tests
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
api-level: [ 28 ]
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: 11
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Start synapse server
|
||||
uses: michaelkaye/setup-matrix-synapse@v1.0.1
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
disableRateLimiting: true
|
||||
# package: org.matrix.android.sdk.session
|
||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.session] API[${{ matrix.api-level }}]
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator-session.log
|
||||
chmod 777 emulator-session.log
|
||||
adb logcat >> emulator-session.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.session' matrix-sdk-android:connectedDebugAndroidTest
|
||||
- name: Read Results [org.matrix.android.sdk.session]
|
||||
if: always()
|
||||
id: get-comment-body-session
|
||||
run: python3 ./tools/ci/render_test_output.py session ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
||||
- name: Remove adb logcat
|
||||
if: always()
|
||||
run: pkill -9 adb
|
||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.account] API[${{ matrix.api-level }}]
|
||||
if: always()
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator-account.log
|
||||
chmod 777 emulator-account.log
|
||||
adb logcat >> emulator-account.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.account' matrix-sdk-android:connectedDebugAndroidTest
|
||||
- name: Read Results [org.matrix.android.sdk.account]
|
||||
if: always()
|
||||
id: get-comment-body-account
|
||||
run: python3 ./tools/ci/render_test_output.py account ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
||||
- name: Remove adb logcat
|
||||
if: always()
|
||||
run: pkill -9 adb
|
||||
# package: org.matrix.android.sdk.internal
|
||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.internal] API[${{ matrix.api-level }}]
|
||||
if: always()
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator-internal.log
|
||||
chmod 777 emulator-internal.log
|
||||
adb logcat >> emulator-internal.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.internal' matrix-sdk-android:connectedDebugAndroidTest
|
||||
- name: Read Results [org.matrix.android.sdk.internal]
|
||||
if: always()
|
||||
id: get-comment-body-internal
|
||||
run: python3 ./tools/ci/render_test_output.py internal ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
||||
- name: Remove adb logcat
|
||||
if: always()
|
||||
run: pkill -9 adb
|
||||
# package: org.matrix.android.sdk.ordering
|
||||
- name: Run integration tests for Matrix SDK [org.matrix.android.sdk.ordering] API[${{ matrix.api-level }}]
|
||||
if: always()
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator-ordering.log
|
||||
chmod 777 emulator-ordering.log
|
||||
adb logcat >> emulator-ordering.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.package='org.matrix.android.sdk.ordering' matrix-sdk-android:connectedDebugAndroidTest
|
||||
- name: Read Results [org.matrix.android.sdk.ordering]
|
||||
if: always()
|
||||
id: get-comment-body-ordering
|
||||
run: python3 ./tools/ci/render_test_output.py ordering ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
||||
- name: Remove adb logcat
|
||||
if: always()
|
||||
run: pkill -9 adb
|
||||
# package: class PermalinkParserTest
|
||||
- name: Run integration tests for Matrix SDK class [org.matrix.android.sdk.PermalinkParserTest] API[${{ matrix.api-level }}]
|
||||
if: always()
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator-permalink.log
|
||||
chmod 777 emulator-permalink.log
|
||||
adb logcat >> emulator-permalink.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -Pandroid.testInstrumentationRunnerArguments.class='org.matrix.android.sdk.PermalinkParserTest' matrix-sdk-android:connectedDebugAndroidTest
|
||||
- name: Read Results [org.matrix.android.sdk.PermalinkParserTest]
|
||||
if: always()
|
||||
id: get-comment-body-permalink
|
||||
run: python3 ./tools/ci/render_test_output.py permalink ./matrix-sdk-android/build/outputs/androidTest-results/connected/*.xml
|
||||
- name: Remove adb logcat
|
||||
if: always()
|
||||
run: pkill -9 adb
|
||||
# package: class PermalinkParserTest
|
||||
- name: Find Comment
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Integration Tests Results
|
||||
- name: Publish results to PR
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
### Matrix SDK
|
||||
## Integration Tests Results:
|
||||
- `[org.matrix.android.sdk.session]`<br>${{ steps.get-comment-body-session.outputs.session }}
|
||||
- `[org.matrix.android.sdk.account]`<br>${{ steps.get-comment-body-account.outputs.account }}
|
||||
- `[org.matrix.android.sdk.internal]`<br>${{ steps.get-comment-body-internal.outputs.internal }}
|
||||
- `[org.matrix.android.sdk.ordering]`<br>${{ steps.get-comment-body-ordering.outputs.ordering }}
|
||||
- `[org.matrix.android.sdk.PermalinkParserTest]`<br>${{ steps.get-comment-body-permalink.outputs.permalink }}
|
||||
edit-mode: replace
|
||||
- name: Upload Test Report Log
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: integrationtest-error-results
|
||||
path: |
|
||||
emulator-permalink.log
|
||||
emulator-internal.log
|
||||
emulator-ordering.log
|
||||
emulator-account.log
|
||||
emulator-session.log
|
||||
|
||||
ui-tests:
|
||||
name: UI Tests (Synapse)
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
api-level: [ 28 ]
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: Install towncrier
|
||||
run: |
|
||||
python3 -m pip install towncrier
|
||||
- name: Prepare changelog file
|
||||
run: |
|
||||
mv towncrier.toml towncrier.toml.bak
|
||||
sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml
|
||||
rm towncrier.toml.bak
|
||||
yes n | towncrier build --version nightly
|
||||
- name: Build and upload Gplay Nightly APK
|
||||
run: |
|
||||
./gradlew assembleGplayRustCryptoNightly appDistributionUploadGplayRustCryptoNightly $CI_GRADLE_ARG_PROPERTIES
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Start synapse server
|
||||
uses: michaelkaye/setup-matrix-synapse@v1.0.1
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
disableRateLimiting: true
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- name: Run sanity tests on API ${{ matrix.api-level }}
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator.log
|
||||
chmod 777 emulator.log
|
||||
adb logcat >> emulator.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || (adb pull storage/emulated/0/Pictures/failure_screenshots && exit 1 )
|
||||
- name: Upload Test Report Log
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: uitest-error-results
|
||||
path: |
|
||||
emulator.log
|
||||
failure_screenshots/
|
||||
|
||||
codecov-units:
|
||||
name: Unit tests with code coverage
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- run: ./gradlew allCodeCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
- name: Upload Codecov data
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: codecov-xml
|
||||
path: |
|
||||
build/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml
|
||||
|
||||
sonarqube:
|
||||
name: Sonarqube upload
|
||||
runs-on: macos-latest
|
||||
if: always() && github.event_name == 'schedule'
|
||||
needs:
|
||||
- codecov-units
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: codecov-xml # will restore to allCodeCoverageReport.xml by default; we restore to the same location in following tasks
|
||||
- run: mkdir -p build/reports/jacoco/allCodeCoverageReport/
|
||||
- run: mv allCodeCoverageReport.xml build/reports/jacoco/allCodeCoverageReport/
|
||||
- run: ./gradlew sonarqube $CI_GRADLE_ARG_PROPERTIES
|
||||
env:
|
||||
ELEMENT_ANDROID_NIGHTLY_KEYID: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYID }}
|
||||
ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD }}
|
||||
ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD }}
|
||||
FIREBASE_TOKEN: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_FIREBASE_TOKEN }}
|
||||
ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
||||
# Notify the channel about scheduled runs, or pushes to the release branches, do not notify for manually triggered runs
|
||||
notify:
|
||||
name: Notify matrix
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- integration-tests
|
||||
- ui-tests
|
||||
- sonarqube
|
||||
if: always() && github.event_name != 'workflow_dispatch'
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: michaelkaye/matrix-hookshot-action@v1.0.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
hookshot_url: ${{ secrets.ELEMENT_ANDROID_HOOKSHOT_URL }}
|
||||
text_template: "{{#if '${{ github.event_name }}' == 'schedule' }}Nightly test run{{else}}Test run (on ${{ github.ref }}){{/if }}: {{#each job_statuses }}{{#with this }}{{#if completed }} {{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
|
||||
html_template: "{{#if '${{ github.event_name }}' == 'schedule' }}Nightly test run{{else}}Test run (on ${{ github.ref }}){{/if }}: {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{icon conclusion}} {{name}} <font color='{{color conclusion}}'>{{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a></font>{{/if}}{{/with}}{{/each}}"
|
||||
|
46
.github/workflows/nightly_er.yml
vendored
46
.github/workflows/nightly_er.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Build and release Element R nightly APK
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Every nights at 4
|
||||
- cron: "0 4 * * *"
|
||||
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
|
||||
|
||||
jobs:
|
||||
nightly:
|
||||
name: Build and publish ER nightly Gplay APK to Firebase
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Install towncrier
|
||||
run: |
|
||||
python3 -m pip install towncrier
|
||||
- name: Prepare changelog file
|
||||
run: |
|
||||
mv towncrier.toml towncrier.toml.bak
|
||||
sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml
|
||||
rm towncrier.toml.bak
|
||||
yes n | towncrier build --version nightly
|
||||
- name: Build and upload Gplay Nightly ER APK
|
||||
run: |
|
||||
./gradlew assembleGplayRustCryptoNightly appDistributionUploadGplayRustCryptoNightly $CI_GRADLE_ARG_PROPERTIES
|
||||
env:
|
||||
ELEMENT_ANDROID_NIGHTLY_KEYID: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYID }}
|
||||
ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD }}
|
||||
ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD }}
|
||||
FIREBASE_TOKEN: ${{ secrets.ELEMENT_R_NIGHTLY_FIREBASE_TOKEN }}
|
102
.github/workflows/post-pr.yml
vendored
102
.github/workflows/post-pr.yml
vendored
@@ -1,102 +0,0 @@
|
||||
name: Integration Tests
|
||||
|
||||
# This runs for all closed pull requests against main, including those closed without merge.
|
||||
# Further filtering occurs in 'should-i-run'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches: [develop]
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
|
||||
|
||||
jobs:
|
||||
|
||||
# More info on should-i-run:
|
||||
# If this fails to run (the IF doesn't complete) then the needs will not be satisfied for any of the
|
||||
# other jobs below, so none will run.
|
||||
# except for the notification job at the bottom which will run all the time, unless should-i-run isn't
|
||||
# successful, or all the other jobs have succeeded
|
||||
|
||||
should-i-run:
|
||||
name: Check if PR is suitable for analysis
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.merged # Additionally require PR to have been completely merged.
|
||||
steps:
|
||||
- run: echo "Run those tests!" # no-op success
|
||||
|
||||
ui-tests:
|
||||
name: UI Tests (Synapse)
|
||||
needs: should-i-run
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
timeout-minutes: 90 # We might need to increase it if the time for tests grows
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
api-level: [ 28 ]
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- name: Configure gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
- name: Start synapse server
|
||||
uses: michaelkaye/setup-matrix-synapse@v1.0.4
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
disableRateLimiting: true
|
||||
public_baseurl: "http://10.0.2.2:8080/"
|
||||
- name: Run sanity tests on API ${{ matrix.api-level }}
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
emulator-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator.log
|
||||
chmod 777 emulator.log
|
||||
adb logcat >> emulator.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || (adb pull storage/emulated/0/Pictures/failure_screenshots && exit 1 )
|
||||
- name: Upload Test Report Log
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: uitest-error-results
|
||||
path: |
|
||||
emulator.log
|
||||
failure_screenshots/
|
||||
|
||||
# Notify the channel about delayed failures
|
||||
notify:
|
||||
name: Notify matrix
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- should-i-run
|
||||
- ui-tests
|
||||
if: always() && (needs.should-i-run.result == 'success' ) && (needs.ui-tests.result != 'success')
|
||||
# No concurrency required, runs every time on a schedule.
|
||||
steps:
|
||||
- uses: michaelkaye/matrix-hookshot-action@v1.0.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
hookshot_url: ${{ secrets.ELEMENT_ANDROID_HOOKSHOT_URL }}
|
||||
text_template: "Post-merge validation of ${{ github.head_ref }} into ${{ github.base_ref }} by ${{ github.event.pull_request.merged_by.login }} failed: {{#each job_statuses }}{{#with this }}{{#if completed }} {{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
|
||||
html_template: "Post-merge validation of ${{ github.head_ref }} into ${{ github.base_ref }} by ${{ github.event.pull_request.merged_by.login }} failed: {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{icon conclusion}} {{name}} <font color='{{color conclusion}}'>{{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a></font>{{/if}}{{/with}}{{/each}}"
|
161
.github/workflows/quality.yml
vendored
161
.github/workflows/quality.yml
vendored
@@ -5,11 +5,6 @@ on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -XX:MaxPermSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Project Check Suite
|
||||
@@ -19,78 +14,136 @@ jobs:
|
||||
- name: Run code quality check suite
|
||||
run: ./tools/check/check_code_quality.sh
|
||||
|
||||
# Knit for all the modules (https://github.com/Kotlin/kotlinx-knit)
|
||||
knit:
|
||||
name: Knit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run knit
|
||||
run: |
|
||||
./gradlew knitCheck $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
# Check the project: ktlint, detekt, lint
|
||||
lint:
|
||||
name: Android Linter
|
||||
# ktlint for all the modules
|
||||
ktlint:
|
||||
name: Kotlin Linter
|
||||
runs-on: ubuntu-latest
|
||||
# Allow all jobs on main and develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('lint-develop-{0}', github.sha) || format('lint-{0}', github.ref) }}
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('ktlint-develop-{0}', github.sha) || format('ktlint-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run ktlint
|
||||
run: |
|
||||
./gradlew ktlintCheck $CI_GRADLE_ARG_PROPERTIES --continue
|
||||
- name: Run detekt
|
||||
if: always()
|
||||
run: |
|
||||
./gradlew detekt $CI_GRADLE_ARG_PROPERTIES
|
||||
- name: Run lint
|
||||
# Not always, if ktlint or detekt fail, avoid running the long lint check.
|
||||
run: |
|
||||
./gradlew vector-app:lintGplayKotlinCryptoRelease $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew vector-app:lintFdroidKotlinCryptoRelease $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew vector-app:lintGplayRustCryptoRelease $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew vector-app:lintFdroidRustCryptoRelease $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew ktlintCheck --continue
|
||||
- name: Upload reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linting-report
|
||||
name: ktlinting-report
|
||||
path: |
|
||||
*/build/reports/**/*.*
|
||||
- name: Prepare Danger
|
||||
*/build/reports/ktlint/ktlint*/ktlint*.txt
|
||||
- name: Handle Results
|
||||
if: always()
|
||||
id: ktlint-results
|
||||
run: |
|
||||
npm install --save-dev @babel/core
|
||||
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
||||
yarn add danger-plugin-lint-report --dev
|
||||
- name: Danger lint
|
||||
if: always()
|
||||
uses: danger/danger-js@11.2.6
|
||||
results="$(cat */*/build/reports/ktlint/ktlint*/ktlint*.txt */build/reports/ktlint/ktlint*/ktlint*.txt | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g")"
|
||||
if [ -z "$results" ]; then
|
||||
echo "::set-output name=add_comment::false"
|
||||
else
|
||||
body="👎\`Failed${results}\`"
|
||||
body="${body//'%'/'%25'}"
|
||||
body="${body//$'\n'/'%0A'}"
|
||||
body="${body//$'\r'/'%0D'}"
|
||||
body="$( echo $body | sed 's/\/home\/runner\/work\/element-android\/element-android\//\`<br\/>\`/g')"
|
||||
body="$( echo $body | sed 's/\/src\/main\/java\// 🔸 /g')"
|
||||
body="$( echo $body | sed 's/im\/vector\/app\///g')"
|
||||
body="$( echo $body | sed 's/im\/vector\/lib\/attachmentviewer\///g')"
|
||||
body="$( echo $body | sed 's/im\/vector\/lib\/multipicker\///g')"
|
||||
body="$( echo $body | sed 's/im\/vector\/lib\///g')"
|
||||
body="$( echo $body | sed 's/org\/matrix\/android\/sdk\///g')"
|
||||
body="$( echo $body | sed 's/\/src\/androidTest\/java\// 🔸 /g')"
|
||||
echo "::set-output name=add_comment::true"
|
||||
echo "::set-output name=body::$body"
|
||||
fi
|
||||
- name: Find Comment
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: fc
|
||||
with:
|
||||
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
|
||||
env:
|
||||
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
|
||||
# Fallback for forks
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Ktlint Results
|
||||
- name: Add comment if needed
|
||||
if: always() && github.event_name == 'pull_request' && steps.ktlint-results.outputs.add_comment == 'true'
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
### Ktlint Results
|
||||
|
||||
# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
|
||||
dependency-analysis:
|
||||
name: Dependency analysis
|
||||
${{ steps.ktlint-results.outputs.body }}
|
||||
edit-mode: replace
|
||||
- name: Delete comment if needed
|
||||
if: always() && github.event_name == 'pull_request' && steps.fc.outputs.comment-id != '' && steps.ktlint-results.outputs.add_comment == 'false'
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
github.issues.deleteComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: ${{ steps.fc.outputs.comment-id }}
|
||||
})
|
||||
|
||||
# Lint for main module
|
||||
android-lint:
|
||||
name: Android Linter
|
||||
runs-on: ubuntu-latest
|
||||
# Allow all jobs on main and develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('dep-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('dep-develop-{0}', github.sha) || format('dep-{0}', github.ref) }}
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('android-lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('android-lint-develop-{0}', github.sha) || format('android-lint-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Dependency analysis
|
||||
run: ./gradlew dependencyCheckAnalyze $CI_GRADLE_ARG_PROPERTIES
|
||||
- name: Upload dependency analysis
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Lint analysis
|
||||
run: ./gradlew clean :vector:lint --stacktrace
|
||||
- name: Upload reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dependency-analysis
|
||||
path: build/reports/dependency-check-report.html
|
||||
name: lint-report
|
||||
path: |
|
||||
vector/build/reports/*.*
|
||||
|
||||
# Lint for Gplay and Fdroid release APK
|
||||
apk-lint:
|
||||
name: Lint APK (${{ matrix.target }})
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref != 'refs/heads/main'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [ Gplay, Fdroid ]
|
||||
# Allow all jobs on develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/develop' && format('apk-lint-develop-{0}-{1}', matrix.target, github.sha) || format('apk-lint-{0}-{1}', matrix.target, github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Lint ${{ matrix.target }} release
|
||||
run: ./gradlew clean lint${{ matrix.target }}Release --stacktrace
|
||||
- name: Upload ${{ matrix.target }} linting report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: release-lint-report-${{ matrix.target }}
|
||||
path: |
|
||||
vector/build/reports/*.*
|
||||
|
13
.github/workflows/sync-from-external-sources.yml
vendored
13
.github/workflows/sync-from-external-sources.yml
vendored
@@ -1,6 +1,5 @@
|
||||
name: Sync Data From External Sources
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# At 00:00 on every Monday UTC
|
||||
- cron: '0 0 * * 1'
|
||||
@@ -14,7 +13,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install Prerequisite dependencies
|
||||
@@ -24,7 +23,7 @@ jobs:
|
||||
- name: Run Emoji script
|
||||
run: ./tools/import_emojis.py
|
||||
- name: Create Pull Request for Emojis
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: Sync Emojis
|
||||
title: Sync Emojis
|
||||
@@ -41,7 +40,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install Prerequisite dependencies
|
||||
@@ -50,7 +49,7 @@ jobs:
|
||||
- name: Run SAS String script
|
||||
run: ./tools/import_sas_strings.py
|
||||
- name: Create Pull Request for SAS Strings
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: Sync SAS Strings
|
||||
title: Sync SAS Strings
|
||||
@@ -69,7 +68,7 @@ jobs:
|
||||
- name: Run analytics import script
|
||||
run: ./tools/import_analytic_plan.sh
|
||||
- name: Create Pull Request for analytics plan
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: Sync analytics plan
|
||||
title: Sync analytics plan
|
||||
@@ -81,4 +80,4 @@ jobs:
|
||||
|
||||
*Note*: Change are coming from [this project](https://github.com/matrix-org/matrix-analytics-events)
|
||||
branch: sync-analytics-plan
|
||||
base: develop
|
||||
base: develop
|
102
.github/workflows/tests-rust.yml
vendored
102
.github/workflows/tests-rust.yml
vendored
@@ -1,102 +0,0 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
pull_request: { }
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx5g -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx3g" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Runs all tests with rust crypto
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
timeout-minutes: 90 # We might need to increase it if the time for tests grows
|
||||
strategy:
|
||||
matrix:
|
||||
api-level: [28]
|
||||
# Allow all jobs on main and develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-rust-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-rust-{0}', github.sha) || format('unit-tests-rust-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: true
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
gradle-home-cache-cleanup: ${{ github.ref == 'refs/heads/develop' }}
|
||||
|
||||
# - name: Run screenshot tests
|
||||
# run: ./gradlew verifyScreenshots $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
# - name: Archive Screenshot Results on Error
|
||||
# if: failure()
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: screenshot-results
|
||||
# path: |
|
||||
# **/out/failures/
|
||||
# **/build/reports/tests/*UnitTest/
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: michaelkaye/setup-matrix-synapse@v1.0.4
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
disableRateLimiting: true
|
||||
public_baseurl: "http://10.0.2.2:8080/"
|
||||
|
||||
- name: Run all the codecoverage tests at once
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
# continue-on-error: true
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
target: playstore
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
# emulator-build: 7425822
|
||||
script: |
|
||||
./gradlew gatherGplayRustCryptoDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew instrumentationTestsRustWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
- name: Upload Rust Integration Test Report Log
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: integration-test-rust-error-results
|
||||
path: |
|
||||
*/build/outputs/androidTest-results/connected/
|
||||
*/build/reports/androidTests/connected/
|
||||
|
||||
# For now ignore sonar
|
||||
# - name: Publish results to Sonar
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any
|
||||
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
# ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
|
||||
# if: ${{ always() && env.GITHUB_TOKEN != '' && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }}
|
||||
# run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
- name: Format unit test results
|
||||
if: always()
|
||||
run: python3 ./tools/ci/render_test_output.py unit ./**/build/test-results/**/*.xml
|
||||
|
||||
|
190
.github/workflows/tests.yml
vendored
190
.github/workflows/tests.yml
vendored
@@ -1,150 +1,84 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
pull_request: { }
|
||||
pull_request: {}
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
branches: [main, develop]
|
||||
|
||||
# Enrich gradle.properties for CI/CD
|
||||
env:
|
||||
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
|
||||
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon
|
||||
CI_GRADLE_ARG_PROPERTIES: >
|
||||
-Porg.gradle.jvmargs=-Xmx2g
|
||||
-Porg.gradle.parallel=false
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Runs all tests
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
timeout-minutes: 90 # We might need to increase it if the time for tests grows
|
||||
strategy:
|
||||
matrix:
|
||||
api-level: [28]
|
||||
# Build Android Tests
|
||||
build-android-tests:
|
||||
name: Build Android Tests
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: 11
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Build Android Tests
|
||||
run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
||||
|
||||
unit-tests:
|
||||
name: Run Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
# Allow all jobs on main and develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
lfs: true
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '11'
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
gradle-home-cache-cleanup: ${{ github.ref == 'refs/heads/develop' }}
|
||||
|
||||
- name: Run screenshot tests
|
||||
run: ./gradlew verifyScreenshots $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
- name: Archive Screenshot Results on Error
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: screenshot-results
|
||||
path: |
|
||||
**/out/failures/
|
||||
**/build/reports/tests/*UnitTest/
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- uses: michaelkaye/setup-matrix-synapse@v1.0.4
|
||||
with:
|
||||
uploadLogs: true
|
||||
httpPort: 8080
|
||||
disableRateLimiting: true
|
||||
public_baseurl: "http://10.0.2.2:8080/"
|
||||
|
||||
- name: Run all the codecoverage tests at once
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
# continue-on-error: true
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
target: playstore
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
# emulator-build: 7425822
|
||||
script: |
|
||||
./gradlew gatherGplayKotlinCryptoDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves steps.tests.outcome = 'failure'
|
||||
### - name: Run all the codecoverage tests at once (retry if emulator failed)
|
||||
### uses: reactivecircus/android-emulator-runner@v2
|
||||
### if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
|
||||
### with:
|
||||
### api-level: 28
|
||||
### arch: x86
|
||||
### profile: Nexus 5X
|
||||
### force-avd-creation: false
|
||||
### emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
### disable-animations: true
|
||||
### emulator-build: 7425822
|
||||
### script: |
|
||||
### ./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||
### ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
### ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
### ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
- name: Upload Integration Test Report Log
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: integration-test-error-results
|
||||
path: |
|
||||
*/build/outputs/androidTest-results/connected/
|
||||
*/build/reports/androidTests/connected/
|
||||
|
||||
# we may have failed a previous step and retried, that's OK
|
||||
- name: Publish results to Sonar
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.SONARQUBE_GITHUB_API_TOKEN }} # Needed to get PR information, if any
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }}
|
||||
if: ${{ always() && env.GITHUB_TOKEN != '' && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }}
|
||||
run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Run unit tests
|
||||
run: ./gradlew clean test $CI_GRADLE_ARG_PROPERTIES --stacktrace
|
||||
- name: Format unit test results
|
||||
if: always()
|
||||
run: python3 ./tools/ci/render_test_output.py unit ./**/build/test-results/**/*.xml
|
||||
- name: Publish Unit Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
if: always() &&
|
||||
github.event.sender.login != 'dependabot[bot]' &&
|
||||
( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
|
||||
with:
|
||||
files: ./**/build/test-results/**/*.xml
|
||||
|
||||
# can't be run on macos due to containers.
|
||||
# - name: Publish Unit Test Results
|
||||
# uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
# if: always() &&
|
||||
# github.event.sender.login != 'dependabot[bot]' &&
|
||||
# ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
|
||||
# with:
|
||||
# files: ./**/build/test-results/**/*.xml
|
||||
|
||||
# Unneeded as part of the test suite above, kept around in case we want to re-enable them.
|
||||
#
|
||||
# # Build Android Tests
|
||||
# build-android-tests:
|
||||
# name: Build Android Tests
|
||||
# runs-on: ubuntu-latest
|
||||
# concurrency:
|
||||
# group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('build-android-tests-{0}', github.ref) }}
|
||||
# cancel-in-progress: true
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: actions/setup-java@v3
|
||||
# with:
|
||||
# distribution: 'adopt'
|
||||
# java-version: 11
|
||||
# - name: Configure gradle
|
||||
# uses: gradle/gradle-build-action@v2
|
||||
# with:
|
||||
# cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||
# - name: Build Android Tests
|
||||
# run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES
|
||||
# Notify the channel about runs against develop or main that have failures, as PRs should have caught these first.
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- unit-tests
|
||||
- build-android-tests
|
||||
if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' ) && failure() }}
|
||||
steps:
|
||||
- uses: michaelkaye/matrix-hookshot-action@v0.3.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
matrix_access_token: ${{ secrets.ELEMENT_ANDROID_NOTIFICATION_ACCESS_TOKEN }}
|
||||
matrix_room_id: ${{ secrets.ELEMENT_ANDROID_INTERNAL_ROOM_ID }}
|
||||
text_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}{{name}} {{conclusion}} at {{completed_at}}, {{/if}}{{/with}}{{/each}}"
|
||||
html_template: "Build is broken for ${{ github.ref }}: {{#each job_statuses }}{{#with this }}{{#if completed }}<br />{{icon conclusion }} {{name}} <font color='{{color conclusion }}'>{{conclusion}} at {{completed_at}} <a href=\"{{html_url}}\">[details]</a></font>{{/if}}{{/with}}{{/each}}"
|
||||
|
||||
|
10
.github/workflows/triage-incoming.yml
vendored
10
.github/workflows/triage-incoming.yml
vendored
@@ -10,16 +10,8 @@ jobs:
|
||||
# Skip in forks
|
||||
if: github.repository == 'vector-im/element-android'
|
||||
steps:
|
||||
- uses: alex-page/github-project-automation-plus@7ffb872c64bd809d23563a130a0a97d01dfa8f43
|
||||
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
|
||||
with:
|
||||
project: Issue triage
|
||||
column: Incoming
|
||||
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
triage-new-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/91
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
334
.github/workflows/triage-labelled.yml
vendored
334
.github/workflows/triage-labelled.yml
vendored
@@ -9,16 +9,15 @@ jobs:
|
||||
name: Add Z-Labs label for features behind labs flags
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'A-Maths') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Tags') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
|
||||
contains(github.event.issue.labels.*.name, 'A-Maths') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Tags')
|
||||
steps:
|
||||
- uses: actions/github-script@v5
|
||||
with:
|
||||
@@ -30,23 +29,6 @@ jobs:
|
||||
labels: ['Z-Labs']
|
||||
})
|
||||
|
||||
apply_Help-Wanted_label:
|
||||
name: Add "Help Wanted" label to all "good first issue" and Hacktoberfest
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'good first issue') ||
|
||||
contains(github.event.issue.labels.*.name, 'Hacktoberfest')
|
||||
steps:
|
||||
- uses: actions/github-script@v5
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['Help Wanted']
|
||||
})
|
||||
|
||||
move_needs_info_issues:
|
||||
name: X-Needs-Info issues to Need info column on triage board
|
||||
runs-on: ubuntu-latest
|
||||
@@ -60,35 +42,215 @@ jobs:
|
||||
column-name: "Need info"
|
||||
label-name: "X-Needs-Info"
|
||||
|
||||
add_design_issues_to_project:
|
||||
name: X-Needs-Design to Design project board
|
||||
add_priority_design_issues_to_project:
|
||||
name: P1 X-Needs-Design to Design project board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
|
||||
(contains(github.event.issue.labels.*.name, 'S-Critical') &&
|
||||
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
|
||||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
|
||||
(contains(github.event.issue.labels.*.name, 'S-Major') &&
|
||||
contains(github.event.issue.labels.*.name, 'O-Frequent')) ||
|
||||
contains(github.event.issue.labels.*.name, 'A11y'))
|
||||
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
|
||||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
|
||||
contains(github.event.issue.labels.*.name, 'S-Major') &&
|
||||
contains(github.event.issue.labels.*.name, 'O-Frequent') ||
|
||||
contains(github.event.issue.labels.*.name, 'A11y') &&
|
||||
contains(github.event.issue.labels.*.name, 'O-Frequent'))
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
id: add_to_project
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/18
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc0sUA"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
add_product_issues:
|
||||
name: X-Needs-Product to Product project board
|
||||
name: X-Needs-Product to Design project board
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
|
||||
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
id: add_to_project
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/28
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc4AAg6N"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
delight_issues_to_board:
|
||||
name: Spaces issues to Delight project board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
(contains(github.event.issue.labels.*.name, 'A-Spaces') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Space-Settings') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Subspaces') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-IA'))
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc1HvQ"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_voice-message_issues:
|
||||
name: A-Voice Messages to voice message board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
contains(github.event.issue.labels.*.name, 'A-Voice Messages')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc2KCw"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_threads_issues:
|
||||
name: A-Threads to Thread board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
contains(github.event.issue.labels.*.name, 'A-Threads')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc0rRA"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_message_bubbles_issues:
|
||||
name: A-Message-Bubbles to Message bubbles board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc3m-g"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_ftue_issues:
|
||||
name: Z-FTUE to Mobile FTUE board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
contains(github.event.issue.labels.*.name, 'Z-FTUE')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc4AAqVx"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_WTF_issues:
|
||||
name: Z-WTF to WTF board
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
contains(github.event.issue.labels.*.name, 'Z-WTF')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc4AArk0"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
move_element_x_issues:
|
||||
name: ElementX issues to ElementX project board
|
||||
@@ -96,75 +258,23 @@ jobs:
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
(contains(github.event.issue.labels.*.name, 'Z-BBQ-Alpha') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-BBQ-Beta') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-BBQ-Release') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-Banquet-Alpha') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-Banquet-Beta') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-Banquet-Release'))
|
||||
(contains(github.event.issue.labels.*.name, 'Z-ElementX-Alpha') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-ElementX-Beta') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-ElementX'))
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/43
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
ex_plorers:
|
||||
name: Add labelled issues to X-Plorer project
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'Team: Element X Feature')
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/73
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
ps_features1:
|
||||
name: Add labelled issues to PS features team 1
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
||||
(contains(github.event.issue.labels.*.name, 'A-Voice-Messages') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-Broadcast')) ||
|
||||
(contains(github.event.issue.labels.*.name, 'A-Session-Mgmt') &&
|
||||
contains(github.event.issue.labels.*.name, 'A-User-Settings'))
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/56
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
ps_features2:
|
||||
name: Add labelled issues to PS features team 2
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'A-DM-Start') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Broadcast')
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/58
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
ps_features3:
|
||||
name: Add labelled issues to PS features team 3
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/57
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
voip:
|
||||
name: Add labelled issues to VoIP project board
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'Team: VoIP')
|
||||
steps:
|
||||
- uses: actions/add-to-project@main
|
||||
with:
|
||||
project-url: https://github.com/orgs/vector-im/projects/41
|
||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc4ABTXY"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
@@ -60,8 +60,8 @@ jobs:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!, $contentid:ID!) {
|
||||
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
|
||||
item {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.pull_request.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PVT_kwDOAM0swc0sUA"
|
||||
PROJECT_ID: "PN_kwDOAM0swc0sUA"
|
||||
TEAM: "design"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
@@ -129,8 +129,8 @@ jobs:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!, $contentid:ID!) {
|
||||
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
|
||||
item {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -138,6 +138,6 @@ jobs:
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.pull_request.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PVT_kwDOAM0swc4AAg6N"
|
||||
PROJECT_ID: "PN_kwDOAM0swc4AAg6N"
|
||||
TEAM: "product"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
11
.github/workflows/triage-priority-bugs.yml
vendored
11
.github/workflows/triage-priority-bugs.yml
vendored
@@ -14,7 +14,10 @@ jobs:
|
||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-Spaces') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') &&
|
||||
!contains(github.event.issue.labels.*.name, 'A-Subspaces')) &&
|
||||
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
|
||||
contains(github.event.issue.labels.*.name, 'S-Critical') &&
|
||||
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
|
||||
@@ -24,10 +27,10 @@ jobs:
|
||||
contains(github.event.issue.labels.*.name, 'A11y') &&
|
||||
contains(github.event.issue.labels.*.name, 'O-Frequent'))
|
||||
steps:
|
||||
- uses: alex-page/github-project-automation-plus@7ffb872c64bd809d23563a130a0a97d01dfa8f43
|
||||
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
|
||||
with:
|
||||
project: Android App Team
|
||||
column: Important Issues & Topics (P1)
|
||||
column: P1
|
||||
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
P1_issues_to_crypto_team_workboard:
|
||||
@@ -50,7 +53,7 @@ jobs:
|
||||
contains(github.event.issue.labels.*.name, 'A11y') &&
|
||||
contains(github.event.issue.labels.*.name, 'O-Frequent')))
|
||||
steps:
|
||||
- uses: alex-page/github-project-automation-plus@7ffb872c64bd809d23563a130a0a97d01dfa8f43
|
||||
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
|
||||
with:
|
||||
project: Crypto Team
|
||||
column: Ready
|
||||
|
2
.github/workflows/triage-unlabelled.yml
vendored
2
.github/workflows/triage-unlabelled.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Move issue
|
||||
uses: alex-page/github-project-automation-plus@7ffb872c64bd809d23563a130a0a97d01dfa8f43
|
||||
uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
|
||||
if: ${{ env.ALREADY_IN_BOARD == 'true' }}
|
||||
with:
|
||||
project: Issue triage
|
||||
|
15
.github/workflows/validate-lfs.yml
vendored
15
.github/workflows/validate-lfs.yml
vendored
@@ -1,15 +0,0 @@
|
||||
name: Validate Git LFS
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Validate
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
lfs: 'true'
|
||||
|
||||
- run: |
|
||||
./tools/validate_lfs.sh
|
15
.gitignore
vendored
15
.gitignore
vendored
@@ -5,28 +5,15 @@
|
||||
.idea/caches
|
||||
.idea/libraries
|
||||
.idea/inspectionProfiles
|
||||
.idea/sonarlint
|
||||
.idea/*.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/benchmark-out
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
rust-sdk/target/*
|
||||
rust-sdk/src/uniffi/*
|
||||
Cargo.lock
|
||||
|
||||
/tmp
|
||||
/fastlane/private
|
||||
/fastlane/report.xml
|
||||
|
||||
/**/build
|
||||
|
||||
# Added by yarn
|
||||
/package.json
|
||||
/yarn.lock
|
||||
/node_modules
|
||||
**/out/failures
|
||||
|
||||
# For manual dependency to rust crypto sdk
|
||||
library/rustCrypto/matrix-rust-sdk-crypto.aar
|
||||
/library/build
|
||||
|
3
.idea/codeStyles/Project.xml
generated
3
.idea/codeStyles/Project.xml
generated
@@ -8,7 +8,8 @@
|
||||
</value>
|
||||
</option>
|
||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||
<option name="LINE_BREAK_AFTER_MULTILINE_WHEN_ENTRY" value="false" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
||||
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="true" />
|
||||
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="true" />
|
||||
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="true" />
|
||||
|
1
.idea/codeStyles/codeStyleConfig.xml
generated
1
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +1,6 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
2
.idea/dictionaries/bmarty.xml
generated
2
.idea/dictionaries/bmarty.xml
generated
@@ -40,11 +40,9 @@
|
||||
<w>sygnal</w>
|
||||
<w>threepid</w>
|
||||
<w>uisi</w>
|
||||
<w>unifiedpush</w>
|
||||
<w>unpublish</w>
|
||||
<w>unwedging</w>
|
||||
<w>vctr</w>
|
||||
<w>vodozemac</w>
|
||||
<w>wellknown</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
18
.travis.yml
Normal file
18
.travis.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
# FTR: Configuration on https://travis-ci.org/github/vector-im/element-android/settings
|
||||
#
|
||||
# - Build only if .travis.yml is present -> On
|
||||
# - Limit concurrent jobs -> Off
|
||||
# - Build pushed branches -> On (build the branch)
|
||||
# - Build pushed pull request -> On (build the PR after auto-merge)
|
||||
#
|
||||
# - Auto cancel branch builds -> On
|
||||
# - Auto cancel pull request builds -> On
|
||||
|
||||
sudo: false
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
# Just run a simple script here
|
||||
script:
|
||||
- ./tools/travis/check_pr.sh
|
1277
CHANGES.md
1277
CHANGES.md
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,10 @@
|
||||
# Contributing to Element Android
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Contributing code to Matrix](#contributing-code-to-matrix)
|
||||
* [Android Studio settings](#android-studio-settings)
|
||||
* [Template](#template)
|
||||
* [Compilation](#compilation)
|
||||
* [I want to help translating Element](#i-want-to-help-translating-element)
|
||||
* [I want to submit a PR to fix an issue](#i-want-to-submit-a-pr-to-fix-an-issue)
|
||||
* [Kotlin](#kotlin)
|
||||
* [Changelog](#changelog)
|
||||
* [Code quality](#code-quality)
|
||||
* [Internal tool](#internal-tool)
|
||||
* [ktlint](#ktlint)
|
||||
* [knit](#knit)
|
||||
* [lint](#lint)
|
||||
* [Unit tests](#unit-tests)
|
||||
* [Tests](#tests)
|
||||
* [Internationalisation](#internationalisation)
|
||||
* [Adding new string](#adding-new-string)
|
||||
* [Plurals](#plurals)
|
||||
* [Editing existing strings](#editing-existing-strings)
|
||||
* [Removing existing strings](#removing-existing-strings)
|
||||
* [Renaming string ids](#renaming-string-ids)
|
||||
* [Reordering strings](#reordering-strings)
|
||||
* [Accessibility](#accessibility)
|
||||
* [Layout](#layout)
|
||||
* [Authors](#authors)
|
||||
* [Thanks](#thanks)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Contributing code to Matrix
|
||||
# Contributing code to Matrix
|
||||
|
||||
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
|
||||
|
||||
Element Android support can be found in this room: [](https://matrix.to/#/#element-android:matrix.org).
|
||||
|
||||
The rest of the document contains specific rules for Matrix Android projects
|
||||
# Specific rules for Matrix Android projects
|
||||
|
||||
## Android Studio settings
|
||||
|
||||
@@ -127,23 +94,6 @@ Note that you can run
|
||||
|
||||
For ktlint to fix some detected errors for you (you still have to check and commit the fix of course)
|
||||
|
||||
#### knit
|
||||
|
||||
[knit](https://github.com/Kotlin/kotlinx-knit) is a tool which checks markdown files on the project. Also it generates/updates the table of content (toc) of the markdown files.
|
||||
|
||||
So everytime the toc should be updated, just run
|
||||
<pre>
|
||||
./gradlew knit
|
||||
</pre>
|
||||
|
||||
and commit the changes.
|
||||
|
||||
The CI will check that markdown files are up to date by running
|
||||
|
||||
<pre>
|
||||
./gradlew knitCheck
|
||||
</pre>
|
||||
|
||||
#### lint
|
||||
|
||||
<pre>
|
||||
@@ -170,21 +120,17 @@ You should consider adding Unit tests with your PR, and also integration tests (
|
||||
|
||||
Translations are handled using an external tool: [Weblate](https://translate.element.io/projects/element-android/)
|
||||
|
||||
**As a general rule, please never edit or add or remove translations to the project in a Pull Request**. It can lead to merge conflict if the translations are also modified in Weblate side. Pull Request containing change(s) on the translation files cannot be merged.
|
||||
As a general rule, please never edit or add or remove translations to the project in a Pull Request. It can lead to merge conflict if the translations are also modified in Weblate side.
|
||||
|
||||
#### Adding new string
|
||||
|
||||
When adding new string resources, please only add new entries in the file `values/strings.xml` ([this file](./library/ui-strings/src/main/res/values/strings.xml)). Translations will be added later by the community of translators using Weblate.
|
||||
When adding new string resources, please only add new entries in the file `value/strings.xml`. Translations will be added later by the community of translators using Weblate.
|
||||
|
||||
The file `values/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings.
|
||||
The file `value/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings.
|
||||
|
||||
New strings can be added anywhere in the file `values/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file.
|
||||
New strings can be added anywhere in the file `value/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file.
|
||||
|
||||
##### Plurals
|
||||
|
||||
Please use `plurals` resources when appropriate, and note that some languages have specific rules for `plurals`, so even if the string will always be at the plural form for English, please always create a `plurals` resource.
|
||||
|
||||
Specific plural forms can be found [here](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html).
|
||||
Do not hesitate to use plurals when appropriate.
|
||||
|
||||
#### Editing existing strings
|
||||
|
||||
@@ -204,23 +150,6 @@ And add `tools:ignore="UnusedResources"` to the string, to let lint ignore that
|
||||
|
||||
The string will be removed during the next sync with Weblate.
|
||||
|
||||
#### Renaming string ids
|
||||
|
||||
This is possible to rename ids of the String resources, but since translation files cannot be edited, add TODO in the main strings.xml file above the strings you want to rename.
|
||||
|
||||
```xml
|
||||
<!-- TODO Rename id to put_new_id_here -->
|
||||
<string name="current_id">Hello Matrix world!</string>
|
||||
```
|
||||
|
||||
The string id(s) will be renamed during the next Weblate sync.
|
||||
|
||||
#### Reordering strings
|
||||
|
||||
To group strings per feature, or for any other reasons, it is possible to reorder string resources, but only in the [main strings.xml file](./library/ui-strings/src/main/res/values/strings.xml). ). We do not mind about ordering in the translation files, and anyway this is forbidden to edit manually the translation files.
|
||||
|
||||
It is also possible to add empty lines between string resources, and to add XML comments. Please note that the XML comment just above a String resource will also appear on Weblate and be visible to the translators.
|
||||
|
||||
### Accessibility
|
||||
|
||||
Please consider accessibility as an important point. As a minimum requirement, in layout XML files please use attributes such as `android:contentDescription` and `android:importantForAccessibility`, and test with a screen reader if it's working well. You can add new string resources, dedicated to accessibility, in this case, please prefix theirs id with `a11y_`.
|
||||
|
168
Gemfile.lock
168
Gemfile.lock
@@ -1,72 +1,50 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.5)
|
||||
rexml
|
||||
CFPropertyList (3.0.3)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
artifactory (3.0.15)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.619.0)
|
||||
aws-sdk-core (3.132.0)
|
||||
aws-eventstream (1.1.1)
|
||||
aws-partitions (1.479.0)
|
||||
aws-sdk-core (3.117.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.525.0)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.58.0)
|
||||
aws-sdk-core (~> 3, >= 3.127.0)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-kms (1.44.0)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.114.0)
|
||||
aws-sdk-core (~> 3, >= 3.127.0)
|
||||
aws-sdk-s3 (1.96.1)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.4)
|
||||
aws-sigv4 (1.5.1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.4)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
claide (1.1.0)
|
||||
claide-plugins (0.9.2)
|
||||
cork
|
||||
nap
|
||||
open4 (~> 1.3)
|
||||
claide (1.0.3)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
cork (0.3.0)
|
||||
colored2 (~> 3.1)
|
||||
danger (8.6.1)
|
||||
claide (~> 1.0)
|
||||
claide-plugins (>= 0.9.2)
|
||||
colored2 (~> 3.1)
|
||||
cork (~> 0.1)
|
||||
faraday (>= 0.9.0, < 2.0)
|
||||
faraday-http-cache (~> 2.0)
|
||||
git (~> 1.7)
|
||||
kramdown (~> 2.3)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
no_proxy_fix
|
||||
octokit (~> 4.7)
|
||||
terminal-table (>= 1, < 4)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.6.4)
|
||||
digest-crc (0.6.3)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
excon (0.92.4)
|
||||
faraday (1.10.1)
|
||||
dotenv (2.7.6)
|
||||
emoji_regex (3.2.2)
|
||||
excon (0.85.0)
|
||||
faraday (1.5.1)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-httpclient (~> 1.0.1)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.1)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
faraday (>= 0.8.0)
|
||||
@@ -74,22 +52,16 @@ GEM
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-http-cache (2.4.1)
|
||||
faraday (>= 0.8)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.4)
|
||||
multipart-post (~> 2)
|
||||
faraday-net_http (1.0.1)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.0)
|
||||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.6)
|
||||
fastlane (2.209.0)
|
||||
fastimage (2.2.4)
|
||||
fastlane (2.187.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
babosa (>= 1.0.3, < 2.0.0)
|
||||
@@ -104,7 +76,7 @@ GEM
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-androidpublisher_v3 (~> 0.1)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
@@ -113,7 +85,6 @@ GEM
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (~> 2.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (~> 0.1.1)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.3)
|
||||
@@ -127,12 +98,9 @@ GEM
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
gh_inspector (1.1.3)
|
||||
git (1.13.0)
|
||||
addressable (~> 2.8)
|
||||
rchardet (~> 1.8)
|
||||
google-apis-androidpublisher_v3 (0.25.0)
|
||||
google-apis-core (>= 0.7, < 2.a)
|
||||
google-apis-core (0.7.0)
|
||||
google-apis-androidpublisher_v3 (0.8.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-core (0.4.0)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
@@ -141,64 +109,52 @@ GEM
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
webrick
|
||||
google-apis-iamcredentials_v1 (0.13.0)
|
||||
google-apis-core (>= 0.7, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.10.0)
|
||||
google-apis-core (>= 0.7, < 2.a)
|
||||
google-apis-storage_v1 (0.17.0)
|
||||
google-apis-core (>= 0.7, < 2.a)
|
||||
google-apis-iamcredentials_v1 (0.6.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.5.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-storage_v1 (0.6.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-cloud-core (1.6.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.2.0)
|
||||
google-cloud-storage (1.38.0)
|
||||
addressable (~> 2.8)
|
||||
google-cloud-env (1.5.0)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
google-cloud-errors (1.1.0)
|
||||
google-cloud-storage (1.34.1)
|
||||
addressable (~> 2.5)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.17.0)
|
||||
google-apis-storage_v1 (~> 0.1)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.2.0)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
googleauth (0.16.2)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
signet (~> 0.14)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.5)
|
||||
http-cookie (1.0.4)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.6.1)
|
||||
json (2.6.2)
|
||||
jwt (2.4.1)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
jmespath (1.4.0)
|
||||
json (2.5.1)
|
||||
jwt (2.2.3)
|
||||
memoist (0.16.2)
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.2)
|
||||
mini_mime (1.1.0)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.0.0)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
naturally (2.2.1)
|
||||
no_proxy_fix (0.1.2)
|
||||
octokit (4.25.1)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
open4 (1.3.4)
|
||||
optparse (0.1.1)
|
||||
os (1.1.4)
|
||||
os (1.1.1)
|
||||
plist (3.6.0)
|
||||
public_suffix (4.0.7)
|
||||
public_suffix (4.0.6)
|
||||
rake (13.0.6)
|
||||
rchardet (1.8.0)
|
||||
representable (3.2.0)
|
||||
representable (3.1.1)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
@@ -207,13 +163,10 @@ GEM
|
||||
rouge (2.0.7)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
security (0.1.3)
|
||||
signet (0.17.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
signet (0.15.0)
|
||||
addressable (~> 2.3)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.8)
|
||||
@@ -222,7 +175,7 @@ GEM
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
trailblazer-option (0.1.2)
|
||||
trailblazer-option (0.1.1)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.1)
|
||||
tty-spinner (0.9.3)
|
||||
@@ -230,11 +183,11 @@ GEM
|
||||
uber (0.1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.8.2)
|
||||
unicode-display_width (1.8.0)
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
webrick (1.7.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.22.0)
|
||||
xcodeproj (1.20.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
@@ -247,12 +200,9 @@ GEM
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
universal-darwin-21
|
||||
x86_64-darwin-20
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
danger
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
|
17
README.md
17
README.md
@@ -1,9 +1,9 @@
|
||||
[](https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Adevelop)
|
||||
[](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
|
||||
[](https://translate.element.io/engage/element-android/?utm_source=widget)
|
||||
[](https://matrix.to/#/#element-android:matrix.org)
|
||||
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
|
||||
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
|
||||
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-android)
|
||||
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||
|
||||
# Element Android
|
||||
|
||||
@@ -14,7 +14,7 @@ It is a total rewrite of [Riot-Android](https://github.com/vector-im/riot-androi
|
||||
[<img src="resources/img/google-play-badge.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.app)
|
||||
[<img src="resources/img/f-droid-badge.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.app)
|
||||
|
||||
Build of develop branch: [](https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Adevelop) Nightly test status: [](https://github.com/vector-im/element-android/actions/workflows/nightly.yml)
|
||||
Nightly build: [](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop) Nighly test status: [](https://github.com/vector-im/element-android/actions/workflows/nightly.yml)
|
||||
|
||||
|
||||
# New Android SDK
|
||||
@@ -40,19 +40,16 @@ If you would like to receive releases more quickly (bearing in mind that they ma
|
||||
|
||||
1. [Sign up to receive beta releases](https://play.google.com/apps/testing/im.vector.app) via the Google Play Store.
|
||||
2. Install a [release APK](https://github.com/vector-im/element-android/releases) directly - download the relevant .apk file and allow installing from untrusted sources in your device settings. Note: these releases are the Google Play version, which depend on some Google services. If you prefer to avoid that, try the latest dev builds, and choose the F-Droid version.
|
||||
3. If you're really brave, install the [very latest dev build](https://github.com/vector-im/element-android/actions/workflows/build.yml?query=branch%3Adevelop) - pick a build, then click on `Summary` to download the APKs from there: `vector-Fdroid-debug` and `vector-Gplay-debug` contains the APK for the desired store. Each file contains 5 APKs. 4 APKs for every supported specific architecture of device. In doubt you can install the `universal` APK.
|
||||
3. If you're really brave, install the [very latest dev build](https://buildkite.com/matrix-dot-org/element-android/builds/latest?branch=develop&state=passed) - click on *Assemble (GPlay or FDroid) Debug version* then on *Artifacts*.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
|
||||
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
|
||||
|
||||
Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org).
|
||||
|
||||
Also [this documentation](./docs/_developer_onboarding.md) can hopefully help developers to start working on the project.
|
||||
|
||||
## Triaging issues
|
||||
|
||||
Issues are triaged by community members and the Android App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process).
|
||||
|
||||
We use [issue labels](https://github.com/vector-im/element-meta/wiki/Issue-labelling) to sort all incoming issues.
|
||||
|
||||
|
@@ -1,5 +0,0 @@
|
||||
# Reporting a Vulnerability
|
||||
|
||||
**If you've found a security vulnerability, please report it to security@matrix.org**
|
||||
|
||||
For more information on our security disclosure policy, visit https://www.matrix.org/security-disclosure-policy/
|
229
build.gradle
229
build.gradle
@@ -5,17 +5,10 @@ buildscript {
|
||||
apply from: 'dependencies_groups.gradle'
|
||||
|
||||
repositories {
|
||||
// Do not use `google()`, it prevents Dependabot from working properly
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
google()
|
||||
maven {
|
||||
url "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
// Do not use `mavenCentral()`, it prevents Dependabot from working properly
|
||||
maven {
|
||||
url 'https://repo1.maven.org/maven2'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -24,33 +17,20 @@ buildscript {
|
||||
classpath libs.gradle.gradlePlugin
|
||||
classpath libs.gradle.kotlinPlugin
|
||||
classpath libs.gradle.hiltPlugin
|
||||
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.0'
|
||||
classpath 'com.google.gms:google-services:4.3.15'
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.0.0.2929'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
|
||||
classpath "com.likethesalad.android:stem-plugin:2.4.1"
|
||||
classpath 'org.owasp:dependency-check-gradle:8.2.1'
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.10"
|
||||
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
|
||||
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
|
||||
classpath libs.squareup.paparazziPlugin
|
||||
classpath 'com.google.gms:google-services:4.3.10'
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
|
||||
classpath "com.likethesalad.android:stem-plugin:2.0.0"
|
||||
classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.21"
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
// ktlint Plugin
|
||||
plugins {
|
||||
// ktlint Plugin
|
||||
id "org.jlleitschuh.gradle.ktlint" version "11.3.2"
|
||||
// Detekt
|
||||
id "io.gitlab.arturbosch.detekt" version "1.22.0"
|
||||
// Ksp
|
||||
id "com.google.devtools.ksp" version "1.8.10-1.0.9"
|
||||
|
||||
// Dependency Analysis
|
||||
id 'com.autonomousapps.dependency-analysis' version "1.20.0"
|
||||
// Gradle doctor
|
||||
id "com.osacky.doctor" version "0.8.1"
|
||||
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
|
||||
}
|
||||
|
||||
// https://github.com/jeremylong/DependencyCheck
|
||||
@@ -63,30 +43,16 @@ dependencyCheck {
|
||||
]
|
||||
}
|
||||
|
||||
// Gradle doctor configuration
|
||||
apply from: './tools/gradle/doctor.gradle'
|
||||
|
||||
allprojects {
|
||||
apply plugin: "org.jlleitschuh.gradle.ktlint"
|
||||
apply plugin: "io.gitlab.arturbosch.detekt"
|
||||
|
||||
repositories {
|
||||
// Do not use `mavenCentral()`, it prevents Dependabot from working properly
|
||||
maven {
|
||||
url 'https://repo1.maven.org/maven2'
|
||||
mavenCentral {
|
||||
content {
|
||||
groups.mavenCentral.regex.each { includeGroupByRegex it }
|
||||
groups.mavenCentral.group.each { includeGroup it }
|
||||
}
|
||||
}
|
||||
// snapshots repository
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots"
|
||||
content {
|
||||
groups.snapshot.regex.each { includeGroupByRegex it }
|
||||
groups.snapshot.group.each { includeGroup it }
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
content {
|
||||
@@ -96,27 +62,25 @@ allprojects {
|
||||
}
|
||||
// Jitsi repo
|
||||
maven {
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-8.1.1"
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-5.0.2"
|
||||
// Note: to test Jitsi release you can use a local file like this:
|
||||
// url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-8.1.1"
|
||||
// url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-3.10.0"
|
||||
content {
|
||||
groups.jitsi.regex.each { includeGroupByRegex it }
|
||||
groups.jitsi.group.each { includeGroup it }
|
||||
}
|
||||
}
|
||||
// Do not use `google()`, it prevents Dependabot from working properly
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
google {
|
||||
content {
|
||||
groups.google.regex.each { includeGroupByRegex it }
|
||||
groups.google.group.each { includeGroup it }
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url 'https://s01.oss.sonatype.org/content/repositories/snapshots'
|
||||
//noinspection JcenterRepositoryObsolete
|
||||
jcenter {
|
||||
content {
|
||||
groups.mavenSnapshots.regex.each { includeGroupByRegex it }
|
||||
groups.mavenSnapshots.group.each { includeGroup it }
|
||||
groups.jcenter.regex.each { includeGroupByRegex it }
|
||||
groups.jcenter.group.each { includeGroup it }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,16 +105,8 @@ allprojects {
|
||||
enableExperimentalRules = true
|
||||
// display the corresponding rule
|
||||
verbose = true
|
||||
reporters {
|
||||
reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.PLAIN)
|
||||
// To have XML report for Danger
|
||||
reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
|
||||
}
|
||||
filter {
|
||||
exclude { element -> element.file.path.contains("$buildDir/generated/") }
|
||||
}
|
||||
disabledRules = [
|
||||
// TODO Re-enable these 4 rules after reformatting project
|
||||
// TODO: Re-enable these 4 rules after reformatting project
|
||||
"indent",
|
||||
"experimental:argument-list-wrapping",
|
||||
"max-line-length",
|
||||
@@ -169,19 +125,8 @@ allprojects {
|
||||
"experimental:comment-wrapping",
|
||||
// - A KDoc comment after any other element on the same line must be separated by a new line
|
||||
"experimental:kdoc-wrapping",
|
||||
// Ignore error "Redundant curly braces", since we use it to fix false positives, for instance in "elementLogs.${i}.txt"
|
||||
"string-template",
|
||||
]
|
||||
}
|
||||
|
||||
detekt {
|
||||
// preconfigure defaults
|
||||
buildUponDefaultConfig = true
|
||||
// activate all available (even unstable) rules.
|
||||
allRules = true
|
||||
// point to your custom config defining rules to run, overwriting default behavior
|
||||
config = files("$rootDir/tools/detekt/detekt.yml")
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
@@ -194,20 +139,20 @@ def launchTask = getGradle()
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
|
||||
if (launchTask.contains("coverage".toLowerCase())) {
|
||||
if (launchTask.contains("codeCoverageReport".toLowerCase())) {
|
||||
apply from: 'coverage.gradle'
|
||||
}
|
||||
|
||||
apply plugin: 'org.sonarqube'
|
||||
|
||||
// To run a sonar analysis:
|
||||
// Run './gradlew sonar -Dsonar.login=<REPLACE_WITH_SONAR_KEY>'
|
||||
// Run './gradlew sonarqube -Dsonar.login=<REPLACE_WITH_SONAR_KEY>'
|
||||
// The SONAR_KEY is stored in passbolt as Token Sonar Cloud Bma
|
||||
|
||||
sonar {
|
||||
sonarqube {
|
||||
properties {
|
||||
property "sonar.projectName", "element-android"
|
||||
property "sonar.projectKey", "vector-im_element-android"
|
||||
property "sonar.projectName", "Element-Android"
|
||||
property "sonar.projectKey", "im.vector.app.android"
|
||||
property "sonar.host.url", "https://sonarcloud.io"
|
||||
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
|
||||
property "sonar.sourceEncoding", "UTF-8"
|
||||
@@ -217,13 +162,13 @@ sonar {
|
||||
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
|
||||
property "sonar.organization", "new_vector_ltd_organization"
|
||||
property "sonar.java.coveragePlugin", "jacoco"
|
||||
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/generateCoverageReport/generateCoverageReport.xml"
|
||||
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/allCodeCoverageReport/allCodeCoverageReport.xml"
|
||||
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
|
||||
}
|
||||
}
|
||||
|
||||
project(":vector") {
|
||||
sonar {
|
||||
sonarqube {
|
||||
properties {
|
||||
property "sonar.sources", project(":vector").android.sourceSets.main.java.srcDirs
|
||||
// exclude source code from analyses separated by a colon (:)
|
||||
@@ -233,14 +178,14 @@ project(":vector") {
|
||||
}
|
||||
}
|
||||
|
||||
project(":library:external:diff-match-patch") {
|
||||
sonar {
|
||||
project(":library:diff-match-patch") {
|
||||
sonarqube {
|
||||
skipProject = true
|
||||
}
|
||||
}
|
||||
|
||||
//project(":matrix-sdk-android") {
|
||||
// sonar {
|
||||
// sonarqube {
|
||||
// properties {
|
||||
// property "sonar.sources", project(":matrix-sdk-android").android.sourceSets.main.java.srcDirs
|
||||
// // exclude source code from analyses separated by a colon (:)
|
||||
@@ -248,121 +193,3 @@ project(":library:external:diff-match-patch") {
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
dependencyAnalysis {
|
||||
dependencies {
|
||||
bundle("kotlin-stdlib") {
|
||||
includeGroup("org.jetbrains.kotlin")
|
||||
}
|
||||
bundle("react") {
|
||||
includeGroup("com.facebook.react")
|
||||
}
|
||||
}
|
||||
issues {
|
||||
all {
|
||||
ignoreKtx(true)
|
||||
onUsedTransitiveDependencies {
|
||||
// Transitively used dependencies that should be declared directly
|
||||
severity("ignore")
|
||||
}
|
||||
onUnusedDependencies {
|
||||
severity("fail")
|
||||
}
|
||||
onUnusedAnnotationProcessors {
|
||||
severity("fail")
|
||||
exclude("com.airbnb.android:epoxy-processor", "com.google.dagger:hilt-compiler") // False positives
|
||||
}
|
||||
}
|
||||
project(":library:jsonviewer") {
|
||||
onUnusedDependencies {
|
||||
exclude("org.json:json") // Used in unit tests, overwrites the one bundled into Android
|
||||
}
|
||||
}
|
||||
project(":library:ui-styles")
|
||||
project(":matrix-sdk-android") {
|
||||
onUnusedDependencies {
|
||||
exclude("io.reactivex.rxjava2:rxkotlin") // Transitively required for mocking realm as monarchy doesn't expose Rx
|
||||
}
|
||||
}
|
||||
project(":matrix-sdk-android-flow") {
|
||||
onUnusedDependencies {
|
||||
exclude("androidx.paging:paging-runtime-ktx") // False positive
|
||||
}
|
||||
}
|
||||
project(":vector") {
|
||||
onUnusedDependencies {
|
||||
// False positives
|
||||
exclude(
|
||||
"androidx.fragment:fragment-testing",
|
||||
"com.facebook.soloader:soloader",
|
||||
"com.vanniktech:emoji-google",
|
||||
"com.vanniktech:emoji-material",
|
||||
"org.maplibre.gl:android-plugin-annotation-v9",
|
||||
"org.maplibre.gl:android-sdk",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("recordScreenshots", GradleBuild) {
|
||||
startParameter.projectProperties.screenshot = ""
|
||||
tasks = [':vector:recordPaparazziDebug']
|
||||
}
|
||||
|
||||
tasks.register("verifyScreenshots", GradleBuild) {
|
||||
startParameter.projectProperties.screenshot = ""
|
||||
tasks = [':vector:verifyPaparazziRustCryptoDebug']
|
||||
}
|
||||
|
||||
ext.initScreenshotTests = { project ->
|
||||
def hasScreenshots = project.hasProperty("screenshot")
|
||||
if (hasScreenshots) {
|
||||
project.apply plugin: 'app.cash.paparazzi'
|
||||
}
|
||||
project.dependencies { testCompileOnly libs.squareup.paparazzi }
|
||||
project.android.testOptions.unitTests.all {
|
||||
def screenshotTestCapture = "**/*ScreenshotTest*"
|
||||
if (hasScreenshots) {
|
||||
include screenshotTestCapture
|
||||
} else {
|
||||
exclude screenshotTestCapture
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
maxHeapSize = "2g"
|
||||
}
|
||||
|
||||
// Workaround to have KSP generated Kotlin code available in the IDE (for code completion)
|
||||
// Ref: https://github.com/airbnb/epoxy/releases/tag/5.0.0beta02
|
||||
subprojects { project ->
|
||||
afterEvaluate {
|
||||
if (project.hasProperty("android")) {
|
||||
android {
|
||||
if (it instanceof com.android.build.gradle.LibraryExtension) {
|
||||
libraryVariants.all { variant ->
|
||||
def outputFolder = new File("build/generated/ksp/${variant.name}/kotlin")
|
||||
if (outputFolder.exists()) {
|
||||
variant.addJavaSourceFoldersToModel(outputFolder)
|
||||
android.sourceSets.getAt(variant.name).java {
|
||||
srcDir(outputFolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (it instanceof com.android.build.gradle.AppExtension) {
|
||||
applicationVariants.all { variant ->
|
||||
def outputFolder = new File("build/generated/ksp/${variant.name}/kotlin")
|
||||
if (outputFolder.exists()) {
|
||||
variant.addJavaSourceFoldersToModel(outputFolder)
|
||||
android.sourceSets.getAt(variant.name).java {
|
||||
srcDir(outputFolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
changelog.d/5421.bugfix
Normal file
1
changelog.d/5421.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fixes crash when accepting or receiving VOIP calls
|
2
changelog.d/5575.sdk
Normal file
2
changelog.d/5575.sdk
Normal file
@@ -0,0 +1,2 @@
|
||||
- Added registrationCustom into RegistrationWizard to send custom auth params for sign up
|
||||
- Moved terms converter into api package to make it accessible in sdk
|
1
changelog.d/5592.bugfix
Normal file
1
changelog.d/5592.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Improve/fix crashes on messages decryption
|
1
changelog.d/5652.bugfix
Normal file
1
changelog.d/5652.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Tentative fix of images crashing when being sent or shared from gallery
|
1
changelog.d/5721.bugfix
Normal file
1
changelog.d/5721.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Improving deactivation experience along with a crash fix
|
1
changelog.d/5772.feature
Normal file
1
changelog.d/5772.feature
Normal file
@@ -0,0 +1 @@
|
||||
Improve management of ignored users
|
1
changelog.d/5773.misc
Normal file
1
changelog.d/5773.misc
Normal file
@@ -0,0 +1 @@
|
||||
Move "Ignored users" setting section into "Security & Privacy"
|
1
changelog.d/5774.misc
Normal file
1
changelog.d/5774.misc
Normal file
@@ -0,0 +1 @@
|
||||
Add a picto for ignored users in the room member list screen
|
1
changelog.d/5783.wip
Normal file
1
changelog.d/5783.wip
Normal file
@@ -0,0 +1 @@
|
||||
Reorders the registration steps to prioritise email, then terms for the FTUE onboarding
|
1
changelog.d/5805.misc
Normal file
1
changelog.d/5805.misc
Normal file
@@ -0,0 +1 @@
|
||||
Autoformats entire project
|
1
changelog.d/5811.feature
Normal file
1
changelog.d/5811.feature
Normal file
@@ -0,0 +1 @@
|
||||
VoIP Screen Sharing Permission
|
1
changelog.d/5812.sdk
Normal file
1
changelog.d/5812.sdk
Normal file
@@ -0,0 +1 @@
|
||||
Move package `org.matrix.android.sdk.api.pushrules` to `org.matrix.android.sdk.api.session.pushrules`
|
1
changelog.d/5814.feature
Normal file
1
changelog.d/5814.feature
Normal file
@@ -0,0 +1 @@
|
||||
Live location sharing: updating beacon state event content structure
|
2
changelog.d/5816.sdk
Normal file
2
changelog.d/5816.sdk
Normal file
@@ -0,0 +1,2 @@
|
||||
Some `Session` apis are now available by requesting the service first. For instance `Session.updateAvatar(...)` is now `Session.profileService().updateAvatar(...)`
|
||||
The shortcut `Room.search()` has been removed, you have to use `Session.searchService().search()`
|
1
changelog.d/5826.bugfix
Normal file
1
changelog.d/5826.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Adds missing suggested tag for rooms in Explore Space
|
1
changelog.d/5832.misc
Normal file
1
changelog.d/5832.misc
Normal file
@@ -0,0 +1 @@
|
||||
Add a GH workflow to push ElementX issues to the global board.
|
1
changelog.d/5836.doc
Normal file
1
changelog.d/5836.doc
Normal file
@@ -0,0 +1 @@
|
||||
Update the PR process doc with 2 reviewers and a new reviewer team.
|
1
changelog.d/5847.bugfix
Normal file
1
changelog.d/5847.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fixes missing call icons when threads are enabled
|
1
changelog.d/5854.doc
Normal file
1
changelog.d/5854.doc
Normal file
@@ -0,0 +1 @@
|
||||
Improve documentation of the project and of the SDK
|
1
changelog.d/5855.sdk
Normal file
1
changelog.d/5855.sdk
Normal file
@@ -0,0 +1 @@
|
||||
- Add return type to RoomApi.sendStateEvent() to retrieve the created event id
|
1
changelog.d/5858.sdk
Normal file
1
changelog.d/5858.sdk
Normal file
@@ -0,0 +1 @@
|
||||
`Room` apis are now available by requesting the service first. For instance `Room.updateAvatar(...)` is now `Room.stateService().updateAvatar(...)`
|
1
changelog.d/5862.wip
Normal file
1
changelog.d/5862.wip
Normal file
@@ -0,0 +1 @@
|
||||
[Live location sharing] Improve aggregation process of events
|
1
changelog.d/5871.bugfix
Normal file
1
changelog.d/5871.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fix UX freezing when creating secure backup
|
1
changelog.d/5872.misc
Normal file
1
changelog.d/5872.misc
Normal file
@@ -0,0 +1 @@
|
||||
Faster Olm decrypt when there is a lot of existing sessions
|
1
changelog.d/5874.bugfix
Normal file
1
changelog.d/5874.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fixes sign in via other requiring homeserver registration to be enabled
|
1
changelog.d/5886.bugfix
Normal file
1
changelog.d/5886.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fix UISIDetector grace period bug
|
1
changelog.d/5890.sdk
Normal file
1
changelog.d/5890.sdk
Normal file
@@ -0,0 +1 @@
|
||||
Remove unecessary field `eventId` from `EventAnnotationsSummary` and `ReferencesAggregatedSummary`
|
1
changelog.d/5924.bugfix
Normal file
1
changelog.d/5924.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fix a crash with space invitations in the space list, and do not display space invitation twice.
|
1
changelog.d/5925.bugfix
Normal file
1
changelog.d/5925.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Fixes crash on android api 21/22 devices when opening messages due to Konfetti library
|
@@ -1,37 +1,9 @@
|
||||
def excludes = [
|
||||
// dependency injection graph
|
||||
'**/*Module.*',
|
||||
'**/*Module*.*',
|
||||
|
||||
// Framework entry points
|
||||
'**/*Activity*',
|
||||
'**/*Fragment*',
|
||||
'**/*Application*',
|
||||
'**/*AndroidService*',
|
||||
|
||||
// We would like to exclude android widgets as well but our naming is inconsistent
|
||||
|
||||
// Proof of concept
|
||||
'**/*Login2*',
|
||||
|
||||
// Generated
|
||||
'**/*JsonAdapter*',
|
||||
'**/*Item.*',
|
||||
'**/*$Holder.*',
|
||||
'**/*ViewHolder.*',
|
||||
'**/*View.*',
|
||||
'**/*BottomSheet.*'
|
||||
]
|
||||
def excludes = [ ]
|
||||
|
||||
def initializeReport(report, projects, classExcludes) {
|
||||
projects.each { project -> project.apply plugin: 'jacoco' }
|
||||
report.executionData { fileTree(rootProject.rootDir.absolutePath).include("**/build/jacoco/*.exec") }
|
||||
|
||||
report.executionData {
|
||||
fileTree(rootProject.rootDir.absolutePath).include(
|
||||
"**/build/**/*.exec",
|
||||
"**/build/outputs/code_coverage/**/coverage.ec",
|
||||
)
|
||||
}
|
||||
report.reports {
|
||||
xml.enabled true
|
||||
html.enabled true
|
||||
@@ -71,27 +43,13 @@ def collectProjects(predicate) {
|
||||
return subprojects.findAll { it.buildFile.isFile() && predicate(it) }
|
||||
}
|
||||
|
||||
task generateCoverageReport(type: JacocoReport) {
|
||||
task allCodeCoverageReport(type: JacocoReport) {
|
||||
outputs.upToDateWhen { false }
|
||||
rootProject.apply plugin: 'jacoco'
|
||||
def projects = collectProjects { ['vector-app', 'vector', 'matrix-sdk-android'].contains(it.name) }
|
||||
// to limit projects in a specific report, add
|
||||
// def excludedProjects = [ ... ]
|
||||
// def projects = collectProjects { !excludedProjects.contains(it.name) }
|
||||
def projects = collectProjects { true }
|
||||
dependsOn { projects*.test }
|
||||
initializeReport(it, projects, excludes)
|
||||
}
|
||||
|
||||
task unitTestsWithCoverage(type: GradleBuild) {
|
||||
// the 7.1.3 android gradle plugin has a bug where enableTestCoverage generates invalid coverage
|
||||
startParameter.projectProperties.coverage = "false"
|
||||
tasks = ['testDebugUnitTest']
|
||||
}
|
||||
|
||||
task instrumentationTestsWithCoverage(type: GradleBuild) {
|
||||
startParameter.projectProperties.coverage = "true"
|
||||
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
|
||||
tasks = [':vector-app:connectedGplayKotlinCryptoDebugAndroidTest', ':vector:connectedKotlinCryptoDebugAndroidTest', 'matrix-sdk-android:connectedKotlinCryptoDebugAndroidTest']
|
||||
}
|
||||
|
||||
task instrumentationTestsRustWithCoverage(type: GradleBuild) {
|
||||
startParameter.projectProperties.coverage = "true"
|
||||
startParameter.projectProperties['android.testInstrumentationRunnerArguments.notPackage'] = 'im.vector.app.ui'
|
||||
tasks = [':vector-app:connectedGplayRustCryptoDebugAndroidTest', ':vector:connectedRustCryptoDebugAndroidTest', 'matrix-sdk-android:connectedRustCryptoDebugAndroidTest']
|
||||
}
|
||||
|
@@ -1,45 +1,43 @@
|
||||
ext.versions = [
|
||||
|
||||
'minSdk' : 21,
|
||||
'compileSdk' : 33,
|
||||
'targetSdk' : 33,
|
||||
'compileSdk' : 31,
|
||||
'targetSdk' : 31,
|
||||
'sourceCompat' : JavaVersion.VERSION_11,
|
||||
'targetCompat' : JavaVersion.VERSION_11,
|
||||
]
|
||||
|
||||
def gradle = "7.4.2"
|
||||
def gradle = "7.0.4"
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
def kotlin = "1.8.10"
|
||||
def kotlinCoroutines = "1.6.4"
|
||||
def dagger = "2.45"
|
||||
def firebaseBom = "32.0.0"
|
||||
def appDistribution = "16.0.0-beta08"
|
||||
def kotlin = "1.6.0"
|
||||
def kotlinCoroutines = "1.6.0"
|
||||
def dagger = "2.40.5"
|
||||
def retrofit = "2.9.0"
|
||||
def arrow = "0.8.2"
|
||||
def markwon = "4.6.2"
|
||||
def moshi = "1.14.0"
|
||||
def lifecycle = "2.5.1"
|
||||
def moshi = "1.13.0"
|
||||
def lifecycle = "2.4.0"
|
||||
def flowBinding = "1.2.0"
|
||||
def flipper = "0.190.0"
|
||||
def epoxy = "5.0.0"
|
||||
def mavericks = "3.0.2"
|
||||
def glide = "4.15.1"
|
||||
def epoxy = "4.6.2"
|
||||
def mavericks = "2.5.0"
|
||||
def glide = "4.12.0"
|
||||
def bigImageViewer = "1.8.1"
|
||||
def jjwt = "0.11.5"
|
||||
def vanniktechEmoji = "0.16.0"
|
||||
def sentry = "6.18.1"
|
||||
// Use 1.6.0 alpha to fix issue with test
|
||||
def fragment = "1.6.0-beta01"
|
||||
def jjwt = "0.11.2"
|
||||
def vanniktechEmoji = "0.8.0"
|
||||
|
||||
// Testing
|
||||
def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
|
||||
def espresso = "3.5.1"
|
||||
def androidxTest = "1.5.0"
|
||||
def androidxOrchestrator = "1.4.2"
|
||||
def paparazzi = "1.2.0"
|
||||
def mockk = "1.12.1"
|
||||
def espresso = "3.4.0"
|
||||
def androidxTest = "1.4.0"
|
||||
def androidxOrchestrator = "1.4.1"
|
||||
|
||||
|
||||
ext.libs = [
|
||||
gradle : [
|
||||
'gradlePlugin' : "com.android.tools.build:gradle:$gradle",
|
||||
'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin",
|
||||
'hiltPlugin' : "com.google.dagger:hilt-android-gradle-plugin:$dagger"
|
||||
|
||||
],
|
||||
jetbrains : [
|
||||
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
|
||||
@@ -47,20 +45,16 @@ ext.libs = [
|
||||
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
||||
],
|
||||
androidx : [
|
||||
'activity' : "androidx.activity:activity-ktx:1.7.2",
|
||||
'appCompat' : "androidx.appcompat:appcompat:1.6.1",
|
||||
'biometric' : "androidx.biometric:biometric:1.1.0",
|
||||
'core' : "androidx.core:core-ktx:1.10.1",
|
||||
'recyclerview' : "androidx.recyclerview:recyclerview:1.3.0",
|
||||
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.6",
|
||||
'fragmentKtx' : "androidx.fragment:fragment-ktx:$fragment",
|
||||
'fragmentTesting' : "androidx.fragment:fragment-testing:$fragment",
|
||||
'fragmentTestingManifest' : "androidx.fragment:fragment-testing-manifest:$fragment",
|
||||
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.4",
|
||||
'work' : "androidx.work:work-runtime-ktx:2.8.1",
|
||||
'appCompat' : "androidx.appcompat:appcompat:1.4.0",
|
||||
'core' : "androidx.core:core-ktx:1.7.0",
|
||||
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
|
||||
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
|
||||
'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.0",
|
||||
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.2",
|
||||
'work' : "androidx.work:work-runtime-ktx:2.7.1",
|
||||
'autoFill' : "androidx.autofill:autofill:1.1.0",
|
||||
'preferenceKtx' : "androidx.preference:preference-ktx:1.2.0",
|
||||
'junit' : "androidx.test.ext:junit:1.1.5",
|
||||
'preferenceKtx' : "androidx.preference:preference-ktx:1.1.1",
|
||||
'junit' : "androidx.test.ext:junit:1.1.3",
|
||||
'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle",
|
||||
'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle",
|
||||
'lifecycleProcess' : "androidx.lifecycle:lifecycle-process:$lifecycle",
|
||||
@@ -68,58 +62,40 @@ ext.libs = [
|
||||
'datastore' : "androidx.datastore:datastore:1.0.0",
|
||||
'datastorepreferences' : "androidx.datastore:datastore-preferences:1.0.0",
|
||||
'pagingRuntimeKtx' : "androidx.paging:paging-runtime-ktx:2.1.2",
|
||||
'coreTesting' : "androidx.arch.core:core-testing:2.2.0",
|
||||
'coreTesting' : "androidx.arch.core:core-testing:2.1.0",
|
||||
'testCore' : "androidx.test:core:$androidxTest",
|
||||
'orchestrator' : "androidx.test:orchestrator:$androidxOrchestrator",
|
||||
'testRunner' : "androidx.test:runner:$androidxTest",
|
||||
'testRules' : "androidx.test:rules:$androidxTest",
|
||||
'espressoCore' : "androidx.test.espresso:espresso-core:$espresso",
|
||||
'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso",
|
||||
'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso",
|
||||
'viewpager2' : "androidx.viewpager2:viewpager2:1.0.0",
|
||||
'transition' : "androidx.transition:transition:1.4.1",
|
||||
'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso"
|
||||
],
|
||||
google : [
|
||||
'material' : "com.google.android.material:material:1.9.0",
|
||||
'firebaseBom' : "com.google.firebase:firebase-bom:$firebaseBom",
|
||||
'messaging' : "com.google.firebase:firebase-messaging",
|
||||
'appdistributionApi' : "com.google.firebase:firebase-appdistribution-api-ktx:$appDistribution",
|
||||
'appdistribution' : "com.google.firebase:firebase-appdistribution:$appDistribution",
|
||||
// Phone number https://github.com/google/libphonenumber
|
||||
'phonenumber' : "com.googlecode.libphonenumber:libphonenumber:8.13.11"
|
||||
'material' : "com.google.android.material:material:1.5.0"
|
||||
],
|
||||
dagger : [
|
||||
'dagger' : "com.google.dagger:dagger:$dagger",
|
||||
'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger",
|
||||
'hilt' : "com.google.dagger:hilt-android:$dagger",
|
||||
'hiltAndroidTesting' : "com.google.dagger:hilt-android-testing:$dagger",
|
||||
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
|
||||
],
|
||||
flipper : [
|
||||
'flipper' : "com.facebook.flipper:flipper:$flipper",
|
||||
'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper",
|
||||
],
|
||||
element : [
|
||||
'opusencoder' : "io.element.android:opusencoder:1.1.0",
|
||||
'wysiwyg' : "io.element.android:wysiwyg:2.2.2"
|
||||
],
|
||||
squareup : [
|
||||
'moshi' : "com.squareup.moshi:moshi:$moshi",
|
||||
'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi",
|
||||
'moshi' : "com.squareup.moshi:moshi-adapters:$moshi",
|
||||
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
|
||||
'moshiAdapters' : "com.squareup.moshi:moshi-adapters:$moshi",
|
||||
'paparazzi' : "app.cash.paparazzi:paparazzi:$paparazzi",
|
||||
'paparazziPlugin' : "app.cash.paparazzi:paparazzi-gradle-plugin:$paparazzi",
|
||||
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
|
||||
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
||||
],
|
||||
rx : [
|
||||
'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0"
|
||||
],
|
||||
arrow : [
|
||||
'core' : "io.arrow-kt:arrow-core:$arrow",
|
||||
'instances' : "io.arrow-kt:arrow-instances-core:$arrow"
|
||||
],
|
||||
markwon : [
|
||||
'core' : "io.noties.markwon:core:$markwon",
|
||||
'extLatex' : "io.noties.markwon:ext-latex:$markwon",
|
||||
'imageGlide' : "io.noties.markwon:image-glide:$markwon",
|
||||
'inlineParser' : "io.noties.markwon:inline-parser:$markwon",
|
||||
'html' : "io.noties.markwon:html:$markwon"
|
||||
],
|
||||
@@ -131,10 +107,6 @@ ext.libs = [
|
||||
'mavericks' : "com.airbnb.android:mavericks:$mavericks",
|
||||
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
|
||||
],
|
||||
maplibre : [
|
||||
'androidSdk' : "org.maplibre.gl:android-sdk:10.0.2",
|
||||
'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0"
|
||||
],
|
||||
mockk : [
|
||||
'mockk' : "io.mockk:mockk:$mockk",
|
||||
'mockkAndroid' : "io.mockk:mockk-android:$mockk"
|
||||
@@ -163,17 +135,11 @@ ext.libs = [
|
||||
'emojiGoogle' : "com.vanniktech:emoji-google:$vanniktechEmoji"
|
||||
],
|
||||
apache : [
|
||||
'commonsImaging' : "org.apache.commons:commons-imaging:1.0-alpha3"
|
||||
],
|
||||
sentry: [
|
||||
'sentryAndroid' : "io.sentry:sentry-android:$sentry"
|
||||
'commonsImaging' : "org.apache.sanselan:sanselan:0.97-incubator"
|
||||
],
|
||||
tests : [
|
||||
'kluent' : "org.amshove.kluent:kluent-android:1.73",
|
||||
'kluent' : "org.amshove.kluent:kluent-android:1.68",
|
||||
'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1",
|
||||
'junit' : "junit:junit:4.13.2",
|
||||
'robolectric' : "org.robolectric:robolectric:4.9",
|
||||
'junit' : "junit:junit:4.13.2"
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
ext.groups = [
|
||||
jitpack : [
|
||||
jitpack : [
|
||||
regex: [
|
||||
],
|
||||
group: [
|
||||
@@ -9,13 +9,12 @@ ext.groups = [
|
||||
'com.github.jetradarmobile',
|
||||
'com.github.MatrixFrog',
|
||||
'com.github.tapadoo',
|
||||
'com.github.UnifiedPush',
|
||||
'com.github.vector-im',
|
||||
'com.github.yalantis',
|
||||
'com.github.Zhuinden',
|
||||
]
|
||||
],
|
||||
jitsi : [
|
||||
jitsi : [
|
||||
regex: [
|
||||
],
|
||||
group: [
|
||||
@@ -24,7 +23,7 @@ ext.groups = [
|
||||
'org.webkit',
|
||||
]
|
||||
],
|
||||
google : [
|
||||
google : [
|
||||
regex: [
|
||||
'androidx\\..*',
|
||||
'com\\.android\\.tools\\..*',
|
||||
@@ -32,30 +31,15 @@ ext.groups = [
|
||||
],
|
||||
group: [
|
||||
'com.android',
|
||||
'com.android.ndk.thirdparty',
|
||||
'com.android.tools',
|
||||
'com.google.firebase',
|
||||
'com.google.testing.platform',
|
||||
]
|
||||
],
|
||||
snapshot: [
|
||||
regex: [
|
||||
],
|
||||
group: [
|
||||
]
|
||||
],
|
||||
mavenSnapshots: [
|
||||
regex: [
|
||||
],
|
||||
group: [
|
||||
'org.matrix.rustcomponents'
|
||||
]
|
||||
],
|
||||
mavenCentral: [
|
||||
regex: [
|
||||
],
|
||||
group: [
|
||||
'app.cash.paparazzi',
|
||||
'ch.qos.logback',
|
||||
'com.adevinta.android',
|
||||
'com.airbnb.android',
|
||||
@@ -68,7 +52,6 @@ ext.groups = [
|
||||
'com.dropbox.core',
|
||||
'com.soywiz.korlibs.korte',
|
||||
'com.facebook.fbjni',
|
||||
'com.facebook.flipper',
|
||||
'com.facebook.fresco',
|
||||
'com.facebook.infer.annotation',
|
||||
'com.facebook.soloader',
|
||||
@@ -83,14 +66,14 @@ ext.groups = [
|
||||
'com.gabrielittner.threetenbp',
|
||||
'com.getkeepsafe.relinker',
|
||||
'com.github.bumptech.glide',
|
||||
'com.github.filippudak',
|
||||
'com.github.filippudak.progresspieview',
|
||||
'com.github.javaparser',
|
||||
'com.github.piasy',
|
||||
'com.github.shyiko.klob',
|
||||
'com.github.rubensousa',
|
||||
'com.google',
|
||||
'com.google.android',
|
||||
'com.google.api.grpc',
|
||||
'com.google.auto',
|
||||
'com.google.auto.service',
|
||||
'com.google.auto.value',
|
||||
'com.google.code.findbugs',
|
||||
@@ -108,23 +91,18 @@ ext.groups = [
|
||||
'com.googlecode.json-simple',
|
||||
'com.googlecode.libphonenumber',
|
||||
'com.ibm.icu',
|
||||
'com.intellij',
|
||||
'com.jakewharton.android.repackaged',
|
||||
'com.jakewharton.timber',
|
||||
'com.kgurgul.flipper',
|
||||
'com.linkedin.dexmaker',
|
||||
'com.mapbox.mapboxsdk',
|
||||
'com.nulab-inc',
|
||||
'com.otaliastudios',
|
||||
'com.otaliastudios.opengl',
|
||||
'com.parse.bolts',
|
||||
'com.pinterest',
|
||||
'com.pinterest.ktlint',
|
||||
'com.posthog.android',
|
||||
'com.squareup',
|
||||
'com.squareup.curtains',
|
||||
'com.squareup.duktape',
|
||||
'com.squareup.leakcanary',
|
||||
'com.squareup.moshi',
|
||||
'com.squareup.okhttp3',
|
||||
'com.squareup.okio',
|
||||
@@ -141,12 +119,10 @@ ext.groups = [
|
||||
'commons-io',
|
||||
'commons-logging',
|
||||
'info.picocli',
|
||||
'io.element.android',
|
||||
'io.github.davidburstrom.contester',
|
||||
'io.arrow-kt',
|
||||
'io.github.detekt.sarif4k',
|
||||
'io.github.microutils',
|
||||
'io.github.reactivecircus.flowbinding',
|
||||
'io.gitlab.arturbosch.detekt',
|
||||
'io.grpc',
|
||||
'io.jsonwebtoken',
|
||||
'io.kindedj',
|
||||
@@ -154,21 +130,17 @@ ext.groups = [
|
||||
'io.netty',
|
||||
'io.noties.markwon',
|
||||
'io.opencensus',
|
||||
'io.perfmark',
|
||||
'io.reactivex.rxjava2',
|
||||
'io.realm',
|
||||
'io.sentry',
|
||||
'it.unimi.dsi',
|
||||
'jakarta.activation',
|
||||
'jakarta.xml.bind',
|
||||
'javax.activation',
|
||||
'javax.annotation',
|
||||
'javax.inject',
|
||||
'javax.xml.bind',
|
||||
'jline',
|
||||
'jp.wasabeef',
|
||||
'junit',
|
||||
'kxml2',
|
||||
'me.leolin',
|
||||
'me.saket',
|
||||
'net.bytebuddy',
|
||||
'net.java',
|
||||
@@ -183,29 +155,24 @@ ext.groups = [
|
||||
'org.apache.ant',
|
||||
'org.apache.commons',
|
||||
'org.apache.httpcomponents',
|
||||
'org.apache.sanselan',
|
||||
'org.bouncycastle',
|
||||
'org.ccil.cowan.tagsoup',
|
||||
'org.checkerframework',
|
||||
'org.codehaus',
|
||||
'org.codehaus.groovy',
|
||||
'org.codehaus.mojo',
|
||||
'org.codehaus.woodstox',
|
||||
'org.conscrypt',
|
||||
'org.eclipse.ee4j',
|
||||
'org.ec4j.core',
|
||||
'org.freemarker',
|
||||
'org.glassfish.jaxb',
|
||||
'org.hamcrest',
|
||||
'org.jacoco',
|
||||
'org.java-websocket',
|
||||
'org.jcodec',
|
||||
'org.jetbrains',
|
||||
'org.jetbrains.dokka',
|
||||
'org.jetbrains.intellij.deps',
|
||||
'org.jetbrains.kotlin',
|
||||
'org.jetbrains.kotlinx',
|
||||
'org.jetbrains.trove4j',
|
||||
'org.jitsi',
|
||||
'org.json',
|
||||
'org.jsoup',
|
||||
'org.junit',
|
||||
@@ -214,7 +181,6 @@ ext.groups = [
|
||||
'org.jvnet.staxex',
|
||||
'org.maplibre.gl',
|
||||
'org.matrix.android',
|
||||
'org.matrix.rustcomponents',
|
||||
'org.mockito',
|
||||
'org.mongodb',
|
||||
'org.objenesis',
|
||||
@@ -229,10 +195,23 @@ ext.groups = [
|
||||
'org.testng',
|
||||
'org.threeten',
|
||||
'org.webjars',
|
||||
'org.yaml',
|
||||
'ru.noties',
|
||||
'xerces',
|
||||
'xml-apis',
|
||||
]
|
||||
],
|
||||
jcenter : [
|
||||
regex: [
|
||||
],
|
||||
group: [
|
||||
'com.amulyakhare',
|
||||
'com.otaliastudios',
|
||||
'com.yqritc',
|
||||
// https://github.com/cmelchior/realmfieldnameshelper/issues/42
|
||||
'dk.ilios',
|
||||
'im.dlg',
|
||||
'me.dm7.barcodescanner',
|
||||
'me.gujun.android',
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@@ -1,259 +0,0 @@
|
||||
# Developer on boarding
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Quick introduction to Matrix](#quick-introduction-to-matrix)
|
||||
* [Matrix data](#matrix-data)
|
||||
* [Room](#room)
|
||||
* [Event](#event)
|
||||
* [Sync](#sync)
|
||||
* [Glossary about syncs](#glossary-about-syncs)
|
||||
* [The Android project](#the-android-project)
|
||||
* [Matrix SDK](#matrix-sdk)
|
||||
* [Application](#application)
|
||||
* [MvRx](#mvrx)
|
||||
* [Behavior](#behavior)
|
||||
* [Epoxy](#epoxy)
|
||||
* [Other frameworks](#other-frameworks)
|
||||
* [Push](#push)
|
||||
* [Dependencies management](#dependencies-management)
|
||||
* [Test](#test)
|
||||
* [Other points](#other-points)
|
||||
* [Logging](#logging)
|
||||
* [Rageshake](#rageshake)
|
||||
* [Tips](#tips)
|
||||
* [Happy coding!](#happy-coding)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This doc is a quick introduction about the project and its architecture.
|
||||
|
||||
It's aim is to help new developers to understand the overall project and where to start developing.
|
||||
|
||||
Other useful documentation:
|
||||
- all the docs in this folder!
|
||||
- the [contributing doc](../CONTRIBUTING.md), that you should also read carefully.
|
||||
|
||||
### Quick introduction to Matrix
|
||||
|
||||
Matrix website: [matrix.org](https://matrix.org), [discover page](https://matrix.org/discover).
|
||||
*Note*: Matrix.org is also hosting a homeserver ([.well-known file](https://matrix.org/.well-known/matrix/client)).
|
||||
The reference homeserver (this is how Matrix servers are called) implementation is [Synapse](https://github.com/matrix-org/synapse/). But other implementations exist. The Matrix specification is here to ensure that any Matrix client, such as Element Android and its SDK can talk to any Matrix server.
|
||||
|
||||
Have a quick look to the client-server API documentation: [Client-server documentation](https://spec.matrix.org/v1.3/client-server-api/). Other network API exist, the list is here: (https://spec.matrix.org/latest/)
|
||||
|
||||
Matrix is an open source protocol. Change are possible and are tracked using [this GitHub repository](https://github.com/matrix-org/matrix-doc/). Changes to the protocol are called MSC: Matrix Spec Change. These are PullRequest to this project.
|
||||
|
||||
Matrix object are Json data. Unstable prefixes must be used for Json keys when the MSC is not merged (i.e. accepted).
|
||||
|
||||
#### Matrix data
|
||||
|
||||
There are many object and data in the Matrix worlds. Let's focus on the most important and used, `Room` and `Event`
|
||||
|
||||
##### Room
|
||||
|
||||
`Room` is a place which contains ordered `Event`s. They are identified with their `room_id`. Nearly all the data are stored in rooms, and shared using homeserver to all the Room Member.
|
||||
|
||||
*Note*: Spaces are also Rooms with a different `type`.
|
||||
|
||||
##### Event
|
||||
|
||||
`Events` are items of a Room, where data is embedded.
|
||||
|
||||
There are 2 types of Room Event:
|
||||
|
||||
- Regular Events: contain useful content for the user (message, image, etc.), but are not necessarily displayed as this in the timeline (reaction, message edition, call signaling).
|
||||
- State Events: contain the state of the Room (name, topic, etc.). They have a non null value for the key `state_key`.
|
||||
|
||||
Also all the Room Member details are in State Events: one State Event per member. In this case, the `state_key` is the matrixId (= userId).
|
||||
|
||||
Important Fields of an Event:
|
||||
- `event_id`: unique across the Matrix universe;
|
||||
- `room_id`: the room the Event belongs to;
|
||||
- `type`: describe what the Event contain, especially in the `content` section, and how the SDK should handle this Event;
|
||||
- `content`: dynamic Event data; depends on the `type`.
|
||||
|
||||
So we have a triple `event_id`, `type`, `state_key` which uniquely defines an Event.
|
||||
|
||||
#### Sync
|
||||
|
||||
The `Sync` is a way for the Matrix client to be up to date regarding the user data hosted by the server. All the Events are coming through the sync response. More details can be found here: [spec.matrix.org/v1.3/client-server-api/#syncing](https://spec.matrix.org/v1.3/client-server-api/#syncing)
|
||||
When the application is in foreground, this is a looping request. We are using Https requests, which offer the advantage to be compatible with any homeserver. A sync token is used as request parameter, to let the server know what the client knows.
|
||||
The `SyncThread` is responsible to manage the sync request loop.
|
||||
|
||||
When the application is in background, a Push will trigger a sync request.
|
||||
|
||||
##### Glossary about syncs
|
||||
|
||||
- **initial sync**: a sync request without a token. This is the first request a client perform after login or after a clear cache. The server will include in the response all your rooms with the full state (all the room membership Event will not be present), with the latest messages for each room. We are in the process to replace this by version 3: sliding sync. All data are inserted to the Database (currently [Realm](https://www.mongodb.com/docs/realm/sdk/java/)).
|
||||
- **incremental sync**: sync request with a token.
|
||||
- **gappy sync**: sync request where all the new Events are not returned for one or several Rooms. Also called `limited sync`. It can be limited per Room. To get all the missing Events, a Room pagination API has to be called.
|
||||
- **sync token**: `next_batch` value in the previous sync response. Will be provided as the `since` parameter for the next sync request.
|
||||
|
||||
### The Android project
|
||||
|
||||
The project should compile out of the box.
|
||||
|
||||
The project is split into several modules. The main ones are:
|
||||
For the app
|
||||
- `vector-app`: application entry point;
|
||||
- `vector`: legacy application, but now a library. In the process of being split into several modules;
|
||||
- `vector-config`: this is where all the configuration of the application should occurs. Should because we are in the process of migrating all the configuration here;
|
||||
- `library/ui-strings`: this is where all the string resources are stored. Please refer to [contributing doc](../CONTRIBUTING.md) to know how to make change on this module;
|
||||
- `library/ui-styles`: this is where the Android styles are defined.
|
||||
|
||||
For the SDK
|
||||
- `matrix-sdk-android`: the main SDK module. The sources are in this project, but are also exported to [its own project](https://github.com/matrix-org/matrix-android-sdk2). All the PRs and issues related to the SDK take place in the Element Android project;
|
||||
- `matrix-sdk-android-flow`: contains some wrapper to expose `Flow` to the application.
|
||||
|
||||
### Matrix SDK
|
||||
|
||||
SDK exposes `Services` to the client application. `Services` are public interface, and are defined in this parent package: `org.matrix.android.sdk.api`. Default implementation are internal to the SDK, in this parent package: `org.matrix.android.sdk.internal`. Note that you also have to declare the classes as `internal` when adding classes to the `org.matrix.android.sdk.internal` package.
|
||||
|
||||
Interface allows us to replace the implementation for testing purpose.
|
||||
|
||||
A generated documentation of the SDK is available [here](https://matrix-org.github.io/matrix-android-sdk2/). Updated after each release. Please ensure that the documentation (KDoc) of all the SDK Services is up to date, and is clear for a SDK user.
|
||||
The SDK generated documentation also contains information about the entry points of the SDK.
|
||||
|
||||
[Dagger](https://dagger.dev/) is used to inject all the dependencies to the SDK classes.
|
||||
|
||||
SDK is exposing data as `LiveData`, but we are progressively migrating to `Flow`. Database is the source of truth.
|
||||
|
||||
Example:
|
||||
- Client send an Event using the `SendService`;
|
||||
- At the end a `SendEvent` task is used;
|
||||
- Retrofit API is used to send data to the server;
|
||||
- Goes to the server, which returns only the `event_id`;
|
||||
- The `Event` is coming back from the `sync` response with eventually extra added data.
|
||||
|
||||
### Application
|
||||
|
||||
This is the UI part of the project.
|
||||
|
||||
There are two variants of the application: `Gplay` and `Fdroid`.
|
||||
|
||||
The main difference is about using Firebase on `Gplay` variant, to have Push from Google Services. `FDroid` variant cannot contain closed source dependency.
|
||||
|
||||
`Fdroid` is using background polling to lack the missing of Pushed. Now a solution using UnifiedPush has ben added to the project. See refer to [the dedicated documentation](./unifiedpush.md) for more details.
|
||||
|
||||
#### MvRx
|
||||
|
||||
[Maverick](https://airbnb.io/mavericks/#/README) (or MvRx) is an Android MVI framework that helps to develop Reactive application on Android.
|
||||
|
||||
- Activity: holder for Fragment. See the parent [VectorBaseActivity](../vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt);
|
||||
- Fragment: manage screen of the application. See the parent [VectorBaseFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt);
|
||||
- BottomSheet: see the parent [VectorBaseBottomSheetDialogFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt);
|
||||
- ViewModel: this is where the logic is placed. All our ViewModel has a `handle()` which takes action as parameter. See the parent [VectorViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt);
|
||||
- VectorSharedActionViewModel: Specific ViewModel that can be used to communicate between Fragment(s) and the host Activity. See the parent [VectorSharedActionViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorSharedActionViewModel.kt);
|
||||
- ViewState: this are `data class`, and this represent the state of the View. Has to be copied and set to be updated. Fragment will update the UI regarding the current state (`invalidate()` method). `Async` class from MvRx can be used in the ViewState, especially for asynchronous data loading. Nullability can also be used for optional data. ViewStates have to implement `MavericksState`;
|
||||
- ViewEvents: useful when the ViewModel asks the View to trigger a specific action: navigation, show dialog, etc. See the parent [VectorViewEvents](../vector/src/main/java/im/vector/app/core/platform/VectorViewEvents.kt);
|
||||
- ViewAction (`VectorViewModelAction`): useful when the UI (generally the Fragment) asks the ViewModel to do something. See the parent [VectorViewModelAction](../vector/src/main/java/im/vector/app/core/platform/VectorViewModelAction.kt);
|
||||
- Controller: see the `Epoxy` section just below.
|
||||
|
||||
##### Behavior
|
||||
|
||||
Fragment asks the ViewModel to perform an action (coming from the user, but not necessarily. ViewModel can then talk to the SDK, updates the state once or several times. Fragment update the UI regarding the new state.
|
||||
|
||||
When ViewModel is instantiated, it can subscribe using the SDK Services to get live state of the data.
|
||||
|
||||
`invalidate()` has to be used by default, but it's possible to listen to specific member(s) of the `ViewState` using `onEach`. TODO Add an example.
|
||||
`awaitState()` method
|
||||
|
||||
#### Epoxy
|
||||
|
||||
[Epoxy](https://github.com/airbnb/epoxy) is an Android library for building complex screens in a RecyclerView. Please read [the introduction](https://github.com/airbnb/epoxy#epoxy).
|
||||
|
||||
- Controller declares items of the RecyclerView. Controller is injected in the Fragment. Controller extends `EpoxyController`, or one of its subclass, especially `TypedEpoxyController`;
|
||||
- Fragment gives the state to the controller using `setData`;
|
||||
- `buildModels` will be called by the framework;
|
||||
- Controller will create ordered Items.
|
||||
|
||||
Epoxy does the diffing, and handle many other thing for us, like handling item type, etc.
|
||||
|
||||
See for instance the controller [AccountDataEpoxyController](../vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt)) for a simple example.
|
||||
|
||||
Warning: do not use twice the same item `id` or it will crash.
|
||||
|
||||
#### Other frameworks
|
||||
|
||||
- Dependency injection is managed by [Dagger](https://dagger.dev/) (SDK) and [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) (App);
|
||||
- [Retrofit](https://square.github.io/retrofit/) and [OkHttp3](https://square.github.io/okhttp/): network requests;
|
||||
- [Moshi](https://github.com/square/moshi) is used to parse and serialize Json object;
|
||||
|
||||
### Push
|
||||
|
||||
Please see the dedicated documentation for more details.
|
||||
|
||||
This is the classical scenario:
|
||||
|
||||
- App receives a Push. Note: Push is ignored if app is in foreground;
|
||||
- App asks the SDK to load Event data (fastlane mode). We have a change to get the data faster and display the notification faster;
|
||||
- App asks the SDK to perform a sync request.
|
||||
|
||||
### Dependencies management
|
||||
|
||||
All the dependencies are declared in `build.gradle` files. But some versions are declared in [this dedicated file](../dependencies.gradle).
|
||||
|
||||
When adding a new dependency, you will have to update the file [dependencies_groups.gradle](../dependencies_groups.gradle) to allow the dependency to be downloaded from the artifact repository. Sometimes sub-dependencies need to be added too, until the project can compile.
|
||||
|
||||
[Dependabot](https://github.com/dependabot) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one.
|
||||
dependencies_group, gradle files, Dependabot, etc.
|
||||
|
||||
### Test
|
||||
|
||||
Please refer to [this dedicated document](./ui-tests.md).
|
||||
|
||||
TODO add link to the dedicated screenshot test documentation
|
||||
|
||||
### Other points
|
||||
|
||||
#### Logging
|
||||
|
||||
**Important warning: ** NEVER log private user data, or use the flag `LOG_PRIVATE_DATA`. Be very careful when logging `data class`, all the content will be output!
|
||||
|
||||
[Timber](https://github.com/JakeWharton/timber) is used to log data to logcat. We do not use directly the `Log` class. If possible please use a tag, as per
|
||||
|
||||
````kotlin
|
||||
Timber.tag(loggerTag.value).d("my log")
|
||||
````
|
||||
|
||||
because automatic tag (= class name) will not be available on the release version.
|
||||
|
||||
Also generally it is recommended to provide the `Throwable` to the Timber log functions.
|
||||
|
||||
Last point, not that `Timber.v` function may have no effect on some devices. Prefer using `Timber.d` and up.
|
||||
|
||||
#### Rageshake
|
||||
|
||||
Rageshake is a feature to send bug report directly from the application. Just shake your phone and you will be prompted to send a bug report.
|
||||
|
||||
Bug report can contain:
|
||||
- a screenshot of the current application state
|
||||
- the application logs from up to 15 application starts
|
||||
- the logcat logs
|
||||
- the key share history (crypto data)
|
||||
|
||||
The data will be sent to an internal server, which is not publicly accessible. A GitHub issue will also be created to a private GitHub repository.
|
||||
|
||||
Rageshake can be very useful to get logs from a release version of the application.
|
||||
|
||||
### Tips
|
||||
|
||||
- Element Android has a `developer mode` in the `Settings/Advanced settings`. Other useful options are available here;
|
||||
- Show hidden Events can also help to debug feature. When developer mode is enabled, it is possible to view the source (= the Json content) of any Events;
|
||||
- Type `/devtools` in a Room composer to access a developer menu. There are some other entry points. Developer mode has to be enabled;
|
||||
- Hidden debug menu: when developer mode is enabled and on debug build, there are some extra screens that can be accessible using the green wheel. In those screens, it will be possible to toggle some feature flags;
|
||||
- Using logcat, filtering with `onResume` can help you to understand what screen are currently displayed on your device. Searching for string displayed on the screen can also help to find the running code in the codebase.
|
||||
- When this is possible, prefer using `sealed interface` instead of `sealed class`;
|
||||
- When writing temporary code, using the string "DO NOT COMMIT" in a comment can help to avoid committing things by mistake. If committed and pushed, the CI will detect this String and will warn the user about it.
|
||||
|
||||
## Happy coding!
|
||||
|
||||
The team is here to support you, feel free to ask anything to other developers.
|
||||
|
||||
Also please feel to update this documentation, if incomplete/wrong/obsolete/etc.
|
||||
|
||||
**Thanks!**
|
@@ -1,34 +1,5 @@
|
||||
# Adding and removing ThreePids to an account
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Add email](#add-email)
|
||||
* [User enter the email](#user-enter-the-email)
|
||||
* [The email is already added to an account](#the-email-is-already-added-to-an-account)
|
||||
* [The email is free](#the-email-is-free)
|
||||
* [User receives an e-mail](#user-receives-an-e-mail)
|
||||
* [User clicks on the link](#user-clicks-on-the-link)
|
||||
* [User returns on Element](#user-returns-on-element)
|
||||
* [User enters his password](#user-enters-his-password)
|
||||
* [The link has not been clicked](#the-link-has-not-been-clicked)
|
||||
* [Wrong password](#wrong-password)
|
||||
* [The link has been clicked and the account password is correct](#the-link-has-been-clicked-and-the-account-password-is-correct)
|
||||
* [Remove email](#remove-email)
|
||||
* [User want to remove an email from his account](#user-want-to-remove-an-email-from-his-account)
|
||||
* [Email was not bound to an identity server](#email-was-not-bound-to-an-identity-server)
|
||||
* [Email was bound to an identity server](#email-was-bound-to-an-identity-server)
|
||||
* [Add phone number](#add-phone-number)
|
||||
* [The phone number is already added to an account](#the-phone-number-is-already-added-to-an-account)
|
||||
* [The phone number is free](#the-phone-number-is-free)
|
||||
* [User receive a text message](#user-receive-a-text-message)
|
||||
* [User enter the code to the app](#user-enter-the-code-to-the-app)
|
||||
* [Wrong code](#wrong-code)
|
||||
* [Correct code](#correct-code)
|
||||
* [Remove phone number](#remove-phone-number)
|
||||
* [User wants to remove a phone number from his account](#user-wants-to-remove-a-phone-number-from-his-account)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Add email
|
||||
|
||||
### User enter the email
|
||||
@@ -66,9 +37,9 @@ Wording: "We've sent you an email to verify your address. Please follow the inst
|
||||
}
|
||||
```
|
||||
|
||||
## User receives an e-mail
|
||||
## User receive an e-mail
|
||||
|
||||
> `homeserver.org` Validate your email
|
||||
> [homeserver.org] Validate your email
|
||||
>
|
||||
> A request to add an email address to your Matrix account has been received. If this was you, please click the link below to confirm adding this email:
|
||||
https://homeserver.org/_matrix/client/unstable/add_threepid/email/submit_token?token=WUnEhQAmJrXupdEbXgdWvnVIKaGYZFsU&client_secret=TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh&sid=bxyDHuJKsdkjMlTJ
|
||||
|
@@ -1,13 +1,5 @@
|
||||
# Analytics in Element
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Solution](#solution)
|
||||
* [How to add a new Event](#how-to-add-a-new-event)
|
||||
* [Forks of Element](#forks-of-element)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Solution
|
||||
|
||||
Element is using PostHog to send analytics event.
|
||||
|
@@ -1,14 +1,5 @@
|
||||
# Color migration
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Changes](#changes)
|
||||
* [Main change for developers](#main-change-for-developers)
|
||||
* [Remaining work](#remaining-work)
|
||||
* [Migration guide](#migration-guide)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
### Changes
|
||||
|
||||
- use colors defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0
|
||||
|
106
docs/danger.md
106
docs/danger.md
@@ -1,106 +0,0 @@
|
||||
## Danger
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [What does danger checks](#what-does-danger-checks)
|
||||
* [PR check](#pr-check)
|
||||
* [Quality check](#quality-check)
|
||||
* [Setup](#setup)
|
||||
* [Run danger locally](#run-danger-locally)
|
||||
* [Danger user](#danger-user)
|
||||
* [Useful links](#useful-links)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## What does danger checks
|
||||
|
||||
### PR check
|
||||
|
||||
See the [dangerfile](../tools/danger/dangerfile.js). If you add rules in the dangerfile, please update the list below!
|
||||
|
||||
Here are the checks that Danger does so far:
|
||||
|
||||
- PR description is not empty
|
||||
- Big PR got a warning to recommend to split
|
||||
- PR contains a file for towncrier and extension is checked
|
||||
- PR does not modify frozen classes
|
||||
- PR contains a Sign-Off, with exception for Element employee contributors
|
||||
- PR with change on layout should include screenshot in the description
|
||||
- PR which adds png file warn about the usage of vector drawables
|
||||
- non draft PR should have a reviewer
|
||||
- files containing translations are not modified by developers
|
||||
|
||||
### Quality check
|
||||
|
||||
After all the checks that generate checkstyle XML report, such as Ktlint, lint, or Detekt, Danger is run with this [dangerfile](../tools/danger/dangerfile-lint.js), in order to post comments to the PR with the detected error and warnings.
|
||||
|
||||
To run locally, you will have to install the plugin `danger-plugin-lint-report` using:
|
||||
|
||||
```shell
|
||||
yarn add danger-plugin-lint-report --dev
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
This operation should not be necessary, since Danger is already setup for the project.
|
||||
|
||||
To setup danger to the project, run:
|
||||
|
||||
```shell
|
||||
bundle exec danger init
|
||||
```
|
||||
|
||||
## Run danger locally
|
||||
|
||||
When modifying the [dangerfile](../tools/danger/dangerfile.js), you can check it by running Danger locally.
|
||||
|
||||
To run danger locally, install it and run:
|
||||
|
||||
```shell
|
||||
bundle exec danger pr <PR_URL> --dangerfile=./tools/danger/dangerfile.js
|
||||
```
|
||||
|
||||
For instance:
|
||||
|
||||
```shell
|
||||
bundle exec danger pr https://github.com/vector-im/element-android/pull/6637 --dangerfile=./tools/danger/dangerfile.js
|
||||
```
|
||||
|
||||
We may need to create a GitHub token to have less API rate limiting, and then set the env var:
|
||||
|
||||
```shell
|
||||
export DANGER_GITHUB_API_TOKEN='YOUR_TOKEN'
|
||||
```
|
||||
|
||||
Swift and Kotlin (just in case)
|
||||
|
||||
```shell
|
||||
bundle exec danger-swift pr <PR_URL> --dangerfile=./tools/danger/dangerfile.js
|
||||
bundle exec danger-kotlin pr <PR_URL> --dangerfile=./tools/danger/dangerfile.js
|
||||
```
|
||||
|
||||
## Danger user
|
||||
|
||||
To let Danger check all the PRs, including PRs form forks, a GitHub account have been created:
|
||||
- login: ElementBot
|
||||
- password: Stored on Passbolt
|
||||
- GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
|
||||
|
||||
PRs from forks do not always have access to the secret `secrets.DANGER_GITHUB_API_TOKEN`, so `secrets.GITHUB_TOKEN` is also provided to the job environment. If `secrets.DANGER_GITHUB_API_TOKEN` is available, it will be used, so user `ElementBot` will comment the PR. Else `secrets.GITHUB_TOKEN` will be used, and bot `github-actions` will comment the PR.
|
||||
|
||||
## Useful links
|
||||
|
||||
- https://danger.systems/
|
||||
- https://danger.systems/js/
|
||||
- https://danger.systems/js/guides/getting_started.html
|
||||
- https://danger.systems/js/reference.html
|
||||
- https://github.com/danger/awesome-danger
|
||||
|
||||
Some danger files to get inspired from
|
||||
|
||||
- https://github.com/artsy/emission/blob/master/dangerfile.ts
|
||||
- https://github.com/facebook/react-native/blob/master/bots/dangerfile.js
|
||||
- https://github.com/apollographql/apollo-client/blob/master/config/dangerfile.ts
|
||||
- https://github.com/styleguidist/react-styleguidist/blob/master/dangerfile.js
|
||||
- https://github.com/storybooks/storybook/blob/master/dangerfile.js
|
||||
- https://github.com/ReactiveX/rxjs/blob/master/dangerfile.js
|
@@ -1,55 +0,0 @@
|
||||
<!--- TOC -->
|
||||
|
||||
* [Testing database migration](#testing-database-migration)
|
||||
* [Creating a reference database](#creating-a-reference-database)
|
||||
* [Testing](#testing)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Testing database migration
|
||||
|
||||
### Creating a reference database
|
||||
|
||||
Databases are encrypted, the key to decrypt is needed to setup the test.
|
||||
A special build property must be enabled to extract it.
|
||||
|
||||
Set `vector.debugPrivateData=true` in `~/.gradle/gradle.properties` (to avoid committing by mistake)
|
||||
|
||||
Launch the app in your emulator, login and use the app to fill up the database.
|
||||
|
||||
Save the key for the tested database
|
||||
```
|
||||
RealmKeysUtils W Database key for alias `session_db_fe9f212a611ccf6dea1141777065ed0a`: 935a6dfa0b0fc5cce1414194ed190....
|
||||
RealmKeysUtils W Database key for alias `crypto_module_fe9f212a611ccf6dea1141777065ed0a`: 7b9a21a8a311e85d75b069a343.....
|
||||
```
|
||||
|
||||
|
||||
Use the [Device File Explorer](https://developer.android.com/studio/debug/device-file-explorer) to extrat the database file from the emulator.
|
||||
|
||||
Go to `data/data/im.vector.app.debug/files/<hash>/`
|
||||
Pick the database you want to test (name can be found in SessionRealmConfigurationFactory):
|
||||
- crypto_store.realm for crypto
|
||||
- disk_store.realm for session
|
||||
- etc...
|
||||
|
||||
Download the file on your disk
|
||||
|
||||
### Testing
|
||||
|
||||
Copy the file in `src/AndroidTest/assets`
|
||||
|
||||
see `CryptoSanityMigrationTest` or `RealmSessionStoreMigration43Test` for sample tests.
|
||||
|
||||
There are already some databases in the assets folder.
|
||||
The existing test will properly detect schema changes, and fail with such errors if a migration is missing:
|
||||
|
||||
```
|
||||
io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:
|
||||
- Property 'CryptoMetadataEntity.foo' has been added.
|
||||
```
|
||||
|
||||
If you want to test properly more complex database migration (dynamic transforms) ensure that the database contains
|
||||
the entity you want to migrate.
|
||||
|
||||
You can explore the database with [realm studio](https://www.mongodb.com/docs/realm/studio/) if needed.
|
||||
|
@@ -1,31 +1,5 @@
|
||||
# Element Android design
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [How to import from Figma to the Element Android project](#how-to-import-from-figma-to-the-element-android-project)
|
||||
* [Colors](#colors)
|
||||
* [Text](#text)
|
||||
* [Dimension, position and margin](#dimension-position-and-margin)
|
||||
* [Icons](#icons)
|
||||
* [Export drawable from Figma](#export-drawable-from-figma)
|
||||
* [Import in Android Studio](#import-in-android-studio)
|
||||
* [Images](#images)
|
||||
* [Figma links](#figma-links)
|
||||
* [Coumpound](#coumpound)
|
||||
* [Login](#login)
|
||||
* [Login v2](#login-v2)
|
||||
* [Room list](#room-list)
|
||||
* [Timeline](#timeline)
|
||||
* [Voice message](#voice-message)
|
||||
* [Room settings](#room-settings)
|
||||
* [VoIP](#voip)
|
||||
* [Presence](#presence)
|
||||
* [Spaces](#spaces)
|
||||
* [List to be continued...](#list-to-be-continued)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Introduction
|
||||
|
||||
Design at element.io is done using Figma - https://www.figma.com
|
||||
|
@@ -1,58 +0,0 @@
|
||||
# Flipper
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Setup](#setup)
|
||||
* [Troubleshoot](#troubleshoot)
|
||||
* [No device found issue](#no-device-found-issue)
|
||||
* [Diagnostic Activity](#diagnostic-activity)
|
||||
* [Other](#other)
|
||||
* [Links](#links)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Introduction
|
||||
|
||||
[Flipper](https://fbflipper.com) is a powerful tool from Meta, which allow to inspect the running application details and states from your computer.
|
||||
|
||||
Flipper is configured in the Element Android project to let the developers be able to:
|
||||
- inspect all the Realm databases content;
|
||||
- do layout inspection;
|
||||
- see the crash logs;
|
||||
- see the logcat;
|
||||
- see all the network requests;
|
||||
- see all the SharedPreferences;
|
||||
- take screenshots and record videos of the device;
|
||||
- and more!
|
||||
|
||||
## Setup
|
||||
|
||||
- Install Flipper on your computer. Follow instructions here: https://fbflipper.com/docs/getting-started/index/
|
||||
- Run the debug version of Element on an emulator or on a real device.
|
||||
|
||||
### Troubleshoot
|
||||
|
||||
#### No device found issue
|
||||
|
||||
The configuration of the Flipper application has to be updated. The issue has been asked and answered here: https://stackoverflow.com/questions/71744103/android-emulator-unable-to-connect-to-flipper/72608113#72608113
|
||||
|
||||
#### Diagnostic Activity
|
||||
|
||||
Flipper comes with a Diagnostic Activity that you can start from command line using:
|
||||
|
||||
```shell
|
||||
adb shell am start -n im.vector.app.debug/com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity
|
||||
```
|
||||
|
||||
It provides some log which can help to figure out what's going on client side.
|
||||
|
||||
#### Other
|
||||
|
||||
https://fbflipper.com/docs/getting-started/troubleshooting/android/ may help.
|
||||
|
||||
## Links
|
||||
|
||||
- Official Flipper website: https://fbflipper.com
|
||||
- Realm Plugin for Flipper: https://github.com/kamgurgul/Flipper-Realm
|
||||
- Dedicated Matrix room: https://matrix.to/#/#unifiedpush:matrix.org
|
@@ -7,8 +7,8 @@ Hilt is built on top of Dagger 2 and simplify usage by removing needs to create
|
||||
When you create a new feature, you should have the following:
|
||||
|
||||
Annotate your Activity with @AndroidEntryPoint
|
||||
Annotate your Fragment with @AndroidEntryPoint
|
||||
If you have a BottomSheetFragment => Annotate it with @AndroidEntryPoint
|
||||
Otherwise => Add your Fragment to the FragmentModule
|
||||
Add your ViewModel.Factory to the MavericksViewModelModule
|
||||
Makes sure your ViewModel as the following code:
|
||||
|
||||
|
@@ -1,19 +1,5 @@
|
||||
# Identity server
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Implementation](#implementation)
|
||||
* [Related MSCs](#related-mscs)
|
||||
* [Steps and requirements](#steps-and-requirements)
|
||||
* [Screens](#screens)
|
||||
* [Settings](#settings)
|
||||
* [Discovery screen](#discovery-screen)
|
||||
* [Set identity server screen](#set-identity-server-screen)
|
||||
* [Ref:](#ref:)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
Issue: #607
|
||||
PR: #1354
|
||||
|
||||
|
@@ -1,52 +0,0 @@
|
||||
## Installing from CI
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Installing from Buildkite](#installing-from-buildkite)
|
||||
* [Installing from GitHub](#installing-from-github)
|
||||
* [Create a GitHub token](#create-a-github-token)
|
||||
* [Provide artifact URL](#provide-artifact-url)
|
||||
* [Next steps](#next-steps)
|
||||
* [Future improvement](#future-improvement)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
Installing APK build by the CI is possible
|
||||
|
||||
### Installing from Buildkite
|
||||
|
||||
The script `./tools/install/installFromBuildkite.sh` can be used, but Builkite will be removed soon. See next section.
|
||||
|
||||
### Installing from GitHub
|
||||
|
||||
To install an APK built by a GitHub action, run the script `./tools/install/installFromGitHub.sh`. You will need to pass a GitHub token to do so.
|
||||
|
||||
#### Create a GitHub token
|
||||
|
||||
You can create a GitHub token going to your Github account, at this page: [https://github.com/settings/tokens](https://github.com/settings/tokens).
|
||||
|
||||
You need to create a token (classic) with the scope `repo/public_repo`. So just check the corresponding checkbox.
|
||||
Validity can be long since the scope of this token is limited. You will still be able to delete the token and generate a new one.
|
||||
Click on Generate token and save the token locally.
|
||||
|
||||
### Provide artifact URL
|
||||
|
||||
The script will ask for an artifact URL. You can get this artifact URL by following these steps:
|
||||
|
||||
- open the pull request
|
||||
- in the check at the bottom, click on `APK Build / Build debug APKs`
|
||||
- click on `Summary`
|
||||
- scroll to the bottom of the page
|
||||
- copy the link `vector-Fdroid-debug` if you want the F-Droid variant or `vector-Gplay-debug` if you want the Gplay variant.
|
||||
|
||||
The copied link can be provided to the script.
|
||||
|
||||
### Next steps
|
||||
|
||||
The script will download the artifact, unzip it and install the correct version (regarding arch) on your device.
|
||||
|
||||
Files will be added to the folder `./tmp/DebugApks`. Feel free to cleanup this folder from time to time, the script will not delete files.
|
||||
|
||||
### Future improvement
|
||||
|
||||
The script could ask the user for a Pull Request number and Gplay/Fdroid choice like it was done with Buildkite script. Using GitHub API may be possible to do that.
|
@@ -1,18 +1,5 @@
|
||||
# Integration tests
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Pre requirements](#pre-requirements)
|
||||
* [Install and run Synapse](#install-and-run-synapse)
|
||||
* [Run the test](#run-the-test)
|
||||
* [Stop Synapse](#stop-synapse)
|
||||
* [Troubleshoot](#troubleshoot)
|
||||
* [Android Emulator does cannot reach the homeserver](#android-emulator-does-cannot-reach-the-homeserver)
|
||||
* [Tests partially run but some fail with "Unable to contact localhost:8080"](#tests-partially-run-but-some-fail-with-"unable-to-contact-localhost:8080")
|
||||
* [virtualenv command fails](#virtualenv-command-fails)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
Integration tests are useful to ensure that the code works well for any use cases.
|
||||
|
||||
They can also be used as sample on how to use the Matrix SDK.
|
||||
@@ -56,17 +43,14 @@ virtualenv -p python3 env
|
||||
source env/bin/activate
|
||||
pip install -e .
|
||||
demo/start.sh --no-rate-limit
|
||||
|
||||
```
|
||||
|
||||
Alternatively, to install the latest Synapse release package (and not a cloned branch) you can run the following instead of `git clone` and `pip install -e .`:
|
||||
Alternatively, to install the latest Synapse release package (and not a cloned branch) you can run the following instead of `pip install -e .`:
|
||||
|
||||
```bash
|
||||
pip install matrix-synapse
|
||||
```
|
||||
|
||||
On your first run, you will want to stop the demo and edit the config to correct the `public_baseurl` to http://10.0.2.2:8080 and restart the server.
|
||||
|
||||
You should now have 3 running federated Synapse instances 🎉, at http://127.0.0.1:8080/, http://127.0.0.1:8081/ and http://127.0.0.1:8082/, which should display a "It Works! Synapse is running" message.
|
||||
|
||||
## Run the test
|
||||
@@ -103,18 +87,6 @@ You'll need python3 to be able to run synapse
|
||||
|
||||
Try on the Emulator browser to open "http://10.0.2.2:8080". You should see the "Synapse is running" message.
|
||||
|
||||
### Tests partially run but some fail with "Unable to contact localhost:8080"
|
||||
|
||||
This is because the `public_baseurl` of synapse is not consistent with the endpoint that the tests are connecting to.
|
||||
|
||||
Ensure you have the following configuration in `demo/etc/8080.config`.
|
||||
|
||||
```
|
||||
public_baseurl: http://10.0.2.2:8080/
|
||||
```
|
||||
|
||||
After changing this you will need to restart synapse using `demo/stop.sh` and `demo/start.sh` to load the new configuration.
|
||||
|
||||
### virtualenv command fails
|
||||
|
||||
You can try using
|
||||
|
@@ -1,40 +1,28 @@
|
||||
# Jitsi in Element Android
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Native Jitsi SDK](#native-jitsi-sdk)
|
||||
* [How to build the Jitsi Meet SDK](#how-to-build-the-jitsi-meet-sdk)
|
||||
* [Jitsi version](#jitsi-version)
|
||||
* [Run the build script](#run-the-build-script)
|
||||
* [Link with the new generated library](#link-with-the-new-generated-library)
|
||||
* [Sanity tests](#sanity-tests)
|
||||
* [Export the build library](#export-the-build-library)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
Native Jitsi support has been added to Element Android by the PR [#1914](https://github.com/vector-im/element-android/pull/1914). The description of the PR contains some documentation about the behaviour in each possible room configuration.
|
||||
|
||||
Also, ensure to have a look on [the documentation from Element Web](https://github.com/vector-im/element-web/blob/develop/docs/jitsi.md)
|
||||
|
||||
The official documentation about how to integrate the Jitsi SDK in an Android app is available here: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk.
|
||||
|
||||
## Native Jitsi SDK
|
||||
# Native Jitsi SDK
|
||||
|
||||
The Jitsi SDK is built by ourselves with the flag LIBRE_BUILD, to be able to be integrated on the F-Droid version of Element Android.
|
||||
|
||||
The generated maven repository is then host in the project https://github.com/vector-im/jitsi_libre_maven
|
||||
|
||||
### How to build the Jitsi Meet SDK
|
||||
## How to build the Jitsi Meet SDK
|
||||
|
||||
#### Jitsi version
|
||||
### Jitsi version
|
||||
|
||||
Update the script `./tools/jitsi/build_jisti_libs.sh` with the tag of the project `https://github.com/jitsi/jitsi-meet`.
|
||||
|
||||
Latest tag can be found from this page: https://github.com/jitsi/jitsi-meet-release-notes/blob/master/CHANGELOG-MOBILE-SDKS.md
|
||||
|
||||
Currently we are building the version with the tag `android-sdk-8.1.1`.
|
||||
Currently we are building the version with the tag `android-sdk-3.10.0`.
|
||||
|
||||
#### Run the build script
|
||||
### Run the build script
|
||||
|
||||
At the root of the Element Android, run the following script:
|
||||
|
||||
@@ -44,12 +32,12 @@ At the root of the Element Android, run the following script:
|
||||
|
||||
It will build the Jitsi Meet Android library and put every generated files in the folder `/tmp/jitsi`
|
||||
|
||||
#### Link with the new generated library
|
||||
### Link with the new generated library
|
||||
|
||||
- Update the file `./build.gradle` to use the previously created local Maven repository. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-8.1.1"
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-3.10.0"
|
||||
```
|
||||
|
||||
You can uncomment and update the line starting with `// url "file://...` and comment the line starting with `url`, to test the library using the locally generated Maven repository.
|
||||
@@ -57,19 +45,19 @@ You can uncomment and update the line starting with `// url "file://...` and com
|
||||
- Update the dependency of the Jitsi Meet library in the file `./vector/build.gradle`. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
api('org.jitsi.react:jitsi-meet-sdk:8.1.1')
|
||||
implementation('org.jitsi.react:jitsi-meet-sdk:3.10.0')
|
||||
```
|
||||
|
||||
- Update the dependency of the WebRTC library in the file `./vector/build.gradle`. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
implementation('com.facebook.react:react-native-webrtc:111.0.0-jitsi-13672566@aar')
|
||||
implementation('com.facebook.react:react-native-webrtc:1.92.1-jitsi-9093212@aar')
|
||||
```
|
||||
|
||||
- Perform a gradle sync and build the project
|
||||
- Perform test
|
||||
|
||||
#### Sanity tests
|
||||
### Sanity tests
|
||||
|
||||
In order to validate that the upgrade of the Jitsi and WebRTC dependency does not break anything, the following sanity tests have to be performed, using two devices:
|
||||
- Make 1-1 audio call (so using WebRTC)
|
||||
@@ -77,7 +65,7 @@ In order to validate that the upgrade of the Jitsi and WebRTC dependency does no
|
||||
- Create and join a conference call with audio only (so using Jitsi library). Leave the conference. Join it again.
|
||||
- Create and join a conference call with audio and video (so using Jitsi library) Leave the conference. Join it again.
|
||||
|
||||
#### Export the build library
|
||||
### Export the build library
|
||||
|
||||
If all the tests are passed, you can export the generated Jitsi library to our Maven repository.
|
||||
|
||||
@@ -88,9 +76,9 @@ If all the tests are passed, you can export the generated Jitsi library to our M
|
||||
- Update the file `./build.gradle` to use the previously created Maven repository. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-8.1.1"
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-3.10.0"
|
||||
```
|
||||
|
||||
- Build the project and perform the sanity tests again.
|
||||
|
||||
- Create a PR for project Element Android and add a changelog file `<PR_NUMBER>.misc` to notify about the library upgrade.
|
||||
- Update the file `/CHANGES.md` to notify about the library upgrade, and create a regular PR for project Element Android.
|
@@ -1,54 +0,0 @@
|
||||
# Nightly builds
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Configuration](#configuration)
|
||||
* [How to register to get nightly build](#how-to-register-to-get-nightly-build)
|
||||
* [Build nightly manually](#build-nightly-manually)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Configuration
|
||||
|
||||
The nightly build will contain what's on develop, in release mode, for Gplay variant. It is signed using a dedicated signature, and has a dedicated appId (`im.vector.app.nightly`), so it can be installed along with the production version of Element Android. The only other difference compared to Element Android is a different app icon background. We do not want to change the app name since it will also affect some strings in the app, and we do want to do that.
|
||||
|
||||
Nightly builds are built and released to Firebase every days, and automatically.
|
||||
|
||||
This is recommended to exclusively use this app, with your main account, instead of Element Android, and fallback to Element Android just in case of regression, to discover as soon as possible any regression, and report it to the team. To avoid double notification, you may want to disable the notification from the Element Android production version. Just open Element Android, navigate to `Settings/Notifications` and uncheck `Enable notifications for this session`.
|
||||
|
||||
*Note:* Due to a limitation of Firebase, the nightly build is the universal build, which means that the size of the APK is a bit bigger, but this should not have any other side effect.
|
||||
|
||||
## How to register to get nightly build
|
||||
|
||||
Provide your email to the Android team, who will add it to the list "External testers" on Firebase. You will then receive an invite on the provided email.
|
||||
|
||||
Follow the instructions on the email to install the latest nightly build. This is not clear yet if new nightly build will be automatically installed or not.
|
||||
|
||||
## Build nightly manually
|
||||
|
||||
Nightly build can be built manually from your computer. You will need to retrieved some secrets from Passbolt and add them to your file `~/.gradle/gradle.properties`:
|
||||
|
||||
```
|
||||
signing.element.nightly.storePassword=VALUE_FROM_PASSBOLT
|
||||
signing.element.nightly.keyId=VALUE_FROM_PASSBOLT
|
||||
signing.element.nightly.keyPassword=VALUE_FROM_PASSBOLT
|
||||
```
|
||||
|
||||
You will also need to add the environment variable `FIREBASE_TOKEN`:
|
||||
|
||||
```sh
|
||||
export FIREBASE_TOKEN=VALUE_FROM_PASSBOLT
|
||||
```
|
||||
|
||||
Then you can run the following commands (which are also used in the file for [the GitHub action](../.github/workflows/nightly.yml)):
|
||||
|
||||
```sh
|
||||
git checkout develop
|
||||
mv towncrier.toml towncrier.toml.bak
|
||||
sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml
|
||||
rm towncrier.toml.bak
|
||||
yes n | towncrier build --version nightly
|
||||
./gradlew assembleGplayRustCryptoNightly appDistributionUploadRustKotlinCryptoNightly $CI_GRADLE_ARG_PROPERTIES
|
||||
```
|
||||
|
||||
Then you can reset the change on the codebase.
|
@@ -1,42 +1,37 @@
|
||||
This document aims to describe how Element android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
||||
|
||||
# Table of Contents
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||
* [How does a matrix client get a message from a homeserver?](#how-does-a-matrix-client-get-a-message-from-a-homeserver?)
|
||||
* [How does a mobile app receives push notification](#how-does-a-mobile-app-receives-push-notification)
|
||||
* [Push VS Notification](#push-vs-notification)
|
||||
* [Push in the matrix federated world](#push-in-the-matrix-federated-world)
|
||||
* [How does the homeserver know when to notify a client?](#how-does-the-homeserver-know-when-to-notify-a-client?)
|
||||
* [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
|
||||
* [Background processing limitations](#background-processing-limitations)
|
||||
* [Element Notification implementations](#element-notification-implementations)
|
||||
* [Requirements](#requirements)
|
||||
* [Foreground sync mode (Gplay and F-Droid)](#foreground-sync-mode-gplay-and-f-droid)
|
||||
* [Push (FCM) received in background](#push-fcm-received-in-background)
|
||||
* [FCM Fallback mode](#fcm-fallback-mode)
|
||||
* [F-Droid background Mode](#f-droid-background-mode)
|
||||
* [Application Settings](#application-settings)
|
||||
|
||||
<!--- END -->
|
||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||
* [How does a matrix client get a message from a homeserver?](#how-does-a-matrix-client-get-a-message-from-a-homeserver)
|
||||
* [How does a mobile app receives push notification?](#how-does-a-mobile-app-receives-push-notification)
|
||||
* [Push VS Notification](#push-vs-notification)
|
||||
* [Push in the matrix federated world](#push-in-the-matrix-federated-world)
|
||||
* [How does the homeserver know when to notify a client?](#how-does-the-homeserver-know-when-to-notify-a-client)
|
||||
* [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
|
||||
* [Background processing limitations](#background-processing-limitations)
|
||||
2. [Element Notification implementations](#element-notification-implementations)
|
||||
* [Requirements](#requirements)
|
||||
* [Foreground sync mode (Gplay & F-Droid)](#foreground-sync-mode-gplay-f-droid)
|
||||
* [Push (FCM) received in background](#push-fcm-received-in-background)
|
||||
* [FCM Fallback mode](#fcm-fallback-mode)
|
||||
* [F-Droid background Mode](#f-droid-background-mode)
|
||||
3. [Application Settings](#application-settings)
|
||||
|
||||
|
||||
First let's start with some prerequisite knowledge
|
||||
|
||||
## Prerequisites Knowledge
|
||||
# Prerequisites Knowledge
|
||||
|
||||
### How does a matrix client get a message from a homeserver?
|
||||
## How does a matrix client get a message from a homeserver?
|
||||
|
||||
In order to get messages from a homeserver, a matrix client need to perform a ``sync`` operation.
|
||||
|
||||
`To read events, the intended flow of operation is for clients to first call the /sync API without a since parameter. This returns the most recent message events for each room, as well as the state of the room at the start of the returned timeline. `
|
||||
|
||||
The client need to call the `sync` API periodically in order to get incremental updates of the server state (new messages).
|
||||
The client need to call the `sync`API periodically in order to get incremental updates of the server state (new messages).
|
||||
This mechanism is known as **HTTP long Polling**.
|
||||
|
||||
Using the **HTTP Long Polling** mechanism a client polls a server requesting new information.
|
||||
Using the **HTTP Long Polling** mechanism a client polls a server requesting new information.
|
||||
The server *holds the request open until new data is available*.
|
||||
Once available, the server responds and sends the new information.
|
||||
When the client receives the new information, it immediately sends another request, and the operation is repeated.
|
||||
@@ -57,7 +52,7 @@ By default, this is 0, so the server will return immediately even if the respons
|
||||
|
||||
When the Element Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
||||
|
||||
### How does a mobile app receives push notification
|
||||
## How does a mobile app receives push notification
|
||||
|
||||
Push notification is used as a way to wake up a mobile application when some important information is available and should be processed.
|
||||
|
||||
@@ -71,22 +66,22 @@ FCM will only work on android devices that have Google plays services installed
|
||||
(In simple terms, Google Play Services is a background service that runs on Android, which in turn helps in integrating Google’s advanced functionalities to other applications)
|
||||
|
||||
De-Googlified devices need to rely on something else in order to stay up to date with a server.
|
||||
There some cases when devices with google services cannot use FCM (network infrastructure limitations -firewalls-,
|
||||
privacy and or independence requirement, source code licence)
|
||||
There some cases when devices with google services cannot use FCM (network infrastructure limitations -firewalls- ,
|
||||
privacy and or independency requirement, source code licence)
|
||||
|
||||
### Push VS Notification
|
||||
## Push VS Notification
|
||||
|
||||
This need some disambiguation, because it is the source of common confusion:
|
||||
|
||||
|
||||
*The fact that you see a notification on your screen does not mean that you have successfully configured your PUSH platform.*
|
||||
*The fact that you see a notification on your screen does not mean that you have successfully configured your PUSH plateform.*
|
||||
|
||||
Technically there is a difference between a push and a notification. A notification is what you see on screen and/or in the notification Menu/Drawer (in the top bar of the phone).
|
||||
|
||||
Notifications are not always triggered by a push (One can display a notification locally triggered by an alarm)
|
||||
|
||||
|
||||
### Push in the matrix federated world
|
||||
## Push in the matrix federated world
|
||||
|
||||
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
|
||||
This server is called a **Push Gateway** in the matrix world
|
||||
@@ -123,11 +118,11 @@ Client/Server API + | | | | |
|
||||
```
|
||||
|
||||
Recommended reading:
|
||||
* https://thomask.sdf.org/blog/2016/12/11/riots-magical-push-notifications-in-ios.html
|
||||
* https://thomask.sdf.org/blog/2016/12/11/riots-magical-push-notifications-in-ios.html
|
||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id128
|
||||
|
||||
|
||||
### How does the homeserver know when to notify a client?
|
||||
## How does the homeserver know when to notify a client?
|
||||
|
||||
This is defined by [**push rules**](https://matrix.org/docs/spec/client_server/r0.4.0.html#push-rules-).
|
||||
|
||||
@@ -145,14 +140,14 @@ Of course, content patterns matching cannot be used for encrypted messages serve
|
||||
|
||||
That is why clients are able to **process the push rules client side** to decide what kind of notification should be presented for a given event.
|
||||
|
||||
### Push vs privacy, and mitigation
|
||||
## Push vs privacy, and mitigation
|
||||
|
||||
As seen previously, App developers don't directly send a push to the end user's device, they use a Push Provider as intermediary. So technically this intermediary is able to read the content of what is sent.
|
||||
|
||||
App developers usually mitigate this by sending a `silent notification`, that is a notification with no identifiable data, or with an encrypted payload. When the push is received the app can then synchronise to it's server in order to generate a local notification.
|
||||
|
||||
|
||||
### Background processing limitations
|
||||
## Background processing limitations
|
||||
|
||||
A mobile applications process live in a managed word, meaning that its process can be limited (e.g no network access), stopped or killed at almost anytime by the Operating System.
|
||||
|
||||
@@ -172,15 +167,15 @@ The documentation on this subject is vague, and as per our experiments not alway
|
||||
|
||||
It is getting more and more complex to have reliable notifications when FCM is not used.
|
||||
|
||||
## Element Notification implementations
|
||||
# Element Notification implementations
|
||||
|
||||
### Requirements
|
||||
## Requirements
|
||||
|
||||
Element Android must work with and without FCM.
|
||||
* The Element android app published on F-Droid do not rely on FCM (all related dependencies are not present)
|
||||
* The Element android app published on google play rely on FCM, with a fallback mode when FCM registration has failed (e.g outdated or missing Google Play Services)
|
||||
|
||||
### Foreground sync mode (Gplay and F-Droid)
|
||||
## Foreground sync mode (Gplay & F-Droid)
|
||||
|
||||
When in foreground, Element performs sync continuously with a timeout value set to 10 seconds (see HttpPooling).
|
||||
|
||||
@@ -188,9 +183,9 @@ As this mode does not need to live beyond the scope of the application, and as p
|
||||
|
||||
This mode is turned on when the app enters foreground, and off when enters background.
|
||||
|
||||
In background, and depending on whether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
|
||||
In background, and depending on wether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
|
||||
|
||||
### Push (FCM) received in background
|
||||
## Push (FCM) received in background
|
||||
|
||||
In order to enable Push, Element must first get a push token from the firebase SDK, then register a pusher with this token on the homeserver.
|
||||
|
||||
@@ -230,10 +225,10 @@ Upon reception of the FCM push, Element will perform a sync call to the homeserv
|
||||
|
||||
Element implements several strategies in these cases (TODO document)
|
||||
|
||||
### FCM Fallback mode
|
||||
## FCM Fallback mode
|
||||
|
||||
It is possible that Element is not able to get a FCM push token.
|
||||
Common errors (among several others) that can cause that:
|
||||
Common errors (amoung several others) that can cause that:
|
||||
* Google Play Services is outdated
|
||||
* Google Play Service fails in someways with FCM servers (infamous `SERVICE_NOT_AVAILABLE`)
|
||||
|
||||
@@ -251,7 +246,7 @@ Usually in this mode, what happen is when you take back your phone in your hand,
|
||||
|
||||
The fallback mode is supposed to be a temporary state waiting for the user to fix issues for FCM, or for App Developers that has done a fork to correctly configure their FCM settings.
|
||||
|
||||
### F-Droid background Mode
|
||||
## F-Droid background Mode
|
||||
|
||||
The F-Droid Element flavor has no dependencies to FCM, therefore cannot relies on Push.
|
||||
|
||||
@@ -261,7 +256,7 @@ Only solution left is to use `AlarmManager`, that offers new API to allow launch
|
||||
|
||||
Notice that these alarms, due to their potential impact on battery life, can still be restricted by the system. Documentation says that they will not be triggered more than every minutes under normal system operation, and when in low power mode about every 15 mn.
|
||||
|
||||
These restrictions can be relaxed by requiring the app to be white listed from battery optimization.
|
||||
These restrictions can be relaxed by requirering the app to be white listed from battery optimization.
|
||||
|
||||
F-Droid version will schedule alarms that will then trigger a Broadcast Receiver, that in turn will launch a Service (in the classic android way), and the reschedule an alarm for next time.
|
||||
|
||||
@@ -271,7 +266,9 @@ That is why on Element F-Droid, the broadcast receiver will acquire a temporary
|
||||
|
||||
Note that foreground services require to put a notification informing the user that the app is doing something even if not launched).
|
||||
|
||||
## Application Settings
|
||||
|
||||
|
||||
# Application Settings
|
||||
|
||||
**Notifications > Enable notifications for this account**
|
||||
|
||||
|
@@ -1,43 +1,5 @@
|
||||
# Pull requests
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Who should read this document?](#who-should-read-this-document?)
|
||||
* [Submitting PR](#submitting-pr)
|
||||
* [Who can submit pull requests?](#who-can-submit-pull-requests?)
|
||||
* [Humans](#humans)
|
||||
* [Draft PR?](#draft-pr?)
|
||||
* [Base branch](#base-branch)
|
||||
* [PR Review Assignment](#pr-review-assignment)
|
||||
* [PR review time](#pr-review-time)
|
||||
* [Re-request PR review](#re-request-pr-review)
|
||||
* [When create split PR?](#when-create-split-pr?)
|
||||
* [Avoid fixing other unrelated issue in a big PR](#avoid-fixing-other-unrelated-issue-in-a-big-pr)
|
||||
* [Bots](#bots)
|
||||
* [Dependabot](#dependabot)
|
||||
* [Gradle wrapper](#gradle-wrapper)
|
||||
* [Sync analytics plan](#sync-analytics-plan)
|
||||
* [Reviewing PR](#reviewing-pr)
|
||||
* [Who can review pull requests?](#who-can-review-pull-requests?)
|
||||
* [What to have in mind when reviewing a PR](#what-to-have-in-mind-when-reviewing-a-pr)
|
||||
* [Rules](#rules)
|
||||
* [Check the form](#check-the-form)
|
||||
* [PR title](#pr-title)
|
||||
* [PR description](#pr-description)
|
||||
* [File change](#file-change)
|
||||
* [Check the commit](#check-the-commit)
|
||||
* [Check the substance](#check-the-substance)
|
||||
* [Make a dedicated meeting to review the PR](#make-a-dedicated-meeting-to-review-the-pr)
|
||||
* [What happen to the issue(s)?](#what-happen-to-the-issues?)
|
||||
* [Merge conflict](#merge-conflict)
|
||||
* [When and who can merge PR](#when-and-who-can-merge-pr)
|
||||
* [Merge type](#merge-type)
|
||||
* [Resolve conversation](#resolve-conversation)
|
||||
* [Responsibility](#responsibility)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Introduction
|
||||
|
||||
This document gives some clue about how to efficiently manage Pull Requests (PR). This document is a first draft and may be improved later.
|
||||
@@ -68,31 +30,17 @@ In any case, it is better to explicitly declare in the description why the PR is
|
||||
|
||||
Also, draft PR should not stay indefinitely in this state. It may be removed if it is the case and the submitter does not update it after a few days.
|
||||
|
||||
##### Base branch
|
||||
|
||||
The `develop` branch is generally the base branch for every PRs.
|
||||
|
||||
Exceptions can occur:
|
||||
|
||||
- if a feature implementation is split into multiple PRs. We can have a chain of PRs in this case. PR can be merged one by one on develop, and GitHub change the target branch to `develop` for the next PR automatically.
|
||||
- we want to merge a PR from the community, but there is still work to do, and the PR is not updated by the submitter. First, we can kindly ask the submitter if they will update their PR, by commenting it. If there is no answer after a few days (including a week-end), we can create a new branch, push it, and change the target branch of the PR to this new branch. The PR can then be merged, and we can add more commits to fix the issues. After that a new PR can be created with `develop` as a target branch.
|
||||
|
||||
**Important notice 1:** Releases are created from the `develop` branch. So `develop` branch should always contain a "releasable" source code. So when a feature is being implemented with several PRs, it has to be disabled by default (using a feature flag for instance), until the feature is fully implemented. A last PR to enable the feature can then be created.
|
||||
|
||||
**Important notice 2:** Database migration: some developers and some people from the community are using the nightly build from `develop`. Multiple database migrations should be properly handled for them. This is OK to have multiple migrations between 2 releases, this is not OK to add steps to the pending database migration on `develop`. So for instance `develop` users will migrate from version 11 to version 12, then 13, then 14, and `main` users will do all those steps after they get the app upgrade.
|
||||
|
||||
##### PR Review Assignment
|
||||
|
||||
We use automatic assignment for PR reviews. **A PR is automatically routed by GitHub to one team member** using the round robin algorithm. Additional reviewers can be used for complex changes or when the first reviewer is not confident enough on the changes.
|
||||
The process is the following:
|
||||
We use automatic assignment for PR reviews. A PR is automatically routed by GitHub to 2 team members using the round robin algorithm. The process is the following:
|
||||
|
||||
- The PR creator selects the [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) team as a reviewer.
|
||||
- GitHub automatically assign the reviewer. If the reviewer is not available (holiday, etc.), remove them and set again the team, GitHub will select another reviewer.
|
||||
- Alternatively, the PR creator can directly assign specific people if they have another Android developer in their team or they think a specific reviewer should take a look at their PR.
|
||||
- The PR creator can assign specific people if they have another Android developer in their team or they think a specific reviewer should take a look at the PR.
|
||||
- If there are missing reviewers, the PR creator assigns the [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) team as a reviewer.
|
||||
- GitHub automatically assigns other reviewers. If one of the chosen reviewers is not available (holiday, etc.), remove them and set again the team, GitHub will select another reviewer.
|
||||
- Reviewers get a notification to make the review: they review the code following the good practice (see the rest of this document).
|
||||
- After making their own review, if they feel not confident enough, they can ask another person for a full review, or they can tag someone within a PR comment to check specific lines.
|
||||
|
||||
For PRs coming from the community, the issue wrangler can assign either the team [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) or any member directly.
|
||||
For PRs coming from the community, the issue wrangler can assign either the team [element-android-reviewers](https://github.com/orgs/vector-im/teams/element-android-reviewers) or any members directly.
|
||||
|
||||
##### PR review time
|
||||
|
||||
@@ -103,7 +51,6 @@ Some tips to achieve it:
|
||||
- Set up your GH notifications correctly
|
||||
- Check your pulls page: [https://github.com/pulls](https://github.com/pulls)
|
||||
- Check your pending assigned PRs before starting or resuming your day to day tasks
|
||||
- If you are busy with high priority tasks, inform the author. They will find another developer
|
||||
|
||||
It is hard to define a deadline for a review. It depends on the PR size and the complexity. Let's start with a goal of 24h (working day!) for a PR smaller than 500 lines. If bigger, the submitter and the reviewer should discuss.
|
||||
|
||||
@@ -156,7 +103,7 @@ Review such PR is the same recipe than for PR from Dependabot
|
||||
##### Sync analytics plan
|
||||
|
||||
This tools imports any update in the analytics plan. See instruction in the PR itself to handle it.
|
||||
More info can be found in the file [analytics.md](./analytics.md)
|
||||
More info can be found in the file [analytics.md]
|
||||
|
||||
## Reviewing PR
|
||||
|
||||
@@ -191,7 +138,7 @@ Examples of prefixes:
|
||||
- `[Bugfix]`
|
||||
- etc.
|
||||
|
||||
Also, it's still possible to add labels to the PRs, such as `A-` or `T-` labels, even if this is not a strong requirement. We prefer to spend time to add labels on issues.
|
||||
Also, it's still possible to add labels to the PRs, such as `A-` or `T-` labels, even if this is not a string requirement. We prefer to spend time to add labels on issues.
|
||||
|
||||
##### PR description
|
||||
|
||||
@@ -287,4 +234,4 @@ Also "Resolve conversation" should probably be hit by the creator of the convers
|
||||
|
||||
PR submitter is responsible of the incoming change. PR reviewers who approved the PR take a part of responsibility on the code which will land to develop, and then be used by our users, and the user of our forks.
|
||||
|
||||
That said, bug may still be merged on `develop`, this is still acceptable of course. In this case, please make sure an issue is created and correctly labelled. Ideally, such issues should be fixed before the next release candidate, i.e. with a higher priority. But as we release the application every 10 working days, it can be hard to fix every bugs. That's why PR should be fully tested and reviewed before being merge and we should never comment code review remark with "will be handled later", or similar comments.
|
||||
That said, bug may still be merged on `develop`, this is still acceptable of course. In this case, please make sure an issue is created and correctly labelled. Ideally, such issues should be fixed before the next release candidate, i.e. with a higher priority. But as we release the application every 10 working days, it can be hard to fix every bugs. That's why PR should be fully tested and reviewed before being merge and we should never comment code review remark with "will be handled later", or similar comments.
|
@@ -1,63 +0,0 @@
|
||||
## Overview
|
||||
|
||||
Until the final migration to [rust crypto sdk](https://github.com/matrix-org/matrix-rust-components-kotlin), the Element Android project will support two
|
||||
different SDK as a product flavor.
|
||||
|
||||
The `matrix-sdk-android` module is defining a new flavor dimension `crypto`, with two flavors `kotlinCrypto` and `rustCrypto`.
|
||||
The crypto module cannot be changed at runtime, it's a build time configuration. The app supports migration from kotlinCrypto to rustCrypto but not the other
|
||||
way around.
|
||||
|
||||
The code that is not shared between the flavors is located in dedicated source sets (`src/kotlinCrypto/`, `src/rustCrypto/`). Some tests are also extracted
|
||||
in different source sets because they were accessing internal API and won't work with the rust crypto sdk.
|
||||
|
||||
## Noticeable changes
|
||||
|
||||
As a general rule, if you stick to the `kotlinCrypto` the app should behave as it was before the integration of favours.
|
||||
There is a noticeable exception though:
|
||||
In order to integrate the rust crypto several APIs had to be migrated from callback code to suspendable code. This change
|
||||
impacted a lot the key verification engine (user and device verification), so this part has been refactored for `kotlinCrypto`. The UI is also impacted,
|
||||
the verification flows now match the web experience.
|
||||
|
||||
TLDR; Verification UI and engine has been refactored.
|
||||
|
||||
## Testing with a local rust aar
|
||||
|
||||
In order to run a custom rust SDK branch you can follow the direction in the [bindings repository](https://github.com/matrix-org/matrix-rust-components-kotlin)
|
||||
in order to build the `matrix-rust-sdk-crypto.aar`.
|
||||
|
||||
Copy this lib in `library/rustCrypto/`, and rename it `matrix-rust-sdk-crypto.aar`.
|
||||
|
||||
Then go to `matrix-sdk-android/build.gradle` and toggle the comments between the following lines.
|
||||
|
||||
````
|
||||
rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.1")
|
||||
// rustCryptoApi project(":library:rustCrypto")
|
||||
````
|
||||
|
||||
## Changes in CI
|
||||
|
||||
The workflow files have been updated to use the `kotlinCrypto` flavor, e.g
|
||||
|
||||
`assembleGplayNightly` => `assembleGplayKotlinCryptoNightly`
|
||||
|
||||
So building the unsigned release kotlin crypto apk is now:
|
||||
|
||||
`> ./gradlew assembleGplayKotlinCryptoRelease`
|
||||
|
||||
An additional workflow has been added to build the `rustCrypto` flavor (elementr.yml, ` Build debug APKs ER`).
|
||||
|
||||
|
||||
## Database migration from kotlin to rust
|
||||
|
||||
With the kotlin flavor, the crypto information are persisted in the crypto realm database.
|
||||
With the rust flavor, the crypto information are in a sqllite database.
|
||||
|
||||
The migration is handled when injecting `@SessionRustFilesDirectory` in the olmMachine.
|
||||
When launching the first time after migration, the app will detect that there is no rust data repository and it will
|
||||
create one. If there is an existing realm database, the data will then migrated to rust. See `ExtractMigrationDataUseCase`.
|
||||
This will extract your device keys, account secrets, active olm and megolm sessions.
|
||||
|
||||
There is no inverse migration for now, as there is not yet rust pickle to olm pickle support in the sdk.
|
||||
|
||||
If you migrate your app to rust, and want to revert to kotlin you have to logout then login again.
|
||||
|
@@ -1,72 +0,0 @@
|
||||
# Screenshot testing
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Setup](#setup)
|
||||
* [Recording](#recording)
|
||||
* [Verifying](#verifying)
|
||||
* [Contributing](#contributing)
|
||||
* [Example](#example)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Overview
|
||||
|
||||
- Screenshot tests are tests which record the content of a rendered screen and verify subsequent runs to check if the screen renders differently.
|
||||
- Element uses [Paparazzi](https://github.com/cashapp/paparazzi) to render, record and verify android layouts.
|
||||
- The screenshot verification occurs on every pull request as part of the `tests.yml` workflow.
|
||||
|
||||
## Setup
|
||||
|
||||
- Install Git LFS through your package manager of choice (`brew install git-lfs` | `yay -S git-lfs`).
|
||||
- Install the Git LFS hooks into the project.
|
||||
|
||||
```bash
|
||||
# with element-android as the current working directory
|
||||
git lfs install --local
|
||||
```
|
||||
|
||||
- If installed correctly, `git push` and `git pull` will now include LFS content.
|
||||
|
||||
## Recording
|
||||
|
||||
- `./gradlew recordScreenshots`
|
||||
- Paparazzi will generate images in `${module}/src/test/snapshots`, which will need to be committed to the repository using Git LFS.
|
||||
|
||||
## Verifying
|
||||
|
||||
- `./gradlew verifyScreenshots`
|
||||
- In the case of failure, Paparazzi will generate images in `${module}/out/failure`. The images will show the expected and actual screenshots along with a delta of the two images.
|
||||
|
||||
## Contributing
|
||||
|
||||
- When creating a test, the file (and class) name names must include `ScreenshotTest`, eg `ItemScreenshotTest`.
|
||||
- After creating the new test, record and commit the newly rendered screens.
|
||||
- `./tools/validate_lfs` can be ran to ensure everything is working correctly with Git LFS, the CI also runs this check.
|
||||
|
||||
## Example
|
||||
|
||||
```kotlin
|
||||
class PaparazziExampleScreenshotTest {
|
||||
|
||||
@get:Rule
|
||||
val paparazzi = Paparazzi(
|
||||
deviceConfig = PIXEL_3,
|
||||
theme = "Theme.Vector.Light",
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `example paparazzi test`() {
|
||||
// Inflate the layout
|
||||
val view = paparazzi.inflate<ConstraintLayout>(R.layout.item_radio)
|
||||
|
||||
// Bind data to the view
|
||||
view.findViewById<TextView>(R.id.actionTitle).text = paparazzi.resources.getString(R.string.room_settings_all_messages)
|
||||
view.findViewById<ImageView>(R.id.radioIcon).setImageResource(R.drawable.ic_radio_on)
|
||||
|
||||
// Record the bound view
|
||||
paparazzi.snapshot(view)
|
||||
}
|
||||
}
|
||||
```
|
@@ -2,27 +2,6 @@
|
||||
|
||||
This document describes the flow of signin to a homeserver, and also the flow when user want to reset his password. Examples come from the `matrix.org` homeserver.
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Sign in flows](#sign-in-flows)
|
||||
* [Get the flow](#get-the-flow)
|
||||
* [Login with username](#login-with-username)
|
||||
* [Incorrect password](#incorrect-password)
|
||||
* [Correct password:](#correct-password:)
|
||||
* [Login with email](#login-with-email)
|
||||
* [Unknown email](#unknown-email)
|
||||
* [Known email, wrong password](#known-email-wrong-password)
|
||||
* [Known email, correct password](#known-email-correct-password)
|
||||
* [Login with Msisdn](#login-with-msisdn)
|
||||
* [Login with SSO](#login-with-sso)
|
||||
* [Reset password](#reset-password)
|
||||
* [Send email](#send-email)
|
||||
* [When the email is not known](#when-the-email-is-not-known)
|
||||
* [When the email is known](#when-the-email-is-known)
|
||||
* [User clicks on the link](#user-clicks-on-the-link)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Sign in flows
|
||||
|
||||
### Get the flow
|
||||
@@ -343,4 +322,4 @@ curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":
|
||||
{}
|
||||
```
|
||||
|
||||
The password has been changed, and all the existing token are invalidated. User can now login with the new password.
|
||||
The password has been changed, and all the existing token are invalidated. User can now login with the new password.
|
@@ -4,20 +4,6 @@ This document describes the flow of registration to a homeserver. Examples come
|
||||
|
||||
*Ref*: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Sign up flows](#sign-up-flows)
|
||||
* [First step](#first-step)
|
||||
* [Step 1: entering user name and password](#step-1:-entering-user-name-and-password)
|
||||
* [If username already exists](#if-username-already-exists)
|
||||
* [Step 2: entering email](#step-2:-entering-email)
|
||||
* [Step 2 bis: user enters an email](#step-2-bis:-user-enters-an-email)
|
||||
* [Step 3: Accepting T&C](#step-3:-accepting-t&c)
|
||||
* [Step 4: Captcha](#step-4:-captcha)
|
||||
* [Step 5: MSISDN](#step-5:-msisdn)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Sign up flows
|
||||
|
||||
### First step
|
||||
|
@@ -10,20 +10,6 @@ Currently the test are covering a small set of application flows:
|
||||
- Self verification via emoji
|
||||
- Self verification via passphrase
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Prerequisites:](#prerequisites:)
|
||||
* [Run the tests](#run-the-tests)
|
||||
* [From the source code](#from-the-source-code)
|
||||
* [From command line](#from-command-line)
|
||||
* [Recipes](#recipes)
|
||||
* [Wait for initial sync](#wait-for-initial-sync)
|
||||
* [Accessing current activity](#accessing-current-activity)
|
||||
* [Interact with other session](#interact-with-other-session)
|
||||
* [Contributing to the UiAllScreensSanityTest](#contributing-to-the-uiallscreenssanitytest)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Prerequisites:
|
||||
|
||||
Out of the box, the tests use one of the homeservers (located at http://localhost:8080) of the "Demo Federation of Homeservers" (https://github.com/matrix-org/synapse#running-a-demo-federation-of-synapses).
|
||||
@@ -190,4 +176,4 @@ class SettingsAdvancedRobot {
|
||||
clickOn(R.string.settings_developer_mode_summary)
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
@@ -1,58 +0,0 @@
|
||||
# UnifiedPush
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Configuration in Element-Android and their forks](#configuration-in-element-android-and-their-forks)
|
||||
* [Enabling and disabling the feature](#enabling-and-disabling-the-feature)
|
||||
* [Override the configuration at runtime](#override-the-configuration-at-runtime)
|
||||
* [Enabling the feature](#enabling-the-feature)
|
||||
* [Disabling the feature](#disabling-the-feature)
|
||||
* [Useful links](#useful-links)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Introduction
|
||||
|
||||
The recently started UnifiedPush project is an Android protocol and library for apps to be able to receive distributor-agnostic push notifications.
|
||||
|
||||
The *F-Droid* and *Gplay* flavors of Element Android support UnifiedPush, so the user can use any distributor installed on their devices. This would make it possible to have push notifications without depending on Google services or libraries. Currently, the main distributors are [ntfy](https://ntfy.sh) which does not require any setup (like manual registration) to use the public server and [NextPush](https://github.com/UP-NextPush/android), available as a nextcloud application.
|
||||
|
||||
The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor. A [FCM Rewrite Proxy](https://unifiedpush.org/developers/embedded_fcm/#fcm-rewrite-proxy) is not required for Element Android's implementation of the FCM distributor - it will work with an existing Matrix push provider, such as [Sygnal](https://github.com/matrix-org/sygnal).
|
||||
|
||||
The *F-Droid* variant does not use this library to avoid any proprietary blob. It will use a polling service if the user has not installed any distributor.
|
||||
|
||||
In all cases, if there are other distributors available, the user will have to opt-in to one of them in the preferences.
|
||||
|
||||
## Configuration in Element-Android and their forks
|
||||
|
||||
### Enabling and disabling the feature
|
||||
|
||||
Allowing the user to use an alternative distributor can be changed in [Config](../vector-config/src/main/java/im/vector/app/config/Config.kt). The flag is named `ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS`. Default value is `true`.
|
||||
|
||||
#### Override the configuration at runtime
|
||||
|
||||
On debug version, it is possible to override this configuration at runtime, using the `Feature` screen. The Feature is named `Allow external UnifiedPush distributors`.
|
||||
|
||||
#### Enabling the feature
|
||||
|
||||
This is the default behavior of Element Android.
|
||||
|
||||
If `ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS` is set to true, it allows any available external UnifiedPush distributor to be chosen by the user.
|
||||
- For Gplay variant it means that FCM will be used by default, but user can choose another UnifiedPush distributor;
|
||||
- For F-Droid variant, it means that background polling will be used by default, but user can choose another UnifiedPush distributor.
|
||||
- On the UI, the setting to choose an alternative distributor will be visible to the user, and some tests in the notification troubleshoot screen will shown.
|
||||
- For F-Droid, if the user has chosen a distributor, the settings to configure the background polling will be hidden.
|
||||
|
||||
#### Disabling the feature
|
||||
|
||||
If `ALLOW_EXTERNAL_UNIFIED_PUSH_DISTRIBUTORS` is set to false, it prevents the usage of external UnifiedPush distributors.
|
||||
- For Gplay variant it means that only FCM will be used;
|
||||
- For F-Droid variant, it means that only background polling will be used.
|
||||
- On the UI, the setting to choose an alternative distributor will be hidden to the user, and some tests in the notification troubleshoot screen will be hidden.
|
||||
|
||||
### Useful links
|
||||
|
||||
- UnifiedPush official website: [https://unifiedpush.org/](https://unifiedpush.org/)
|
||||
- List of available distributors can be retrieved here: [https://unifiedpush.org/users/distributors/](https://unifiedpush.org/users/distributors/)
|
||||
- UnifiedPush project discussion can occurs here: [#unifiedpush:matrix.org](https://matrix.to/#/#unifiedpush:matrix.org)
|
@@ -1,351 +0,0 @@
|
||||
# Table of Contents
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Best Practices](#best-practices)
|
||||
* [Project Conventions](#project-conventions)
|
||||
* [Setup](#setup)
|
||||
* [Naming](#naming)
|
||||
* [Format](#format)
|
||||
* [Assertions](#assertions)
|
||||
* [Constants](#constants)
|
||||
* [Mocking](#mocking)
|
||||
* [Fakes](#fakes)
|
||||
* [Fixtures](#fixtures)
|
||||
* [Examples](#examples)
|
||||
* [Extensions used to streamline the test setup](#extensions-used-to-streamline-the-test-setup)
|
||||
* [Fakes and Fixtures](#fakes-and-fixtures)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Overview
|
||||
|
||||
Unit tests are a mechanism to validate our code executes the way we expect. They help to inform the design of our systems by requiring testability and
|
||||
understanding, they describe the inner workings without relying on inline comments and protect from unexpected regressions.
|
||||
|
||||
However, unit tests are not a magical solution to solve all our problems and come at a cost. Unreliable and hard to maintain tests often end up ignored, deleted
|
||||
or worse, provide a false sense of security.
|
||||
|
||||
### Best Practices
|
||||
|
||||
Tests can be written in many ways, the main rule is to keep them simple and maintainable. Some ways to help achieve this are...
|
||||
|
||||
- Break out logic into single units (following the Single Responsibility Principle) to reduce test complexity.
|
||||
- Favour pure functions, avoiding mutable state.
|
||||
- Prefer dependency injection to static calls to allow for simpler test setup.
|
||||
- Write concise tests with a single function under test, clearly showing the inputs and expected output.
|
||||
- Create separate test cases instead of changing parameters and grouping multiple assertions within a single test to help trace back failure causes (with the
|
||||
exception of parameterised tests).
|
||||
- Assert against entire models instead of subsets of properties to capture any possible changes within the test scope.
|
||||
- Avoid invoking logic from production instances other than the class under test to guard from unrelated changes.
|
||||
- Always inject `Dispatchers` and `Clock` instances and provide fake implementations for tests to avoid non deterministic results.
|
||||
|
||||
## Project Conventions
|
||||
|
||||
#### Setup
|
||||
|
||||
- Test file and class name should be the class under test with the Test suffix, created in a `test` sourceset, with the same package name as the class under
|
||||
test.
|
||||
- Dependencies of the class are instantiated inline, junit will recreate the test class for each test run.
|
||||
- A line break between the dependencies and class under test helps clarify the instance being tested.
|
||||
|
||||
```kotlin
|
||||
|
||||
class MyClassTest {
|
||||
|
||||
private val fakeUppercaser = FakeUppercaser()
|
||||
|
||||
// line break between the class under test and its dependencies
|
||||
private val myClass = MyClass(fakeUppercaser.instance)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Naming
|
||||
|
||||
- Test names use the `Gherkin` format, `given, when, then` mapping to the input, logic under test and expected result.
|
||||
- `given` - Uniqueness about the environment or dependencies in which the test case is running. _"given device is android 12 and supports dark mode"_
|
||||
- `when` - The action/function under test. _"when reading dark mode status"_
|
||||
- `then` - The expected result from the combination of _given_ and _when_. _"then returns dark mode enabled"_
|
||||
- Test names are written using kotlin back ticks to enable sentences _ish_.
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
fun `given a lowercase label, when uppercasing, then returns label uppercased`
|
||||
```
|
||||
|
||||
When the input is given directly to the _when_, this can also be represented as...
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
fun `when uppercasing a lowercase label, then returns label uppercased`
|
||||
```
|
||||
|
||||
Multiple given or returns statements can be used in the name although it could be a sign that the logic being tested does too much.
|
||||
|
||||
---
|
||||
|
||||
#### Format
|
||||
|
||||
- Test bodies are broken into sections through the use of blank lines where the sections correspond to the test name.
|
||||
- Sections can span multiple lines.
|
||||
|
||||
```kotlin
|
||||
// comments are for illustrative purposes
|
||||
/* given */ val lowercaseLabel = "hello world"
|
||||
|
||||
/* when */ val result = textUppercaser.uppercase(lowercaseLabel)
|
||||
|
||||
/* then */ result shouldBeEqualTo "HELLO WORLD"
|
||||
```
|
||||
|
||||
- Functions extracted from test bodies are placed beneath all the unit tests.
|
||||
|
||||
---
|
||||
|
||||
#### Assertions
|
||||
|
||||
- Assertions against test results are made using [Kluent's](https://github.com/MarkusAmshove/Kluent) _fluent_ api.
|
||||
- Typically `shouldBeEqualTo`is the main assertion to use for asserting function return values as by project convention we assert against entire objects or
|
||||
lists.
|
||||
|
||||
```kotlin
|
||||
val result = listOf("hello", "world")
|
||||
|
||||
// Fail
|
||||
result shouldBeEqualTo listOf("hello")
|
||||
```
|
||||
|
||||
```kotlin
|
||||
data class Person(val age: Int, val name: String)
|
||||
|
||||
val result = Person(age = 100, name = "Gandalf")
|
||||
|
||||
// Avoid
|
||||
result.age shouldBeEqualTo 100
|
||||
|
||||
// Prefer
|
||||
result shouldBeEqualTo Person(age = 100, "Gandalf")
|
||||
```
|
||||
|
||||
- Exception throwing can be asserted against using `assertFailsWith<T : Throwable>`.
|
||||
- When asserting reusable exceptions, include the message to distinguish between them.
|
||||
|
||||
```kotlin
|
||||
assertFailsWith<ConcreteException>(message = "Details about error") {
|
||||
// when section of the test
|
||||
codeUnderTest()
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Constants
|
||||
|
||||
- Reusable values are extracted to file level immutable properties or constants.
|
||||
- These can be parameters or expected results.
|
||||
- The naming convention is to prefix with `A` or `AN` for better matching with the test name.
|
||||
|
||||
```kotlin
|
||||
private const val A_LOWERCASE_LABEL = "hello"
|
||||
|
||||
class MyTest {
|
||||
@Test
|
||||
fun `when uppercasing a lowercase label, then returns label uppercased`() {
|
||||
val result = TextUppercaser().uppercase(A_LOWERCASE_LABEL)
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Mocking
|
||||
|
||||
- In order to provide different behaviour for dependencies within tests our main method is through mocking, using [Mockk](https://mockk.io/).
|
||||
- We avoid using relaxed mocks in favour of explicitly declaring mock behaviour through the _Fake_ convention. There are exceptions when mocking framework
|
||||
classes which would require a lot of boilerplate.
|
||||
- Using `Spy` is discouraged as it inherently requires real instances, which we are avoiding in our tests. There are exceptions such as `VectorFeatures` which
|
||||
acts like a `Fixture` in release builds.
|
||||
|
||||
---
|
||||
|
||||
#### Fakes
|
||||
|
||||
- Fakes are reusable instances of classes purely for testing purposes. They provide functions to replace the functions of the interface/class they're faking
|
||||
with test specific values.
|
||||
- When faking an interface, the _Fake_ can be written using delegation or by stubbing
|
||||
- All Fakes currently reside in the same package `${package}.test.fakes`
|
||||
|
||||
```kotlin
|
||||
// Delegating to a mock
|
||||
class FakeClock : Clock by mockk() {
|
||||
fun givenEpoch(epoch: Long) {
|
||||
every { epochMillis() } returns epoch
|
||||
}
|
||||
}
|
||||
|
||||
// Stubbing the interface
|
||||
class FakeClock(private val epoch: Long) : Clock {
|
||||
override fun epochMillis() = epoch
|
||||
}
|
||||
```
|
||||
|
||||
It's currently more common for fakes to fake class behaviour, we achieve this by wrapping and exposing a mock instance.
|
||||
|
||||
```kotlin
|
||||
class FakeCursor {
|
||||
val instance = mockk<Cursor>()
|
||||
fun givenEmpty() {
|
||||
every { instance.count } returns 0
|
||||
every { instance.moveToFirst() } returns false
|
||||
}
|
||||
}
|
||||
|
||||
val fakeCursor = FakeCursor().apply { givenEmpty() }
|
||||
```
|
||||
|
||||
#### Fixtures
|
||||
|
||||
- Fixtures are a reusable wrappers around data models. They provide default values to make creating instances as easy as possible, with the option to override
|
||||
specific parameters when needed.
|
||||
- Are namespaced within an `object`.
|
||||
- Reduces the _find usages_ noise when searching for usages of the origin class construction.
|
||||
- All Fixtures currently reside in the same package `${package}.test.fixtures`.
|
||||
|
||||
```kotlin
|
||||
object ContentAttachmentDataFixture {
|
||||
fun aContentAttachmentData(
|
||||
type: ContentAttachmentData.Type.TEXT,
|
||||
mimeType: String? = null
|
||||
) = ContentAttachmentData(type, mimeType)
|
||||
}
|
||||
```
|
||||
|
||||
- Fixtures can also be used to manage specific combinations of parameters
|
||||
|
||||
```kotlin
|
||||
fun aContentAttachmentAudioData() = aContentAttachmentData(
|
||||
type = ContentAttachmentData.Type.AUDIO,
|
||||
mimeType = "audio/mp3",
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Examples
|
||||
|
||||
##### Extensions used to streamline the test setup
|
||||
|
||||
```kotlin
|
||||
class CircularCacheTest {
|
||||
|
||||
@Test
|
||||
fun `when putting more than cache size then cache is limited to cache size`() {
|
||||
val (cache, internalData) = createIntCache(cacheSize = 3)
|
||||
|
||||
cache.putInOrder(1, 1, 1, 1, 1, 1)
|
||||
|
||||
internalData shouldBeEqualTo arrayOf(1, 1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIntCache(cacheSize: Int): Pair<CircularCache<Int>, Array<Int?>> {
|
||||
var internalData: Array<Int?>? = null
|
||||
val factory: (Int) -> Array<Int?> = {
|
||||
Array<Int?>(it) { null }.also { array -> internalData = array }
|
||||
}
|
||||
return CircularCache(cacheSize, factory) to internalData!!
|
||||
}
|
||||
|
||||
private fun CircularCache<Int>.putInOrder(vararg values: Int) {
|
||||
values.forEach { put(it) }
|
||||
}
|
||||
```
|
||||
|
||||
##### Fakes and Fixtures
|
||||
|
||||
```kotlin
|
||||
class LateInitUserPropertiesFactoryTest {
|
||||
|
||||
private val fakeActiveSessionDataSource = FakeActiveSessionDataSource()
|
||||
private val fakeVectorStore = FakeVectorStore()
|
||||
private val fakeContext = FakeContext()
|
||||
private val fakeSession = FakeSession().also {
|
||||
it.givenVectorStore(fakeVectorStore.instance)
|
||||
}
|
||||
|
||||
private val lateInitUserProperties = LateInitUserPropertiesFactory(
|
||||
fakeActiveSessionDataSource.instance,
|
||||
fakeContext.instance
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `given no active session, when creating properties, then returns null`() {
|
||||
val result = lateInitUserProperties.createUserProperties()
|
||||
|
||||
result shouldBeEqualTo null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a teams use case set on an active session, when creating properties, then includes the remapped WorkMessaging selection`() {
|
||||
fakeVectorStore.givenUseCase(FtueUseCase.TEAMS)
|
||||
fakeActiveSessionDataSource.setActiveSession(fakeSession)
|
||||
|
||||
val result = lateInitUserProperties.createUserProperties()
|
||||
|
||||
result shouldBeEqualTo UserProperties(
|
||||
ftueUseCaseSelection = UserProperties.FtueUseCaseSelection.WorkMessaging
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### ViewModel
|
||||
|
||||
- `ViewModels` tend to be one of the most complex areas to unit test due to their position as a coordinator of data flows and bridge between domains.
|
||||
- As the project uses a slightly tweaked`MvRx`, our API for the `ViewModel` is simplified down to `input - ViewModel.handle(Action)`
|
||||
and `output Flows - ViewModel.viewEvents & ViewModel.stateFlow`. A `ViewModel` test asserter has been created to further simplify the process.
|
||||
|
||||
```kotlin
|
||||
class ViewModelTest {
|
||||
|
||||
private var initialState = ViewState.Empty
|
||||
|
||||
@get:Rule
|
||||
val mavericksTestRule = MavericksTestRule(testDispatcher = UnconfinedTestDispatcher())
|
||||
|
||||
@Test
|
||||
fun `when handling MyAction, then emits Loading and Content states`() {
|
||||
val viewModel = ViewModel<State>(initialState)
|
||||
val test = viewModel.test() // must be invoked before interacting with the VM
|
||||
|
||||
viewModel.handle(MyAction)
|
||||
|
||||
test
|
||||
.assertViewStates(initialState, State.Loading, State.Content())
|
||||
.assertNoEvents()
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `ViewModels` often emit multiple states which are copies of the previous state, the `test` extension `assertStatesChanges` allows only the difference to be
|
||||
supplied.
|
||||
|
||||
```kotlin
|
||||
data class ViewState(val name: String? = null, val age: Int? = null)
|
||||
val initialState = ViewState()
|
||||
val viewModel = ViewModel<State>(initialState)
|
||||
val test = viewModel.test()
|
||||
|
||||
viewModel.handle(ChangeNameAction("Gandalf"))
|
||||
|
||||
test
|
||||
.assertStatesChanges(
|
||||
initialState,
|
||||
{ copy(name = "Gandalf") },
|
||||
)
|
||||
.finish()
|
||||
```
|
@@ -1 +1 @@
|
||||
برنامج المراسلة الجماعية - الرسائل المشفرة والدردشة الجماعية ومكالمات الفيديو
|
||||
مُحادثة آمنة لا مركزية و VoIP. حافظ على بياناتك آمنة من الأطراف الثالثة.
|
||||
|
@@ -1 +1 @@
|
||||
إيليمنت - تطبيق محادثات أمن
|
||||
Element (Riot.im سابقًا)
|
||||
|
@@ -1 +0,0 @@
|
||||
Qrup mesajlaşma - şifrəli mesajlaşma, qrup söhbəti və video zənglər
|
@@ -1 +0,0 @@
|
||||
Element
|
@@ -1,2 +0,0 @@
|
||||
Hlavní změny v této verzi: Posun přehrávání v hlasových zprávách. Opravy různých chyb a vylepšení stability.
|
||||
Úplný seznam změn: https://github.com/vector-im/element-android/releases
|
@@ -1,2 +0,0 @@
|
||||
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
|
||||
Úplný seznam změn: https://github.com/vector-im/element-android/releases
|
@@ -1,2 +0,0 @@
|
||||
Hlavní změny v této verzi: Umožňuje uživatelům zobrazovat se offline a přidává zvukový přehrávač pro zvukové přílohy
|
||||
Úplný seznam změn: https://github.com/vector-im/element-android/releases
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user