使用 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,但請不要在生產中使用,鬼知道我何時就會把這個停用了。

相關文章
相關標籤/搜索