nix: add config defaults and temp keystore generation
Changes: * Create `nix/config.nix` with `config` defaults * Add `nix/tools/gradlePropParser.nix` for reading `gradle.properties` * Add `nix/mobile/android/keystore.nix` for generating a keystore * Load keystore generation in `nix/mobile/android/default.nix` * Use generated keystore if it's not provided via `config` * Add `-deststoretype pkcs12` in `scripts/generate-keystore.sh` * Add `nix/lib/assertEnvVarSet.nix` for checking if env var is set Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
parent
b39d26ed4c
commit
f2c96dcd3b
|
@ -31,6 +31,7 @@ config = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
You can see the defaults in [`nix/config.nix`](./config.nix).
|
||||||
|
|
||||||
## Shell
|
## Shell
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Status defaults for config
|
||||||
|
{
|
||||||
|
status-im = {
|
||||||
|
build-type = "pr"; # Build type (influences which .env file gets used for feature flags)
|
||||||
|
build-number = 9999; # Used for versionCode and CFBundleVersion in Android and iOS respectively
|
||||||
|
|
||||||
|
android = {
|
||||||
|
gradle-opts = null; # Gradle options passed for Android builds
|
||||||
|
keystore-path = null; # Path to keystore for signing the APK
|
||||||
|
abi-split = false; # If APKs should be split based on architectures
|
||||||
|
abi-include = "armeabi-v7a;arm64-v8a;x86"; # Android architectures to build for
|
||||||
|
};
|
||||||
|
|
||||||
|
nimbus = { src-override = null; };
|
||||||
|
status-go = { src-override = null; };
|
||||||
|
};
|
||||||
|
|
||||||
|
# Android SDK requires an accepted license
|
||||||
|
android_sdk.accept_license = true;
|
||||||
|
# Android Env still needs old OpenSSL
|
||||||
|
permittedInsecurePackages = [ "openssl-1.0.2u" ];
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Helper for verifying an environment variable is set
|
||||||
|
name: ''
|
||||||
|
if [[ -z ''$${name} ]]; then
|
||||||
|
echo 'Not env var set: ${name}' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
''
|
|
@ -4,4 +4,5 @@
|
||||||
getConfig = import ./getConfig.nix { inherit lib config; };
|
getConfig = import ./getConfig.nix { inherit lib config; };
|
||||||
mkFilter = import ./mkFilter.nix { inherit lib; };
|
mkFilter = import ./mkFilter.nix { inherit lib; };
|
||||||
mergeSh = import ./mergeSh.nix { inherit lib; };
|
mergeSh = import ./mergeSh.nix { inherit lib; };
|
||||||
|
assertEnvVarSet = import ./assertEnvVarSet.nix;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
, status-go, androidPkgs, androidShell }:
|
, status-go, androidPkgs, androidShell }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
# For generating a temporary keystore for local development
|
||||||
|
keystore = callPackage ./keystore.nix { };
|
||||||
|
|
||||||
# Import a jsbundle compiled out of clojure codebase
|
# Import a jsbundle compiled out of clojure codebase
|
||||||
jsbundle = callPackage ./jsbundle { };
|
jsbundle = callPackage ./jsbundle { };
|
||||||
|
|
||||||
|
@ -10,12 +13,12 @@ let
|
||||||
|
|
||||||
# TARGETS
|
# TARGETS
|
||||||
release = callPackage ./release.nix {
|
release = callPackage ./release.nix {
|
||||||
inherit jsbundle status-go watchmanFactory;
|
inherit keystore jsbundle status-go watchmanFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in {
|
||||||
# TARGETS
|
# TARGETS
|
||||||
inherit release jsbundle;
|
inherit keystore release jsbundle;
|
||||||
|
|
||||||
shell = mkShell {
|
shell = mkShell {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
|
|
|
@ -22,9 +22,9 @@ stdenv.mkDerivation {
|
||||||
ignoreVCS = false;
|
ignoreVCS = false;
|
||||||
include = [
|
include = [
|
||||||
"VERSION" "BUILD_NUMBER" "scripts/version/.*"
|
"VERSION" "BUILD_NUMBER" "scripts/version/.*"
|
||||||
|
"src/.*" "shadow-cljs.edn" "index.js"
|
||||||
# I want to avoid including the whole .git directory
|
# I want to avoid including the whole .git directory
|
||||||
".git/HEAD" ".git/objects" ".git/refs/heads/.*"
|
".git/HEAD" ".git/objects" ".git/refs/heads/.*"
|
||||||
"src/.*" "shadow-cljs.edn" "index.js"
|
|
||||||
# shadow-cljs expects these for deps resolution
|
# shadow-cljs expects these for deps resolution
|
||||||
"mobile/js_files/package.json" "mobile/js_files/yarn.lock"
|
"mobile/js_files/package.json" "mobile/js_files/yarn.lock"
|
||||||
# build stat's images to check if they exist
|
# build stat's images to check if they exist
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#
|
||||||
|
# Generates an ad-hoc and temporary keystore for signing debug/pr builds.
|
||||||
|
#
|
||||||
|
# WARNING: Do NOT use this to make a keystore that needs to be secret!
|
||||||
|
# Using a derivation will store the inputs in a .drv file.
|
||||||
|
#
|
||||||
|
{ stdenv, lib, pkgs }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) getAttr;
|
||||||
|
|
||||||
|
gradleProps = pkgs.gradlePropParser ../../../android/gradle.properties;
|
||||||
|
|
||||||
|
# Loading defaults from gradle.properties which should be safe.
|
||||||
|
KEYSTORE_ALIAS = getAttr "KEYSTORE_ALIAS" gradleProps;
|
||||||
|
KEYSTORE_PASSWORD = getAttr "KEYSTORE_PASSWORD" gradleProps;
|
||||||
|
KEYSTORE_KEY_PASSWORD = getAttr "KEYSTORE_KEY_PASSWORD" gradleProps;
|
||||||
|
|
||||||
|
in stdenv.mkDerivation {
|
||||||
|
name = "status-react-android-keystore";
|
||||||
|
|
||||||
|
buildInputs = [ pkgs.openjdk8 ];
|
||||||
|
|
||||||
|
phases = [ "generatePhase" ];
|
||||||
|
generatePhase = ''
|
||||||
|
keytool -genkey -v \
|
||||||
|
-keyalg RSA \
|
||||||
|
-keysize 2048 \
|
||||||
|
-validity 10000 \
|
||||||
|
-deststoretype pkcs12 \
|
||||||
|
-dname "CN=, OU=, O=, L=, S=, C=" \
|
||||||
|
-keystore "$out" \
|
||||||
|
-alias "${KEYSTORE_ALIAS}" \
|
||||||
|
-storepass "${KEYSTORE_PASSWORD}" \
|
||||||
|
-keypass "${KEYSTORE_KEY_PASSWORD}" \
|
||||||
|
>&2
|
||||||
|
'';
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
export KEYSTORE_ALIAS="${KEYSTORE_ALIAS}"
|
||||||
|
export KEYSTORE_PASSWORD="${KEYSTORE_PASSWORD}"
|
||||||
|
export KEYSTORE_KEY_PASSWORD="${KEYSTORE_KEY_PASSWORD}"
|
||||||
|
'';
|
||||||
|
}
|
|
@ -1,22 +1,30 @@
|
||||||
{ stdenv, pkgs, deps, lib, config, callPackage,
|
{ stdenv, pkgs, deps, lib, config, callPackage,
|
||||||
watchmanFactory, androidPkgs, patchMavenSources,
|
watchmanFactory, androidPkgs, patchMavenSources,
|
||||||
jsbundle, status-go }:
|
keystore, jsbundle, status-go }:
|
||||||
|
|
||||||
{
|
{
|
||||||
buildEnv ? "prod", # Value for BUILD_ENV checked by Clojure code at compile time
|
# Value for BUILD_ENV checked by Clojure code at compile time
|
||||||
secretsFile ? "", # Path to the file containing secret environment variables
|
buildEnv ? "prod",
|
||||||
watchmanSockPath ? "", # Path to the socket file exposed by an external watchman instance (workaround needed for building Android on macOS)
|
# Path to the file containing secret environment variables
|
||||||
|
secretsFile ? "",
|
||||||
|
# Path to the socket file exposed by an external watchman instance
|
||||||
|
# (workaround needed for building Android on macOS)
|
||||||
|
watchmanSockPath ? "",
|
||||||
}:
|
}:
|
||||||
|
|
||||||
assert (lib.stringLength watchmanSockPath) > 0 -> stdenv.isDarwin;
|
assert (lib.stringLength watchmanSockPath) > 0 -> stdenv.isDarwin;
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib) toLower optionalString stringLength getConfig makeLibraryPath;
|
inherit (lib)
|
||||||
|
toLower optionalString stringLength
|
||||||
|
getConfig makeLibraryPath assertEnvVarSet;
|
||||||
|
|
||||||
buildType = getConfig "build-type" "prod";
|
buildType = getConfig "build-type" "prod";
|
||||||
buildNumber = getConfig "build-number" 9999;
|
buildNumber = getConfig "build-number" 9999;
|
||||||
gradleOpts = getConfig "android.gradle-opts" null;
|
gradleOpts = getConfig "android.gradle-opts" null;
|
||||||
keystorePath = getConfig "android.keystore-path" null;
|
# Keystore can be provided via config and extra-sandbox-paths.
|
||||||
|
# If it is not we use an ad-hoc one generated with default password.
|
||||||
|
keystorePath = getConfig "android.keystore-path" keystore;
|
||||||
|
|
||||||
baseName = "release-android";
|
baseName = "release-android";
|
||||||
name = "status-react-build-${baseName}";
|
name = "status-react-build-${baseName}";
|
||||||
|
@ -73,7 +81,8 @@ in stdenv.mkDerivation rec {
|
||||||
STATUS_GO_ANDROID_LIBDIR = "${status-go}";
|
STATUS_GO_ANDROID_LIBDIR = "${status-go}";
|
||||||
|
|
||||||
phases = [
|
phases = [
|
||||||
"unpackPhase" "secretPhase" "buildPhase" "checkPhase" "installPhase"
|
"unpackPhase" "secretsPhase" "secretsCheckPhase"
|
||||||
|
"buildPhase" "checkPhase" "installPhase"
|
||||||
];
|
];
|
||||||
|
|
||||||
unpackPhase = ''
|
unpackPhase = ''
|
||||||
|
@ -81,7 +90,9 @@ in stdenv.mkDerivation rec {
|
||||||
chmod u+w -R ./
|
chmod u+w -R ./
|
||||||
runHook postUnpack
|
runHook postUnpack
|
||||||
'';
|
'';
|
||||||
postUnpack = assert lib.assertMsg (keystorePath != null) "keystore-file has to be set!"; ''
|
postUnpack =
|
||||||
|
assert lib.assertMsg (keystorePath != null) "keystore-file has to be set!";
|
||||||
|
''
|
||||||
# Keep the same keystore path for determinism
|
# Keep the same keystore path for determinism
|
||||||
export KEYSTORE_PATH="$PWD/status-im.keystore"
|
export KEYSTORE_PATH="$PWD/status-im.keystore"
|
||||||
cp -a --no-preserve=ownership "${keystorePath}" "$KEYSTORE_PATH"
|
cp -a --no-preserve=ownership "${keystorePath}" "$KEYSTORE_PATH"
|
||||||
|
@ -107,8 +118,14 @@ in stdenv.mkDerivation rec {
|
||||||
# Patch build.gradle to use local repo
|
# Patch build.gradle to use local repo
|
||||||
${patchMavenSources} ./android/build.gradle
|
${patchMavenSources} ./android/build.gradle
|
||||||
'';
|
'';
|
||||||
secretPhase = optionalString (secretsFile != "") ''
|
# if secretsFile is not set we use generate keystore
|
||||||
|
secretsPhase = if (secretsFile != "") then ''
|
||||||
source "${secretsFile}"
|
source "${secretsFile}"
|
||||||
|
'' else keystore.shellHook;
|
||||||
|
secretsCheckPhase = ''
|
||||||
|
${assertEnvVarSet "KEYSTORE_ALIAS"}
|
||||||
|
${assertEnvVarSet "KEYSTORE_PASSWORD"}
|
||||||
|
${assertEnvVarSet "KEYSTORE_KEY_PASSWORD"}
|
||||||
'';
|
'';
|
||||||
buildPhase = let
|
buildPhase = let
|
||||||
adhocEnvVars = optionalString stdenv.isLinux
|
adhocEnvVars = optionalString stdenv.isLinux
|
||||||
|
|
|
@ -28,8 +28,8 @@ in {
|
||||||
react-native = callPackage ./deps/react-native { };
|
react-native = callPackage ./deps/react-native { };
|
||||||
};
|
};
|
||||||
|
|
||||||
# For patching Node.js modules with Gradle repo path
|
# For parsing gradle.properties into an attrset
|
||||||
patchNodeModules = callPackage ./tools/patchNodeModules.nix { };
|
gradlePropParser = callPackage ./tools/gradlePropParser.nix { };
|
||||||
|
|
||||||
# Package version adjustments
|
# Package version adjustments
|
||||||
xcodeWrapper = super.xcodeenv.composeXcodeWrapper { version = "11.4.1"; };
|
xcodeWrapper = super.xcodeenv.composeXcodeWrapper { version = "11.4.1"; };
|
||||||
|
|
11
nix/pkgs.nix
11
nix/pkgs.nix
|
@ -19,16 +19,11 @@ let
|
||||||
# nix-prefetch-url --unpack https://github.com/${ORG}/nixpkgs/archive/${REV}.tar.gz
|
# nix-prefetch-url --unpack https://github.com/${ORG}/nixpkgs/archive/${REV}.tar.gz
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Status specific configuration defaults
|
||||||
|
defaultConfig = import ./config.nix;
|
||||||
|
|
||||||
# Override some packages and utilities
|
# Override some packages and utilities
|
||||||
pkgsOverlay = import ./overlay.nix;
|
pkgsOverlay = import ./overlay.nix;
|
||||||
|
|
||||||
# we want these packages easily available via callPackage
|
|
||||||
defaultConfig = {
|
|
||||||
android_sdk.accept_license = true;
|
|
||||||
# Android Env still needs old OpenSSL
|
|
||||||
permittedInsecurePackages = [ "openssl-1.0.2u" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
in
|
in
|
||||||
# import nixpkgs with a config override
|
# import nixpkgs with a config override
|
||||||
(import nixpkgsSrc) {
|
(import nixpkgsSrc) {
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Parser for android/gradle.properties file.
|
||||||
|
# Returns an attrset with keys and values from it.
|
||||||
|
{ lib }:
|
||||||
|
|
||||||
|
gradlePropsFile:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) head last filter listToAttrs splitString nameValuePair hasPrefix readFile;
|
||||||
|
|
||||||
|
# Read lines
|
||||||
|
lines = splitString "\n" (readFile gradlePropsFile);
|
||||||
|
|
||||||
|
isKeyValueLine = line: line != "" && !hasPrefix "#" line;
|
||||||
|
cleanup = lines: filter isKeyValueLine lines;
|
||||||
|
extractKeyValues = line:
|
||||||
|
let flag = splitString "=" line;
|
||||||
|
in nameValuePair (head flag) (last flag);
|
||||||
|
parseAttrs = lines: listToAttrs (map extractKeyValues lines);
|
||||||
|
in
|
||||||
|
parseAttrs (cleanup lines)
|
|
@ -45,6 +45,7 @@ keytool -genkey -v \
|
||||||
-keyalg RSA \
|
-keyalg RSA \
|
||||||
-keysize 2048 \
|
-keysize 2048 \
|
||||||
-validity 10000 \
|
-validity 10000 \
|
||||||
|
-deststoretype pkcs12 \
|
||||||
-dname "CN=, OU=, O=, L=, S=, C=" \
|
-dname "CN=, OU=, O=, L=, S=, C=" \
|
||||||
-keystore "${KEYSTORE_PATH}" \
|
-keystore "${KEYSTORE_PATH}" \
|
||||||
-alias "${KEYSTORE_ALIAS}" \
|
-alias "${KEYSTORE_ALIAS}" \
|
||||||
|
|
Loading…
Reference in New Issue