使用 Electrode OTA Server 建立 React Native/Angular Cordova 私有 Code Push 服务

一直用着 Microsoft 的 AppCenter.ms 服务都不错,功能强大,可是最近老是抽风,没办法,只能本身部署私有 Code Push Server了,若是直接搜索 Code Push Server,通常获得的结果都是 github.com/lisong/code… 这个,我安装过,不过并无实现去测试,由于发现它并无完美的实现 Code Push 的逻辑,在各类坛里面找了好几天以后,终于发现了 Electrode.io,Walmart Labs 的东西老是这么难发现, Hapijs 也是。java

什么是 Electrode ,你们能够直接上官方去了解,咱们只使用 Electrode OTA Server 功能,我自己就是一个长期的 HapiJS 用户,因此一看到这货,仍是很亲切的。node

安装运行环境

安装 Node

安装 nvm

nvm 是一个很不错的 Node 版本管理工具,使用下面任何一个命令安装便可,若是在安装过程当中有任何疑问,请直接自行解决 github.com/nvm-sh/nvmmysql

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
复制代码

或者react

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
复制代码

安装最新版本 Node

nvm install node
复制代码

安装 Docker

这个不是必须的,可是若是只是在本地测试的话,建议安装,Electrode OTA Server 默认使用的是 Apache Cassandra 数据库,有了 Docker 以后,数据库的问题更好解决,不然须要在本机安装个 Cassandra 也是很烦人的一件事情,固然,若是不使用 Cassandra 的话,也能够直接使用 MariaDB 数据,这个下面都会说,由于个人机器配置不高,因此,最终仍是选择了 MariaDB 数据库。linux

若是你已经安装了 Docker 了,那么直接跳过这一步,若是感受没有安装过,那么继续,使用下面的命令删除全部过往的 docker 版本。android

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
复制代码

安装安装 yum-utils 以提供 yum-config-manager 工具,同时,device-mapper-persistent-data 以及 lvm2devicemapper 所必须的库:nginx

sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
复制代码

使用下面的命令设置 stable 版本 dockergit

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
复制代码

使用下面命令安装 dockergithub

sudo yum install docker-ce docker-ce-cli containerd.io
复制代码

安装数据库

基于 docker 以后,咱们就直接安装 MariaDB 以及 Cassandra 数据库了。sql

安装 Cassandra

docker pull cassandra
复制代码

或者有一个加强版本的选择:

docker pull datastax/dse-server
复制代码

两个任选一个便可

docker run --name parcmg-cassandra -p 9042:9042 -d cassandra
docker container start parcmg-cassandra
复制代码

安装 MariaDB

docker pull mariadb
docker run --name parcmg-mariadb -p 3306:3306 -d mariadb
docker container start parcmg-mariadb
复制代码

如今咱们已经有了可用的数据库服务了,接下来,部署 Electrode OTA Server

建立 Github App

这一步就很少说了,直接在 Github 后台建立一个 App,拿到 ClientId 以及 ClientSecret 两个值,在下面会用。

部署 Electrode OTA Server

建立 parcmg-ota-server 项目

mkdir parcmg-ota-server
yarn init
yarn add electrode-ota-server electrode-ota-server-dao-mariadb
复制代码

添加 config/default.json 配置文件

