Skip to content

Commit

Permalink
Merge branch 'ensure-relay-list-is-built-and-bundled-in-a-reproducibl…
Browse files Browse the repository at this point in the history
…e-way-droid-1674'
  • Loading branch information
Pururun committed Jan 28, 2025
2 parents 95e51f0 + 1fd061c commit ad60808
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 101 deletions.
53 changes: 0 additions & 53 deletions .github/workflows/android-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,49 +104,6 @@ jobs:
if-no-files-found: error
retention-days: 7

generate-relay-list:
name: Generate relay list # Used by wait for jobs.
needs: prepare
runs-on: ubuntu-latest
container:
image: ${{ needs.prepare.outputs.container_image }}
steps:
# Fix for HOME path overridden by GH runners when building in containers, see:
# https://github.com/actions/runner/issues/863
- name: Fix HOME path
run: echo "HOME=/root" >> $GITHUB_ENV

- name: Get date
id: get-date
shell: bash
run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT

- name: Cache
uses: actions/cache@v4
id: cache-relay-list
with:
path: android/app/build/extraAssets/relays.json
key: relay-list-${{ steps.get-date.outputs.date }}

- name: Checkout repository
if: steps.cache-relay-list.outputs.cache-hit != 'true'
uses: actions/checkout@v4
with:
submodules: true

- name: Generate
if: steps.cache-relay-list.outputs.cache-hit != 'true'
shell: bash
run: ./android/gradlew -p android generateRelayList

- name: Upload
uses: actions/upload-artifact@v4
with:
name: relay-list
path: android/app/build/extraAssets/relays.json
if-no-files-found: error
retention-days: 7

build-native:
name: Build native # Used by wait for jobs.
needs: prepare
Expand Down Expand Up @@ -311,10 +268,6 @@ jobs:
"workflowFile": "android-app.yml",
"jobMatchMode": "prefix",
"jobName": "Build native"
},
{
"workflowFile": "android-app.yml",
"jobName": "Generate relay list"
}
]
Expand All @@ -324,11 +277,6 @@ jobs:
path: android/app/build/rustJniLibs/android
merge-multiple: true

- uses: actions/download-artifact@v4
with:
name: relay-list
path: android/app/build/extraAssets

- name: Build app
uses: burrunan/gradle-cache-action@v1
with:
Expand Down Expand Up @@ -410,7 +358,6 @@ jobs:
arguments: |
${{ matrix.assemble-command }}
-x cargoBuild
-x generateRelayList
-x mergeOssProdDebugJniLibFolders
-x mergePlayStagemoleDebugJniLibFolders
gradle-version: wrapper
Expand Down
44 changes: 5 additions & 39 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
import java.io.ByteArrayOutputStream
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.Properties
import org.gradle.internal.extensions.stdlib.capitalized

Expand All @@ -21,8 +19,7 @@ plugins {
}

val repoRootPath = rootProject.projectDir.absoluteFile.parentFile.absolutePath
val extraAssetsDirectory = layout.buildDirectory.dir("extraAssets").get()
val relayListPath = extraAssetsDirectory.file("relays.json").asFile
val relayListDirectory = file("$repoRootPath/dist-assets/relays/").absolutePath
val defaultChangelogAssetsDirectory = "$repoRootPath/android/src/main/play/release-notes/"
val rustJniLibsDir = layout.buildDirectory.dir("rustJniLibs/android").get()

Expand Down Expand Up @@ -133,7 +130,7 @@ android {
gradleLocalProperties(rootProject.projectDir, providers)
.getOrDefault("OVERRIDE_CHANGELOG_DIR", defaultChangelogAssetsDirectory)

assets.srcDirs(extraAssetsDirectory, changelogDir)
assets.srcDirs(relayListDirectory, changelogDir)
}
}

