Little tricks with XCTest

Tried to call all other tests in one test function.

    // alternate what setup done
    // full tests in alternated state
    NSArray * tests = [FileLibraryTests testInvocations];
    for (NSInvocation * inv in tests ) {
        NSString * sel = NSStringFromSelector(inv.selector);
        if (![sel containsString:@"WithInit"] && ![sel containsString:@"Monitoring"]) {
            [inv invokeWithTarget:self];
        }
    }
    //back to normal state

And just noticed XCode6 added XCTestExpetation, no longer need semaphore like:

    #import 
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_after(dispatch_time(0, (int64_t)(0.2 * NSEC_PER_SEC)), 
        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
        ^{
            ... dispatch_semaphore_signal(sema); ...
        }
    );
dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 30*NSEC_PER_SEC));

It is much simple to test async operations now:

    XCTestExpectation *expectation = [self expectationWithDescription:@"xxx"];
// invoke it in code async executing
    ... ^(){
        [expectation fulfill];
    } ...
[self waitForExpectationsWithTimeout:1 handler:^(NSError *error) {
        // cleanup.
    }];

CocoaPods and objc_msgSend

I got this “Too Many arguments to function call, expected 0, have 3” error while compiling a project relies on QuickDialog.

According “https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html”, it is easy to fix, just cast the function to right prototype, like:

int (*action)(id, SEL, int) = (int (*)(id, SEL, int)) objc_msgSend;

But, the invocation is in a pod project which is locked for editing and even if I unlock it, the change will lose at next checking out of the project.

Further peek at objc/message.h shows it is a trick to help compiler ensuring the call is with right frame, the signature is still available with OBJC_OLD_DISPATCH_PROTOTYPES micro. Then I found the:Screen Shot 2015-06-12 at 9.27.25 AM

Set “Enable Strict Checking of objc_msgSend Calls” in QuickDialog target of Pod project, done.

原型工具小结

耍了一堆原型工具,感觉可以分成三类:

  1. 动图型:已经有界面的图片了,不管是手绘还是 PS / Sketch 3,有许多工具都可以导入后加上热区跳转和交互效果了。
  2. 描绘型:提供各种图形组件,可以快速描画界面,普通可以快速实现界面跳转,复杂的交互和条件处理只有少量组件可以了。
  3. 编程型:无论是直接拿 html/js 开练,还是拿 Quartz Composer 用图形语言写,本质上都是在编程了,看用的人会写js还是熟图形处理了。

目前看下来,还是 Axure 功能比较全面,其它的工具处理处理小项目还成,管理复杂项目还是费劲点。Pencil 这个开源项目其实很不错,就是蛮久没人维护了。

Apple Watch 使用小结

Apple Watch 到手有些日子了,用下来还不错。

最为担心的问题是电池,实际表现非常好,我基本早上7点带上,到晚上23点左右取下来,正常一天下来还剩40~50%的电量,工作日活动比较少且没时间不停折腾表的话,2天其实也坚持得过来。

运动探测不是太准,比如我在键盘上工作时,它有时就会误判而影响久坐提醒,1.0.1说改进了算法,希望会好一点。

抬腕亮屏需要的加速度或行程比较大,有时手本来就抬着,再举到眼前偶尔会有不亮屏的情况,需要再来一次;而开车时,转动方向盘则会经常自己亮着,是经常呀,这个略浪费电。

导航功能就是个样子货,还是手机开语音比较实在。接电话很酷,特别是开车的时候,方便多了,就是音质实在太差!

现在改用太阳表盘了,每天看看日出日落时间还蛮酷的, Module 表盘太快就看疲劳了。

第三方应用普遍还打磨得不大够。

微信,消息功能做得还比较完整,能收能看能开朋友圈,就是时不时跳出来说“您收到了一条消息”又不告诉我是啥,而且打开消息时速度比较闹心。在对话里图片处理也不细致,似乎是按比例缩放的,而不是占满全屏,经常大一点又不是正方形的图片会看不清楚。但凑合着用还是可以的,且而微信手机版本的主界面还蛮好看的。

