FerryVip's Blog

技术分享

微信小程序开发 Jenkins 合并代码提交体验版本

1. 起因

最近公司项目在做小程序开发,有多个小伙伴一起开发,测试的小伙伴也要加入测试,为了做到敏捷开发,我这个懒人就在想有啥办法可以做到这点,最后发现微信的小程序工具提供命令行调用,查看其文档发现了新大陆,也就有了这篇文章;

2. 流程

  1. 开发人员开发后代码推到 git 仓库;
  2. 测试人员或开发触发 Jenkins 构建;
  3. 通过微信的工具上传微信小程序最新代码,并通过钉钉机器人通知打包成功;
  4. 测试就可以打开微信小程序的体验版开始体验最新的修改;

3. Jenkins 配置

1. 配置参数化构建, 主要是配置了 接口请求环境,和打包的 Git 分支

2. Git 配置

3. Build 执行 shell 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo ------------ 构建分支 --------------
echo $BRANCH
echo ------------ 打包环境 --------------
echo $ENV

# 导入 node 环境
export PATH=$PATH:/usr/local/bin

# 执行 接口请求环境的 替换操作
node env.js $ENV

# 上传最新修改到微信小程序
/Applications/wechatwebdevtools.app/Contents/MacOS/cli -u 1.0.0@$PWD --upload-desc 'Jenkins 小程序更新最新代码了,快去体验版查看'
# 上传成功后发送钉钉通知
node index.js $ENV $BRANCH

4. 微信开发工具配置

  1. 微信开发工具登录并打开设置里面安全的服务端口,还有就是微信版本管理把这个上传的微信版本选为体验版,这样下次再上传上去体验版就可以下载最新的上传修改了;

本人手上是有一台 Mac 电脑专门用来打包 App 的,所以只讲了 Mac 的,但道理是差不多一样的,可以自己折腾 Windows 的系统,要在这台打包电脑安装 Jenkins 还有 微信开发工具;(因为自己脚本写的太差了,所以有两个地方用到了 node 来实现,所以还安装了 node 环境);

钉钉设置机器人

之前我已经写了几个涉及钉钉机器人的配置,直接看之前的配置

配置完成后,获取里面的 token

5. 主要代码配置

1. 配置环境的文件 './config/index.js'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 全局配置文件
let HOST = '', USERHOST = '';

let ENV = 'DEV'; // 设置环境 测试 DEV, 正式环境 PROD

if (ENV === 'PROD') {
// 正式环境 host
HOST = 'https://api.prod.com';
USERHOST = 'https://user.prod.com';
} else {
// 测试环境 host
HOST = 'https://api.dev.com';
USERHOST = 'https://user.dev.com';
}

module.exports = {
ENV: ENV,
HOST: HOST,
USERHOST: USERHOST,
}

2. 替换接口环境的文件 './env.js'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const fs = require('fs');
const ENV = process.argv[2];
console.log(`/************* 替换环境为 ${ENV} 开始 *************/`);
// 环境文本
const prodTep = `
// 全局配置文件
let HOST = '', USERHOST = '';
let ENV = '${ENV}'; // 设置环境 测试 DEV, 正式环境 PROD
if (ENV === 'PROD') {
// 正式环境 host
HOST = 'https://api.prod.com';
USERHOST = 'https://user.prod.com';
} else {
// 测试环境 host
HOST = 'https://api.dev.com';
USERHOST = 'https://user.dev.com';
}
module.exports = {
ENV: ENV,
HOST: HOST,
USERHOST: USERHOST,
}
`;
process.chdir(`./config`); // cd $1
console.log(`/************* 前往 config 文件夹,并替换写入文件 *************/`);
console.log(prodTep);
fs.writeFileSync('index.js', prodTep);
console.log(`/************* 替换环境为 ${ENV} 成功 *************/`);
process.exit(0);

3. 发送钉钉消息的文件 './index.js'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const ENV = process.argv[2];
const branch = process.argv[3];

const ddtoken = 'you-dingding-token'; // 钉钉机器人 token
const qrurl = 'you-qrcode-url'; // 微信体验版的 二维码地址

