nix: don't generate keystore inside of Nix build

changes:
- Stops scripts/generate-keystore.sh runnig for every new TARGET=android shell
- Moves running scripts/generate-keystore.sh to keystore Makefile target
- Makes generate-keystore.sh accept STATUS_RELEASE_STORE_FILE as env variable
- Fixes error about missing lsof from start-react-native.sh
- Fixes error about unknown -keystore command in scripts/generate-keystore.sh
- Fixes getting OS_NAME without calling Nix shell
- Fixes getting TMP_BUILD_NUMBER without calling Nix shell
- Adds lsof used in start-react-native.sh to Android release Nix derivation
- Simplified how nix/scripts/build.sh appends the --keep flag
- Made use of colors.sh in more scripts

Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
Jakub Sokołowski 2020-03-02 12:18:01 +01:00
parent efa420def4
commit de53581ef4
No known key found for this signature in database
GPG Key ID: 4EF064D0E6D63020
14 changed files with 123 additions and 91 deletions

View File

@ -47,6 +47,12 @@ ifdef TARGET_OS
export TARGET ?= $(TARGET_OS)
endif
# Useful for checking if we are on NixOS
OS_NAME := $(shell awk -F= '/^NAME/{print $2}' /etc/os-release)
# Useful for Andoird release builds
TMP_BUILD_NUMBER := $(shell ./scripts/version/gen_build_no.sh | cut -c1-10)
# MacOS root is read-only, read nix/README.md for details
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
@ -54,9 +60,6 @@ export NIX_IGNORE_SYMLINK_STORE=1
export _NIX_ROOT = /opt/nix
endif
# Useful for checking if we are on NixOS
OS_NAME ?= $(shell source /etc/os-release && echo $${NAME})
#----------------
# Nix targets
#----------------
@ -152,19 +155,24 @@ update-fleets: ##@prepare Download up-to-date JSON file with current fleets stat
| jq --indent 4 --sort-keys . \
> resources/config/fleets.json
keystore: export TARGET := keytool
keystore: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
keystore: ##@prepare Generate a Keystore for signing Android APKs
@./scripts/generate-keystore.sh
#----------------
# Release builds
#----------------
release: release-android release-ios ##@build build release for Android and iOS
release-android: export TARGET ?= android
release-android: export TARGET := android
release-android: export BUILD_ENV ?= prod
release-android: export BUILD_TYPE ?= nightly
release-android: export BUILD_NUMBER ?= $(shell ./scripts/version/gen_build_no.sh | cut -c1-10)
release-android: export KEYSTORE_FILE ?= $(HOME)/.gradle/status-im.keystore
release-android: export BUILD_NUMBER ?= $(TMP_BUILD_NUMBER)
release-android: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
release-android: export ANDROID_ABI_SPLIT ?= false
release-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
release-android: ##@build build release for Android
release-android: keystore ##@build build release for Android
scripts/release-android.sh
release-ios: export TARGET ?= ios

View File