微博,有直接消息时还是会弹通知的,还可以回,不过万一当时没回,就再也看不到了。平常它在手机上只会卖萌,完全没用,那个计步功能现在也没搞清楚怎么生效,反正我这儿一直是0.

Twitter 做得还是不错的,可惜没 wi-fi 时翻墙比较烦人,基本只拿来收通知了。丫的 iOS 客户端我没找到在哪里设置代理,Android 版本倒是很好找。

搜狐视频动作很快,已经有表上的播放控制和个人收藏查看功能了,不过它没法控制 iPad 上的播放呀,手机我就拿手上看了,放远了看不清楚呀。也试了 AirPlay 到 Apple TV 上,这个不知道是我不会用还是咋得,音量似乎控制不了,也不能控制 airplay 切换。顺便吐个槽,在 iPad 上做个看得见的 AirPlay 目标切换菜单就那么有挑战性?

淘宝有交易时会弹通知,不过平时基本在捣乱,时不时发一个上边“手机淘宝”,下边“关闭”,中间啥也没有的消息是几个意思?招行的客户端就文明多了。

听说这货防水其实很 NB,不过坏了不保,想来想去还是没带它去游泳,反正也没有游泳统计模式。

最后越来越觉得还是应该买 42mm 的,特别是被某人吐槽说 38mm 的在我手上颇有基佬范以后。

Apple Watch 初体验

Apple Watch 用了大半天了。感觉很不错,操作流畅,电力持久,屏幕明亮艳丽,就是铝壳比表盘还是逊色不少,应该买不锈钢的。

手表的基本功能自然是时间管理。
默认的时钟表盘一点也不花哨,但是很实用:时间、日期、最近事项提示、运动量摘要、气温都有了。如果不满意,用力按一下,就可以换表盘了,还可以对现有表盘做一些定制,试下来还是觉得默认的实用。
自带的世界时钟,能够自动同步我在手机上添加过的地区;自带的秒表,设计很花心思,默认的视图是一个大表盘,最近一圈与总时间用两根不同颜色的指针显示在表盘上,上划一下,则进入具有分、秒、厘秒三个小表盘并附每圈记录清单
自带的小定时器非常直接,默认最多12小时,用力按一次则可以切换12/24小时。
自带的日历就略显简陋,默认显示从今天起的待办事项清单,可以滑动到以后的日子,点左上角的日期可以显示整个月,但是似乎不能切到其它月。用力按可以将清单换成今天视图。
自带的闹钟功能齐全,可以用力按新建闹钟,点击已有的闹钟可以修改时间、重复、提醒等等,功能很全。不过,在我这个38mm表盘上操作实在让人精神紧张,还是用 Siri 设置闹钟更舒服。

另一个基本功能则是运动和健康管理。
自带的健康活动非常简单,久坐会提醒我站起来活动活动非常有帮助。不过 Apple Watch 防溅不防水,不能带着游泳,是个遗憾,我目前主要靠游泳锻炼身体。
自带的健身功能也不错,支持各种常见的锻炼方式。我家小 Nemo 发现它之后,就开了室内跑步在家来回跑,玩得可欢了。结束时会提供热量消耗、心率等统计数据。
另外装了 Nike+ Runnign和咕咚运动。Nike+需要先在手机上完成设置,它会下载 viavoice 套件,可以在跑步过程中播放音乐、打气,当然也有各种统计和朋友间的排名。咕咚的功能也挺全,支持的活动类型挺多,就是需要在应用里先绑定一下健康设备,允许读写健康数据,这个没有放在初始设定过程里,有点小绕。

通知与消息
将各种通知弹到手表上,这种提醒方式很方便。手机经常需要静音,不静音也会时不时错过。手表会把通知显示在表面上,如果错过了,从顶上向下划一下就会显示清单了,跟 iPhone 上的方式是一样的。除了系统本身的短信、电话、邮件,微信、微博、QQ、Twitter 这类消息型应用,支付宝、招商银行掌上生活等也会有提醒。不过居然没看到 Facebook。

