Commit 22d04ff8 authored by Torsten Grote's avatar Torsten Grote

Use disorderfs deterministic file system to fix differences in resources.arsc

Thanks @goapunk for the prototype and the heavy lifting! :)
parent 04c2a281
Pipeline #1733 passed with stages
in 23 minutes and 34 seconds
......@@ -24,12 +24,14 @@ build:
stage: test
- docker run ${TEST_IMAGE} ./ release-1.0.1
# Consider adding the cap and the device directly to the CI config
- docker run --cap-add SYS_ADMIN --device /dev/fuse ${TEST_IMAGE} ./ release-1.0.1
stage: test
- if docker run ${TEST_IMAGE} ./ release-1.0.3; then exit 1; else exit 0; fi
- if docker run --cap-add SYS_ADMIN --device /dev/fuse ${TEST_IMAGE} ./ release-1.0.3; then exit 1; else exit 0; fi
stage: release
......@@ -72,12 +72,22 @@ Build our Docker image:
### Run the verification
Currently, the verification needs `disorderfs` as a deterministic file-system.
Therefore, please make sure that `fuse` is installed on your host system.
apt install fuse
To verify a specific version of Briar, run
docker run briar/reproducer:latest ./ [tag]
docker run --cap-add SYS_ADMIN --device /dev/fuse briar/reproducer:latest ./ [tag]
Where `[tag]` is the git tag (source code snapshot) that identifies the version
you want to test, for example `release-1.0.1`.
You can find a list of tags in Briar's
[source code repository](
The `SYS_ADMIN` capability and the `fuse` device are required,
so the container can build the app inside a `disorderfs`.
We hope to be able to drop this requirement
once this [upstream issue]( is fixed.
\ No newline at end of file
......@@ -5,5 +5,7 @@ set -x
apt-get install -y --no-install-recommends \
git \
default-jdk-headless \
fuse \
disorderfs \
unzip \
#!/usr/bin/env python3
import os
import subprocess
from subprocess import call, check_call, check_output
import sys
REPO_DIR = "briar"
GRADLE_TASK = "briar-android:assembleRelease"
APK_PATH = "briar-android/build/outputs/apk/release/briar-android-release-unsigned.apk"
BUILD_DIR = "briar-build"
def main():
......@@ -22,14 +23,19 @@ def main():
version = tag.split('-')[1]
url = REFERENCE_URL % version
reference_apk = "briar-%s.apk" % version
subprocess.check_call(['wget', '--no-verbose', url, '-O', reference_apk])
check_call(['wget', '--no-verbose', url, '-O', reference_apk])
# use deterministic file system for building the app
if not os.path.exists(BUILD_DIR):
check_call(['disorderfs', '--sort-dirents=yes', '--reverse-dirents=no', REPO_DIR, BUILD_DIR])
# build the app
repo_call(["./gradlew", "--no-daemon", GRADLE_TASK])
check_call(["./gradlew", "--no-daemon", GRADLE_TASK], cwd=BUILD_DIR)
# check if both APKs match
apk = os.path.join(REPO_DIR, APK_PATH)
if['./', reference_apk, apk]) == 0:
apk = os.path.join(BUILD_DIR, APK_PATH)
if call(['./', reference_apk, apk]) == 0:
print("Version '%s' was built reproducible! :)" % tag)
......@@ -44,7 +50,7 @@ def prepare_repo(tag):
repo_call(['git', 'checkout', '-f', 'master'])
# clone repo
subprocess.check_call(['git', 'clone', os.environ.get("REPO_URL"), REPO_DIR])
check_call(['git', 'clone', os.environ.get("REPO_URL"), REPO_DIR])
# undo all changes
repo_call(['git', 'reset', '--hard'])
......@@ -54,7 +60,7 @@ def prepare_repo(tag):
# use latest tag if none given
if tag is None:
result = subprocess.check_output(['git', 'describe', '--abbrev=0', '--tags'], cwd=REPO_DIR)
result = check_output(['git', 'describe', '--abbrev=0', '--tags'], cwd=REPO_DIR)
tag = result.decode().rstrip() # strip away line-break
# checkout tag
......@@ -65,7 +71,7 @@ def prepare_repo(tag):
def repo_call(command):
subprocess.check_call(command, cwd=REPO_DIR)
check_call(command, cwd=REPO_DIR)
def fail(msg=""):
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment