ユビレジのテスト版ベータ配信をCrashlytics/Fabricに移行した

TestFlight has moved.とのことなのでひと月ぐらい前から移行先を検討していて、各社の動向を探りつつ(ネットウォッチで)どのプラットフォームに我々の未来を託すべきか・・と熟考した末。全く記憶から消していて昨日いきなり思い出してやばいと思ってどれでもいいからとすぐに移行した。

https://get.fabric.io/beta

Crashlyticsはクラッシュレポートを収集する組込みSDKを提供していたサービスなんだけどFabric - Twitter's Mobile Development Platformの一部になって(デプロイツールでもフリマアプリでもない)
「Beta by Crashlytics」というモジュールも追加されたのでこれがTestFlightの代替になる。利用は個人でもビジネスでも無償。

ユビレジではクラッシュレポート分析にCrittercismを利用しているのでCrashlytics SDKは組み込んでいないんだけど(Crittercism > Crashlytics と評価しているわけでもなく。そもそもクラッシュ頻度が少なくCoreDataやUIKit深部のなぞエラーばかり来る)
ベータ配信は実質的に Crashlytics.framework の内部コマンドにIPA形式のファイルとAPIトークンを渡せばできるので、アプリケーションにリンクする必要はなかった。

セットアップは基本的にCrashlytics公式のガイドに従っていくとコンプリートできるようにはなっているんだけど。ちょっとめんどくさいのがFabric, Crashlytics, Twitterのそれぞれのアカウントを使ってセットアップするところが非常にわかりづらかった。これはFabricプラットフォーム自体が整備されたら改善しそう。

またAPIトークンを手に入れるにも一度 Fabric.framework という別物のSDKを組込み作業をMacXcodeGUIのセットアップフローでこなす必要があった。個人的にはまわりくどくてめんどくさいと思っていたが、「設定が簡単で気が効いている」という声も結構あるようだ。実際Fabricチームの作るWebアプリのGUIはよくできていると思った。


具体的にやったことはまず、ユビレジアプリはDistributionまわりは可能な限り自働化してあり。Travis-CIをテスト実行だけでなくリモートのOS X上で好きな処理を実行できる汎用のMacマシンとして活用しているので。その過程で肥大化していったRakefileXCJobsという名前でgem化していて。これに組込めるようなものを想定して