微信在手机上能够正常使用,不仅可以看消息,还可以发消息。微博则选择了另一个方向,做得比较好玩,感觉是猜测新上手的手表用户们应该急于显摆,所以提供了第多少位手表微博用户和朋友圈里运动量排名的功能,有新消息时也可以看、赞,但发不了消息,可以用力按然后分享到微博。我是第21090位用户,可见国内已经发了不少货了。

工具
系统自带了挺多功能的,向上划一下,会有:
手机连接状态与控制,音乐(会在手机上放而不是在表上),心率,电量,健康活动,日历,天气,股票,地图,和日照情况。

mwCalculator 是个小计算器,咋一看只有数字,还是挺困扰的,用力按也没用,后来发现是点击结果显示区域切换数字和运算符,这个就不应该用同样的颜色了,最好再加一个视觉暗示。

用手表来控制 Keynote / PowerPoint 是个很酷的主意。 Keynote 的手机扩展可以自动发现电脑上运行着的 Keynote 并控制翻页,就是测试的过程中断掉过一回,着实让人担心。

电池续航能力确实有点让人担心,14.5小时左右从100%到1%,其中打了1个10分钟左右的电话,下班高峰时段导航了约么10公里走了约30分钟,测量了1.7公里的户外步行约30分钟,额外测过五六次心跳,其余使用应该还在日常范围之内。

用 CSS 给 FORM Input 换行

自从若干年前看过《超越CSS:WEB设计艺术精髓》一书之后,再看 HTML 源文件就经常有各种心理障碍。刚才试着写个小注册表单,就有一个字段分行的问题。直接写:

<label><input>
<label><input>

会连成一行显示。这个问题非常容易解决,不管是用 div/p/br,还是用 label 包住 input 然后 display:box; 之,都可以达成效果。前者插了一堆没意义的标签,而且把布局与内容混为一体了;后者逻辑上感觉不太对,label 是 input 的一个修饰件才对嘛。

这个问题应该用 CSS 解决。直接的想法是 input:after ,不过 content:’\a’ 不起作用,又不能放标签,试了一下附个图片把后边的东东挤开,也没成。
再试 label:before,这回成了。
label:before { content: ‘\a’; white-space:pre; }


折腾图片的时候又掉坑里了,在 meteor app 里图片死活出不来,iron-router 总是跳出来说 template 找不着,明明图片是放在 public 下面,iron-rotuer 也是v1.0.7呀。各种疑神疑鬼,好久才发现,这 public 自己放到 /client 下边了,挪回顶上就好了。

** 扔草稿箱里居然忘了

在 Docker 里构造 Meteor 持续集成环境

持续集成由以下环节组成:

      1. 代码版本库 (gitlab)
      2. CI服务 (gitlab-ci/jenkins coordinator)
      3. CI Runner

 

当开发者将修改推送到版本库时,版本库会通知 CI服务,CI服务则会取出一份代码,交给 Runner进行检测,Runner将检测结果汇报给 CI服力。当然,开发者在提交代码之前,应该已经在自己的环境里做过必要的测试了。

 

Meteor已经选定 Velocity做为官方测试框架,通过 meteor run –test可以调用不同的测试工具完成单元测试到集成测试的各种测试,自带 reporter,同时也考虑了对 CI服务的支持。

 

例如https://github.com/dcsan/velo-ci是对接 Travis CI服务的示例,主要工作就是写了个 .trivis.yml放在项目根目录下,这样<通过还不清楚的机制>meteor run –test 运行测试时会将测试结果汇报给 Trivis服务器。Trivis github.com提供的配套云端CI服务,对于开源项目免费,商业项目收费。

 

使用 Gitlab搭建内部的代码库通常是出于价格、网络速度、私有性方面的考虑,因此再搭建一个内部的CI服务也就顺理成章了。不过,其实合理设置内部的 Runner 服务器,使用公有 CI服务也是可行的。

 