let tokens = [
wscUrl,
];
const env = ENV === 'PROD' ? '正式环境' : '测试环境';
var exec = require('child_process').exec;
// git 最近 5 条修改的 commit 信息
const str = `git log -5 --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:"* %cd - %s "`;
function runExec(cmdStr) {
return new Promise((resolve, reject) => {
exec(cmdStr, function (err, stdout, stderr) {
if (err) {
console.log('runExec error:' + stderr);
reject();
} else {
// console.log(stdout);
resolve(stdout);
}
});
});
}
let gitlog = '';
runExec(str).then(res => {
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
gitlog = res;
sendDing(token, gitlog)
}
});
function sendDing(token, gitlog) {
var https = require('https');
var options = {
hostname: "oapi.dingtalk.com", // 呼叫的域名
port: 443, // 端口固定
path: `/robot/send?access_token=${token}`, // 请求的api名称
method: "POST", // get和post请求
json: true, // 此地方表示json
rejectUnauthorized: true, //请校验服务器证书,否则ssl没有意义。
headers: {
'Accept': 'application/json;version=2.0',
'Content-Type': 'application/json', //此地方和json很有关联,需要注意
}
};
var post_data = {
"msgtype": "markdown",
"markdown": {
"title": "小程序新包更新",
"text": `# 小程序新包发布 \n \n > 分支: ${branch} \n \n > 服务器环境: ${env} \n \n > 更新内容: \n \n ${gitlog} \n \n > 微信扫码体验小程序: ![](${qrurl})`
}
};
var json = JSON.stringify(post_data);
var req = https.request(options, function (res) {
res.setEncoding('utf8');
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
req.write(json);
req.end();
}

6. 最终钉钉消息效果

地址

GitHub 仓库地址

个人博客

博客地址:
https://gblog.ferryvip.com/

项目说明

在用 ReactNative 开发 App 时,会用到 CodePush 做应用的热更新,但是在升级的时候没有好看的弹窗提示,自己就找了个时间写了一个简单集成 ReactNative 又有好看的更新弹窗;

准备工作

  1. 首先是安装 react-native-code-push, yarn add react-native-code-push;
  2. link 一下项目, react-native link react-native-code-push;
  3. 安装 react-native-code-push-dialog, yarn add react-native-code-push-dialog;

项目中配置

最简单的配置如下,尽量把 节点放在顶层的节点处;

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button, Dimensions} from 'react-native';


import HotUpdate, { ImmediateCheckCodePush } from 'react-native-code-push-dialog';

export default class Index extends React.Component {
render() {
return <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text> CodePushExample </Text>
<HotUpdate />
<Text onPress={()=>{
ImmediateCheckCodePush();
}}>点击立即检查</Text>
</View>;
}
}

更多用法

props PropTypes use description
deploymentKey PropTypes.string jaasdasdsa2w12wed2we3e23 code-push deploymentKey 非必须参数,没有会读取原生的;
isActiveCheck PropTypes.bool true or false code-push CheckFrequency 检查更新策略,只提供2种, true 每次返回前台就更新(高频率), false 只有 App 启动才检测更新, 默认 true;
js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button, Dimensions} from 'react-native';


import HotUpdate, { ImmediateCheckCodePush } from 'react-native-code-push-dialog';

export default class Index extends React.Component {
render() {
return <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text> CodePushExample </Text>
<HotUpdate deploymentKey={'askjdkas32232dw32d'} isActiveCheck={false}/>
<Text onPress={()=>{
ImmediateCheckCodePush();
}}>点击立即检查</Text>
</View>;
}
}

推热更新代码的时候如果是有多条类型的,尽量在推更新的时候弄成每条后面回车,这样到时候展示的内容才能换行美观;

code-push release-react App android --des "1.按照区域展示轮播内容; 2.分析数据,优化体验;" -t "5.1.2"

显示效果

地址

GitHub 仓库地址

小型失物招领后端(Koa 版本)

项目说明

本身是搞 iOS 的后面入了 ReactNative 的坑,慢慢的就比较多的接触 JavaScript ,还有就是 JavaScript 慢慢的可以做的东西越来越多;
不仅可以做前端网页,还可以做移动端 App(ReactNative),还能做后端(Node.js),还有其他的;

