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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
env:
SKIRK_OAUTH_CLIENT_ID: ${{ secrets.SKIRK_OAUTH_CLIENT_ID }}
SKIRK_OAUTH_CLIENT_SECRET: ${{ secrets.SKIRK_OAUTH_CLIENT_SECRET }}
SKIRK_REQUIRE_BUILTIN_OAUTH: "1"
SKIRK_REQUIRE_BUILTIN_OAUTH: "0"
run: VERSION="${GITHUB_REF_NAME}" scripts/package_release.sh

- uses: actions/upload-artifact@v7
Expand Down Expand Up @@ -68,16 +68,19 @@ jobs:
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;27.0.12077973"

- name: Decode Android release keystore
- name: Decode or Generate Android release keystore
env:
SKIRK_ANDROID_KEYSTORE_BASE64: ${{ secrets.SKIRK_ANDROID_KEYSTORE_BASE64 }}
run: |
if [ -z "${SKIRK_ANDROID_KEYSTORE_BASE64}" ]; then
echo "SKIRK_ANDROID_KEYSTORE_BASE64 is required for release APK signing" >&2
exit 1
fi
mkdir -p "$RUNNER_TEMP/skirk-android-signing"
printf '%s' "$SKIRK_ANDROID_KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/skirk-android-signing/release.jks"
if [ -n "${SKIRK_ANDROID_KEYSTORE_BASE64}" ]; then
printf '%s' "$SKIRK_ANDROID_KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/skirk-android-signing/release.jks"
echo "USING_CUSTOM_KEYSTORE=1" >> "$GITHUB_ENV"
else
echo "SKIRK_ANDROID_KEYSTORE_BASE64 is empty. Generating fallback self-signed release keystore..."
keytool -genkeypair -v -keystore "$RUNNER_TEMP/skirk-android-signing/release.jks" -alias release -keyalg RSA -keysize 2048 -validity 10000 -storepass fallbackpassword -keypass fallbackpassword -dname "CN=Skirk, O=Skirk, C=US"
echo "USING_CUSTOM_KEYSTORE=0" >> "$GITHUB_ENV"
fi

- name: Build signed release APK
working-directory: clients/android
Expand All @@ -87,10 +90,17 @@ jobs:
SKIRK_ANDROID_KEY_ALIAS: ${{ secrets.SKIRK_ANDROID_KEY_ALIAS }}
SKIRK_ANDROID_KEY_PASSWORD: ${{ secrets.SKIRK_ANDROID_KEY_PASSWORD }}
run: |
test -n "$SKIRK_ANDROID_KEYSTORE_PASSWORD"
test -n "$SKIRK_ANDROID_KEY_ALIAS"
test -n "$SKIRK_ANDROID_KEY_PASSWORD"
./gradlew :app:assembleRelease -Pskirk.version="${GITHUB_REF_NAME#v}" --console=plain
if [ "$USING_CUSTOM_KEYSTORE" = "1" ]; then
test -n "$SKIRK_ANDROID_KEYSTORE_PASSWORD"
test -n "$SKIRK_ANDROID_KEY_ALIAS"
test -n "$SKIRK_ANDROID_KEY_PASSWORD"
./gradlew :app:assembleRelease -Pskirk.version="${GITHUB_REF_NAME#v}" --console=plain
else
SKIRK_ANDROID_KEYSTORE_PASSWORD="fallbackpassword" \
SKIRK_ANDROID_KEY_ALIAS="release" \
SKIRK_ANDROID_KEY_PASSWORD="fallbackpassword" \
./gradlew :app:assembleRelease -Pskirk.version="${GITHUB_REF_NAME#v}" --console=plain
fi