服务器有很多选择。Gitlab是比较流行的仿 github 代码服务,它从2013年开始提供配套的 Gitlab-CI,这个CI还比较新,因此功能相对简单一点,界面相应的新颖一些。另一个更为成熟的开源 CI服务是JenkinsGitlab一直没有提供对 Jenkins的支持,倒是 Jenkins社区提供了支持 Gitlab的插件。Gitlab如果内置对 Jenkins的支持,使用起来会更方便,比如 Gitlab内置了对 JIRA的支持,开发者可以在 commit message 里提一下 Closes #MyPrj-7,代码推送到版本库之后,Gitlab会通知 JIRA修改对应的 issue的状态。

 

所以嘛,既然上了 Gitlab,那就 Gitlab-CI吧。麻烦的是,东西太新,资料较少,折腾起来费劲。

 

首先当然是安装环境,如果机器富裕,直接用Omnibus安装包安装就好了,会更容易一点。我这没那么宽裕,所以是在一台 Docker服务器里折腾。

 

首先当然是做好 Docker环境了,然后参照https://peteris.rocks/blog/docker-gitlab-and-gitlab-ci/的说明进行安装。这个说明是能找到的最详细的傻瓜式教程了,不过还是有几个重要细节没提到,半道上出各种问题,还是得回头去看 github上原始的项目,好在sameersbn的说明文档很详细,重要的信息都在。现在看我这个改良版就行了,当然要愿意踩一遍坑加强一下感受,也是群众喜闻乐见的。

 

安装过程如下:

      1. 安装 gitlab,这部分还挺顺。不过 Peteris Rocks 的命令少了几个环境变量,在 Gitlab里创建的项目提示的 repo都是基于 localhost域名的,email用户也没写会发不出邮件的。

另外,所有的容器我都加上了 –restart=”always”,这样机器重起后就不用手工起动容器了。

EMail的话建议给 gitlab专门开一个用户,默认会用 GMail  SMTP,国内的服务器小心连不上。

 

#创建 Redis缓存服务,其实不是必须的。

docker run –name=gitlab-redis –restart=”always” -d sameersbn/redis:latest

 

#创建数据库,喜欢 MySQL的话去 github上看说明,我还蛮喜欢 Postegresql的,有几年工作就跟丫博斗。

docker run –name=gitlab-postgresql –restart=”always” -d \

-e ‘DB_NAME=gitlab’ -e ‘DB_USER=gitlab’ -e ‘DB_PASS=gitlab’ \

-v /opt/gitlab/db:/var/lib/postgresql \

sameersbn/postgresql

 

#终于干正事了,创建 GitLab容器。

#VIRTUAL_HOST=dev.my.com这个环境变量对于 GitLab没用,是给还没安装的 nginx-proxy准备的,后面会说明。

#GITLAB_*是用来生成 GitLab配置文件用的:

#    HOST一定要写外部ip或域名,不然  GitLab 网页上提示的代码库 URL全是 localhost;

#   两个 PORT分别是 web服务和 ssh服务在 docker容器上的端口

#SMTP_*自然是配置怎么往外发邮件的,默认用GMail,我倒是挺喜欢 GMail的,可惜身在墙内呀。

#第一个 -v是将 Docker Host也就是主机上的 /home/git/data目录映射到容器内用来存储数据,不然容器一关数据就没了。

docker run –name=gitlab –restart=”always” -d \

-e ‘VIRTUAL_HOST=gitlab.my.com’ \

-e ‘GITLAB_HOST=gitlab.my.com’ \

-e ‘GITLAB_PORT=10080’ -e ‘GITLAB_SSH_PORT=10022’ \

-e ‘GITLAB_BACKUPS=daily’ \

-e ‘GITLAB_CI_HOST=ci.my.com’ \

-e ‘SMTP_DOMAIN=ym.163.com’ \

-e ‘SMTP_HOST=smtp.ym.163.com’ \

-e ‘SMTP_PORT=25’ \

-e ‘SMTP_USER=gitlab@my.com’ \

  -e ‘SMTP_PASS=<你的密码>’ \

-p 10022:22 -p 10080:80 \

-v /opt/gitlab/repos:/home/git/data \

-v /var/run/docker.sock:/run/docker.sock \

-v $(which docker):/bin/docker \

–link gitlab-postgresql:postgresql \