这个失物招领是为了练手 Node.js,同时也为了配合这个写了个 App 前端(iOS 和 安卓),链接在后面也会放出了;

目前主要的 Feature:

  1. 用户登录注册;
  2. 基本的管理员权限管理;
  3. 失物招领信息发布,关注收藏,通知审核等;
  4. 管理员的基本功能的管理与审核;
  5. 极光推送对接,使内容实时推送给用户;

本地运行条件

  • MongoDB 数据库
  • Node.js 环境

基础配置

  1. 七牛配置
    1. 七牛配置是为了保存图片到七牛;
    2. 申请相应的开发者账号,填入到 config文件夹的config文件;
    3. 配置错误,或未配置调用到会导致程序崩溃;


  1. 极光配置
    1. 使消息即使让用户知道;
    2. 申请相应的开发者账号,填入到 config文件夹的config文件;
    3. 配置错误,或未配置调用到会导致程序崩溃;

造一些假数据的

项目目录下执行 node data.js 两次就行;

1
2
3
4
超级管理员
用户名: admin@163.com
密码: 123456
其他的用户: user[1 - 10]@163.com 密码: 123456

启动

  • 本地启动

    1. 首先启动本地 MongoDB 数据库,项目目录下执行 npm run mongo 数据库跑默认的段口;
    2. 项目目录下执行 npm start 启动;
    3. 就可以打开文档 http://localhost:5566/docs/
  • 服务器部署(主要使用 pm2 部署)

    1. 服务器安装 node pm2 MongoDB 环境等;
    2. 项目目录下执行
      1. 测试 pm2 start dev.json
      2. 正式 pm2 start dev.json
    3. 查看日志 pm2 logs

对应的客户端

  • 目前就只做了 App 端,按理说目前接口基本可以做个网页前端的,微信公众号以及小程序,在做些修改也是应该可以的;

下载体验

iOS 没有发布,下载安卓体验

安卓 fir.im 下载

或者直接扫码下载

扫码下载

仓库地址

Express 版本 GitHub 地址,具体配置看文档

Koa 版本 GitHub 地址,具体配置看文档

App 地址,具体配置看文档

个人博客

博客地址: https://cblog.ferryvip.com/

项目说明

在一些 Node 的项目中,一直使用 log4js 的做日志插件,然后发现里面有个 appenders 插件,可以发送消息到国外软件 slack 里,这样就可以便捷的做一些扩展,可是本人最近在用钉钉,而且那个接触也少,所以本着东西(接口文档的)都有,就找了时间自己撸了一个出来.

准备工作

找了一下两家的文档

log4js 文档

Log4js - Appenders

Slack Appender

钉钉自定义机器人文档

安装

npm install --save log4jsdd log4js

配置 log4js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

const log4js = require('log4js');
log4js.configure({
appenders: {
out: { type: 'stdout'},
dingding: {
type: 'log4jsdd',
hookUrl: '填写获取钉钉里面设置的 webhook 地址',
title: 'Node 消息'
}
},
categories: { default: { appenders: ['out', 'dingding'], level: 'debug' }}
});

let app = log4js.getLogger();
app.info('测试发送到钉钉');

钉钉机器人配置






地址

GitHub 仓库地址

npm 地址

个人博客

博客地址: https://cblog.ferryvip.com/

小型失物招领 App 客户端(iOS && 安卓)

项目说明

本身是搞 iOS 的后面入了 ReactNative 的坑,慢慢的就比较多的接触 JavaScript ,还有就是 JavaScript 慢慢的可以做的东西越来越多;
不仅可以做前端网页,还可以做移动端 App(ReactNative),还能做后端(Node.js),还有其他的;

这个 App 是为了搭配小型失物招领后端所做的,同时也使用了 redux react-navigation 等的做数据管理以及路由切换;

目前主要的 Feature:

  1. 用户登录注册;
  2. 基本的管理员权限管理;
  3. 失物招领信息发布,关注收藏,通知审核等;
  4. 管理员的基本功能的管理与审核;
  5. 极光推送对接,使内容实时推送给用户;