notes = 'notes.txt' # リリースノートのテキストファイル
group = 'Dev' # Crashlytics上で設定したグループ名
command = %[./Frameworks/Crashlytics.framework/submit #{FABRIC_API_KEY} #{FABRIC_API_SECRET} -ipaPath #{File.join(BUILD_DIR, "#{SCHEME}.ipa")} -groupAliases #{group} -notesPath #{notes} -notifications YES] # YES でメール通知
sh command do |ok, res|
  puts res
  fail 'Submit to Crashlytics-Beta has failed' unless ok
end

Beta Distribution with iOS build servers – Support for Crashlytics を参考に。

みたいなことをするRakeタスクを定義してTravis-CI上からアップロードしている。Crashlytics自体Fabricの過渡期に巻き込まれてこれからどんどん変わっていきそうなので、方法とかドキュメントとかが落ち着いてきたら見直そうと思っている。xcjobs-0.0.7でもできるようになった(README参照)

APIキーは https://fabric.io/settings/organizations からリンクを辿るとこのへんからも取得できる。

注意点としてはCocoaPodsでインストールできる Crashlytics.framework はオフィシャルのものではなく有志がメンテしている感じなのでFabricのサーバーからダウンロードできるバイナリと比べると古いバージョンだということがあった。そのため上記のセットアップフローを手動で最後までやってFrameworkをまずダウンロードしてくる必要がある。

https://fabric.io/downloads/xcode

ライブラリの選定基準

今回のように「こういうことを実現したいのでライブラリの力を借りる必要がある」というケースに結構出会す。

以前はその界隈の最新の流行のものをとか自分が気に入っているもの、みたいな基準で選んでいたのだけど最近は「1年後のメンテナに恨まれない選択(なぜならこころがつらいから)」という至極後ろ向きな視点を心掛けているので

Vue.js が辛くなってきた | status code 51

とかも結構共感する。

これは良い面をみると経験を積んで長期的で安定で保守的な思考になっているというといわれはいいんだけど、ずばり老いと筋力の低下が影響して公平な判断ができなくなっているんだと予想している。

ssig33.com - インターネットが面白くなくなった

つまり、ライブラリを選定する立場の人やシステムアーキテクトに必要なのは強靭な肉体。自重トレをしろ。

はてなブックマークの検索結果からコメントないfavoritesの人を消すUserScript

// ==UserScript==
// @name         はてなブックマークの検索結果からコメントないfavoritesの人を消す
// @namespace    http://lai.so/
// @version      0.1
// @description  $name
// @author       laiso
// @match        http://b.hatena.ne.jp/search/*
// @grant        none
// ==/UserScript==

setTimeout(function() {
  $('ul.favorite li')
    .filter(function(){ return $(this).find('span.comment').text() === "" })
    .map(function(){ this.style.display = 'none' });
}, 3*1000);

いつもの感じのやつです

f:id:laiso:20150129125444p:plain

これがつらいので

f:id:laiso:20150129125443p:plain

こうする。

この部分非同期に挿入しているようでちゃんと書くのがめんどくさかったので3秒待って実行することにした。

Tampermonkey

はてなブックマークトップのPR記事を消す.user.js

// ==UserScript==
// @name        はてなブックマークトップのPR記事を消す.user.js
// @namespace    http://lai.so/
// @version      0.1
// @description  はてなブックマークトップのPR記事を消す.user.js
// @author       laiso
// @match        http://b.hatena.ne.jp/
// @grant        none
// ==/UserScript==

var entries = document.querySelectorAll('li.entry-unit');
var prs = _.filter(entries, function(entry){ return entry.querySelector('li.pr') !== null; });
_.each(prs, function(entry){ entry.style.display = 'none'; });

Tampermonkey に放り込んでる

Desk.comのケースを自動で閉じるChrome拡張ができました

Releases · laiso/desk-neglector-chrome

desk-neglector-*.crx をダウンロードして、Window -> Extension のタブに放り込みます。

仕様

/agent ページを訪れた時に10秒ごとにケースを開いているかチェックして、開いていたら60秒後に閉じます。

'use strict';

var hasOpenCases = false;
window.setInterval(function () {
    if ($('.tab_closer').length > 0 && !hasOpenCases){
        hasOpenCases = true;
        window.setTimeout(function(){
            hasOpenCases = false;
            $('.tab_closer').each(function(){ $(this).click() });
        }, 60*1000);
    }
}, 10*1000);

GitHubでWatchしてるリポジトリの通知をマージされたプルリクエストだけに絞る

f:id:laiso:20150117103931p:plain

GitHubで試しにWatch増やしていってみたら全部追えなくなって自然とマージされたやつだけ目grepするようになっていたのでbookmarkletにした。

$("li.list-group-item")
  .filter(function(){ return this.getElementsByClassName("type-icon-state-merged").length === 0 })
  .map(function(){ this.style.display = "none" });

おまけ: プルリクエストだけにする

$("li.list-group-item")
  .filter(function(){ return $(this).find('span.type-icon').attr('aria-label') !== 'pull request' })
  .map(function(){ this.style.display = "none" });

AWS Lambda でS3 にファイルをアップロードしたらSlackチャットに通知するやつ

f:id:laiso:20150116150750p:plain

AWS Lambda をさわってみたら楽しげだったので作ってみた。

ソース: aws-lambda-samples/s3slack at master · laiso/aws-lambda-samples

zip圧縮してブラウザからアップロードできます(ルートをフォルダで包まないこと)。 やっていることは以下。

const SLACK_TOKEN = "xxx...xxx";

var req = require('request');

exports.handler = function(event, context) {
    var filename = event.Records[0].s3.object.key;
    req.post('https://slack.com/api/chat.postMessage')
        .form({
            token: SLACK_TOKEN,
            channel: "#s3",
            text: "Put: "+filename
        })
        .on('response', function (response) {
          response.on('data', function(data) {
            context.done(null, data);
          });
        })
        .on('error', function (err) {
            cotext.done(err, 'Failed post the chat');
        });
};

SLACK_TOKEN: Slack Web API | Slack このへんで取れます

S3: Amazon Web Services ブログ: 【AWS発表】S3の新しいイベント通知機能 このへんと

AWS Lambda: 初めてのJavaScript、初めてのAWS Lambda | Developers.IO このへんを参考にセットアップしてください

知見

  • RebelMail/node-lambda · GitHub を使うと。Eventオブジェクトのfixtureつけてrunしてくれたりするのでローカルでテストできる
  • npmの外部モジュール使いたい時はzipファイルにしてディレクトリ直下に全部必要なファイルバンドルする
  • npm installしたnode_modules以下はシンボリックリンクなのでそのままだとzipファイルには入らない
  • node-lambda でデプロイまでできるみたいだからこのへん気にしなくてもよくなるかもしれない
  • cotext.done 呼ばないと未完了扱いになって自動で3回リトライされる

他の活用事例

AWS Lambda Advent Calendar 2014 - Qiita

AWS Lambda Shell Hack

なんか楽しそうなやつ

factory_girl みたいなやつ in #iOSDev

のどちらか。

FactoryGentleman はSoundCloud社で作ってるので普通に考えたらCMFactoryより寿命が長い(CedarとKiwiの事例があるけど……)。
オブジェクト生成は NSInvocation を使ってある程度ダイナミクに実現しているようだ。

CMFactoryはJSONやplistのfixturesを用意しておいてそれを読み込むためのユーテリティという感じ。あとMantleサポートがある。