Skip to content

Commit

Permalink
Publish (#5)
Browse files Browse the repository at this point in the history
* step interface revision + deploy option

* allow to force certain react native version after eject

* logging update

* install new node dependencies

* pr update

* pr fix
  • Loading branch information
godrei authored Oct 31, 2018
1 parent b3ca09b commit daaa787
Show file tree
Hide file tree
Showing 7 changed files with 459 additions and 30 deletions.
14 changes: 13 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 19 additions & 3 deletions bitrise.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ app:
envs:
- BITRISE_STEP_GIT_CLONE_URL: https://github.com/bitrise-steplib/steps-expo-detach.git

- ORIGIN_SOURCE_DIR: $BITRISE_SOURCE_DIR
- SAMPLE_APP_URL: https://github.com/bitrise-samples/react-native-expo.git

# Define it in .bitrise.secrets.yml
- USER_NAME: $USER_NAME
- PASSWORD: $PASSWORD

workflows:
test:
envs:
- ORIGIN_SOURCE_DIR: $BITRISE_SOURCE_DIR
- SAMPLE_APP_URL: https://github.com/bitrise-samples/react-native-expo.git
before_run:
- audit-this-step
steps:
Expand Down Expand Up @@ -45,6 +45,7 @@ workflows:
inputs:
- project_path: $BITRISE_SOURCE_DIR
- expo_cli_verson: "latest"
- override_react_native_version: 0.55.4

plain_2_0_0:
before_run:
Expand Down Expand Up @@ -130,6 +131,21 @@ workflows:
- path: ${ORIGIN_SOURCE_DIR}/_tmp
- is_create_path: true

dep-update:
title: Dep update
description: |
Used for updating bitrise dependencies with dep
steps:
- script:
title: Dependency update
inputs:
- content: |-
#!/bin/bash
set -ex
go get -u -v github.com/golang/dep/cmd/dep
dep ensure -v
dep ensure -v -update
# ----------------------------------------------------------------
# --- workflows to Share this step into a Step Library
audit-this-step:
Expand Down
132 changes: 116 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
package main

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/bitrise-io/go-utils/command"
"github.com/bitrise-io/go-utils/errorutil"
"github.com/bitrise-io/go-utils/fileutil"
"github.com/bitrise-io/go-utils/log"
"github.com/bitrise-io/go-utils/pathutil"
"github.com/bitrise-tools/go-steputils/stepconf"
"github.com/bitrise-tools/xcode-project/serialized"
)

// Config ...
type Config struct {
ProjectPath string `env:"project_path,dir"`
ExpoCLIVersion string `env:"expo_cli_verson,required"`
UserName string `env:"user_name"`
Password stepconf.Secret `env:"password"`
Workdir string `env:"project_path,dir"`
ExpoCLIVersion string `env:"expo_cli_verson,required"`
UserName string `env:"user_name"`
Password stepconf.Secret `env:"password"`
RunPublish string `env:"run_publish"`
OverrideReactNativeVersion string `env:"override_react_native_version"`
}

// EjectMethod if the project is using Expo SDK and you choose the "plain" --eject-method those imports will stop working.
Expand All @@ -28,14 +35,11 @@ const (
ExpoKit EjectMethod = "expoKit"
)

func (m EjectMethod) String() string {
return string(m)
}

// Expo CLI
type Expo struct {
Version string
Method EjectMethod
Workdir string
}

// installExpoCLI runs the install npm command to install the expo-cli
Expand All @@ -51,7 +55,7 @@ func (e Expo) installExpoCLI() error {
cmd.SetStdout(os.Stdout)
cmd.SetStderr(os.Stderr)

log.Printf("$ " + cmd.PrintableCommandArgs())
log.Donef("$ " + cmd.PrintableCommandArgs())
return cmd.Run()
}