本地运行条件

  • 需要相应后端服务开启,本地 server 服务或者线上 server,下面会有相应的配置说明;

下载体验

iOS 没有发布,下载安卓体验

安卓 fir.im 下载

或者直接扫码下载

扫码下载

基础配置

  • 代码热更新配置(可不配置);

iOS
Android

  • 极光推送 appkey 配置

iOS
Android

  • 后端服务器地址配置

把在相应的服务地址填入对应环境中,设置 SET_ENV DEV 为开发地址 APP 为线上地址

config

仓库地址

服务器地址 GitHub 地址,具体配置看文档

App 地址,具体配置看文档

个人博客

博客地址: https://cblog.ferryvip.com/

小型失物招领后端(Express 版本)

项目说明

本身是搞 iOS 的后面入了 ReactNative 的坑,慢慢的就比较多的接触 JavaScript ,还有就是 JavaScript 慢慢的可以做的东西越来越多;
不仅可以做前端网页,还可以做移动端 App(ReactNative),还能做后端(Node.js),还有其他的;

这个失物招领是为了练手 Node.js,同时也为了配合这个写了个 App 前端(iOS 和 安卓),链接在后面也会放出了;

目前主要的 Feature:

  1. 用户登录注册;
  2. 基本的管理员权限管理;
  3. 失物招领信息发布,关注收藏,通知审核等;
  4. 管理员的基本功能的管理与审核;
  5. 极光推送对接,使内容实时推送给用户;

本地运行条件

  • MongoDB 数据库
  • Node.js 环境

基础配置

  1. 七牛配置
    1. 七牛配置是为了保存图片到七牛;
    2. 申请相应的开发者账号,填入到 config文件夹的config文件;
    3. 配置错误,或未配置调用到会导致程序崩溃;


  1. 极光配置
    1. 使消息即使让用户知道;
    2. 申请相应的开发者账号,填入到 config文件夹的config文件;
    3. 配置错误,或未配置调用到会导致程序崩溃;

造一些假数据的

项目目录下执行 node data.js 两次就行;

1
2
3
4
超级管理员
用户名: admin@163.com
密码: 123456
其他的用户: user[1 - 10]@163.com 密码: 123456

启动

  • 本地启动

    1. 首先启动本地 MongoDB 数据库,项目目录下执行 npm run mongo 数据库跑默认的段口;
    2. 项目目录下执行 npm start 启动;
    3. 就可以打开文档 http://localhost:5566/docs
  • 服务器部署(主要使用 pm2 部署)

    1. 服务器安装 node pm2 MongoDB 环境等;
    2. 项目目录下执行
      1. 测试 pm2 start dev.json
      2. 正式 pm2 start dev.json
    3. 查看日志 pm2 logs

对应的客户端

  • 目前就只做了 App 端,按理说目前接口基本可以做个网页前端的,微信公众号以及小程序,在做些修改也是应该可以的;

下载体验

iOS 没有发布,下载安卓体验

安卓 fir.im 下载

或者直接扫码下载

扫码下载

仓库地址

服务器地址 GitHub 地址,具体配置看文档

App 地址,具体配置看文档

个人博客

博客地址: https://cblog.ferryvip.com/

起因

最近用着钉钉,突然发现有个神奇的功能叫 Webhook 机器人,里面有 Github 的机器人,然鹅竟然没有我一直在用的 Coding.net 的机器人,这个不能忍,本着程序员自己动手丰衣足食的勤劳准则,想着就自己折腾弄一个玩玩;

因为自己只会点 Node.js 所以就做了个包,具体的看下面;

效果图

准备工作

找了一下两家的文档

Coding Webhook 文档

钉钉自定义机器人文档

大概原理就是,钉钉提供一个发送消息的 Webhook 地址给你,然后 Coding 家提供了一个给你填入 Webhook 的地址接口,当仓库有信息变化,就会给你这个地址接口发消息;然而钉钉没有做这个 Coding 的接口,所以不能提供 Coding 直接把消息发到钉钉上,所以只能自己搭个服务器,先把 Coding 的消息解析一下,在发给钉钉.基本原理就是这样,说的有点乱,哈哈;

服务器