–link gitlab-redis:redisio \

sameersbn/gitlab

注意:第一次启动 GitLab会在 compile assests之类的环节工作很久,在完成之前访问 10080端口应该会出 502或者503错误,这是正常的!你可以用 docker logs git-lab看看进行到哪了。如果看到下面这一堆就是好了:

2015-04-22 01:46:06,781 INFO success: sidekiq entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

2015-04-22 01:46:06,781 INFO success: unicorn entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

2015-04-22 01:46:06,781 INFO success: cron entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

2015-04-22 01:46:06,781 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

2015-04-22 01:46:06,781 INFO success: sshd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

 

      1. 用默认的 root / 5iveL!fe帐号登录,强烈建议在 profile里把 root用户改个名字。

 

这不是凭空变出来的,安装好 GitLab-CI以后它会提示你用这样一个 url去创建 app,不过ci_dommain_name部分极有可能是 localhost或者 docker internal ip,不要用这个值,不然下一步你会发现 GitLab-CI网站上回 Gitlab进行 OAuth授权的链接都点不开。

 GitLab生成的 AppIDAppSecret都记下来,或者开着这个页面别动也成,一会要用。

 

      1. 安装 GitLab-CI,注意传给新容器的环境变量里有 AppID  AppSecret,值改成上一步记下来的。

Peteris Rocks没提这两个重要的环境变量!如果已经把 GitLab-CI运行起来了,docker rm gitlab-ci重来吧。

#GITLAB_*说明 GitLab服务在哪里,虽然已经  –link了,但是要是不想被一堆奇奇怪怪的 URL困扰,_URL还是写上吧。

#-v让容器把数据库等文件存到 /opt/gitlab-ci/data里,

#   如果练手时 rm gitlab-ci-postgresql了,再创建容器时会报数据库已经存在了,这时可以去这个目录把 db目录删了。

docker run –name=gitlab-ci –restart=”always” -d \

-p 11080:80 \

-e ‘VIRTUAL_HOST=ci.my.com’ \

-e ‘GITLAB_URL=http://gitlab.my.com’ \

  -e ‘GITLAB_APP_ID=刚才生成的ID‘ \

  -e ‘GITLAB_APP_SECRET=刚才生成的密钥‘ \

-e ‘SMTP_DOMAIN=ym.163.com’ \

-e ‘SMTP_HOST=smtp.ym.163.com’ \

-e ‘SMTP_PORT=25’ \

-e ‘SMTP_USER=gitlab@my.com’ \

  -e ‘SMTP_PASS=<密码>’ \

-v /opt/gitlab-ci/data:/home/gitlab_ci/data \

-v /var/run/docker.sock:/run/docker.sock \

-v $(which docker):/bin/docker \

–link gitlab:gitlab \

–link gitlab-ci-postgresql:postgresql \

–link gitlab-ci-redis:redisio \

sameersbn/gitlab-ci

 

它怎么知道 GitLab在哪里呢?创建 GitLab-CI容器的命令里给的环境变更GITLAB_URL呀。

登录、授权之后,浏览器会跳回 GitLab-CI,现在 GitLab-CI就装好了。它会提示你:

Now you need Runners to process your builds.

Checkout the GitLab Runner section to install it

呵呵。

      1. 最后装上 nginx-proxy做为反向代理,这样就可以直接用各个容器的域名直接访问网站,而不用记那些奇怪的端口了。

#这个容器会监视所有的 docker容器的启动,并扫描容器内部的 80端口映到 docker host哪个端口了,然后在 nginx里建对应的虚拟主机,将该容器的域名(由容器内的环境变指定)上的HTTP请求转发过去。

docker run -d –name=”nginx-proxy” –restart=”always” -p 80:80 \

-v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy

 

      1. 没找到 gitlab-ci-runner-meteor,自己动手做吧。动手前搞清楚 GitLab CI Runner 是怎么工作的非常有必要。

