2019-06-04 16:50:29 +00:00
{ stdenv , stdenvNoCC , lib , target-os , callPackage ,
2019-09-10 09:50:09 +00:00
mkFilter , bash , file , gnumake , watchmanFactory , gradle ,
2019-07-15 16:34:33 +00:00
androidEnvShellHook , mavenAndNpmDeps ,
2019-08-06 16:16:51 +00:00
nodejs , openjdk , jsbundle , status-go , unzip , zlib } :
2019-06-04 16:50:29 +00:00
2019-08-14 07:05:32 +00:00
{ build-number ,
build-type , # Build type (e.g. nightly, release, e2e). Default is to use .env.nightly file
2019-06-04 16:50:29 +00:00
gradle-opts ? " " ,
keystore-file ? " " , # Path to the .keystore file used to sign the package
secrets-file ? " " , # Path to the file containing secret environment variables
2019-09-10 09:50:09 +00:00
watchmanSockPath ? " " , # Path to the socket file exposed by an external watchman instance (workaround needed for building Android on macOS)
2019-06-04 16:50:29 +00:00
env ? { } # Attribute set contaning environment variables to expose to the build script
} :
2019-09-10 09:50:09 +00:00
assert ( builtins . stringLength watchmanSockPath ) > 0 -> stdenv . isDarwin ;
2019-06-04 16:50:29 +00:00
let
2019-07-15 16:34:33 +00:00
baseName = " r e l e a s e - ${ target-os } " ;
name = " s t a t u s - r e a c t - b u i l d - ${ baseName } " ;
2019-06-04 16:50:29 +00:00
gradleHome = " $ N I X _ B U I L D _ T O P / . g r a d l e " ;
localMavenRepo = " ${ mavenAndNpmDeps . deriv } / . m 2 / r e p o s i t o r y " ;
sourceProjectDir = " ${ mavenAndNpmDeps . deriv } / p r o j e c t " ;
envFileName =
if ( build-type == " r e l e a s e " || build-type == " n i g h t l y " || build-type == " e 2 e " ) then " . e n v . ${ build-type } " else
if build-type != " " then " . e n v . j e n k i n s " else " . e n v " ;
2019-08-23 15:23:42 +00:00
buildType' = if ( build-type == " p r " || build-type == " e 2 e " ) then " p r " else " r e l e a s e " ; /* P R b u i l d s s h o u l d n ' t r e p l a c e n o r m a l r e l e a s e s */
2019-08-06 16:16:51 +00:00
generatedApkPath = " $ s o u r c e R o o t / a n d r o i d / a p p / b u i l d / o u t p u t s / a p k / ${ buildType' } / a p p - ${ buildType' } . a p k " ;
2019-06-04 16:50:29 +00:00
outApkName = " a p p . a p k " ;
2019-09-10 09:50:09 +00:00
patchedWatchman = watchmanFactory watchmanSockPath ;
2019-06-04 16:50:29 +00:00
in stdenv . mkDerivation {
inherit name ;
src =
let path = ./../../../.. ;
in builtins . path { # We use builtins.path so that we can name the resulting derivation, otherwise the name would be taken from the checkout directory, which is outside of our control
inherit path ;
2019-07-15 16:34:33 +00:00
name = " s t a t u s - r e a c t - s o u r c e - ${ baseName } " ;
2019-06-04 16:50:29 +00:00
filter =
# Keep this filter as restrictive as possible in order to avoid unnecessary rebuilds and limit closure size
mkFilter {
2019-07-29 08:33:35 +00:00
dirRootsToInclude = [
2019-06-04 16:50:29 +00:00
" m o b i l e _ f i l e s "
2019-09-10 09:50:09 +00:00
" m o d u l e s / r e a c t - n a t i v e - s t a t u s / a n d r o i d "
2019-06-04 16:50:29 +00:00
" r e s o u r c e s "
] ;
dirsToExclude = [ " . g i t " " . s v n " " C V S " " . h g " " . g r a d l e " " b u i l d " " i n t e r m e d i a t e s " " l i b s " " o b j " ] ;
2019-09-10 09:50:09 +00:00
filesToInclude = [ envFileName " s t a t u s - g o - v e r s i o n . j s o n " " V E R S I O N " " r e a c t - n a t i v e . c o n f i g . j s " " . w a t c h m a n c o n f i g " ] ;
2019-06-04 16:50:29 +00:00
root = path ;
} ;
} ;
2019-09-10 09:50:09 +00:00
nativeBuildInputs = [ bash gradle unzip ] ++ lib . optionals stdenv . isDarwin [ file gnumake patchedWatchman ] ;
2019-06-04 16:50:29 +00:00
buildInputs = [ nodejs openjdk ] ;
2019-08-06 16:16:51 +00:00
phases = [ " u n p a c k P h a s e " " p a t c h P h a s e " " b u i l d P h a s e " " c h e c k P h a s e " " i n s t a l l P h a s e " ] ;
unpackPhase = ''
runHook preUnpack
cp - r $ src ./project
chmod u + w - R ./project
export sourceRoot = $ PWD/project
runHook postUnpack
'' ;
2019-06-04 16:50:29 +00:00
postUnpack = ''
mkdir - p $ { gradleHome }
$ { if keystore-file != " " then " c p - a - - n o - p r e s e r v e = o w n e r s h i p ${ keystore-file } ${ gradleHome } / ; e x p o r t S T A T U S _ R E L E A S E _ S T O R E _ F I L E = ${ gradleHome } / $ ( b a s e n a m e ${ keystore-file } ) " else " " }
# Ensure we have the right .env file
cp - f $ sourceRoot / $ { envFileName } $ sourceRoot/.env
# Copy index.*.js input file
2019-07-23 20:54:17 +00:00
cp - a - - no-preserve = ownership $ { jsbundle } /index * . js $ sourceRoot /
2019-06-04 16:50:29 +00:00
# Copy android/ directory
cp - a - - no-preserve = ownership $ { sourceProjectDir } /android / $ sourceRoot /
chmod u + w $ sourceRoot/android
chmod u + w $ sourceRoot/android/app
mkdir $ sourceRoot/android/build && chmod - R u + w $ sourceRoot/android/build
# Copy node_modules/ directory
cp - a - - no-preserve = ownership $ { sourceProjectDir } /node_modules / $ sourceRoot /
# Make android/build directories writable under node_modules
2019-09-03 10:51:53 +00:00
for d in ` find $ sourceRoot/node_modules - type f - name build . gradle | xargs dirname ` ; do
2019-06-04 16:50:29 +00:00
chmod - R u + w $ d
done
'' ;
patchPhase = ''
prevSet = $ -
set - e
2019-08-06 16:16:51 +00:00
substituteInPlace $ sourceRoot/android/gradlew \
2019-08-14 07:05:32 +00:00
- - replace \
' exec gradle' \
" e x e c g r a d l e - D m a v e n . r e p o . l o c a l = ' ${ localMavenRepo } ' - - o f f l i n e ${ gradle-opts } "
2019-06-04 16:50:29 +00:00
set $ prevSet
'' ;
buildPhase =
let
inherit ( lib ) catAttrs concatStrings concatStringsSep mapAttrsToList makeLibraryPath optionalString substring toUpper ;
# Take the env attribute set and build a couple of scripts
# (one to export the environment variables, and another to unset them)
exportEnvVars = concatStringsSep " ; " ( mapAttrsToList ( name : value : " e x p o r t ${ name } = ' ${ value } ' " ) env ) ;
unsetEnvVars = concatStringsSep " ; " ( mapAttrsToList ( name : value : " u n s e t ${ name } " ) env ) ;
adhocEnvVars = optionalString stdenv . isLinux " L D _ L I B R A R Y _ P A T H = $ L D _ L I B R A R Y _ P A T H : ${ makeLibraryPath [ zlib ] } " ;
capitalizedBuildType = toUpper ( substring 0 1 buildType' ) + substring 1 ( -1 ) buildType' ;
in ''
export STATUS_REACT_HOME = $ PWD
2019-08-06 16:16:51 +00:00
export HOME = $ sourceRoot
2019-06-04 16:50:29 +00:00
$ { exportEnvVars }
$ { if secrets-file != " " then " s o u r c e ${ secrets-file } " else " " }
$ { androidEnvShellHook }
$ { concatStrings ( catAttrs " s h e l l H o o k " [ mavenAndNpmDeps status-go ] ) }
2019-08-06 16:16:51 +00:00
pushd $ sourceRoot/android
2019-08-14 07:05:32 +00:00
$ { adhocEnvVars } ./gradlew - PversionCode = $ { build-number } assemble $ { capitalizedBuildType } || exit
2019-06-04 16:50:29 +00:00
popd > /dev/null
$ { unsetEnvVars }
'' ;
2019-08-06 16:16:51 +00:00
doCheck = true ;
checkPhase = ''
unzip - l $ { generatedApkPath } | grep ' assets/index.android.bundle '
'' ;
2019-06-04 16:50:29 +00:00
installPhase = ''
mkdir - p $ out
cp $ { generatedApkPath } $ out / $ { outApkName }
'' ;
}