设置 Webhook 路由;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const express = require('express'),
bodyParser = require('body-parser'),
CWD = require('./../index'),
app = express();

// 一般都会设置 bodyParser ,需要用到;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());


// 设置 Webhook 路由,已经中间件 CWD
app.post('/webhook', CWD());

app.listen(5566, function () {
console.log('Express server listening on port http://localhost:6666');
});

CWD 中间件;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const request = require('request');
exports = module.exports = function (options) {
return function CodingHookDingDing (req, res, next) {
let event = req.headers['x-coding-event'],
body = req.body;
// 通过头文件的 event 事件判断传入的参数等,做相应的信息解析;
switch (event){
case "push":
return Push(req, res, next); // 对 push 做解析
case "ping":
return res.json({
"token": "123",
"zen": "Coding! 让开发更简单"
});
default:
return res.json(body);
}
};
};

function Push(req, res, next) {
/*-- 消息的解析拼接 --*/
let body = req.body;
let ding = body.token;
let count = body.commits.length;
let whopush = body.commits[0].committer.name;
let repourl = `${body.repository.owner.web_url}/p/${body.repository.name}/git/tree/${getbranch(body.ref)}`;
let branch = `# [[${body.repository.name}/${getbranch(body.ref)}]](${repourl})`;
let text = `${branch} ${count} commit,push by ${whopush}\n ## commits:\n`;
for (let i = 0; i < count; i++){
let com = body.commits[i];
let name = com.committer.name;
let mes = com.short_message;
let hash6 = com.sha.substring(0,6);
let commit = `> </> ${name}: [[${hash6}]](${com.web_url})-${mes}\n`;
text = text + commit;
}
console.log(text);
/*-- 消息的解析拼接 --*/

// 钉钉消息格式等 body 设置
let rqbody = {
msgtype: "markdown",
markdown: {
title:"仓库有新的代码更新咯!",
text: text
}
};

let options = {
url: ding,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(rqbody) // 消息体内容
};
// request 向钉钉发送消息 Webhook
request.post(options, (err, res, body)=>{
if(!err && res.statusCode == 200){
let info = JSON.parse(body);
console.log(info);
}
});
res.json({mes: 'ok'});
}
function getbranch(str) {
let arr = str.split('/');
return arr[arr.length-1];
}

配置

1. 首先钉钉群里设置自定义机器人

1. 设置自定义机器人

2. 填入机器人名称

3. 复制 webhook 地址,后面有用

2. Coding 仓库 Webhook 设置

1. 点击到要设置的仓库 Webhook 页面,点击新建 Webhook

2. url 填入服务器上要监听的地址, token 填入刚才钉钉复制的 Webhook 地址,以及选取底部的监听类型,至少要勾选 Push

3. 如果配置顺利,在你以后每次仓库的变化,在钉钉上面都会收到消息提醒

npm 包

后面就干脆做了个 npm 包发布上去,目前只对 push 操作做消息发送,后续有时间在完善下其他操作;

安装

npm i --save hookding

使用方法

1
2
3
4
const CWD = require('hookding');

app.post('/router', CWD());

本文参与 Coding 征文计划

curl 基本使用

  1. 最简单的直接请求页面 curl "https://www.baidu.com"
  2. 请求保存页面 curl "https://www.baidu.com" > /path/name.html
  3. -o 保存页面 curl -o /path/name.html "https://www.baidu.com" --progress 显示进度条
  4. -s 加入这个就不会出现进度条,安静模式
  5. -A 参数用来指定 USER-AGENGT curl -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17" http://localhost/learing-curl/show-server-info.php
  6. -e 指定 referer 来源网址 curl -e "https://www.google.com/" http://localhost/learing-curl/show-server-info.php
  7. -d post 请求 curl -d "name=1" "http://localhost:6666/post"
  8. -G 轻质指定表单以 GET 方法提交
  9. -I 只展示 Header curl -I http://www.baidu.com
  10. -D 保存 Header 到文件里 curl -D header.txt http://www.alibaba.com
  11. -L 跟随重定向过去 curl -L http:localhost:6666/red
  12. -F 提交文件 curl -F upload_file=@test.data url
  13. -c 保存 cookie curl -c cookie.txt https://www.baidu.com
  14. -b 带 coolie 访问 curl -b "name=data" url curl -b cookie.txt url
  15. -H 设置请求头
  16. -m 设置最大传输时间 seconds
  17. -u 设置服务器用户名和密码 curl -u name:password url