Expand Down Expand Up @@ -240,9 +237,6 @@ android {

createDistBundle.dependsOn("bundle$capitalizedVariantName")

// Ensure we have relay list ready before merging assets.
tasks["merge${capitalizedVariantName}Assets"].dependsOn(tasks["generateRelayList"])

// Ensure that we have all the JNI libs before merging them.
tasks["merge${capitalizedVariantName}JniLibFolders"].apply {
// This is required for the merge task to run every time the .so files are updated.
Expand All @@ -265,8 +259,10 @@ junitPlatform {
}

cargo {
val localProperties = gradleLocalProperties(rootProject.projectDir, providers)
val isReleaseBuild = isReleaseBuild()
val enableApiOverride = !isReleaseBuild || isAlphaOrDevBuild()
val enableApiOverride =
!isReleaseBuild || isDevBuild(localProperties) || isAlphaBuild(localProperties)
module = repoRootPath
libname = "mullvad-jni"
// All available targets:
Expand Down Expand Up @@ -300,23 +296,6 @@ cargo {
}
}

tasks.register<Exec>("generateRelayList") {
workingDir = File(repoRootPath)
standardOutput = ByteArrayOutputStream()

onlyIf { isReleaseBuild() || !relayListPath.exists() }

commandLine("cargo", "run", "-p", "mullvad-api", "--bin", "relay_list")

doLast {
val output = standardOutput as ByteArrayOutputStream
// Create file if needed
relayListPath.parentFile.mkdirs()
relayListPath.createNewFile()
FileOutputStream(relayListPath).use { it.write(output.toByteArray()) }
}
}

tasks.register<Exec>("cargoClean") {
workingDir = File(repoRootPath)
commandLine("cargo", "clean")
Expand All @@ -330,19 +309,6 @@ if (
tasks["clean"].dependsOn("cargoClean")
}

// This is a hack and will not work correctly under all scenarios.
// See DROID-1696 for how we can improve this.
fun isReleaseBuild() =
gradle.startParameter.getTaskNames().any {
it.contains("release", ignoreCase = true) || it.contains("fdroid", ignoreCase = true)
}

fun isAlphaOrDevBuild(): Boolean {
val localProperties = gradleLocalProperties(rootProject.projectDir, providers)
val versionName = generateVersionName(localProperties)
return versionName.contains("dev") || versionName.contains("alpha")
}

androidComponents {
beforeVariants { variantBuilder ->
variantBuilder.enable =
Expand Down
17 changes: 17 additions & 0 deletions android/buildSrc/src/main/kotlin/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import java.util.*
import org.gradle.api.Project

// This is a hack and will not work correctly under all scenarios.
// See DROID-1696 for how we can improve this.
fun Project.isReleaseBuild() =
gradle.startParameter.getTaskNames().any {
it.contains("release", ignoreCase = true) || it.contains("fdroid", ignoreCase = true)
}

fun Project.isAlphaBuild(localProperties: Properties): Boolean {
val versionName = generateVersionName(localProperties)
return versionName.contains("alpha")
}

fun Project.isDevBuild(localProperties: Properties): Boolean {
val versionName = generateVersionName(localProperties)
return versionName.contains("-dev-")
}

fun Project.generateVersionCode(localProperties: Properties): Int {
return localProperties.getProperty("OVERRIDE_VERSION_CODE")?.toIntOrNull()
?: execVersionCodeCargoCommand()
Expand Down
1 change: 0 additions & 1 deletion android/scripts/update-lockfile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ GRADLE_TASKS=(
"lint"
)
EXCLUDED_GRADLE_TASKS=(
"-xgenerateRelayList"
"-xcargoBuild"
)

Expand Down
13 changes: 12 additions & 1 deletion android/service/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties

plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
Expand All @@ -9,7 +11,16 @@ android {
compileSdk = Versions.compileSdkVersion
buildToolsVersion = Versions.buildToolsVersion

defaultConfig { minSdk = Versions.minSdkVersion }
defaultConfig {
minSdk = Versions.minSdkVersion
val localProperties = gradleLocalProperties(rootProject.projectDir, providers)
val shouldRequireBundleRelayFile = isReleaseBuild() && !isDevBuild(localProperties)
buildConfigField(
"Boolean",
"REQUIRE_BUNDLED_RELAY_FILE",
shouldRequireBundleRelayFile.toString(),
)
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ class MullvadVpnService : TalpidVpnService() {
}

private fun Context.prepareFiles() {
extractAndOverwriteIfAssetMoreRecent(RELAY_LIST_ASSET_NAME)
extractAndOverwriteIfAssetMoreRecent(
RELAY_LIST_ASSET_NAME,
BuildConfig.REQUIRE_BUNDLED_RELAY_FILE,
)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
package net.mullvad.mullvadvpn.service.util

import android.content.Context
import co.touchlab.kermit.Logger
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream

fun Context.extractAndOverwriteIfAssetMoreRecent(assetName: String) {
fun Context.extractAndOverwriteIfAssetMoreRecent(assetName: String, requireAssetFile: Boolean) {
val forceOverwriteIfMoreRecent = lastUpdatedTime() > File(filesDir, assetName).lastModified()
val destination = File(filesDir, assetName)

if (!destination.exists() || forceOverwriteIfMoreRecent) {
extractFile(assetName, destination)
extractFile(assetName, destination, requireAssetFile)
}
}

private fun Context.lastUpdatedTime(): Long =
packageManager.getPackageInfo(packageName, 0).lastUpdateTime

private fun Context.extractFile(asset: String, destination: File) {
val destinationStream = FileOutputStream(destination)
assets.open(asset).copyTo(destinationStream)
destinationStream.close()
private fun Context.extractFile(asset: String, destination: File, requireAssetFile: Boolean) {
if (assets.list("")?.contains(asset) == true) {
val destinationStream = FileOutputStream(destination)
assets.open(asset).copyTo(destinationStream)
destinationStream.close()
} else if (requireAssetFile) {
throw FileNotFoundException("Asset $asset not found")
} else {
Logger.i("Asset $asset not found")
}
}
9 changes: 9 additions & 0 deletions prepare-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ if [[ "$ANDROID" == "true" &&
exit 1
fi

if [[ "$ANDROID" == "true" ]]; then
echo "Generate relays.json"
mkdir dist-assets/relays
cargo run -q -p mullvad-api --bin relay_list > dist-assets/relays/relays.json

git commit -S -m "Add relay list to bundle with $PRODUCT_VERSION" \
dist-assets/relays/relays.json
fi

if [[ "$DESKTOP" == "true" ]]; then
echo "$PRODUCT_VERSION" > dist-assets/desktop-product-version.txt
git commit -S -m "Update desktop app version to $PRODUCT_VERSION" \
Expand Down

0 comments on commit ad60808

Please sign in to comment.