在项目目录下面建立一个名为 config 的目录,在目录中,添加一个 default.json 的配置文件(这个是我最喜欢 HapiJS 的一点,全部东西都是配置优先。

{
  "connection": {
    "host": "localhost",
    "port": 9001,
    "compression": false
  },
  "server": {
    "app": {
      "electrode": true
    }
  },
  "plugins": {
    "electrode-ota-server-dao-plugin": {
      "module": "electrode-ota-server-dao-mariadb",
      "priority": 4,
      "options": {
        "keyspace": "parcmg_ota",
        "contactPoints": ["localhost"],
        "clusterConfig": {
          "canRetry": true,
          "defaultSelector": "ORDER",
          "removeNodeErrorCount": 5,
          "restoreNodeTimeout": 0
        },
        "poolConfigs": [
          {
            "host": "<%Database Host%>",
            "port": 3306,
            "dialect": "mysql",
            "database": "<%Database Name%>",
            "user": "<%Database Username%>",
            "password": "<%Database Password%>"
          }
        ]
      }
    },
    "electrode-ota-server-fileservice-upload": {
      "options": {
        "downloadUrl": "https://<%ota.domain.com%>/storagev2/"
      }
    },
    "electrode-ota-server-auth": {
      "options": {
        "strategy": {
          "github-oauth": {
            "options": {
              "password": "<%RandomKey%>",
              "isSecure": true,
              "location": "https://<%ota.domain.com%>",
              "clientId": "<%GithubClientId%>",
              "clientSecret": "<%GithubClientSecret%>"
            }
          },
          "session": {
            "options": {
              "password": "LYG2AqpUK3L4rKQERbuyJWxCqMYh5nlF",
              "isSecure": true
            }
          }
        }
      }
    }
  }
}
复制代码

而后给 package.json 添加下面两个 script

{
  "scripts": {
    "start": "NODE_ENV=production node node_modules/electrode-ota-server",
    "development": "NODE_ENV=development node node_modules/electrode-ota-server"
  }
}
复制代码

此时,能够直接使用 yarn development 或者 yarn start 运行了。

这里须要注意一点,若是使用 MariaDB,须要本身先创建好数据库以及数据表, schema 保存在 github.com/electrode-i… 这里面,一个一个建立便可。

安装 pm2

安装 pm2 工具

npm install -g pm2
复制代码

添加 ecosystem.config.js 文件

内容以下:

module.exports = {
  apps: [
    {
      name: "parcmg-ota",
      script: "node_modules/electrode-ota-server/index.js",
      env: {
        NODE_ENV: "production"
      }
    }
  ]
};
复制代码

package.json 中添加 serve 命令:

{
  "scripts": {
    "serve": "yarn install && pm2 startOrRestart ecosystem.config.js --env production",
    "start": "NODE_ENV=production node node_modules/electrode-ota-server",
    "development": "NODE_ENV=development node node_modules/electrode-ota-server"
  }
}
复制代码

启动服务

yarn serve
复制代码

或者

pm2 start ecosystem.config.js --env production
复制代码

配置域名

安装 nginx

vi /etc/yum.repos.d/nginx.repo
复制代码

内容以下:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
复制代码

而后执行下面命令安装:

yum install -y
复制代码

添加虚拟主机

/etc/nginx/conf.d 目录下新建一个虚拟主机配置文件:

vi /etc/nginx/conf.d/ota.domain.com.conf
复制代码

内容以下:

upstream parcmg_ota {
    server 127.0.0.1:9001; 
    keepalive 64;
}

server {
  listen               80;
  listen               [::]:80;
  server_name          ota.parcmg.com;
  return 301 https://$host$request_uri;
}

server {

  listen 443 ssl;
  
  ssl_certificate   cert.d/YOUR_PEM.com.pem;
  ssl_certificate_key  cert.d/YOUR_KEY.com.key;
  ssl_session_timeout 5m;
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;

  server_name ota.parcmg.com;

  charset utf-8;

  # Global restrictions configuration file.
  # Designed to be included in any server {} block.
  location = /favicon.ico {
    log_not_found off;
    access_log off;
  }

  location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
  }

  # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
  # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
  location ~ /\. {
    deny all;
  }

  location / {
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      #
      # Custom headers and headers various browsers *should* be OK with but aren't
      #
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      #
      # Tell client that this pre-flight info is valid for 20 days
      #
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Content-Length' 0;
      return 204;
    }
    if ($request_method = 'POST') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
    }
    if ($request_method = 'GET') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
    }

      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Nginx-Proxy true;
      proxy_set_header Connection "";
      proxy_pass http://parcmg_ota; 
  }
}
复制代码

启动 nginx

systemctl start nginx
systemctl enable nginx
复制代码

若是没有 SSL 证书,能够上 Aliyun 或者 QCloud 上面去申请免费的,固然,也能够直接使用 http 协议。

Electrode OTA Desktop

牛逼的Walmart Labs 还提供了一个可视化的管理工具,咱如今就先用上,直接去 github.com/electrode-i… 下载最新版本便可,打开以后,会看到登陆界面。暂时离开一下子,回到 Terminal 中去。

Electrode OTA Desktop Login Screen@2x.png

登陆 OTA Server

退出已有 code-push 会话

若是你之前已经使用了 Appcenter.ms 的服务,那么如今能够退出登陆了。

code-push logout
复制代码

注册

从新在私有 OTA 服务中注册账号:

code-push register https://ota.parcmg.com
复制代码

此时会跳转到 https://ota.parcmg.com 的受权页面,在页面最下方点击 Github 完成 OAuth 受权以后,会获得一个 Access Token,复制该 Token,在 Terminal 中粘贴,按回车,便可登陆成功,同时,将该 Token 粘贴至 Electrode OTA Desktop 应用的登陆框的 Token中,在服务地址中填写你的 OTA 服务地址便可完成会话登陆。

添加 App

Electrode OTA Desktop 里面,建立两个新的应用,就跟使用 appcenter.ms 同样,好比:

MyApp-Android
MyApp-IOS
复制代码

建立成功以后,会分别生成对应的 Production 以及 Staging Key,在接下面咱们会用到。

code push 服务迁移到本身的私有服务器

IOS

打开 info.plist 文件,咱们须要修改之前的 Code Push 配置,找到:

<key>CodePushDeploymentKey</key>
<string>SecrtKey-----------Here</string>
复制代码

在此处,将 MyApp-IOSProduction Key粘贴至此处,同时还须要添加一个配置项目:

<key>CodePushServerURL</key>
<string>https://ota.parcmg.com</string>
复制代码

完整配置以下:

<key>CodePushDeploymentKey</key>
<string><%YourKeyHere%></string>
<key>CodePushServerURL</key>
<string>https://ota.parcmg.com</string>
复制代码

若是你使用的不是 https 协议 ,那么还须要增长:

<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
  <key>NSExceptionDomains</key>
  <dict>
    <key>ota.parcmg.com</key>
    <dict>
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
    </dict>
  </dict>
</dict>
复制代码

Android

MainApplication.java 文件中,找到下面这一行:

new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG)
复制代码

添加一个参数以下,表示我须要使用这个做为 code push 的服务。

new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG, "https://ota.parcmg.com")
复制代码

大功告成了,须要测试的能够直接使用个人 ota 服务: ota.parcmg.com,但请不要在生产中使用,鬼知道我何时就会把这个停用了。

相关文章
相关标签/搜索