1
2
3
4
5
6
7
8
curl 'https://oapi.dingtalk.com/robot/send?access_token=6fb5741248b308d1eb616f993fddf0fb3459f42cb6b4eb86078e33042b5bc4e0' \
-H 'Content-Type: application/json' \
-d \
'{"msgtype": "text",
"text": {
"content": "我就是我, 是不一样的烟火"
}
}'
1
2
3
4
5
6
curl 'http://www.ferryvip.com/v1/me/webhook' \
-H 'Content-Type: application/json ' \
-H 'x-coding-event: push ' \
-d \
'{"ref":"refs/heads/master","before":"fbec0e3aa41f1364587c5d62df9032bcc5406afd","commits":[{"committer":{"name":"chencangshan","email":"chencangshan@huaxiweiying.com"},"web_url":"https://coding.net/u/ferryVip/p/lostwebserver/git/commit/90360e33395e3bb1e1b844b4b85de08d2a559152","short_message":"测试 hook\n","sha":"90360e33395e3bb1e1b844b4b85de08d2a559152"}],"after":"90360e33395e3bb1e1b844b4b85ded2a559152","event":"push","repository":{"owner":{"path":"/u/ferryVip","web_url":"https://coding.net/u/ferryVip","global_key":"ferryVip","name":"ferryVip","avatar":"https://dn-coding-net-production-static.qbox.me/82b7ce57-96ef-4faf-a480-bb0645ab2a1a.jpg?imageMogr2/auto-orient/format/jpeg/crop/!200x200a0a0"},"https_url":"https://git.coding.net/ferryVip/lostwebserver.git","web_url":"https://coding.net/u/ferryVip/p/lostwebserver","project_id":"1219048","ssh_url":"git@git.coding.net:ferryVip/lostwebserver.git","name":"lostwebserver","description":"react webpack node mongodb express\n\n失物招领b server"},"user":{"path":"/u/ferryVip","web_url":"https://coding.net/u/ferryVip","global_key":"ferryVip","name":"ferryVip","avatar":"https://dn-coding-net-production-static.qbox.me/82b7ce57-96ef-4faf-a480-bb0645ab2a1a.jpg?imageMogr2/auto-orient/format/jpeg/crop/!200x200a0a0"},"token":"https://oapi.dingtalk.com/robot/send?access_token=6fb5741248b308d1eb616f993fddf0fb3459f42cb6b4eb86078e33042b5bc4e0"}'

ofo ReactNative 仿版(主要是做 iOS版本)

原因

之前一直想做个 ReactNative 关于地图相关的 demo ,然后近两天在群里看见有人发的 RN 做的 ofo 共享单车的仿版(主要是针对安卓的),就想着乘着这几天活不多,也做一个,用下最新的 RN 版本(0.44),本来是想体验一下一些新特性的,目前主要还是在40以下做项目,主要考虑版本兼容,不过目前看也差不多可以升级40以上了,至于这个 ofo 仿版还是有很多没有用到新的特性的东西,好了话不多说,上效果图;

效果图

iOS 安卓

package.json

1
2
3
4
5
6
7
8
9
10
"native-base": "^2.1.3",
"react": "16.0.0-alpha.6",
"react-native": "0.44.0",
"react-native-blur": "^3.0.0-alpha",
"react-native-camera": "^0.8.0",
"react-native-maps": "^0.15.0",
"react-native-scrollable-tab-view": "^0.6.6",
"react-native-share": "^1.0.20",
"react-native-simple-toast": "^0.0.6",
"react-navigation": "^1.0.0-beta.9"

主要用到的一些依赖,时间比较匆忙,有些没有兼容两个平台,特别是安卓,地图的没有做到很详细;

项目怎么跑起来

  1. 把本仓库下载或者克隆下来; Github 地址: https://github.com/strawferry/reactnativeofo
  2. 前往仓库目录,终端执行 npm install 或者 yarn;
  3. 终端执行 react-native link,链接相关的依赖;
  4. 然后运行项目;