GitLab官方已经把Runner环境程序都弄好了,放在https://gitlab.com/gitlab-org/gitlab-ci-runner项目里了。我们并不需要从头写程序访问 GitLab CI 的 API才能制作 Runner环境。

      1. gitlab-ci-runner.git取一份回来
      2. 在里面 bundle install –deployment 进行安装
        1. 自然需要先把  ruby/gem/bundle 这堆环境都准备好。
        2. 安装后,默认的工作目录:/home/gitlab_ci_runner/gitlab-ci-runner
        3. 配置文件在工作目录里:config.yml

 

      1. 在里面 bundle exec ./bin/setup_and_run完成设置并启动运行。

这一步需要 CI-Runner容器能够顺利访问 GitLab服务器(注意不是GitLab-CI而是GitLab),以便检出代码。以ssh方式的话需要安装信任证书。

      1. (以下是 2015-4-20左右的代码情况,即使有变化原理应该也差不多的)
      1. setup_and_run脚本会读取以下环境变量
        1. CI_SERVER_URLCI服务器地址(http://ci.my.com)
        2. REGISTRATION_TOKEN初次访问 CI 服务器的令牌(http://ci.my.com/admin/runners会显示)
        3. RUNNER_DESCRIPTIONRunner的说明,不提供的话则使用 runner运行环境的 hostname
        4. RUNNER_TAG_LIST还没弄明白
      2. 然后构造一个 json对象, HTTP POST GitLab-CI API

CI_SERVER_URL/api/v1/runners/register.json

BODY:{

    token:REGISTRATION_TOKEN,

    tag_list:RUNNER_TAG_LIST,

    description:RUNNER_DESCRIPTION

}

      1. 注册成功的话,会从 CI服务器取回一个授权令牌,以后用这个令牌与 GitLab-CI通信。
      2. 开始每5秒钟问一次 GitLab 有没有新 Build
        1. 就是把一个只包含注册时得到的 access token的对象 HTTP POST给:

CI_SERVER_URL/api/v1/runners/register.json

      1. 如果 GitLab-CI说有变化了,那么临时生成一个 bash脚本并执行之
        1. 项目源代码会放在工作目录之下:tmp/builds/project-id
        2. git fetch repo (第一次则 clone)
        3. git checkout $ref (ref由服务器返回的信息里提供)
        4. 依次执行 GitLab-CI返回信息里的 commands数组里的每一条命令
          1. 这些命令可以使用以下环境变量来获取必要的信息:
            1. CI_SERVER=’yes’
            2. CI_SERVER_NAME=’GitLab CI’
            3. CI_BUILD_REF, CI_BUILD_BEFORE_SHA, CI_BUILD_REF_NAME, CI_BUILD_ID, CI_BUILD_REPO, CI_PROJECT_ID
            4. CI_PROJECT_DIR(这个是 Runner本地工作目录)
          2. 所有命令要在指定时间时结束,默认是7200秒,GitLab CI 服务器可以为项目指定不同的值。
          3. 命令的 stdout stderr都转向一个临时文件;
          4. 所有命令的输出,以及异常情况都会合并成 trace信息;
          5. 任意一条命令失败,则中止执行,并将执行状态标记为 failed
          6. 所有命令都成功完成,则标记为 sucess状态;
        5.  build的命令执行状态、trace信息发回 GitLab-CI
          1. 就是把 state trace拼成一个 json对象,HTTP POST

CI_SERVER_URL/api/v1/builds/{id}.json”(idGitLab-CI给的build id)

 

 

      1. 总结一下:
        1. GitLab CI Runner是用 ruby做好的一套 Runner环境。
        2. GitLab-CI服务器会把工程信息以及一组命令发给 Runner
        3. GitLab CI Runner 会自动取出源代码,然后执行收到的命令。
        4. GitLab CI Runner会把命令执行的结果、出错时的 trace一起发回 GitLab-CI

所以制作 meteor velocity runner就是要把环境准备好,然后用让项目调用 meteor run –test,用 console reporter输出测试进度,测试失败时meteor run返回一个非0值即可。

话说,GitLab CI Runner其实简单,为此搭上一堆 ruby环境其实挺不值当的,什么时间有空拿 node.js重写一个就完美了。显然我不是第一个这么想的人,https://github.com/evanlucas/gcr已经做了。

 

      1. 要将 meteor velocity runner做成 docker,倒是简单的。

从头写个 Dockerfile也没多麻烦,https://registry.hub.docker.com/u/vdubyna/gitlab-ci-docker-runner/就是个从头写的例子。直接用 docker hub上做好的也有,比如 bobey/docker-gitlab-ci-runner-node就不少人用。我们前面都在用 sameersbn的工作成果,其实也有一个 sameersbn/gitlab-ci-runner。用 Trusted Build派生一个环境多少能省点事。不过既然找到了 gcr,就做一个这样的吧:

      • docker-node:提供 node.js运行环境,跟 sameersbn的几个东东一样基于 ubuntu:latest,虽然  debian会更小一点。
        • docker-gitlab-ci-runner-node:加上 gcr 
        • docker-meteor:加上 meteor 
          • meteor-gitlab-ci-runner:加上 gcr 
      1. 正常运行的 Runner GitLab收到代码之后

gcr info [client] checking for builds…

gcr http 201 http://ci.my.com/api/v1/builds/register.json

gcr info [client] submitting build 1 to coordinator…

gcr http PUThttp://ci.my.com/api/v1/builds/1.json

gcr http 200 http://ci.my.com/api/v1/builds/1.json

gcr info [client] submitting build 1 to coordinator…

gcr http PUThttp://ci.my.com/api/v1/builds/1.json

gcr http 200 http://ci.my.com/api/v1/builds/1.json

gcr info [client] submitting build 1 to coordinator…

gcr http PUThttp://ci.my.com/api/v1/builds/1.json

gcr http 200 http://ci.my.com/api/v1/builds/1.json

gcr info [client] submitting build 1 to coordinator…

gcr http PUThttp://ci.my.com/api/v1/builds/1.json

gcr http 200 http://ci.my.com/api/v1/builds/1.json

gcr info [client] submitting build 1 to coordinator…

gcr http PUThttp://ci.my.com/api/v1/builds/1.json

gcr http 200 http://ci.my.com/api/v1/builds/1.json

gcr info [client] submitting build 1 to coordinator…

gcr http PUThttp://ci.my.com/api/v1/builds/1.json

gcr http 200 http://ci.my.com/api/v1/builds/1.json

gcr info [runner] build success [1]

 

 

 

      1. Velocity自身的 CI模式。

Velocity如果读到环境变量VELOCITY_CI有设置的话,就会以 CI模式运行,具体说就是在development环境里,会对每个已注册的testFramework调用 /reset /run,也就是每次运行时会把所有类型的测试都执行一遍。

!目前碰到的问题是 Mocha client tests不会执行,在Host Ubuntu 14.04里是好的,可见是ubuntu:latest这个环境里有什么不对,还没有找到解决办法。怀疑是 Mocha对于 headless linux支持有问题,但是  mike:mocha里其实有PhantomJS的脚本,不过文档里没有提到类似JASMINE_BROWSER=PhantomJS的选项,代码里也还没找到怎么启用这个脚本。测试下来 Jasmine client unit也有它的问题。

 

测试下来,2G内存的虚拟主机跑这个全 dockerCI环境还是太免强了。还是直接在 VPS里搭环境省心。虽然 Docker具有迁移方便的优点,不过将来把 GitLab/CI/Runner分别迁到自己的服务器里其实也没多麻烦。

– 太长了,英文版先欠着

Symbol Navigation in Atom Editor

There is a “Go to Declaration” in context menu of Atom Editor, but it doesn’t work by default. It is because Atom doesn’t scan the project to generate symbols, it depends on tags, tags can be generated by run command “ctags -R in project root”.

cmd-r can lookup symbols in current buffer (file), it doesn’t requires tags pre-generated.

cmd-shift-r can search the symbol over the whole project, it requires tags.

Go to Declaration shortcut menu is same as cmd-shift-r and typing the symbol under the cursor. It is a frequent operation, thus the hot key cmd-alt-down is assigned 。

Atom doesn’t provide the function to find all the reference to a specific symbol, yet.