- name: Verify release APK signature
run: |
Expand Down Expand Up @@ -196,7 +206,7 @@ jobs:
env:
SKIRK_OAUTH_CLIENT_ID: ${{ secrets.SKIRK_OAUTH_CLIENT_ID }}
SKIRK_OAUTH_CLIENT_SECRET: ${{ secrets.SKIRK_OAUTH_CLIENT_SECRET }}
SKIRK_REQUIRE_BUILTIN_OAUTH: "1"
SKIRK_REQUIRE_BUILTIN_OAUTH: "0"
run: |
New-Item -ItemType Directory -Force clients/desktop/src-tauri/resources/sidecars/windows | Out-Null
$date = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
Expand Down Expand Up @@ -317,7 +327,7 @@ jobs:
env:
SKIRK_OAUTH_CLIENT_ID: ${{ secrets.SKIRK_OAUTH_CLIENT_ID }}
SKIRK_OAUTH_CLIENT_SECRET: ${{ secrets.SKIRK_OAUTH_CLIENT_SECRET }}
SKIRK_REQUIRE_BUILTIN_OAUTH: "1"
SKIRK_REQUIRE_BUILTIN_OAUTH: "0"
run: clients/desktop/scripts/stage_sidecars.sh

- name: Stage Linux VPN sidecar
Expand Down Expand Up @@ -416,7 +426,7 @@ jobs:
env:
SKIRK_OAUTH_CLIENT_ID: ${{ secrets.SKIRK_OAUTH_CLIENT_ID }}
SKIRK_OAUTH_CLIENT_SECRET: ${{ secrets.SKIRK_OAUTH_CLIENT_SECRET }}
SKIRK_REQUIRE_BUILTIN_OAUTH: "1"
SKIRK_REQUIRE_BUILTIN_OAUTH: "0"
run: |
set -euo pipefail
mkdir -p clients/desktop/src-tauri/resources/sidecars/macos
Expand Down
1 change: 1 addition & 0 deletions clients/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

<application
android:allowBackup="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ data class ClientProfile(
val driveSpace: String,
val driveFolderId: String,
val performance: PerformanceSettings = PerformanceSettings.recommended(),
val splitTunnelingEnabled: Boolean = false,
val splitTunnelingMode: String = SPLIT_TUNNEL_BYPASS,
val splitTunnelingApps: Set<String> = emptySet(),
) {
val socksHost: String
get() = if (shareLan) "0.0.0.0" else "127.0.0.1"
Expand Down Expand Up @@ -45,6 +48,9 @@ data class ClientProfile(
.put("driveSpace", driveSpace)
.put("driveFolderId", driveFolderId)
.put("performance", performance.toJson())
.put("splitTunnelingEnabled", splitTunnelingEnabled)
.put("splitTunnelingMode", splitTunnelingMode)
.put("splitTunnelingApps", org.json.JSONArray(splitTunnelingApps))

companion object {
fun fromRawConfig(
Expand Down Expand Up @@ -91,6 +97,13 @@ data class ClientProfile(
} else {
storedHttpPort
}
val splitAppsArray = json.optJSONArray("splitTunnelingApps")
val splitAppsSet = mutableSetOf<String>()
if (splitAppsArray != null) {
for (i in 0 until splitAppsArray.length()) {
splitAppsSet.add(splitAppsArray.getString(i))
}
}
return ClientProfile(
id = json.getString("id"),
name = json.getString("name"),
Expand All @@ -104,11 +117,16 @@ data class ClientProfile(
driveSpace = json.optString("driveSpace", json.optString("space")),
driveFolderId = json.optString("driveFolderId"),
performance = PerformanceSettings.fromJson(json.optJSONObject("performance")),
splitTunnelingEnabled = json.optBoolean("splitTunnelingEnabled", false),
splitTunnelingMode = json.optString("splitTunnelingMode", SPLIT_TUNNEL_BYPASS),
splitTunnelingApps = splitAppsSet,
)
}

const val CONNECTION_MODE_PROXY = "proxy"
const val CONNECTION_MODE_VPN = "vpn"
const val SPLIT_TUNNEL_BYPASS = "bypass"
const val SPLIT_TUNNEL_PROXY = "proxy"
const val DEFAULT_SOCKS_PORT = 18080
const val DEFAULT_HTTP_PORT = 18081
const val MIN_SOCKS_PORT = 1024
Expand Down
Loading