感谢

当时在群里看到这个仓库,发现做的还不错,但是主要是针对安卓的,当时 iOS 适配比较差,就想着搞一个出来;
React Native 仿 ofo 共享单车 App http://www.marno.cn

最近一直在看一些关于持续集成的东西,持续集成会对整个项目的敏捷开发有很大的帮助;

了解过 jenkins, 功能非常强大,但是在做 iOS 持续集成必须在一台 Mac 系统下,后面通过了解和别人介绍,认识到了今天的主角 Travis CI;

hexo虽然可以方便地部署github静态博客,但是仅仅是把最终生成的html保存在repository中,像原始的Markdown文件,hexo配置文件,主题配置文件,修改文件都仅仅是保存在本地。这样不利于保存,也无法查看每篇博客的修改历史。更重要的是无法做到跨平台,也不易于多人写作。

想法是每次写博客,只需要push md文件及博客所需的资源文件即可。Travis CI持续集成tool可以满足此需求。

Travis CI 目前主要是和 GitHub 一起使用,所以今天的例子就以 hexo 博客的每次 push 触发 Travis CI 自动部署到 GitHub 的 Pages 上;

1. 思路

2. 具体实现

2.1 首先需要在 GitHub 上面创建一个仓库(或者已有)

以新建仓库为例

2.2 生成 Personal Access tokens

为后续的功能生成的 token

登录github, settings -> Personal access tokens -> Generate new token

填写token description,比如叫 travis.并勾选上授予的权限,比如我勾选的是repo和gist,然后create.

将产生的token串复制保留下来,后面会使用到,如果丢失,只能重新产生。

2.3 travis-ci 设置

登录 travis-ci 网站,利用 GitHub 账号登录;

同步 GitHub 仓库

选取刚才创建的仓库并打开

添加刚才的 token 作为全局变量

2.4 hexo 博客设置

基本的 hexo 命令

1
2
3
4
5
npm install hexo-cli -g
hexo init blog
cd blog
npm install
hexo server

进入 blog 所在的文件夹下,新建 .travis.yml 文件,并添加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 使用语言
language: node_js
# node版本
node_js: stable
# 设置只监听哪个分支
branches:
only:
- source
# 缓存,可以节省集成的时间,这里我用了yarn,如果不用可以删除
cache:
apt: true
yarn: true
directories:
- node_modules
# tarvis生命周期执行顺序详见官网文档
before_install:
- git config --global user.name "name"
- git config --global user.email "mmail@mail.com"
# 由于使用了yarn,所以需要下载,如不用yarn这两行可以删除
- curl -o- -L https://yarnpkg.com/install.sh | bash
- export PATH=$HOME/.yarn/bin:$PATH
- npm install -g hexo-cli
install:
# 不用yarn的话这里改成 npm i 即可
- yarn
script:
- hexo clean
- hexo generate
after_success:
- cd ./public
- git init
- git add --all .
- git commit -m "Travis CI Auto Builder"
# 这里的 REPO_TOKEN 即之前在 travis 项目的环境变量里添加的
- git push --quiet --force https://$REPO_TOKEN@git@github.com/strawferry/FerryVipBlog.git master

然后,准备 push 该项目到 github ,如果是新项目可参照下面的git指令

1
2
3
4
5
6
7
8
git init
# 添加自己的项目
git remote add origin git@github.com:strawferry/travis.git
# 新建并切换分支
git checkout --orphan source
git add -A
git commit -m "init repo"
git push

2.5 发布博客文章

1
2
3
4
5
前往 source 分支下:
hexo new title // 1. 新建文章;
2. 使用 markdown 软件或者 vim 直接编写文章内容,并保存文件;
3. 把目前分支的内容变化提交到 git 线上仓库;
4. 接着就等待 travis-ci 自动部署到 pages 上;


这样你的博客就已经成功部署到 pages 上面了

总结

这个是一个简单的对 travis-ci 的入门,这样能够给我们提供不少的事,持续集成能够给开发带来极大的便利,让程序员不做一些重复的事情,提高效率;