diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..abb1aeb0b61ba41bb44548f9ca4428b3696acfd7
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,34 @@
+image: briar/ci-image-android:latest
+
+stages:
+  - test
+
+workflow:
+  # when to create a CI pipeline
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
+      when: never # avoids duplicate jobs for branch and MR
+    - if: '$CI_COMMIT_BRANCH'
+    - if: '$CI_COMMIT_TAG'
+
+test:
+  stage: test
+  before_script:
+    - set -e
+    - export GRADLE_USER_HOME=$PWD/.gradle
+  script:
+    - ./gradlew --no-daemon check lint
+  after_script:
+    # these file change every time and should not be cached
+    - rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
+    - rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
+  cache:
+    key: "$CI_COMMIT_REF_SLUG"
+    paths:
+      - .gradle/wrapper
+      - .gradle/caches
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+      when: always
+    - when: always
diff --git a/gradle/ktlint.gradle b/gradle/ktlint.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..59358c39ebde3cd15034378ccf07c44f7c4ad243
--- /dev/null
+++ b/gradle/ktlint.gradle
@@ -0,0 +1,11 @@
+ktlint {
+    version = "0.41.0"
+    android = true
+    enableExperimentalRules = false
+    verbose = true
+    disabledRules = [
+            "import-ordering",
+            "no-blank-line-before-rbrace",
+            "indent", // remove in 0.42 https://github.com/pinterest/ktlint/issues/764
+    ]
+}
diff --git a/mailbox/build.gradle b/mailbox/build.gradle
index c990be55fe1ee9900418f417611ce007530501bb..f6fe2964fe6b7a4ec8d82c172f1348161bf1dd29 100644
--- a/mailbox/build.gradle
+++ b/mailbox/build.gradle
@@ -3,6 +3,7 @@ plugins {
     id 'kotlin-android'
     id 'kotlin-kapt'
     id 'dagger.hilt.android.plugin'
+    id "org.jlleitschuh.gradle.ktlint" version "10.1.0"
 }
 
 android {
@@ -36,9 +37,9 @@ android {
 
 dependencies {
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'androidx.appcompat:appcompat:1.3.0'
-    implementation "androidx.activity:activity-ktx:1.2.3"
-    implementation "androidx.fragment:fragment-ktx:1.3.5"
+    implementation 'androidx.appcompat:appcompat:1.3.1'
+    implementation "androidx.activity:activity-ktx:1.2.4"
+    implementation "androidx.fragment:fragment-ktx:1.3.6"
 
     def lifecycle_version = "2.3.1"
     implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
@@ -55,3 +56,5 @@ dependencies {
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
 }
+
+apply from: "${rootProject.rootDir}/gradle/ktlint.gradle"
diff --git a/mailbox/src/main/java/org/briarproject/mailbox/ApplicationComponent.kt b/mailbox/src/main/java/org/briarproject/mailbox/ApplicationComponent.kt
index 18af8862ded7dfc0afe35259a24195c02997eeaa..f9f2c7562ed247ac9d0e9a4c7ff7a03879e5e7de 100644
--- a/mailbox/src/main/java/org/briarproject/mailbox/ApplicationComponent.kt
+++ b/mailbox/src/main/java/org/briarproject/mailbox/ApplicationComponent.kt
@@ -7,4 +7,4 @@ interface ApplicationComponent {
 
     fun inject(activity: MainActivity)
 
-}
\ No newline at end of file
+}