diff --git a/_tests/integration/manual_config_test.go b/_tests/integration/manual_config_test.go index 856154f2..6e465ba7 100644 --- a/_tests/integration/manual_config_test.go +++ b/_tests/integration/manual_config_test.go @@ -291,14 +291,9 @@ var customConfigVersions = []interface{}{ models.FormatVersion, steps.ActivateSSHKeyVersion, steps.GitCloneVersion, - steps.ScriptVersion, steps.YarnVersion, - steps.ScriptVersion, - steps.ExpoDetachVersion, - steps.InstallMissingAndroidToolsVersion, - steps.AndroidBuildVersion, - steps.CertificateAndProfileInstallerVersion, - steps.XcodeArchiveVersion, + steps.YarnVersion, + steps.RunEASBuildVersion, steps.DeployToBitriseIoVersion, // default-react-native-expo-config/primary @@ -493,9 +488,10 @@ var customConfigResultYML = fmt.Sprintf(`options: none: config: default-macos-config react-native: - title: Was your React Native app created with the Expo CLI and using Managed Workflow? - summary: Will include *Expo Eject** Step if using Expo Managed Workflow (https://docs.expo.io/introduction/managed-vs-bare/). - If ios/android native projects are present in the repository, choose No. + title: Is this an [Expo](https://expo.dev)-based React Native project? + summary: |- + Default deploy workflow runs builds on Expo Application Services (EAS) for Expo-based React Native projects. + Otherwise native iOS and Android build steps will be used. type: selector value_map: "no": @@ -560,240 +556,11 @@ var customConfigResultYML = fmt.Sprintf(`options: enterprise: config: default-react-native-config "yes": - title: The iOS project path generated by running 'expo eject' locally - summary: |- - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. - Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. See https://docs.expo.io/bare/customizing/ for more details. - For example: './ios/myproject.xcworkspace'. - env_key: BITRISE_PROJECT_PATH + title: Expo project directory + summary: Path of the directory containing the project's `+"`package.json`"+` and + app configuration file (`+"`app.json`"+`, `+"`app.config.js`"+`, `+"`app.config.ts`"+`). + env_key: WORKDIR type: user_input - value_map: - "": - title: iOS bundle identifier - summary: |- - Optional, only needs to be entered if the key expo/ios/bundleIdentifier is not set in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so the IPA can be exported. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_IOS_BUNLDE_ID - type: user_input - value_map: - "": - title: The iOS native project scheme name - summary: |- - An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute. You can change the scheme at any time. - - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. - Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. - env_key: BITRISE_SCHEME - type: user_input - value_map: - "": - title: Distribution method - summary: The export method used to create an .ipa file in your - builds, stored as an Environment Variable. You can change this - at any time, or even create several .ipa files with different - export methods in the same build. - env_key: BITRISE_DISTRIBUTION_METHOD - type: selector - value_map: - ad-hoc: - title: Android package name - summary: |- - Optional, only needs to be entered if the key expo/android/package is not set in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input_optional - value_map: - "": - title: Project root directory - summary: The directory of the 'app.json' or 'package.json' - file of your React Native project. - env_key: WORKDIR - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, - stored as an Environment Variable. In your Workflows, - you can specify paths relative to this path. You - can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your - Android project's source code, resource files, - and app level settings, such as the module-level - build file and Android manifest file. Each module - can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds - at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can - add variants at any time, as well as further - configure your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: default-react-native-expo-config - app-store: - title: Android package name - summary: |- - Optional, only needs to be entered if the key expo/android/package is not set in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input_optional - value_map: - "": - title: Project root directory - summary: The directory of the 'app.json' or 'package.json' - file of your React Native project. - env_key: WORKDIR - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, - stored as an Environment Variable. In your Workflows, - you can specify paths relative to this path. You - can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your - Android project's source code, resource files, - and app level settings, such as the module-level - build file and Android manifest file. Each module - can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds - at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can - add variants at any time, as well as further - configure your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: default-react-native-expo-config - development: - title: Android package name - summary: |- - Optional, only needs to be entered if the key expo/android/package is not set in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input_optional - value_map: - "": - title: Project root directory - summary: The directory of the 'app.json' or 'package.json' - file of your React Native project. - env_key: WORKDIR - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, - stored as an Environment Variable. In your Workflows, - you can specify paths relative to this path. You - can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your - Android project's source code, resource files, - and app level settings, such as the module-level - build file and Android manifest file. Each module - can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds - at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can - add variants at any time, as well as further - configure your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: default-react-native-expo-config - enterprise: - title: Android package name - summary: |- - Optional, only needs to be entered if the key expo/android/package is not set in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input_optional - value_map: - "": - title: Project root directory - summary: The directory of the 'app.json' or 'package.json' - file of your React Native project. - env_key: WORKDIR - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, - stored as an Environment Variable. In your Workflows, - you can specify paths relative to this path. You - can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your - Android project's source code, resource files, - and app level settings, such as the module-level - build file and Android manifest file. Each module - can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds - at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can - add variants at any time, as well as further - configure your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: default-react-native-expo-config configs: android: default-android-config: | @@ -880,8 +647,8 @@ configs: - certificate-and-profile-installer@%s: {} - npm@%s: inputs: - - command: install - workdir: $CORDOVA_WORK_DIR + - command: install - generate-cordova-build-configuration@%s: {} - cordova-archive@%s: inputs: @@ -1289,8 +1056,8 @@ configs: - certificate-and-profile-installer@%s: {} - npm@%s: inputs: - - command: install - workdir: $IONIC_WORK_DIR + - command: install - generate-cordova-build-configuration@%s: {} - ionic-archive@%s: inputs: @@ -1495,50 +1262,26 @@ configs: workflows: deploy: description: | - Tests, builds and deploys the app. + Tests the app and runs a build on Expo Application Services (EAS). Next steps: + - Configure the `+"`Run Expo Application Services (EAS) build`"+` Step's `+"`Access Token`"+` input. - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). + - For an alternative deploy workflow checkout the [(React Native) Expo: Build using Turtle CLI recipe](https://github.com/bitrise-io/workflow-recipes/blob/main/recipes/rn-expo-turtle-build.md). steps: - - activate-ssh-key@%s: - run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' + - activate-ssh-key@%s: {} - git-clone@%s: {} - - script@%s: - title: Do anything with Script step - yarn@%s: inputs: - workdir: $WORKDIR - command: install - - script@%s: - title: Set bundleIdentifier, packageName for Expo Eject - inputs: - - content: |- - #!/usr/bin/env bash - set -ex - - appJson="app.json" - tmp="/tmp/app.json" - jq '.expo.android |= if has("package") or env.EXPO_BARE_ANDROID_PACKAGE == "" or env.EXPO_BARE_ANDROID_PACKAGE == null then . else .package = env.EXPO_BARE_ANDROID_PACKAGE end | - .expo.ios |= if has("bundleIdentifier") or env.EXPO_BARE_IOS_BUNLDE_ID == "" or env.EXPO_BARE_IOS_BUNLDE_ID == null then . else .bundleIdentifier = env.EXPO_BARE_IOS_BUNLDE_ID end' <${appJson} >${tmp} - [[ $?==0 ]] && mv -f ${tmp} ${appJson} - - expo-detach@%s: - inputs: - - project_path: $WORKDIR - - install-missing-android-tools@%s: - inputs: - - gradlew_path: $PROJECT_LOCATION/gradlew - - android-build@%s: + - yarn@%s: inputs: - - project_location: $PROJECT_LOCATION - - module: $MODULE - - variant: $VARIANT - - certificate-and-profile-installer@%s: {} - - xcode-archive@%s: + - workdir: $WORKDIR + - command: test + - run-eas-build@%s: inputs: - - project_path: $BITRISE_PROJECT_PATH - - scheme: $BITRISE_SCHEME - - distribution_method: $BITRISE_DISTRIBUTION_METHOD - - configuration: Release + - work_dir: $WORKDIR - deploy-to-bitrise-io@%s: {} primary: description: | diff --git a/_tests/integration/reactnative_expo_test.go b/_tests/integration/reactnative_expo_test.go index ad85f108..6e6d09e7 100644 --- a/_tests/integration/reactnative_expo_test.go +++ b/_tests/integration/reactnative_expo_test.go @@ -33,7 +33,7 @@ func TestReactNativeExpo(t *testing.T) { result, err := fileutil.ReadStringFromFile(scanResultPth) require.NoError(t, err) - validateConfigExpectation(t, "Managed Expo Workflow, no tests", strings.TrimSpace(managedExpoResultsYML), strings.TrimSpace(result)) + validateConfigExpectation(t, "Managed Expo Workflow, no tests", strings.TrimSpace(managedWorkflowNoTestsResultsYML), strings.TrimSpace(result)) } t.Log("Managed workflow with tests") @@ -52,7 +52,7 @@ func TestReactNativeExpo(t *testing.T) { result, err := fileutil.ReadStringFromFile(scanResultPth) require.NoError(t, err) - validateConfigExpectation(t, "Managed Expo Workflow with tests", strings.TrimSpace(managedExpo2ResultsYML), strings.TrimSpace(result)) + validateConfigExpectation(t, "Managed Expo Workflow with tests", strings.TrimSpace(managedWorkflowResultsYML), strings.TrimSpace(result)) } t.Log("Bare workflow") @@ -70,240 +70,27 @@ func TestReactNativeExpo(t *testing.T) { result, err := fileutil.ReadStringFromFile(scanResultPth) require.NoError(t, err) - validateConfigExpectation(t, "Bare Expo Workflow", strings.TrimSpace(sampleAppsExpoBareResultYML), strings.TrimSpace(result)) + validateConfigExpectation(t, "Bare Expo Workflow", strings.TrimSpace(bareWorkflowResultYML), strings.TrimSpace(result)) } } var managedExpoVersions = []interface{}{ models.FormatVersion, - + // deploy + steps.ActivateSSHKeyVersion, + steps.GitCloneVersion, + steps.YarnVersion, + steps.RunEASBuildVersion, + steps.DeployToBitriseIoVersion, + // primary steps.ActivateSSHKeyVersion, steps.GitCloneVersion, - steps.ScriptVersion, steps.YarnVersion, - steps.ScriptVersion, - steps.ExpoDetachVersion, - steps.InstallMissingAndroidToolsVersion, - steps.AndroidBuildVersion, - steps.CertificateAndProfileInstallerVersion, - steps.XcodeArchiveVersion, steps.DeployToBitriseIoVersion, } -var managedExpoResultsYML = fmt.Sprintf(`options: - react-native: - title: iOS bundle identifier - summary: |- - Key expo/ios/bundleIdentifier not present in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so the IPA can be exported. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_IOS_BUNLDE_ID - type: user_input - value_map: - "": - title: The iOS project path generated by running 'expo eject' locally - summary: |- - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. - Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. See https://docs.expo.io/bare/customizing/ for more details. - For example: './ios/myproject.xcworkspace'. - env_key: BITRISE_PROJECT_PATH - type: selector_optional - value_map: - ios/exposample.xcworkspace: - title: Scheme name - summary: An Xcode scheme defines a collection of targets to build, a configuration - to use when building, and a collection of tests to execute. Only shared - schemes are detected automatically but you can use any scheme as a target - on Bitrise. You can change the scheme at any time in your Env Vars. - env_key: BITRISE_SCHEME - type: selector_optional - value_map: - exposample: - title: iOS Development team ID - summary: |- - The Apple Development Team that the iOS version of the app belongs to. Will be used to override code signing settings. See https://devcenter.bitrise.io/getting-started/getting-started-with-expo-apps/#signing-and-exporting-your-ios-app-for-deployment for more details. - - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. - Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. - For example: '1MZX23ABCD4'. - env_key: BITRISE_IOS_DEVELOPMENT_TEAM - type: user_input - value_map: - "": - title: Distribution method - summary: The export method used to create an .ipa file in your - builds, stored as an Environment Variable. You can change this - at any time, or even create several .ipa files with different - export methods in the same build. - env_key: BITRISE_DISTRIBUTION_METHOD - type: selector - value_map: - ad-hoc: - title: Android package name - summary: |- - Key expo/android/package not present in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, stored - as an Environment Variable. In your Workflows, you can - specify paths relative to this path. You can change - this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android - project's source code, resource files, and app level - settings, such as the module-level build file and - Android manifest file. Each module can be independently - built, tested, and debugged. You can add new modules - to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add - variants at any time, as well as further configure - your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config - app-store: - title: Android package name - summary: |- - Key expo/android/package not present in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, stored - as an Environment Variable. In your Workflows, you can - specify paths relative to this path. You can change - this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android - project's source code, resource files, and app level - settings, such as the module-level build file and - Android manifest file. Each module can be independently - built, tested, and debugged. You can add new modules - to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add - variants at any time, as well as further configure - your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config - development: - title: Android package name - summary: |- - Key expo/android/package not present in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, stored - as an Environment Variable. In your Workflows, you can - specify paths relative to this path. You can change - this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android - project's source code, resource files, and app level - settings, such as the module-level build file and - Android manifest file. Each module can be independently - built, tested, and debugged. You can add new modules - to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add - variants at any time, as well as further configure - your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config - enterprise: - title: Android package name - summary: |- - Key expo/android/package not present in 'app.json'. - - Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. - For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. - For example: 'com.sample.myapp'. - env_key: EXPO_BARE_ANDROID_PACKAGE - type: user_input - value_map: - "": - title: The root directory of an Android project - summary: The root directory of your Android project, stored - as an Environment Variable. In your Workflows, you can - specify paths relative to this path. You can change - this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android - project's source code, resource files, and app level - settings, such as the module-level build file and - Android manifest file. Each module can be independently - built, tested, and debugged. You can add new modules - to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add - variants at any time, as well as further configure - your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config +var managedWorkflowNoTestsResultsYML = fmt.Sprintf(`options: + react-native: {} configs: react-native: react-native-expo-config: | @@ -318,52 +105,19 @@ configs: workflows: deploy: description: | - Tests, builds and deploys the app. + Runs a build on Expo Application Services (EAS). Next steps: + - Configure the `+"`Run Expo Application Services (EAS) build`"+` Step's `+"`Access Token`"+` input. - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). + - For an alternative deploy workflow checkout the [(React Native) Expo: Build using Turtle CLI recipe](https://github.com/bitrise-io/workflow-recipes/blob/main/recipes/rn-expo-turtle-build.md). steps: - - activate-ssh-key@%s: - run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' + - activate-ssh-key@%s: {} - git-clone@%s: {} - - script@%s: - title: Do anything with Script step - yarn@%s: inputs: - command: install - - script@%s: - title: Set bundleIdentifier, packageName for Expo Eject - inputs: - - content: |- - #!/usr/bin/env bash - set -ex - - appJson="app.json" - tmp="/tmp/app.json" - jq '.expo.android |= if has("package") or env.EXPO_BARE_ANDROID_PACKAGE == "" or env.EXPO_BARE_ANDROID_PACKAGE == null then . else .package = env.EXPO_BARE_ANDROID_PACKAGE end | - .expo.ios |= if has("bundleIdentifier") or env.EXPO_BARE_IOS_BUNLDE_ID == "" or env.EXPO_BARE_IOS_BUNLDE_ID == null then . else .bundleIdentifier = env.EXPO_BARE_IOS_BUNLDE_ID end' <${appJson} >${tmp} - [[ $?==0 ]] && mv -f ${tmp} ${appJson} - - expo-detach@%s: - inputs: - - project_path: ./ - - install-missing-android-tools@%s: - inputs: - - gradlew_path: $PROJECT_LOCATION/gradlew - - android-build@%s: - inputs: - - project_location: $PROJECT_LOCATION - - module: $MODULE - - variant: $VARIANT - - certificate-and-profile-installer@%s: {} - - xcode-archive@%s: - inputs: - - project_path: $BITRISE_PROJECT_PATH - - scheme: $BITRISE_SCHEME - - configuration: Release - - distribution_method: $BITRISE_DISTRIBUTION_METHOD - - xcconfig_content: |- - COMPILER_INDEX_STORE_ENABLE = NO - DEVELOPMENT_TEAM = $BITRISE_IOS_DEVELOPMENT_TEAM + - run-eas-build@%s: {} - deploy-to-bitrise-io@%s: {} primary: description: | @@ -373,12 +127,12 @@ configs: - Add tests to your project and configure the workflow to run them. - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). steps: - - activate-ssh-key@4: {} - - git-clone@6: {} - - yarn@0: + - activate-ssh-key@%s: {} + - git-clone@%s: {} + - yarn@%s: inputs: - command: install - - deploy-to-bitrise-io@2: {} + - deploy-to-bitrise-io@%s: {} warnings: react-native: [] warnings_with_recommendations: @@ -390,14 +144,9 @@ var managedExpo2Versions = []interface{}{ // deploy steps.ActivateSSHKeyVersion, steps.GitCloneVersion, - steps.ScriptVersion, steps.YarnVersion, steps.YarnVersion, - steps.ExpoDetachVersion, - steps.InstallMissingAndroidToolsVersion, - steps.AndroidBuildVersion, - steps.CertificateAndProfileInstallerVersion, - steps.XcodeArchiveVersion, + steps.RunEASBuildVersion, steps.DeployToBitriseIoVersion, // primary steps.ActivateSSHKeyVersion, @@ -407,157 +156,8 @@ var managedExpo2Versions = []interface{}{ steps.DeployToBitriseIoVersion, } -var managedExpo2ResultsYML = fmt.Sprintf(`options: - react-native: - title: The iOS project path generated by running 'expo eject' locally - summary: |- - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. - Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. See https://docs.expo.io/bare/customizing/ for more details. - For example: './ios/myproject.xcworkspace'. - env_key: BITRISE_PROJECT_PATH - type: selector_optional - value_map: - ios/todomvc.xcworkspace: - title: Scheme name - summary: An Xcode scheme defines a collection of targets to build, a configuration - to use when building, and a collection of tests to execute. Only shared - schemes are detected automatically but you can use any scheme as a target - on Bitrise. You can change the scheme at any time in your Env Vars. - env_key: BITRISE_SCHEME - type: selector_optional - value_map: - todomvc: - title: iOS Development team ID - summary: |- - The Apple Development Team that the iOS version of the app belongs to. Will be used to override code signing settings. See https://devcenter.bitrise.io/getting-started/getting-started-with-expo-apps/#signing-and-exporting-your-ios-app-for-deployment for more details. - - Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. - Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. - For example: '1MZX23ABCD4'. - env_key: BITRISE_IOS_DEVELOPMENT_TEAM - type: user_input - value_map: - "": - title: Distribution method - summary: The export method used to create an .ipa file in your builds, - stored as an Environment Variable. You can change this at any time, - or even create several .ipa files with different export methods - in the same build. - env_key: BITRISE_DISTRIBUTION_METHOD - type: selector - value_map: - ad-hoc: - title: The root directory of an Android project - summary: The root directory of your Android project, stored as - an Environment Variable. In your Workflows, you can specify - paths relative to this path. You can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android project's - source code, resource files, and app level settings, such - as the module-level build file and Android manifest file. - Each module can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add variants - at any time, as well as further configure your existing - variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config - app-store: - title: The root directory of an Android project - summary: The root directory of your Android project, stored as - an Environment Variable. In your Workflows, you can specify - paths relative to this path. You can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android project's - source code, resource files, and app level settings, such - as the module-level build file and Android manifest file. - Each module can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add variants - at any time, as well as further configure your existing - variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config - development: - title: The root directory of an Android project - summary: The root directory of your Android project, stored as - an Environment Variable. In your Workflows, you can specify - paths relative to this path. You can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android project's - source code, resource files, and app level settings, such - as the module-level build file and Android manifest file. - Each module can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add variants - at any time, as well as further configure your existing - variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config - enterprise: - title: The root directory of an Android project - summary: The root directory of your Android project, stored as - an Environment Variable. In your Workflows, you can specify - paths relative to this path. You can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - ./android: - title: Module - summary: Modules provide a container for your Android project's - source code, resource files, and app level settings, such - as the module-level build file and Android manifest file. - Each module can be independently built, tested, and debugged. - You can add new modules to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add variants - at any time, as well as further configure your existing - variants later. - env_key: VARIANT - type: user_input_optional - value_map: - Release: - config: react-native-expo-config +var managedWorkflowResultsYML = fmt.Sprintf(`options: + react-native: {} configs: react-native: react-native-expo-config: | @@ -572,43 +172,22 @@ configs: workflows: deploy: description: | - Tests, builds and deploys the app. + Tests the app and runs a build on Expo Application Services (EAS). Next steps: + - Configure the `+"`Run Expo Application Services (EAS) build`"+` Step's `+"`Access Token`"+` input. - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). + - For an alternative deploy workflow checkout the [(React Native) Expo: Build using Turtle CLI recipe](https://github.com/bitrise-io/workflow-recipes/blob/main/recipes/rn-expo-turtle-build.md). steps: - - activate-ssh-key@%s: - run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' + - activate-ssh-key@%s: {} - git-clone@%s: {} - - script@%s: - title: Do anything with Script step - yarn@%s: inputs: - command: install - yarn@%s: inputs: - command: test - - expo-detach@%s: - inputs: - - project_path: ./ - - install-missing-android-tools@%s: - inputs: - - gradlew_path: $PROJECT_LOCATION/gradlew - - android-build@%s: - inputs: - - project_location: $PROJECT_LOCATION - - module: $MODULE - - variant: $VARIANT - - certificate-and-profile-installer@%s: {} - - xcode-archive@%s: - inputs: - - project_path: $BITRISE_PROJECT_PATH - - scheme: $BITRISE_SCHEME - - configuration: Release - - distribution_method: $BITRISE_DISTRIBUTION_METHOD - - xcconfig_content: |- - COMPILER_INDEX_STORE_ENABLE = NO - DEVELOPMENT_TEAM = $BITRISE_IOS_DEVELOPMENT_TEAM + - run-eas-build@%s: {} - deploy-to-bitrise-io@%s: {} primary: description: | @@ -635,16 +214,14 @@ warnings_with_recommendations: // Bare workflow is the same as react-native with native projects var sampleAppsExpoBareVersions = []interface{}{ models.FormatVersion, - + // deploy steps.ActivateSSHKeyVersion, steps.GitCloneVersion, steps.YarnVersion, steps.YarnVersion, - steps.InstallMissingAndroidToolsVersion, - steps.AndroidBuildVersion, - steps.XcodeArchiveVersion, + steps.RunEASBuildVersion, steps.DeployToBitriseIoVersion, - + // primary steps.ActivateSSHKeyVersion, steps.GitCloneVersion, steps.YarnVersion, @@ -652,69 +229,11 @@ var sampleAppsExpoBareVersions = []interface{}{ steps.DeployToBitriseIoVersion, } -var sampleAppsExpoBareResultYML = fmt.Sprintf(`options: - react-native: - title: The root directory of an Android project - summary: The root directory of your Android project, stored as an Environment - Variable. In your Workflows, you can specify paths relative to this path. You - can change this at any time. - env_key: PROJECT_LOCATION - type: selector - value_map: - android: - title: Module - summary: Modules provide a container for your Android project's source code, - resource files, and app level settings, such as the module-level build file - and Android manifest file. Each module can be independently built, tested, - and debugged. You can add new modules to your Bitrise builds at any time. - env_key: MODULE - type: user_input - value_map: - app: - title: Variant - summary: Your Android build variant. You can add variants at any time, - as well as further configure your existing variants later. - env_key: VARIANT - type: user_input_optional - value_map: - "": - title: Project or Workspace path - summary: The location of your Xcode project or Xcode workspace files, - stored as an Environment Variable. In your Workflows, you can specify - paths relative to this path. - env_key: BITRISE_PROJECT_PATH - type: selector - value_map: - ios/ExpoSample.xcworkspace: - title: Scheme name - summary: An Xcode scheme defines a collection of targets to build, - a configuration to use when building, and a collection of tests - to execute. Only shared schemes are detected automatically but - you can use any scheme as a target on Bitrise. You can change - the scheme at any time in your Env Vars. - env_key: BITRISE_SCHEME - type: selector - value_map: - ExpoSample: - title: Distribution method - summary: The export method used to create an .ipa file in - your builds, stored as an Environment Variable. You can - change this at any time, or even create several .ipa files - with different export methods in the same build. - env_key: BITRISE_DISTRIBUTION_METHOD - type: selector - value_map: - ad-hoc: - config: react-native-android-ios-test-config - app-store: - config: react-native-android-ios-test-config - development: - config: react-native-android-ios-test-config - enterprise: - config: react-native-android-ios-test-config +var bareWorkflowResultYML = fmt.Sprintf(`options: + react-native: {} configs: react-native: - react-native-android-ios-test-config: | + react-native-expo-config: | format_version: "%s" default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git project_type: react-native @@ -726,11 +245,12 @@ configs: workflows: deploy: description: | - Tests, builds and deploys the app using *Deploy to bitrise.io* Step. + Tests the app and runs a build on Expo Application Services (EAS). Next steps: - - Set up an [Apple service with API key](https://devcenter.bitrise.io/en/accounts/connecting-to-services/connecting-to-an-apple-service-with-api-key.html). - - Check out [Getting started with React Native apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-react-native-apps.html). + - Configure the `+"`Run Expo Application Services (EAS) build`"+` Step's `+"`Access Token`"+` input. + - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). + - For an alternative deploy workflow checkout the [(React Native) Expo: Build using Turtle CLI recipe](https://github.com/bitrise-io/workflow-recipes/blob/main/recipes/rn-expo-turtle-build.md). steps: - activate-ssh-key@%s: {} - git-clone@%s: {} @@ -740,27 +260,14 @@ configs: - yarn@%s: inputs: - command: test - - install-missing-android-tools@%s: - inputs: - - gradlew_path: $PROJECT_LOCATION/gradlew - - android-build@%s: - inputs: - - project_location: $PROJECT_LOCATION - - cocoapods-install@2: {} - - xcode-archive@%s: - inputs: - - project_path: $BITRISE_PROJECT_PATH - - scheme: $BITRISE_SCHEME - - distribution_method: $BITRISE_DISTRIBUTION_METHOD - - configuration: Release - - automatic_code_signing: api-key + - run-eas-build@%s: {} - deploy-to-bitrise-io@%s: {} primary: description: | Runs tests. Next steps: - - Check out [Getting started with React Native apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-react-native-apps.html). + - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). steps: - activate-ssh-key@%s: {} - git-clone@%s: {} diff --git a/scanners/cordova/cordova.go b/scanners/cordova/cordova.go index 845bfe18..3546ac7c 100644 --- a/scanners/cordova/cordova.go +++ b/scanners/cordova/cordova.go @@ -5,16 +5,16 @@ import ( "path/filepath" "strings" - yaml "gopkg.in/yaml.v2" + envmanModels "github.com/bitrise-io/envman/models" "github.com/bitrise-io/bitrise-init/models" "github.com/bitrise-io/bitrise-init/scanners/android" "github.com/bitrise-io/bitrise-init/scanners/ios" "github.com/bitrise-io/bitrise-init/steps" "github.com/bitrise-io/bitrise-init/utility" - envmanModels "github.com/bitrise-io/envman/models" "github.com/bitrise-io/go-utils/log" "github.com/bitrise-io/go-utils/pathutil" + "gopkg.in/yaml.v2" ) // ScannerName ... @@ -287,12 +287,14 @@ func (scanner *Scanner) Configs(_ bool) (models.BitriseConfigMap, error) { configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultPrepareStepList(false)...) workdirEnvList := []envmanModels.EnvironmentItemModel{} + workdir := "" if scanner.relCordovaConfigDir != "" { - workdirEnvList = append(workdirEnvList, envmanModels.EnvironmentItemModel{workDirInputKey: "$" + workDirInputEnvKey}) + workdir = "$" + workDirInputEnvKey + workdirEnvList = append(workdirEnvList, envmanModels.EnvironmentItemModel{workDirInputKey: workdir}) } if scanner.hasJasmineTest || scanner.hasKarmaJasmineTest { - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem("install", workdir)) // CI if scanner.hasKarmaJasmineTest { @@ -306,7 +308,7 @@ func (scanner *Scanner) Configs(_ bool) (models.BitriseConfigMap, error) { configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultPrepareStepList(false)...) configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.NpmStepListItem("install", workdir)) if scanner.hasKarmaJasmineTest { configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.KarmaJasmineTestRunnerStepListItem(workdirEnvList...)) @@ -342,7 +344,7 @@ func (scanner *Scanner) Configs(_ bool) (models.BitriseConfigMap, error) { } configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem("install", workdir)) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.GenerateCordovaBuildConfigStepListItem()) @@ -378,9 +380,7 @@ func (*Scanner) DefaultConfigs() (models.BitriseConfigMap, error) { configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem( - envmanModels.EnvironmentItemModel{"command": "install"}, - envmanModels.EnvironmentItemModel{workDirInputKey: "$" + workDirInputEnvKey})) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem("install", "$"+workDirInputEnvKey)) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.GenerateCordovaBuildConfigStepListItem()) diff --git a/scanners/ionic/ionic.go b/scanners/ionic/ionic.go index 3dbe5b70..da9726ea 100644 --- a/scanners/ionic/ionic.go +++ b/scanners/ionic/ionic.go @@ -281,12 +281,14 @@ func (scanner *Scanner) Configs(_ bool) (models.BitriseConfigMap, error) { configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultPrepareStepList(false)...) workdirEnvList := []envmanModels.EnvironmentItemModel{} + workdir := "" if scanner.relCordovaConfigDir != "" { - workdirEnvList = append(workdirEnvList, envmanModels.EnvironmentItemModel{workDirInputKey: "$" + workDirInputEnvKey}) + workdir = "$" + workDirInputEnvKey + workdirEnvList = append(workdirEnvList, envmanModels.EnvironmentItemModel{workDirInputKey: workdir}) } if scanner.hasJasmineTest || scanner.hasKarmaJasmineTest { - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem("install", workdir)) // CI if scanner.hasKarmaJasmineTest { @@ -300,7 +302,7 @@ func (scanner *Scanner) Configs(_ bool) (models.BitriseConfigMap, error) { configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultPrepareStepList(false)...) configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.NpmStepListItem("install", workdir)) if scanner.hasKarmaJasmineTest { configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.KarmaJasmineTestRunnerStepListItem(workdirEnvList...)) @@ -336,7 +338,7 @@ func (scanner *Scanner) Configs(_ bool) (models.BitriseConfigMap, error) { } configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem("install", workdir)) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.GenerateCordovaBuildConfigStepListItem()) @@ -372,9 +374,7 @@ func (Scanner) DefaultConfigs() (models.BitriseConfigMap, error) { configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem( - envmanModels.EnvironmentItemModel{"command": "install"}, - envmanModels.EnvironmentItemModel{workDirInputKey: "$" + workDirInputEnvKey})) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.NpmStepListItem("install", "$"+workDirInputEnvKey)) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.GenerateCordovaBuildConfigStepListItem()) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.IonicArchiveStepListItem( diff --git a/scanners/reactnative/const.go b/scanners/reactnative/const.go index e7b705cf..2c3475f5 100644 --- a/scanners/reactnative/const.go +++ b/scanners/reactnative/const.go @@ -20,19 +20,32 @@ Next steps: - Add tests to your project and configure the workflow to run them. - Check out [Getting started with React Native apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-react-native-apps.html). ` - deployExpoWorkflowDescription = `Tests, builds and deploys the app. +) + +const ( + expoDeployWorkflowDescription = `Tests the app and runs a build on Expo Application Services (EAS). + +Next steps: +- Configure the ` + "`Run Expo Application Services (EAS) build`" + ` Step's ` + "`Access Token`" + ` input. +- Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). +- For an alternative deploy workflow checkout the [(React Native) Expo: Build using Turtle CLI recipe](https://github.com/bitrise-io/workflow-recipes/blob/main/recipes/rn-expo-turtle-build.md). +` + + expoDeployWorkflowNoTestsDescription = `Runs a build on Expo Application Services (EAS). Next steps: +- Configure the ` + "`Run Expo Application Services (EAS) build`" + ` Step's ` + "`Access Token`" + ` input. - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). +- For an alternative deploy workflow checkout the [(React Native) Expo: Build using Turtle CLI recipe](https://github.com/bitrise-io/workflow-recipes/blob/main/recipes/rn-expo-turtle-build.md). ` - primaryExpoWorkflowDescription = `Runs tests. + expoPrimaryWorkflowDescription = `Runs tests. Next steps: - Check out [Getting started with Expo apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-expo-apps.html). ` - primaryExpoWorkflowNoTestsDescription = `Installs dependencies. + expoPrimaryWorkflowNoTestsDescription = `Installs dependencies. Next steps: - Add tests to your project and configure the workflow to run them. diff --git a/scanners/reactnative/expo.go b/scanners/reactnative/expo.go index 803059ae..468ca993 100644 --- a/scanners/reactnative/expo.go +++ b/scanners/reactnative/expo.go @@ -3,17 +3,11 @@ package reactnative import ( "fmt" "path/filepath" - "regexp" - "strings" "github.com/bitrise-io/bitrise-init/models" - "github.com/bitrise-io/bitrise-init/scanners/android" - "github.com/bitrise-io/bitrise-init/scanners/ios" "github.com/bitrise-io/bitrise-init/steps" "github.com/bitrise-io/bitrise-init/utility" - envmanModels "github.com/bitrise-io/envman/models" "github.com/bitrise-io/go-utils/log" - "github.com/pkg/errors" "gopkg.in/yaml.v2" ) @@ -23,189 +17,15 @@ const ( ) const ( - bareIOSProjectPathInputTitle = "The iOS project path generated by running 'expo eject' locally" - bareIOSprojectPathInputSummary = `Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. -Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. See https://docs.expo.io/bare/customizing/ for more details. -For example: './ios/myproject.xcworkspace'.` -) - -const ( - iosBundleIDInputTitle = "iOS bundle identifier" - iosBundleIDInputSummary = `Key expo/ios/bundleIdentifier not present in 'app.json'. - -Will add the Expo Eject Step to the Workflow to generate the native iOS project, so the IPA can be exported. -For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. -For example: 'com.sample.myapp'.` - iosBundleIDInputSummaryDefault = `Optional, only needs to be entered if the key expo/ios/bundleIdentifier is not set in 'app.json'. - -Will add the Expo Eject Step to the Workflow to generate the native iOS project, so the IPA can be exported. -For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. -For example: 'com.sample.myapp'.` - iosBundleIDEnvKey = "EXPO_BARE_IOS_BUNLDE_ID" -) - -const ( - androidPackageInputTitle = "Android package name" - androidPackageInputSummary = `Key expo/android/package not present in 'app.json'. - -Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. -For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. -For example: 'com.sample.myapp'.` - androidPackageInputSummaryDefault = `Optional, only needs to be entered if the key expo/android/package is not set in 'app.json'. - -Will add the Expo Eject Step to the Workflow to generate the native Android project, so the bundle (AAB) can be built. -For your convenience, define it here temporarily. To set this value permanently run 'expo eject' in a local environment and commit 'app.json' changes. -For example: 'com.sample.myapp'.` - androidPackageEnvKey = "EXPO_BARE_ANDROID_PACKAGE" -) - -const ( - iosDevelopmentTeamInputTitle = "iOS Development team ID" - iosDevelopmentTeamInputSummary = `The Apple Development Team that the iOS version of the app belongs to. Will be used to override code signing settings. See https://devcenter.bitrise.io/getting-started/getting-started-with-expo-apps/#signing-and-exporting-your-ios-app-for-deployment for more details. - -Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. -Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories. -For example: '1MZX23ABCD4'.` - iosDevelopmentTeamEnv = "BITRISE_IOS_DEVELOPMENT_TEAM" -) - -const ( - projectRootDirInputTitle = "Project root directory" - projectRootDirInputSummary = "The directory of the 'app.json' or 'package.json' file of your React Native project." -) - -const ( - schemeInputTitle = "The iOS native project scheme name" - schemeInputSummary = `An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute. You can change the scheme at any time. - -Will add the Expo Eject Step to the Workflow to generate the native iOS project, so it can be built and archived. -Run 'expo eject' in a local environment to determine this value. This experiment then can be undone by deleting the ios and android directories.` + expoProjectDirInputTitle = "Expo project directory" + expoProjectDirInputSummary = "Path of the directory containing the project's `package.json` and app configuration file (`app.json`, `app.config.js`, `app.config.ts`)." ) const wordirEnv = "WORKDIR" -const ( - expoBareAddIdentiferScriptTitle = "Set bundleIdentifier, packageName for Expo Eject" - expoAppJSONName = "app.json" -) - -func expoBareAddIdentifiersScript(appJSONPath, androidEnvKey, iosEnvKey string) string { - return fmt.Sprintf(`#!/usr/bin/env bash -set -ex - -appJson="%s" -tmp="/tmp/app.json" -jq '.expo.android |= if has("package") or env.`+androidEnvKey+` == "" or env.`+androidEnvKey+` == null then . else .package = env.`+androidEnvKey+` end | -.expo.ios |= if has("bundleIdentifier") or env.`+iosEnvKey+` == "" or env.`+iosEnvKey+` == null then . else .bundleIdentifier = env.`+iosEnvKey+` end' <${appJson} >${tmp} -[[ $?==0 ]] && mv -f ${tmp} ${appJson}`, appJSONPath) -} - // expoOptions implements ScannerInterface.Options function for Expo based React Native projects. func (scanner *Scanner) expoOptions() (models.OptionNode, models.Warnings, error) { - warnings := models.Warnings{} - if scanner.expoSettings == nil { - return models.OptionNode{}, warnings, errors.New("can not generate expo Options, expoSettings is nil") - } - if !scanner.expoSettings.isAndroid && !scanner.expoSettings.isIOS { - return models.OptionNode{}, warnings, errors.New("can not generate expo Option, neither iOS or Android platform detected") - } - - log.TPrintf("Project name: %v", scanner.expoSettings.name) - var iosNode *models.OptionNode - var distributionMethodOption *models.OptionNode - if scanner.expoSettings.isIOS { // ios options - schemeOption := models.NewOption(ios.SchemeInputTitle, ios.SchemeInputSummary, ios.SchemeInputEnvKey, models.TypeOptionalSelector) - - // predict the ejected project name - projectName := strings.ToLower(regexp.MustCompile(`(?i:[^a-z0-9])`).ReplaceAllString(scanner.expoSettings.name, "")) - projectPathOption := models.NewOption(bareIOSProjectPathInputTitle, bareIOSprojectPathInputSummary, ios.ProjectPathInputEnvKey, models.TypeOptionalSelector) - if projectName != "" { - projectPathOption.AddOption(filepath.Join("./", "ios", projectName+".xcworkspace"), schemeOption) - } else { - projectPathOption.AddOption("", schemeOption) - } - - if scanner.expoSettings.bundleIdentifierIOS == "" { // bundle ID Option - iosNode = models.NewOption(iosBundleIDInputTitle, iosBundleIDInputSummary, iosBundleIDEnvKey, models.TypeUserInput) - iosNode.AddOption("", projectPathOption) - } else { - iosNode = projectPathOption - } - - developmentTeamOption := models.NewOption(iosDevelopmentTeamInputTitle, iosDevelopmentTeamInputSummary, iosDevelopmentTeamEnv, models.TypeUserInput) - schemeOption.AddOption(projectName, developmentTeamOption) - - distributionMethodOption = models.NewOption(ios.DistributionMethodInputTitle, ios.DistributionMethodInputSummary, ios.DistributionMethodEnvKey, models.TypeSelector) - developmentTeamOption.AddOption("", distributionMethodOption) - } - - var androidNode *models.OptionNode - var buildVariantOption *models.OptionNode - if scanner.expoSettings.isAndroid { // android options - packageJSONDir := filepath.Dir(scanner.packageJSONPth) - relPackageJSONDir, err := utility.RelPath(scanner.searchDir, packageJSONDir) - if err != nil { - return models.OptionNode{}, warnings, fmt.Errorf("Failed to get relative package.json dir path, error: %s", err) - } - if relPackageJSONDir == "." { - // package.json placed in the search dir, no need to change-dir in the workflows - relPackageJSONDir = "" - } - - var projectSettingNode *models.OptionNode - var moduleOption *models.OptionNode - if relPackageJSONDir == "" { - projectSettingNode = models.NewOption(android.ProjectLocationInputTitle, android.ProjectLocationInputSummary, android.ProjectLocationInputEnvKey, models.TypeSelector) - - moduleOption = models.NewOption(android.ModuleInputTitle, android.ModuleInputSummary, android.ModuleInputEnvKey, models.TypeUserInput) - projectSettingNode.AddOption("./android", moduleOption) - } else { - projectSettingNode = models.NewOption(projectRootDirInputTitle, projectRootDirInputSummary, wordirEnv, models.TypeSelector) - - projectLocationOption := models.NewOption(android.ProjectLocationInputTitle, android.ProjectLocationInputSummary, android.ProjectLocationInputEnvKey, models.TypeSelector) - projectSettingNode.AddOption(relPackageJSONDir, projectLocationOption) - - moduleOption = models.NewOption(android.ModuleInputTitle, android.ModuleInputSummary, android.ModuleInputEnvKey, models.TypeUserInput) - projectLocationOption.AddOption(filepath.Join(relPackageJSONDir, "android"), moduleOption) - } - - if scanner.expoSettings.packageNameAndroid == "" { - androidNode = models.NewOption(androidPackageInputTitle, androidPackageInputSummary, androidPackageEnvKey, models.TypeUserInput) - androidNode.AddOption("", projectSettingNode) - } else { - androidNode = projectSettingNode - } - - buildVariantOption = models.NewOption(android.VariantInputTitle, android.VariantInputSummary, android.VariantInputEnvKey, models.TypeOptionalUserInput) - moduleOption.AddOption("app", buildVariantOption) - } - - rootNode := iosNode - if iosNode != nil { - if androidNode != nil { - for _, exportMethod := range ios.IosExportMethods { - distributionMethodOption.AddOption(exportMethod, androidNode) - } - } - } else { - rootNode = androidNode - } - - for _, lastOption := range rootNode.LastChilds() { - lastOption.ChildOptionMap = map[string]*models.OptionNode{} - if androidNode != nil { - // Android buildVariantOption is last - lastOption.AddConfig("Release", models.NewConfigOption(expoConfigName, nil)) - continue - } - - // iOS distributionMethodOption is last - for _, exportMethod := range ios.IosExportMethods { - lastOption.AddConfig(exportMethod, models.NewConfigOption(expoConfigName, nil)) - } - } - - return *rootNode, warnings, nil + return models.OptionNode{}, models.Warnings{}, nil } // expoConfigs implements ScannerInterface.Configs function for Expo based React Native projects. @@ -224,28 +44,13 @@ func (scanner *Scanner) expoConfigs(isPrivateRepo bool) (models.BitriseConfigMap } log.TPrintf("Working directory: %v", relPackageJSONDir) - xcodeArchiveStepListItem := steps.XcodeArchiveStepListItem( - envmanModels.EnvironmentItemModel{ios.ProjectPathInputKey: "$" + ios.ProjectPathInputEnvKey}, - envmanModels.EnvironmentItemModel{ios.SchemeInputKey: "$" + ios.SchemeInputEnvKey}, - envmanModels.EnvironmentItemModel{ios.ConfigurationInputKey: "Release"}, - envmanModels.EnvironmentItemModel{ios.DistributionMethodInputKey: "$" + ios.DistributionMethodEnvKey}, - // In case of Expo projects, you do not have the native project in your - // repository. During the build, we ask Expo to generate it (using the - // ExpoDetachStepListItem). The generated native project does not have - // codesigning set up (No valid development team selected). Because of this, we - // ask for the desired development team during the Add New App process and force - // the user-provided Development Team ID using the DEVELOPMENT_TEAM build setting. - envmanModels.EnvironmentItemModel{ios.XCConfigContentInputKey: "COMPILER_INDEX_STORE_ENABLE = NO\n" + - "DEVELOPMENT_TEAM = $BITRISE_IOS_DEVELOPMENT_TEAM"}, - ) - // primary workflow - configBuilder := models.NewDefaultConfigBuilder() - primaryDescription := primaryExpoWorkflowNoTestsDescription - if scanner.hasTest { - primaryDescription = primaryExpoWorkflowDescription + primaryDescription := expoPrimaryWorkflowDescription + if !scanner.hasTest { + primaryDescription = expoPrimaryWorkflowNoTestsDescription } + configBuilder := models.NewDefaultConfigBuilder() configBuilder.SetWorkflowDescriptionTo(models.PrimaryWorkflowID, primaryDescription) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultPrepareStepListV2(steps.PrepareListParams{ ShouldIncludeCache: false, @@ -256,41 +61,21 @@ func (scanner *Scanner) expoConfigs(isPrivateRepo bool) (models.BitriseConfigMap configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultDeployStepListV2(false)...) // deploy workflow - configBuilder.SetWorkflowDescriptionTo(models.DeployWorkflowID, deployExpoWorkflowDescription) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultPrepareStepList(false)...) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, scanner.getTestSteps(relPackageJSONDir)...) - - projectDir := relPackageJSONDir - if relPackageJSONDir == "" { - projectDir = "./" - } - - if !scanner.expoSettings.isAllIdentifierPresent() { - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.ScriptSteplistItem(expoBareAddIdentiferScriptTitle, - envmanModels.EnvironmentItemModel{"content": expoBareAddIdentifiersScript(filepath.Join(projectDir, expoAppJSONName), androidPackageEnvKey, iosBundleIDEnvKey)}, - )) + deployDescription := expoDeployWorkflowDescription + if !scanner.hasTest { + deployDescription = expoDeployWorkflowNoTestsDescription } - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.ExpoDetachStepListItem( - envmanModels.EnvironmentItemModel{"project_path": projectDir}, - )) - - // android build - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.InstallMissingAndroidToolsStepListItem( - envmanModels.EnvironmentItemModel{android.GradlewPathInputKey: "$" + android.ProjectLocationInputEnvKey + "/gradlew"}, - )) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.AndroidBuildStepListItem( - envmanModels.EnvironmentItemModel{android.ProjectLocationInputKey: "$" + android.ProjectLocationInputEnvKey}, - envmanModels.EnvironmentItemModel{android.ModuleInputKey: "$" + android.ModuleInputEnvKey}, - envmanModels.EnvironmentItemModel{android.VariantInputKey: "$" + android.VariantInputEnvKey}, - )) - - // ios build - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, xcodeArchiveStepListItem) - + configBuilder.SetWorkflowDescriptionTo(models.DeployWorkflowID, deployDescription) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultPrepareStepListV2(steps.PrepareListParams{ + ShouldIncludeCache: false, + ShouldIncludeActivateSSH: isPrivateRepo, + })...) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, scanner.getTestSteps(relPackageJSONDir)...) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.RunEASBuildStepListItem(relPackageJSONDir)) configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultDeployStepList(false)...) + // generate bitrise.yml bitriseDataModel, err := configBuilder.Generate(scannerName) if err != nil { return models.BitriseConfigMap{}, err @@ -308,95 +93,37 @@ func (scanner *Scanner) expoConfigs(isPrivateRepo bool) (models.BitriseConfigMap // expoDefaultOptions implements ScannerInterface.DefaultOptions function for Expo based React Native projects. func (Scanner) expoDefaultOptions() models.OptionNode { - // ios options - rootNode := models.NewOption(bareIOSProjectPathInputTitle, bareIOSprojectPathInputSummary, ios.ProjectPathInputEnvKey, models.TypeUserInput) - - bundleIDOption := models.NewOption(iosBundleIDInputTitle, iosBundleIDInputSummaryDefault, iosBundleIDEnvKey, models.TypeUserInput) - rootNode.AddOption("", bundleIDOption) - - schemeOption := models.NewOption(schemeInputTitle, schemeInputSummary, ios.SchemeInputEnvKey, models.TypeUserInput) - bundleIDOption.AddOption("", schemeOption) - - distributionMethodOption := models.NewOption(ios.DistributionMethodInputTitle, ios.DistributionMethodInputSummary, ios.DistributionMethodEnvKey, models.TypeSelector) - schemeOption.AddOption("", distributionMethodOption) - - // android options - androidPackageOption := models.NewOption(androidPackageInputTitle, androidPackageInputSummaryDefault, androidPackageEnvKey, models.TypeOptionalUserInput) - for _, exportMethod := range ios.IosExportMethods { - distributionMethodOption.AddOption(exportMethod, androidPackageOption) - } - - workDirOption := models.NewOption(projectRootDirInputTitle, projectRootDirInputSummary, wordirEnv, models.TypeUserInput) - androidPackageOption.AddOption("", workDirOption) - - projectLocationOption := models.NewOption(android.ProjectLocationInputTitle, android.ProjectLocationInputSummary, android.ProjectLocationInputEnvKey, models.TypeSelector) - workDirOption.AddOption("", projectLocationOption) - - moduleOption := models.NewOption(android.ModuleInputTitle, android.ModuleInputSummary, android.ModuleInputEnvKey, models.TypeUserInput) - projectLocationOption.AddOption("./android", moduleOption) - - buildVariantOption := models.NewOption(android.VariantInputTitle, android.VariantInputSummary, android.VariantInputEnvKey, models.TypeOptionalUserInput) - moduleOption.AddOption("app", buildVariantOption) - - for _, lastOption := range rootNode.LastChilds() { - lastOption.ChildOptionMap = map[string]*models.OptionNode{} - // buildVariantOption is the last Option added - lastOption.AddConfig("Release", models.NewConfigOption(expoDefaultConfigName, nil)) - } - - return *rootNode + // TODO: update options with Expo wording + workDirOption := models.NewOption(expoProjectDirInputTitle, expoProjectDirInputSummary, wordirEnv, models.TypeUserInput) + return *workDirOption } // expoDefaultConfigs implements ScannerInterface.DefaultConfigs function for Expo based React Native projects. -func (Scanner) expoDefaultConfigs() (models.BitriseConfigMap, error) { +func (scanner Scanner) expoDefaultConfigs() (models.BitriseConfigMap, error) { + // TODO: should we ask if test, if yarn, which platform to deploy? configMap := models.BitriseConfigMap{} // primary workflow configBuilder := models.NewDefaultConfigBuilder() - - configBuilder.SetWorkflowDescriptionTo(models.PrimaryWorkflowID, primaryExpoWorkflowDescription) + configBuilder.SetWorkflowDescriptionTo(models.PrimaryWorkflowID, expoPrimaryWorkflowDescription) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultPrepareStepListV2(steps.PrepareListParams{ ShouldIncludeCache: false, ShouldIncludeActivateSSH: true, })...) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{workDirInputKey: "$WORKDIR"}, envmanModels.EnvironmentItemModel{"command": "install"})) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{workDirInputKey: "$WORKDIR"}, envmanModels.EnvironmentItemModel{"command": "test"})) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, getTestSteps("$WORKDIR", true, true)...) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultDeployStepListV2(false)...) // deploy workflow - configBuilder.SetWorkflowDescriptionTo(models.DeployWorkflowID, deployExpoWorkflowDescription) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultPrepareStepList(false)...) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{workDirInputKey: "$WORKDIR"}, envmanModels.EnvironmentItemModel{"command": "install"})) - - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.ScriptSteplistItem(expoBareAddIdentiferScriptTitle, - envmanModels.EnvironmentItemModel{"content": expoBareAddIdentifiersScript(filepath.Join(".", expoAppJSONName), androidPackageEnvKey, iosBundleIDEnvKey)}, - )) - - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.ExpoDetachStepListItem( - envmanModels.EnvironmentItemModel{"project_path": "$WORKDIR"}, - )) - - // android build - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.InstallMissingAndroidToolsStepListItem( - envmanModels.EnvironmentItemModel{android.GradlewPathInputKey: "$" + android.ProjectLocationInputEnvKey + "/gradlew"}, - )) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.AndroidBuildStepListItem( - envmanModels.EnvironmentItemModel{android.ProjectLocationInputKey: "$" + android.ProjectLocationInputEnvKey}, - envmanModels.EnvironmentItemModel{android.ModuleInputKey: "$" + android.ModuleInputEnvKey}, - envmanModels.EnvironmentItemModel{android.VariantInputKey: "$" + android.VariantInputEnvKey}, - )) - - // ios build - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.CertificateAndProfileInstallerStepListItem()) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.XcodeArchiveStepListItem( - envmanModels.EnvironmentItemModel{ios.ProjectPathInputKey: "$" + ios.ProjectPathInputEnvKey}, - envmanModels.EnvironmentItemModel{ios.SchemeInputKey: "$" + ios.SchemeInputEnvKey}, - envmanModels.EnvironmentItemModel{ios.DistributionMethodInputKey: "$" + ios.DistributionMethodEnvKey}, - envmanModels.EnvironmentItemModel{ios.ConfigurationInputKey: "Release"}, - )) - + configBuilder.SetWorkflowDescriptionTo(models.DeployWorkflowID, expoDeployWorkflowDescription) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultPrepareStepListV2(steps.PrepareListParams{ + ShouldIncludeCache: false, + ShouldIncludeActivateSSH: true, + })...) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, getTestSteps("$WORKDIR", true, true)...) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.RunEASBuildStepListItem("$WORKDIR")) configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.DefaultDeployStepList(false)...) + // generate bitrise.yml bitriseDataModel, err := configBuilder.Generate(scannerName) if err != nil { return models.BitriseConfigMap{}, err diff --git a/scanners/reactnative/plain.go b/scanners/reactnative/plain.go index c7e46a08..ef602759 100644 --- a/scanners/reactnative/plain.go +++ b/scanners/reactnative/plain.go @@ -282,8 +282,7 @@ func (scanner *Scanner) defaultConfigs() (models.BitriseConfigMap, error) { ShouldIncludeActivateSSH: true, })...) // Assuming project uses yarn and has tests - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{"command": "install"})) - configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{"command": "test"})) + configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, getTestSteps("", true, true)...) configBuilder.AppendStepListItemsTo(models.PrimaryWorkflowID, steps.DefaultDeployStepListV2(false)...) // deploy @@ -292,8 +291,7 @@ func (scanner *Scanner) defaultConfigs() (models.BitriseConfigMap, error) { ShouldIncludeCache: false, ShouldIncludeActivateSSH: true, })...) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{"command": "install"})) - configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, steps.YarnStepListItem(envmanModels.EnvironmentItemModel{"command": "test"})) + configBuilder.AppendStepListItemsTo(models.DeployWorkflowID, getTestSteps("", true, true)...) // android projectLocationEnv := "$" + android.ProjectLocationInputEnvKey @@ -334,27 +332,24 @@ func (scanner *Scanner) defaultConfigs() (models.BitriseConfigMap, error) { return configMap, nil } -func (scanner *Scanner) getTestSteps(workDir string) []bitriseModels.StepListItemModel { - var ( - testSteps = []bitriseModels.StepListItemModel{} - workdirEnvList = []envmanModels.EnvironmentItemModel{} - ) - - if workDir != "" { - workdirEnvList = append(workdirEnvList, envmanModels.EnvironmentItemModel{workDirInputKey: workDir}) - } +func getTestSteps(workDir string, hasYarnLockFile, hasTest bool) []bitriseModels.StepListItemModel { + var testSteps []bitriseModels.StepListItemModel - if scanner.hasYarnLockFile { - testSteps = append(testSteps, steps.YarnStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) - if scanner.hasTest { - testSteps = append(testSteps, steps.YarnStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "test"})...)) + if hasYarnLockFile { + testSteps = append(testSteps, steps.YarnStepListItem("install", workDir)) + if hasTest { + testSteps = append(testSteps, steps.YarnStepListItem("test", workDir)) } } else { - testSteps = append(testSteps, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "install"})...)) - if scanner.hasTest { - testSteps = append(testSteps, steps.NpmStepListItem(append(workdirEnvList, envmanModels.EnvironmentItemModel{"command": "test"})...)) + testSteps = append(testSteps, steps.NpmStepListItem("install", workDir)) + if hasTest { + testSteps = append(testSteps, steps.NpmStepListItem("test", workDir)) } } return testSteps } + +func (scanner *Scanner) getTestSteps(workDir string) []bitriseModels.StepListItemModel { + return getTestSteps(workDir, scanner.hasYarnLockFile, scanner.hasTest) +} diff --git a/scanners/reactnative/reactnative.go b/scanners/reactnative/reactnative.go index 270388c0..166f39cd 100644 --- a/scanners/reactnative/reactnative.go +++ b/scanners/reactnative/reactnative.go @@ -1,7 +1,6 @@ package reactnative import ( - "encoding/json" "fmt" "path/filepath" @@ -9,10 +8,8 @@ import ( "github.com/bitrise-io/bitrise-init/scanners/android" "github.com/bitrise-io/bitrise-init/scanners/ios" "github.com/bitrise-io/bitrise-init/utility" - "github.com/bitrise-io/go-utils/fileutil" "github.com/bitrise-io/go-utils/log" "github.com/bitrise-io/go-utils/pathutil" - "github.com/bitrise-io/go-xcode/xcodeproject/serialized" ) const scannerName = "react-native" @@ -23,8 +20,8 @@ const ( ) const ( - isExpoCLIInputTitle = "Was your React Native app created with the Expo CLI and using Managed Workflow?" - isExpoCLIInputSummary = "Will include *Expo Eject** Step if using Expo Managed Workflow (https://docs.expo.io/introduction/managed-vs-bare/). If ios/android native projects are present in the repository, choose No." + isExpoBasedProjectInputTitle = "Is this an [Expo](https://expo.dev)-based React Native project?" + isExpoBasedProjectInputSummary = "Default deploy workflow runs builds on Expo Application Services (EAS) for Expo-based React Native projects.\nOtherwise native iOS and Android build steps will be used." ) // Scanner implements the project scanner for plain React Native and Expo based projects. @@ -37,7 +34,7 @@ type Scanner struct { hasYarnLockFile bool packageJSONPth string - expoSettings *expoSettings + isExpoBased bool } // NewScanner creates a new scanner instance. @@ -50,82 +47,29 @@ func (Scanner) Name() string { return scannerName } -type expoSettings struct { - name string - isIOS, isAndroid bool - bundleIdentifierIOS string - packageNameAndroid string -} - -func (settings *expoSettings) isAllIdentifierPresent() bool { - return !(settings.isAndroid && settings.packageNameAndroid == "" || - settings.isIOS && settings.bundleIdentifierIOS == "") -} - -// parseExpoProjectSettings reports whether a project is Expo based and it's settings, like targeted platforms -func parseExpoProjectSettings(packageJSONPth string) (*expoSettings, error) { +func isExpoBasedProject(packageJSONPth string) (bool, error) { packages, err := utility.ParsePackagesJSON(packageJSONPth) if err != nil { - return nil, fmt.Errorf("failed to parse package json file (%s): %s", packageJSONPth, err) + return false, fmt.Errorf("failed to parse package json file (%s): %s", packageJSONPth, err) } if _, found := packages.Dependencies["expo"]; !found { - return nil, nil - } - - // app.json file is a required part of an expo projects and should be placed next to the root package.json file - appJSONPth := filepath.Join(filepath.Dir(packageJSONPth), "app.json") - exist, err := pathutil.IsPathExists(appJSONPth) - if err != nil { - return nil, fmt.Errorf("failed to check if app.json file (%s) exist: %s", appJSONPth, err) - } - if !exist { - return nil, nil - } - - appJSON, err := fileutil.ReadStringFromFile(appJSONPth) - if err != nil { - return nil, err - } - var app serialized.Object - if err := json.Unmarshal([]byte(appJSON), &app); err != nil { - return nil, err + return false, nil } - expoObj, err := app.Object("expo") - if err != nil { - log.Warnf("%s", fmt.Errorf("app.json file (%s) has no 'expo' entry, not an Expo project", appJSONPth)) - return nil, nil - } - projectName, err := expoObj.String("name") - if err != nil || projectName == "" { - log.Debugf("%s", fmt.Errorf("app.json file (%s) has no 'expo/name' entry, can not guess iOS project path, will ask for it during project configuration", appJSONPth)) - } - iosObj, err := expoObj.Object("ios") - if err != nil { - log.TDebugf("%s", fmt.Errorf("app.json file (%s) has no no 'expo/ios entry', assuming iOS is targeted by Expo", appJSONPth)) - } - bundleID, err := iosObj.String("bundleIdentifier") - if err != nil || bundleID == "" { - log.TDebugf("%s", fmt.Errorf("app.json file (%s) has no no 'expo/ios/bundleIdentifier' entry, will ask for it during project configuration", appJSONPth)) - } - androidObj, err := expoObj.Object("android") - if err != nil { - log.TDebugf("%s", fmt.Errorf("app.json file (%s) has no 'expo/android' entry, assuming Android is targeted by Expo", appJSONPth)) - } - packageName, err := androidObj.String("package") - if err != nil || packageName == "" { - log.TDebugf("%s", fmt.Errorf("app.json file (%s) has no no 'expo/android/package' entry, will ask for it during project configuration", appJSONPth)) + expoAppConfigFiles := []string{"app.json", "app.config.js", "app.config.ts"} + for _, base := range expoAppConfigFiles { + expoAppConfigPth := filepath.Join(filepath.Dir(packageJSONPth), base) + exist, err := pathutil.IsPathExists(expoAppConfigPth) + if err != nil { + return false, fmt.Errorf("failed to check if Expo app config exists at: %s: %s", expoAppConfigPth, err) + } + if exist { + return true, nil + } } - // expo/ios and expo/android entry is optional - return &expoSettings{ - name: projectName, - isIOS: true, - isAndroid: true, - packageNameAndroid: packageName, - bundleIdentifierIOS: bundleID, - }, nil + return false, nil } // hasNativeProjects reports whether the project directory contains ios and android native project. @@ -176,21 +120,24 @@ func (scanner *Scanner) DetectPlatform(searchDir string) (bool, error) { log.TPrintf("%d package.json file detected", len(packageJSONPths)) log.TPrintf("Filter relevant package.json files") - var expoSettings *expoSettings + isExpoBased := false var packageFile string for _, packageJSONPth := range packageJSONPths { log.TPrintf("Checking: %s", packageJSONPth) - expoPrefs, err := parseExpoProjectSettings(packageJSONPth) + expoBased, err := isExpoBasedProject(packageJSONPth) if err != nil { - log.TWarnf("failed to check if project uses Expo: %s", err) + log.TWarnf("failed to determine if project is Expo based: %s", err) + } else if expoBased { + log.TPrintf("Project uses expo: %v", expoBased) + isExpoBased = true + packageFile = packageJSONPth + // TODO: This break drops other package.json files + break } - log.TPrintf("Project uses expo: %v", expoPrefs != nil) - if expoPrefs != nil { - log.TPrintf("Expo configuration: %+v", expoPrefs) - } + log.TPrintf("Project uses expo: %v", expoBased) if scanner.iosScanner == nil { scanner.iosScanner = ios.NewScanner() @@ -210,16 +157,8 @@ func (scanner *Scanner) DetectPlatform(searchDir string) (bool, error) { log.TPrintf("Found native android project: %v", android) } - if expoPrefs != nil { - if !(ios || android) { - expoSettings = expoPrefs - packageFile = packageJSONPth - break - } - log.TPrintf("Native ios/android project present, expo eject step will not be included.") - } - if ios || android { + // Treating the project as a plain React Native project packageFile = packageJSONPth break } @@ -229,7 +168,7 @@ func (scanner *Scanner) DetectPlatform(searchDir string) (bool, error) { return false, nil } - scanner.expoSettings = expoSettings + scanner.isExpoBased = isExpoBased scanner.packageJSONPth = packageFile // determine Js dependency manager @@ -253,7 +192,7 @@ func (scanner *Scanner) DetectPlatform(searchDir string) (bool, error) { // Options implements ScannerInterface.Options function. func (scanner *Scanner) Options() (options models.OptionNode, warnings models.Warnings, icons models.Icons, err error) { - if scanner.expoSettings != nil { + if scanner.isExpoBased { options, warnings, err = scanner.expoOptions() } else { options, warnings, err = scanner.options() @@ -264,7 +203,7 @@ func (scanner *Scanner) Options() (options models.OptionNode, warnings models.Wa // Configs implements ScannerInterface.Configs function. func (scanner *Scanner) Configs(isPrivateRepo bool) (models.BitriseConfigMap, error) { - if scanner.expoSettings != nil { + if scanner.isExpoBased { return scanner.expoConfigs(isPrivateRepo) } @@ -273,7 +212,7 @@ func (scanner *Scanner) Configs(isPrivateRepo bool) (models.BitriseConfigMap, er // DefaultOptions implements ScannerInterface.DefaultOptions function. func (scanner *Scanner) DefaultOptions() models.OptionNode { - expoOption := models.NewOption(isExpoCLIInputTitle, isExpoCLIInputSummary, "", models.TypeSelector) + expoOption := models.NewOption(isExpoBasedProjectInputTitle, isExpoBasedProjectInputSummary, "", models.TypeSelector) expoDefaultOptions := scanner.expoDefaultOptions() expoOption.AddOption("yes", &expoDefaultOptions) diff --git a/steps/const.go b/steps/const.go index 9f61e07a..7e10e96d 100644 --- a/steps/const.go +++ b/steps/const.go @@ -212,6 +212,13 @@ const ( ExpoDetachVersion = "1" ) +const ( + // RunEASBuildID ... + RunEASBuildID = "run-eas-build" + // RunEASBuildVersion ... + RunEASBuildVersion = "0" +) + const ( // YarnID ... YarnID = "yarn" diff --git a/steps/steps.go b/steps/steps.go index 7a6a3da1..6316f35f 100644 --- a/steps/steps.go +++ b/steps/steps.go @@ -264,19 +264,39 @@ func KarmaJasmineTestRunnerStepListItem(inputs ...envmanModels.EnvironmentItemMo } // NpmStepListItem ... -func NpmStepListItem(inputs ...envmanModels.EnvironmentItemModel) bitriseModels.StepListItemModel { +func NpmStepListItem(command, workdir string) bitriseModels.StepListItemModel { + var inputs []envmanModels.EnvironmentItemModel + if workdir != "" { + inputs = append(inputs, envmanModels.EnvironmentItemModel{"workdir": workdir}) + } + if command != "" { + inputs = append(inputs, envmanModels.EnvironmentItemModel{"command": command}) + } + stepIDComposite := stepIDComposite(NpmID, NpmVersion) return stepListItem(stepIDComposite, "", "", inputs...) } -// ExpoDetachStepListItem ... -func ExpoDetachStepListItem(inputs ...envmanModels.EnvironmentItemModel) bitriseModels.StepListItemModel { - stepIDComposite := stepIDComposite(ExpoDetachID, ExpoDetachVersion) +// RunEASBuildStepListItem ... +func RunEASBuildStepListItem(workdir string) bitriseModels.StepListItemModel { + var inputs []envmanModels.EnvironmentItemModel + if workdir != "" && workdir != "$BITRISE_SOURCE_DIR" { + inputs = append(inputs, envmanModels.EnvironmentItemModel{"work_dir": workdir}) + } + stepIDComposite := stepIDComposite(RunEASBuildID, RunEASBuildVersion) return stepListItem(stepIDComposite, "", "", inputs...) } // YarnStepListItem ... -func YarnStepListItem(inputs ...envmanModels.EnvironmentItemModel) bitriseModels.StepListItemModel { +func YarnStepListItem(command, workdir string) bitriseModels.StepListItemModel { + var inputs []envmanModels.EnvironmentItemModel + if workdir != "" { + inputs = append(inputs, envmanModels.EnvironmentItemModel{"workdir": workdir}) + } + if command != "" { + inputs = append(inputs, envmanModels.EnvironmentItemModel{"command": command}) + } + stepIDComposite := stepIDComposite(YarnID, YarnVersion) return stepListItem(stepIDComposite, "", "", inputs...) }