@ -219,10 +219,10 @@ android {
}
release {
/* environment variables take precedence over gradle.properties file */
storeFile file(getEnvOrConfig('STATUS_RELEASE_STORE_FILE').replaceAll("~", System.properties['user.home']))
storePassword getEnvOrConfig('STATUS_RELEASE_STORE_PASSWORD')
keyAlias getEnvOrConfig('STATUS_RELEASE_KEY_ALIAS')
keyPassword getEnvOrConfig('STATUS_RELEASE_KEY_PASSWORD')
storeFile file(getEnvOrConfig('KEYSTORE_PATH').replaceAll("~", System.properties['user.home']))
storePassword getEnvOrConfig('KEYSTORE_PASSWORD')
keyAlias getEnvOrConfig('KEYSTORE_ALIAS')
keyPassword getEnvOrConfig('KEYSTORE_KEY_PASSWORD')
}
}
splits {

View File

@ -31,10 +31,10 @@ gradlePluginVersion=3.4.1
android.useAndroidX=true
android.enableJetifier=true
STATUS_RELEASE_STORE_FILE=~/.gradle/status-im.keystore
STATUS_RELEASE_STORE_PASSWORD=password
STATUS_RELEASE_KEY_ALIAS=status
STATUS_RELEASE_KEY_PASSWORD=password
KEYSTORE_PATH=~/.gradle/status-im.keystore
KEYSTORE_PASSWORD=password
KEYSTORE_ALIAS=status
KEYSTORE_KEY_PASSWORD=password
# By default we build a mostly universal APK
ANDROID_ABI_SPLIT=false

View File

@ -27,16 +27,16 @@ def bundle() {
withCredentials([
file(
credentialsId: 'status-im.keystore',
variable: 'STATUS_RELEASE_STORE_FILE'
variable: 'KEYSTORE_PATH'
),
string(
credentialsId: 'android-keystore-pass',
variable: 'STATUS_RELEASE_STORE_PASSWORD'
variable: 'KEYSTORE_PASSWORD'
),
usernamePassword(
credentialsId: 'android-keystore-key-pass',
usernameVariable: 'STATUS_RELEASE_KEY_ALIAS',
passwordVariable: 'STATUS_RELEASE_KEY_PASSWORD'
usernameVariable: 'KEYSTORE_ALIAS',
passwordVariable: 'KEYSTORE_KEY_PASSWORD'
)
]) {
/* Nix target which produces the final APKs */
@ -49,17 +49,17 @@ def bundle() {
'status-im.status-react.build-number': buildNumber,
],
safeEnv: [
'STATUS_RELEASE_KEY_ALIAS',
'STATUS_RELEASE_STORE_PASSWORD',
'STATUS_RELEASE_KEY_PASSWORD',
'KEYSTORE_ALIAS',
'KEYSTORE_PASSWORD',
'KEYSTORE_KEY_PASSWORD',
],
keepEnv: [
'ANDROID_ABI_SPLIT',
'ANDROID_ABI_INCLUDE',
'STATUS_RELEASE_STORE_FILE',
'KEYSTORE_PATH',
],
sandboxPaths: [
env.STATUS_RELEASE_STORE_FILE,
env.KEYSTORE_PATH,
],
link: false
)

View File

@ -1,4 +1,4 @@
{ config, lib, callPackage, mkShell, mergeSh, androidenv, flock, openjdk,
{ config, lib, callPackage, mkShell, mergeSh, androidenv, flock, lsof, openjdk,
status-go, localMavenRepoBuilder, projectNodePackage }:
let
@ -32,6 +32,7 @@ let
buildInputs = [
mavenAndNpmDeps.drv openjdk gradle
lsof # used in start-react-native.sh
flock # used in reset-node_modules.sh
];
@ -45,12 +46,9 @@ in {
inherit buildInputs;
inputsFrom = [ release gradle ];
shellHook = ''
pushd "$STATUS_REACT_HOME" > /dev/null
{
./scripts/generate-keystore.sh
# check if node modules changed and if so install them
./nix/mobile/reset-node_modules.sh "${mavenAndNpmDeps.drv}/project"
}
# check if node modules changed and if so install them
$STATUS_REACT_HOME/nix/mobile/reset-node_modules.sh \
"${mavenAndNpmDeps.drv}/project"
'';
})
(lib.catAttrs "shell" [ status-go mavenAndNpmDeps androidEnv ]);

View File

@ -20,7 +20,8 @@ let
inherit (config.status-im) build-type;
inherit (config.status-im.status-react) build-number;
gradle-opts = (attrByPath ["status-im" "status-react" "gradle-opts"] "" config);
keystore-file = (attrByPath ["status-im" "status-react" "keystore-file"] "" config); # Path to the .keystore file used to sign the package
# Path to the .keystore file used to sign the Android APK
keystore-file = (attrByPath ["status-im" "status-react" "keystore-file"] "" config);
baseName = "release-android";
name = "status-react-build-${baseName}";
gradleHome = "$NIX_BUILD_TOP/.gradle";
@ -48,8 +49,14 @@ in stdenv.mkDerivation {
"modules/react-native-status/android"
"resources"
];
dirsToExclude = [ ".git" ".svn" "CVS" ".hg" ".gradle" "build" "intermediates" "libs" "obj" ];
filesToInclude = [ envFileName "status-go-version.json" "VERSION" "react-native.config.js" ".watchmanconfig" ];
dirsToExclude = [
".git" ".svn" "CVS" ".hg" ".gradle"
"build" "intermediates" "libs" "obj"
];
filesToInclude = [
envFileName "VERSION" ".watchmanconfig"
"status-go-version.json" "react-native.config.js"
];
root = path;
};
};
@ -69,7 +76,7 @@ in stdenv.mkDerivation {
postUnpack = ''
mkdir -p ${gradleHome}
${if keystore-file != "" then "cp -a --no-preserve=ownership ${keystore-file} ${gradleHome}/; export STATUS_RELEASE_STORE_FILE=${gradleHome}/$(basename ${keystore-file})" else ""}
${if keystore-file != "" then "cp -a --no-preserve=ownership ${keystore-file} ${gradleHome}/; export KEYSTORE_PATH=${gradleHome}/$(basename ${keystore-file})" else ""}
# Ensure we have the right .env file
cp -f $sourceRoot/${envFileName} $sourceRoot/.env

View File

@ -51,18 +51,17 @@ nixOpts=(
"--show-trace"
"--attr ${targetAttr}"
"${@}"
"default.nix"
)
# This variable allows specifying which env vars to keep for Nix pure shell
# The separator is a semicolon
# This variable allows specifying which env vars to keep for Nix pure shell.
# The separator is a colon
if [[ -n "${_NIX_KEEP}" ]]; then
nixOpts+=("--keep ${_NIX_KEEP//;/ --keep }")
nixOpts+=("--keep ${_NIX_KEEP//,/ --keep }")
fi
# Run the actual build
echo "Running: nix-build ${nixOpts[@]}"
nixResultPath=$(nix-build ${nixOpts[@]})
echo "Running: nix-build ${nixOpts[@]} default.nix"
nixResultPath=$(nix-build ${nixOpts[@]} default.nix)
echo "Extracting result: ${nixResultPath}"
extractResults "${nixResultPath}"

View File

@ -67,9 +67,9 @@ else
pureDesc='pure '
fi
# This variable allows specifying which env vars to keep for Nix pure shell
# The separator is a semicolon
# The separator is a colon
if [[ -n "${_NIX_KEEP}" ]]; then
shellArgs+=("--keep ${_NIX_KEEP//;/ --keep }")
shellArgs+=("--keep ${_NIX_KEEP//,/ --keep }")
fi
echo -e "${GRN}Configuring ${pureDesc}${_NIX_ATTR:-default} Nix shell for target '${TARGET}'...${RST}" 1>&2
exec nix-shell ${shellArgs[@]} --run "$@" ${entryPoint}

View File

@ -14,14 +14,19 @@ let
buildInputs = with pkgs; [ clojure leiningen flock maven nodejs openjdk ];
};
# for running fastlane commands alone
fastlane-sh = targets.mobile.fastlane.shell;
# for 'make watchman-clean'
watchman-sh = pkgs.mkShell {
buildInputs = [ pkgs.watchman ];
};
# for running fastlane commands alone
fastlane-sh = targets.mobile.fastlane.shell;
# for 'scripts/generate-keystore.sh'
keytool-sh = pkgs.mkShell {
buildInputs = [ pkgs.openjdk8 ];
};
# the default shell that is used when target is not specified
default = pkgs.mkShell {
name = "status-react-shell"; # for identifying all shells
@ -50,6 +55,7 @@ in with pkgs; rec {
lein = leiningen-sh;
watchman = watchman-sh;
fastlane = fastlane-sh;
keytool = keytool-sh;
adb = targets.mobile.android.adb.shell;
# helpers for use with target argument
linux = targets.desktop.linux.shell;

View File

@ -2,12 +2,10 @@
set -e
VERBOSE_LEVEL=${VERBOSE_LEVEL:-1}
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/scripts/colors.sh"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
VERBOSE_LEVEL=${VERBOSE_LEVEL:-1}
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
OS=$(uname -s)
if [ -z "$TARGET" ]; then
@ -56,13 +54,13 @@ JS_BUNDLE_PATH="$WORKFOLDER/index.desktop.bundle"
function init() {
if [ -z $STATUS_REACT_HOME ]; then
echo "${RED}STATUS_REACT_HOME environment variable is not defined!${NC}"
echo "${RED}STATUS_REACT_HOME environment variable is not defined!${RST}"
exit 1
fi
if ! is_windows_target; then
if [ -z $QT_PATH ]; then
echo "${RED}QT_PATH environment variable is not defined!${NC}"
echo "${RED}QT_PATH environment variable is not defined!${RST}"
exit 1
fi
fi
@ -73,7 +71,7 @@ function init() {
if is_windows_target; then
export PATH=$STATUS_REACT_HOME:$PATH
if ! program_exists 'conan'; then
echo "${RED}Conan package manager not found. Exiting...${NC}"
echo "${RED}Conan package manager not found. Exiting...${RST}"
exit 1
fi
@ -95,7 +93,7 @@ function buildJSBundle() {
# create directory for all work related to bundling
rm -rf $WORKFOLDER
mkdir -p $WORKFOLDER
echo -e "${GREEN}Work folder created: $WORKFOLDER${NC}"
echo -e "${GRN}Work folder created: $WORKFOLDER${RST}"
echo ""
# from index.desktop.js create javascript bundle and resources folder
@ -107,7 +105,7 @@ function buildJSBundle() {
--bundle-output "$JS_BUNDLE_PATH" \
--assets-dest "$WORKFOLDER/assets" \
--platform desktop
echo -e "${GREEN}Generating done.${NC}"
echo -e "${GRN}Generating done.${RST}"
echo ""
}
@ -117,7 +115,7 @@ function compile() {
local jsPackagePath=$(joinExistingPath "$STATUS_REACT_HOME" 'desktop/js_files/package.json')
jq ".=(. + {$jsBundleLine})" "$jsPackagePath" | sponge "$jsPackagePath"
echo -e "${YELLOW}Added 'desktopJSBundlePath' line to $jsPackagePath:${NC}"
echo -e "${YLW}Added 'desktopJSBundlePath' line to $jsPackagePath:${RST}"
echo ""
local EXTERNAL_MODULES_DIR="$(jq -r '.desktopExternalModules | @tsv | @text' "$jsPackagePath" | tr '\t' ';')"
@ -132,7 +130,7 @@ function compile() {
local bin_dirs=$(jq -r '.dependencies[0].bin_paths | .[]' toolchain/conanbuildinfo.json)
while read -r bin_dir; do
if [ ! -d $bin ]; then
echo -e "${RED}Could not find $bin_dir directory from 'toolchain/conanbuildinfo.json', aborting${NC}"
echo -e "${RED}Could not find $bin_dir directory from 'toolchain/conanbuildinfo.json', aborting${RST}"
exit 1
fi
export PATH=$bin_dir:$PATH
@ -157,7 +155,7 @@ function bundleWindows() {
local version_file="${STATUS_REACT_HOME}/VERSION"
VERSION=$(cat $version_file)
if [ -z "$VERSION" ]; then
echo "${RED}Could not read version from ${version_file}!${NC}"
echo "${RED}Could not read version from ${version_file}!${RST}"
exit 1
fi
@ -263,7 +261,7 @@ function bundleLinux() {
mv -f ./Status-x86_64.AppImage ..
popd
echo -e "${GREEN}Package ready in ./Status-x86_64.AppImage!${NC}"
echo -e "${GRN}Package ready in ./Status-x86_64.AppImage!${RST}"
echo ""
}
@ -337,7 +335,7 @@ if [[ "$OS" =~ Darwin ]]; then
local targetDepDylib=$(joinExistingPath "/System/Library/Frameworks" "${framework}.framework/${framework}")
if [ ! -f "$targetDepDylib" ]; then
echo -e "${RED}FATAL: system framework not found: ${targetDepDylib}${NC}"
echo -e "${RED}FATAL: system framework not found: ${targetDepDylib}${RST}"
exit 1
fi
@ -348,7 +346,7 @@ if [[ "$OS" =~ Darwin ]]; then
local targetDepDylib=$(joinPath "$frameworksDir" "$(basename $depDylib)")
if [ ! -f "$targetDepDylib" ]; then
echo -e "${RED}FATAL: macdeployqt should have copied the dependency to ${targetDepDylib}${NC}"
echo -e "${RED}FATAL: macdeployqt should have copied the dependency to ${targetDepDylib}${RST}"
exit 1
fi
@ -436,7 +434,7 @@ function bundleMacOS() {
rm -f Status.app.zip
popd
echo -e "${GREEN}Package ready in $WORKFOLDER/Status.app!${NC}"
echo -e "${GRN}Package ready in $WORKFOLDER/Status.app!${RST}"
echo ""
}

View File

@ -4,4 +4,5 @@
YLW='\033[1;33m'
RED='\033[0;31m'
GRN='\033[0;32m'
BLD='\033[1m'
RST='\033[0m'

View File

@ -13,34 +13,37 @@ function property_gradle() {
property ${GIT_ROOT}/android/gradle.properties ${1}
}
TARGET=${1:-debug}
KEYSTORE_PASSWORD=$(property_gradle 'KEYSTORE_PASSWORD')
KEYSTORE_ALIAS=$(property_gradle 'KEYSTORE_ALIAS')
KEYSTORE_KEY_PASSWORD=$(property_gradle 'KEYSTORE_KEY_PASSWORD')
CURRENT_DIR=$(cd "$(dirname "$0")" && pwd)
KEYSTORE_FILE=$(property_gradle 'STATUS_RELEASE_STORE_FILE')
KEYSTORE_FILE=${KEYSTORE_FILE/#\~/$HOME}
STATUS_RELEASE_STORE_PASSWORD=$(property_gradle 'STATUS_RELEASE_STORE_PASSWORD')
STATUS_RELEASE_KEY_ALIAS=$(property_gradle 'STATUS_RELEASE_KEY_ALIAS')
STATUS_RELEASE_KEY_PASSWORD=$(property_gradle 'STATUS_RELEASE_KEY_PASSWORD')
# Allow Makefile modify Keystore path if necessary
if [[ -z ${KEYSTORE_PATH} ]]; then
KEYSTORE_PATH=$(property_gradle 'KEYSTORE_FILE')
fi
# Replace ~ with proper absolute path
KEYSTORE_PATH=${KEYSTORE_FILE/#\~/$HOME}
if [[ -e "${KEYSTORE_FILE}" ]]; then
echo -e "${YLW}Keystore file already exists:${RST} ${KEYSTORE_FILE}" > /dev/stderr
if [[ -e "${KEYSTORE_PATH}" ]]; then
echo -e "${YLW}Keystore file already exists:${RST} ${KEYSTORE_PATH}" > /dev/stderr
echo "${KEYSTORE_PATH}"
exit 0
fi
KEYSTORE_DIR=$(dirname "${KEYSTORE_FILE}")
KEYSTORE_DIR=$(dirname "${S/TATUS_RELEASE_STORE_FILE}")
[[ -d $KEYSTORE_DIR ]] || mkdir -p $KEYSTORE_DIR
echo "Generating keystore ${KEYSTORE_FILE}" > /dev/stderr
echo -e "${GRN}Generating keystore...${RST}" > /dev/stderr
keytool -genkey -v \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-dname "CN=, OU=, O=, L=, S=, C="
-keystore "${KEYSTORE_FILE}" \
-alias "${STATUS_RELEASE_KEY_ALIAS}" \
-storepass "${STATUS_RELEASE_STORE_PASSWORD}" \
-keypass "${STATUS_RELEASE_KEY_PASSWORD}" \
-dname "CN=, OU=, O=, L=, S=, C=" \
-keystore "${KEYSTORE_PATH}" \
-alias "${KEYSTORE_ALIAS}" \
-storepass "${KEYSTORE_PASSWORD}" \
-keypass "${KEYSTORE_KEY_PASSWORD}" \
> /dev/stderr
echo "${KEYSTORE_FILE}"
echo "${KEYSTORE_PATH}"

View File

@ -1,17 +1,31 @@
#!/usr/bin/env bash
# Needed to fail on must_get_env()
set -e
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/scripts/colors.sh"
function must_get_env() {
declare -n VAR_NAME="$1"
if [[ -n "${VAR_NAME}" ]]; then
echo "${VAR_NAME}"
return
fi
echo -e "${RED}No required env variable:${RST} ${BLD}${!VAR_NAME}${RST}" 1>&2
exit 1
}
config=''
config+="status-im.build-type=\"${BUILD_TYPE}\";"
if [ -n "${STATUS_GO_SRC_OVERRIDE}" ]; then
config+="status-im.status-go.src-override=\"${STATUS_GO_SRC_OVERRIDE}\";"
fi
if [ -n "${NIMBUS_SRC_OVERRIDE}" ]; then
config+="status-im.nimbus.src-override=\"${NIMBUS_SRC_OVERRIDE}\";"
fi
config+="status-im.status-react.build-number=\"${BUILD_NUMBER}\";"
config+="status-im.status-react.keystore-file=\"${KEYSTORE_FILE}\";"
config+="status-im.build-type=\"$(must_get_env BUILD_TYPE)\";"
config+="status-im.status-react.build-number=\"$(must_get_env BUILD_NUMBER)\";"
config+="status-im.status-react.keystore-file=\"$(must_get_env KEYSTORE_PATH)\";"
nixOpts=(
"--arg config {${config}}"
"--arg env {BUILD_ENV=\"${BUILD_ENV}\";ANDROID_ABI_SPLIT=\"${ANDROID_ABI_SPLIT}\";ANDROID_ABI_INCLUDE=\"${ANDROID_ABI_INCLUDE}\";}"
@ -24,11 +38,11 @@ if [[ "$OS" =~ Darwin ]]; then
WATCHMAN_SOCKFILE=$(watchman get-sockname --no-pretty | jq -r .sockname)
nixOpts+=(
"--argstr watchmanSockPath ${WATCHMAN_SOCKFILE}"
"--option extra-sandbox-paths ${KEYSTORE_FILE};${WATCHMAN_SOCKFILE}"
"--option extra-sandbox-paths ${KEYSTORE_PATH};${WATCHMAN_SOCKFILE}"
)
else
nixOpts+=(
"--option extra-sandbox-paths ${KEYSTORE_FILE}"
"--option extra-sandbox-paths ${KEYSTORE_PATH}"
)
fi

View File

@ -1,16 +1,14 @@
#!/usr/bin/env bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/scripts/colors.sh"
METRO_PORT=8081
METRO_PID="$(lsof -i :${METRO_PORT} | awk 'NR!=1 {print $2}' | sort -u | tr '\r\n' ' ')"
if [ ! -z "$METRO_PID" ]; then
echo -e "${YELLOW}TCP port ${METRO_PORT} is required by the Metro packager.\nThe following processes currently have the port open, preventing Metro from starting:${NC}"
echo -e "${YLW}TCP port ${METRO_PORT} is required by the Metro packager.\nThe following processes currently have the port open, preventing Metro from starting:${RST}"
ps -fp $METRO_PID
echo -e "${YELLOW}Do you want to terminate them (y/n)?${NC}"
echo -e "${YLW}Do you want to terminate them (y/n)?${RST}"
read -n 1 term
[[ $term == 'y' ]] && kill $METRO_PID
fi