Expand Down Expand Up @@ -82,20 +86,56 @@ func (e Expo) logout() error {

// Eject command creates Xcode and Android Studio projects for your app.
func (e Expo) eject() error {
args := []string{"eject", "--non-interactive", "--eject-method", e.Method.String()}
args := []string{"eject", "--non-interactive", "--eject-method", string(e.Method)}

cmd := command.New("expo", args...)
cmd.SetStdout(os.Stdout)
cmd.SetStderr(os.Stderr)
if e.Workdir != "" {
cmd.SetDir(e.Workdir)
}

log.Printf("$ " + cmd.PrintableCommandArgs())
log.Donef("$ " + cmd.PrintableCommandArgs())
return cmd.Run()
}

func failf(format string, v ...interface{}) {
log.Errorf(format, v...)
log.Warnf("For more details you can enable the debug logs by turning on the verbose step input.")
os.Exit(1)
func (e Expo) publish() error {
args := []string{"publish", "--non-interactive"}

cmd := command.New("expo", args...)
cmd.SetStdout(os.Stdout)
cmd.SetStderr(os.Stderr)
if e.Workdir != "" {
cmd.SetDir(e.Workdir)
}

log.Donef("$ " + cmd.PrintableCommandArgs())
return cmd.Run()
}

func parsePackageJSON(pth string) (serialized.Object, error) {
b, err := fileutil.ReadBytesFromFile(pth)
if err != nil {
return nil, fmt.Errorf("Failed to read package.json file: %s", err)
}

var packages serialized.Object
if err := json.Unmarshal(b, &packages); err != nil {
return nil, fmt.Errorf("Failed to parse package.json file: %s", err)
}
return packages, nil
}

func savePackageJSON(packages serialized.Object, pth string) error {
b, err := json.MarshalIndent(packages, "", " ")
if err != nil {
return fmt.Errorf("Failed to serialize modified package.json file: %s", err)
}

if err := fileutil.WriteBytesToFile(pth, b); err != nil {
return fmt.Errorf("Failed to write modified package.json file: %s", err)
}
return nil
}

func validateUserNameAndpassword(userName string, password stepconf.Secret) error {
Expand All @@ -109,6 +149,11 @@ func validateUserNameAndpassword(userName string, password stepconf.Secret) erro
return nil
}

func failf(format string, v ...interface{}) {
log.Errorf(format, v...)
os.Exit(1)
}

func main() {
var cfg Config
if err := stepconf.Parse(&cfg); err != nil {
Expand Down Expand Up @@ -139,6 +184,7 @@ func main() {
e := Expo{
Version: cfg.ExpoCLIVersion,
Method: ejectMethod,
Workdir: cfg.Workdir,
}

//
Expand Down Expand Up @@ -190,11 +236,65 @@ func main() {
log.Infof("Eject project")
{
if err := e.eject(); err != nil {
failf("Failed to eject project (%s), error: %s", filepath.Base(cfg.ProjectPath), err)
failf("Failed to eject project: %s", err)
}

}

fmt.Println()
log.Donef("Successfully ejected your project")

if cfg.RunPublish == "yes" {
fmt.Println()
log.Infof("Running expo publish")

if err := e.publish(); err != nil {
failf("Failed to publish project: %s", err)
}
}

if cfg.OverrideReactNativeVersion != "" {
//
// Force certain version of React Native in package.json file
fmt.Println()
log.Infof("Set react-native dependency version: %s", cfg.OverrideReactNativeVersion)

packageJSONPth := filepath.Join(cfg.Workdir, "package.json")
packages, err := parsePackageJSON(packageJSONPth)
if err != nil {
failf(err.Error())
}

deps, err := packages.Object("dependencies")
if err != nil {
failf("Failed to parse dependencies from package.json file: %s", err)
}

deps["react-native"] = cfg.OverrideReactNativeVersion
packages["dependencies"] = deps

if err := savePackageJSON(packages, packageJSONPth); err != nil {
failf(err.Error())
}

//
// Install new node dependencies
log.Printf("install new node dependencies")

nodeDepManager := "npm"
if exist, err := pathutil.IsPathExists(filepath.Join(cfg.Workdir, "yarn.lock")); err != nil {
log.Warnf("Failed to check if yarn.lock file exists in the workdir: %s", err)
} else if exist {
nodeDepManager = "yarn"
}

cmd := command.New(nodeDepManager, "install")
out, err := cmd.RunAndReturnTrimmedCombinedOutput()
if err != nil {
if errorutil.IsExitStatusError(err) {
failf("%s failed: %s", cmd.PrintableCommandArgs(), out)
}
failf("%s failed: %s", cmd.PrintableCommandArgs(), err)
}
}
}
52 changes: 42 additions & 10 deletions step.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,21 @@ toolkit:
inputs:
- project_path: $BITRISE_SOURCE_DIR
opts:
title: Project path
summary: Project path
title: Working directory
summary: The root directory of the React Native project
description: |-
The path of your project directory
is_required: true
The root directory of the React Native project (the directory of the project package.js file).
- expo_cli_verson: "latest"
opts:
title: Expo CLI version
summary: Specify the Expo CLI version to install.
description: |-
Specify the Expo CLI version to install.
Specify the Expo CLI version to install.
The Expo CLI ejects your project and creates Xcode and Android Studio projects for your app.
[https://docs.expo.io/versions/latest/introduction/installation#local-development-tool-expo-cli](https://docs.expo.io/versions/latest/introduction/installation#local-development-tool-expo-cli)
A couple of examples:
* "2.0.0"
* latest
Expand All @@ -52,12 +48,48 @@ inputs:
description: |-
Your account's username for `https://expo.io/` .
In case of React Native project __using Expo Kit__ library (any .js file imports expo),
the `user_name` and `password` inputs are __required__.
If you provide these inputs the step will run: `expo eject --eject-method expoKit`,
otherwise: `expo eject --eject-method plain`.
**NOTE** You need to use your username and not your e-mail address.
**NOTE:** You need to use your username and not your e-mail address.
- password: ""
opts:
title: Password for your Expo account
summary: Password for your Expo account.
description: |-
Your password for `https://expo.io/` .
is_sensitive: true
In case of React Native project __using Expo Kit__ library (any .js file imports expo),
the `user_name` and `password` inputs are __required__.
If you provide these inputs the step will run: `expo eject --eject-method expoKit`,
otherwise: `expo eject --eject-method plain`.
is_sensitive: true
- run_publish: "no"
opts:
title: Run expo publish after eject?
summary: Should the step run `expo publish` after eject?
description: |-
Should the step run `expo publish` after eject?
In case of React Native project using Expo Kit library (any .js file imports expo),
`expo publis` command generates the:
- ./android/app/src/main/assets/shell-app-manifest.json
- ./android/app/src/main/assets/shell-app.bundle
- ./ios/bitriseexpokit/Supporting/shell-app-manifest.json
- ./ios/bitriseexpokit/Supporting/shell-app.bundle
files, which are required for the native builds.
value_options:
- "yes"
- "no"
- override_react_native_version:
opts:
title: React Native version to set in package.json
summary: React Native version to set in package.json after the eject process.
description: |-
React Native version to set in package.json after the eject process.
Loading

0 comments on commit daaa787

Please sign in to comment.