おそらくはそれさえも平凡な日々

Kibelaクライアントのkibelasyncを作った

https://github.com/Songmu/kibelasync

Natureでは、Kibelaをナレッジベースとして利用していますが、文章は書き慣れたエディタで書きたいという気持ちがあり、クライアントを作った。GraphQLの勉強にもなると思ったというのもある。

名前やコンセプトはblogsyncのオマージュです。手元にMarkdownをごそっと落としてきて、編集して更新するものです。

Install

% brew install Songmu/tap/homebrew
# or
% go get github.com/Songmu/kibelasync/cmd/kibelasync

https://github.com/Songmu/kibelasync/releases からバイナリ取得も可能です

Setup

KIBELA_TOKENKIBELA_TEAM環境変数を適宜設定してください。

Usage

記事を取得する

デフォルトでは ./notes 以下にごそっとMarkdownを取得します。これは KIBELA_DIR 環境変数や、-dir オプションで変更可能です。

また、取得時にMarkdownファイルのmtimeがその記事の最終更新日時にセットされます。

# 全件一括取得(ローカルファイルのほうが新しい場合は更新されない)
% kibelasync pull
# 全件一括取得(問答無用で全てのファイルを上書き・高速)
% kibelasync pull -full
# limit指定(更新日時が新しいものから指定件数取得)
% kibelasync pull -limit 10
# folder指定
% kibelasync pull -folder=議事録

記事を更新する

落としてきたMarkdownを編集後、そのファイルを引数に指定して、push サブコマンドを叩きます。

% kibelasync push notes/333.md

記事を作成する

サブコマンドpublishに標準入力、もしくはMarkdownファイルを引数に指定することで新規記事を作成できます。

% kibelasync publish --title=こんにちは /path/to/draft.md
% kibelasync publish --title=kibelasync
さてかきはじめるか…
^D
% echo "# こんにちは\nさようなら" | kibelasync publish

この時、何らかの形でのタイトル指定が必須です。Markdownの冒頭にMarkdownのh1要素がある場合、それがタイトルだとみなされます。

# 共同編集を有効にする
% kibelasync publish -co-edit /path/to/draft.md
# 記事投稿後、当該記事のMarkdownをサーバーから取得して保存する
% kibelasync publish -save /path/to/draft.md

-save オプションを利用した場合、元のMarkdownファイルは削除されます。

ということで

だいぶ便利だと思うのでご利用ください。開発にあたってはAPIの挙動に関してKibelaにいくつかフィードバックを送らせてもらい、爆速で対応してもらいました。ありがとうございました。

開発言語はGoですが、実装的に面白い点として、APIリミットに引っかからないように、http.Client.Transport をカスタムして過剰なリクエストを送らないように工夫しています。このあたりは、先日のOpen Go Friday in Fukuokaでお話させてもらいましたが、別記事にまとめるかも知れません。興味がある方は、client/ratelimit.go辺りの実装を見てみてください。

Go Conference'19 Summer in Fukuokaで登壇してきた

https://junkyard.song.mu/slides/gocon2019-fukuoka/#0

色々あってお声がけ頂き、登壇させてもらえることになったので、福岡に行ってきました。出張扱いで、出張費用も所属のNature Japan株式会社に出してもらいました。

話した内容は、Go Conference 2019 Springで20分で話した内容を、単なる再演にならないように内容を膨らませて40分で話した感じです。割と好評のようで良かったです。資料は口頭で説明した部分も多いので、トピックに分けて改めてブログ記事にしたいと思っています。

イベント全体を通して

スタッフの皆さまが少人数ながら的確に動いていて、何もストレスなく快適にイベントを過ごすことができました。すごく楽しかった。ビールや生ハム、スピーカーディナーも楽しませてもらいました。スポンサーの各社に感謝。

会場のFukuoka Growth Nextも小学校をリノベしたスタートアップ支援施設ということで、趣があって良かった。高島市長がいらっしゃったのはびっくりしました。市長のスピーチすごかった…。

交流とか

@k1LoW さんと初めてお話できたのが良かった。ツールを量産していることになんとなく一方的に共感を持っていて、実際、彼の発表でお話されていた「技芸のコードによるボトムアップ」という言葉には共感を感じることができた。

@pyama86さんには毎回福岡行くたびに勝手にお世話になっています。ありがとうございます。

@budougumi0617さんと話が盛り上がった。普段、東京でも交流がありますが、地方のカンファレンスで話すとなんか盛り上がったりして、そういう合宿的な非日常感は地方開催ならではというところ。

あとは、前夜に、メルカリさんの福岡オフィスにお邪魔してOpen Go Friday #5に参加させてもらったのですが、そこで期せずして@dragon3さんに二年ぶり(YAPC::Fukuoka以来!)にお会いできたのが嬉しかった。

その他福岡の皆様と色々交流させてもらいました。なんだかんだで福岡には年に一回くらい行っていて、今後も行きそうなのでまた機会でもよろしくお願いします。

bashでdotenvファイルを環境変数に読み出す

.env みたいな環境変数設定ファイルを読み込んでから指定プログラムをexecするみたいなラッパーが欲しくなる事あると思います。

Goだとgithub.com/joho/godotenvとかあるけど、Goでやるほどでもないよねーという感じだったので、bashで書くなどした。

#!/bin/bash
set -e
if [[ "$#" = "0" ]]; then
    echo "usage: env-wrap.sh cmd [args...]" >&2
    exit 1
fi

# declare -x を引数無しで呼び出して、現状の環境変数をexportableな形式で書き出す
orig_env="$(declare -x)"

envfile=.env

# allexportは`KEY=VALUE`をシェル変数じゃなくて、環境変数としてexportする危険なオプション
set -o allexport
source $envfile
set +o allexport

# 元の環境変数を優先するために書き戻す
eval "$orig_env"

exec "$@"

declare -xset -o allexport とかがポイントです。

bashやzshでしか動かないので、それ以外の環境で動かさないようにお気をつけください。

bashで配列の各要素を適切にクオートする

シェルスクリプトでラッパーを書くときに、exec "$@" とかよくやると思います。$@は特殊な変数で、クオートすることによって、配列の「各要素」が適切にクオートされて関数などに渡される。正確に言うとクオートされるわけではないのですが、要素に空白が含まれていてもばらばらにならないということです。

この振る舞いを普通の配列で実現するにはどうすればいいのか。これは、"$array[@]" のように添字に@を指定してやれば良い。これは配列が存在するbash限定の話です。

Shell Parameter Expansion に色々書いてあって学びがあるので読むとよいです。

certbotを使ってサイトをhttps化した

6月5日から変わっています。wwwも付いたり付かなかったりだったのを付いてない方に統一しました。

アーカイブ 見ると、徐々にはてブが移行されているっぽくて面白い。

令和にもなったし、301を返していれば、はてブも統合されるようになったので、流石に充電期間中httpsにするかーと思っていた。

今どきのオシャレな方法で実現しようかとも思ったが、結局時間が取れなかったので、今のVPSのNginxからRijiで生成した静的ファイルを配信する方式を維持したまま、certbotでぱぱっとやってしまった。非常に簡単だった。同様の事例はたくさんあるが、メモがてらログを残しておく。

環境構築

リポジトリをcloneするだけ。

% git clone https://github.com/certbot/certbot.git
% cd certbot
% ./certbot-auto ...

以降、certbot-auto というコマンドを使って各種操作をおこなうことになりますが、こいつを叩くと、追加依存のインストールや、自動更新、sudoでの実行など諸々よしなにやってくれる。ツールの特性上、自動更新がちゃんとされるのは安心。ただ、いろいろ頑張っているからか、起動はかなり遅く、もっさりしている。致し方ないか。

証明書の発行

以下のようなコマンド実行するだけ。今回はNginxが既に実稼働しているサーバーなので、そのwebrootを指定している。

./certbot-auto certonly --webroot \
  --webroot-path /home/Songmu/htdocs \
  --domain songmu.jp \
  --email y.songmu@gmail.com \
  --agree-tos -n

/etc/letsencrypt 配下に証明書や諸々が書き込まれる。

サーバー設定

/etc/letsencrypt/live/ドメイン 以下に証明書が配置されるので、Nginxであれば以下のように書いてやれば良い。

server {
    listen 443 ssl;
    ssl_certificate     /etc/letsencrypt/live/songmu.jp/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/songmu.jp/privkey.pem;
    server_name  songmu.jp;

証明書の更新

これも非常に簡単で、以下のコマンドを実行すれば良い。

./certbot-auto renew --post-hook 'sudo service nginx reload'

特にドメインの指定などが必要ないのは、/etc/letsencrypt/renewal 以下に /etc/letsencrypt/renewal/songmu.jp.conf のような設定ファイルが書き込まれているため。

ドメイン期限が1ヶ月以内に迫っているときだけ更新をしてくれる親切仕様になっている。また、--post-hook は証明書が更新された時のみ実行される便利フック設定。ここではNginxのリロードを指定している。 certbot-auto renew && sudo service nginx reload などとしてしまうと証明書が更新されてなくても毎回リロードかかってしまうので、ちょっと困る。

上記のコマンドは、実行しても証明書を発行したばかりの時はスキップされるので、更新動作を確認したい場合は、--force-renewalを指定して動作確認をしてみると良いでしょう。ただ、--force-renewal はLet's Encryptのサーバーへの負荷の観点もあり、普段は使わないほうが良いオプションです。

更新の自動化

cronを適当に仕込んでおけばよいが、certbot-autoもNginxのリロードもsudoが必要で、cronでsudoを使えるようにするのは大変。つまり、sudoersのrequirettyのユーザー設定と、パスワード無しでsudoができるコマンドを指定するなどが必要。

めんどい上にセキュリティを緩めることにもなるので、それは避けて普通にrootのcronで動かすようにしてしまった。

# /etc/cron.d/certbot-renew
37 18 * * 5 root /usr/bin/mkr wrap -n certbot-renew -- /home/Songmu/certbot/certbot-auto renew --post-hook '/sbin/service nginx reload'

ちゃんと動くか少し不安なので、mkr wrap を使ってMackerel監視するようにした。便利。

これも、Let's Encrypt側のサーバー負荷の観点から、実行時間を散らすためにランダムスリープなどを入れることが望ましいとされています。実際Debianでパッケージインストールした場合は、 perl -e 'sleep int(rand(3600))' && certbot -q renew というようなcron設定がなされるようです。Perlが使われていてウケる。

それをやっても良いのですが、日次じゃなくて、週次(5なので毎週金曜日)で動かすようにしたので、まあそれでいいでしょう、ということで。

Nature Remo作ってる会社のCTOになったのでみんな買ってくれよな!

6月1日付けでNature Japan株式会社の取締役CTOに就任しました。最初の営業日の6/3(月)からいきなり台湾出張に行ってきました。良いスタートアップ感。ついでに本日6月5日に39歳になりました。新たなチャレンジにワクワクしています。

大塚(@maaash)さん、村瀬(@typester)さんに続く3代目のCTOとなります。2人はカヤック時代の同僚でもありますが、カヤックのラボチームのダブルエースだった彼らの後任としてCTOをやるのは恐れ多いのですが、僕は組織づくりなど含めて僕なりに組織に貢献していきます。

当社はおかげさまでスマートリモコンのNature Remoが好調で、現在はNature Remo Eというスマートエネルギーハブの開発を進めているところです。今後は電力なども見据えて事業を展開していく計画で面白いフェーズにあります。

まだ、社員全員でも10人に満たない小さな会社ですが、これからより成長させて、エンジニアも採用していきたいので、興味のある人は是非連絡ください。オフィスは今は恵比寿です。近くにお立ち寄りの際は、ぜひ遊びに来てください。

こちらからもお声がけなどさせていただくこともあると思いますがよろしくおねがいします。

技術スタック

こんな感じです。インフラからクライアント、組み込みまでまだまだエンジニアに来て欲しい状況です。Cでファームウェアを書くとか僕も全然やったことありませんが、そういう新しいチャレンジをしてみたいという人も歓迎です。

React Nativeに関しては@typesterと@soh335がでている以下のインタビュー記事があります。

React NativeでiOS/Androidアプリを丸っと開発! Nature Remo開発で分かった長所と短所

転職理由とか

以下は個人的な話。

typesterに請われたこと

転職を決めたのは、尊敬しているtypesterさんに熱烈に請われたというのが一番大きな理由です。typesterとはカヤック時代の同僚であり、360度評価で彼に書いてもらった評価文言は今でも大事に保存しています。

rebuild.fmを聞いている方はご存知かも知れませんが、typesterがアメリカに移住するため、その後任のCTOが必要な状況であり、そこで彼に「Songmuが一番良い」と白羽の矢を立てていただきました。

今年の年末年始休暇の際にtypesterから話をもらい、CEOの塩出とも話をさせてもらって、かなり迷ったのですが新しい道に進むことにしました。

「僕が断ったら誰に声かけるつもりだったんですか?」と後で聞いたら、ビッグネームがいろいろ出てきて、それより評価していただいていたのは光栄でした。僕はtypesterの技術を含めた審美眼は信用していて(多くの人が注目する前からNode.jsやRedisやGoやRustを良いと言っていた…!)、その彼が僕にそういう評価を下してくれていたのは非常に嬉しかった。

冒頭でも書きましたが、maaashさん、typesterさんの次のCTOをできるのは非常に光栄なことです。彼らはカヤック時代、僕のソフトウェアシステムアーキテクトの師匠とも言える存在でした。僕がモノリシックなWebアプリケーションの作り方しか知らなかった頃に、彼らが必要に応じて独自デーモンをいくつも作ってシステムを組み上げていく姿には衝撃を受けました。

まあその後の運用が大変になったりもするのですが、そこも含めて彼らが携わったシステムを現職で引き継げることは楽しみに思っています。

IoTハードウェアを作るということ

元々Nature Remo自体は便利に使ってはいたのですが、技術領域として、ハードウェアやIotにはそれほど興味はありませんでした。電子工作とかをするわけでもないので。だからこそ、逆に、こういう未知の領域でチャレンジできるチャンスが舞い込んできたのは面白いと考えました。

情熱があって何かを始める人なんて少なくて、普通は何気なく始めたことに無意識のうちにのめり込んで、そこから情熱が生まれる

岡本太郎のこの言葉が好きで、なんでも前向きに、主体的に取り組んでみたら面白くなるものです。Mackerelも最初は正直そこまで興味があるわけではなかったのだけど、やってみたらめちゃくちゃのめり込んだ。現職でもそういう体験をしたいと思っています。

今も、ECHONET LiteWi-SUNといった全然知らなかったプロトコルや規格の話が出てきて大喜びしています。

ハードウェアを含めた生産を如何にアジャイル的にやるかみたいなところにも興味があり、トライしていきます。

強力なプロダクトオーナー

前職では長らく僕自身がプロダクトオーナーをしていて、それはそれで面白かったのですが、個人的には強烈な個性を持つプロダクトオーナーと一緒にやるのも結構好きというのもあります。

CEOの塩出は個性的なビジョンを持っている人で、まだ若く、頭の回転も速いので、一緒にやっていくのはかなり面白そうだと思っています。

リスクテイク

誘われたとき、正直、生活水準の維持が頭をよぎりました。

はてなで働く中で、子供が2人でき、マンションも購入し、生きていく上で考慮すべき事項が増えました。そして、はてなのエンジニアの中でトップクラスに給与をもらっていましたし、フリーランチもあるので働くには恵まれた状況でした。

だから逆にその環境を捨てるのには躊躇してしまう状況でもありました。今回の話を受け、そういう自分に気づき、身軽さを失っていることに危機感を覚えました。まだギリギリリスクテイクできるだろうということで、妻とも相談し、新しいチャレンジをすることを決めたということもあります。

よく考えてみると、こんなチャンスはなかなかなく、これまでエンジニアとして実績を積み上げてきてよかったとも感じています。

個人的には、ベンチャーの多くのことが決まっていないカオス感が好きです。とはいえこの規模の人数のどベンチャーともなると初めてなので、その中で自分が経営者としてどう振る舞えるか、成長できるかというところには自分のことながら関心を持っています。

ということで、皆様Natureをよろしくお願いいたします。

認定スクラムマスターになりました

https://www.scrumalliance.org/community/profile/mmatsuki2

アトラクタ社の認定スクラムマスター研修を受け、テストも合格し、晴れて認定スクラムマスターとなりました。だからなんだというわけでもないですが、スクラムに関する交流や雑談などしたいとかあれば、ご相談ください。

受けたのは以下の研修で、Gabrielle Benefieldさんと原田騎郎さんが講師でした。

比較的長年アジャイルやスクラムに関わってきたので、良い知識の再整理の機会になりました。ありがとうございました。

私とスクラム

意外かもしれませんが、僕はそれなりにアジャイルやスクラムを経験してきました。とはいえ、今の開発者が押さえておくべき技術分野の一つなので、人並みくらいかもしれません。Mackerelチームでのスクラムを取り入れており、2年弱スクラムマスターを、3年弱プロダクトオーナーを経験してきました。アンチパターンであるPO, SM兼務の経験もしました。

僕とスクラムの出会いは、2012年の頭です。当時のカヤックのソーシャルゲームチームに、あの@ryuzeeさんがコンサルで入っており、そこでいろいろ教わりました。そこでアハ体験があり、その後はアジャイルやスクラムに興味を持ち積極的に考え方なども取り入れるようになったのです。

変化に強くなりましょう、自律的なチームでありましょう、っていうところが特にスクラムの好きなところ。

その後、ryuzeeさんとは継続的に交流させてもらっていますが、その中で彼ほどのスクラムコーチはなかなかいないという実感も強くなりました。一番最初に一番良い人にスクラムを教わったので運が良かった。

研修を受けた訳

それなりにスクラムを自己流で経験してきたので、改めて知識の再確認と振り返りや、トレンドやアップデートのキャッチアップなどのためというのが主。

また、長年プロダクトオーナーをやってきましたが、次の会社ではPOは別にいて、開発体制の整備なども含めてやることになりそうなので、スクラムマスターの研修が良いかなとも思ったというところ。

5月は実質無職だったので、学生の夏休みみたいに何も成果を出せないで浪費してしまうことも懸念されたので、そこは自腹を切って研修を受けて、認定スクラムマスターになるという成果くらいは出すか、という思いもありました。

あと、daiksyさんが最近研修を受けて良かったと言っていたのも後押しになりました。

研修について

参加40人の中で、5年以上スクラム経験ある人が僕含めて3人くらい。Web系よりは、スクラムを最近聞いたとか取り入れたとか、比較的堅めの業界の人も多くて、スクラムの広まりを感じた。いろいろな業界な人が入る分議論が盛り上がって面白かった。

講義の進め方もユニークで、それほど資料は使わず、GabrielleさんがiPadに図や絵を書いて、それをプロジェクターで映しながら講義し、それにワークショップやQ&Aを挟むスタイルで、groove感があって良かった。daiskyさんから聞いていた彼が受けた研修の様子とは結構違いそうだったので講師によってスタイルの違いがあるのだなーと思った。

研修で面白かったところ。

outputよりoutcome

これは再三言われていた。機能をリリースした数ではなく、リリースした機能がどういう効果をもたらしたかが大事、ということ。ベロシティを追い求めすぎると、output過多になってしまい作り過ぎの無駄を背負い込むことにもなるので注意。ベロシティは将来を予測するためのもので、過去をトラッキングするものでもないし、スコアとして追い求めるものでもない。

プロダクトオーナーを複数人が務めるのは有り有りや無しや

これはスクラム専門家の間でも議論がある。基本的には一つのスクラムチームで一人がいいのではないか。ちなみに、顧客がプロダクトオーナーをやるのは無理だと考えたほうが良い。顧客はステークホルダーである。

スクラムマスターはチームにスクラムのプラクティスを遂行させる

思っていたよりも役割としてそれをしっかりやることがスクラムのフレームワークでは求められてるのだなぁということを感じた。ただ、スクラムマスターが権威的になってもいけないというのも同時に言われていて難しいですね、ってなった。「考えさせることが大事」とも。

最近はDoneは「完了」じゃなくて「完成」と訳すようになった

「完了」だと何にせよ終わっていれば良いというニュアンスになってしまうため「完成」の方が適訳。プロダクトバックログがちゃんと出荷可能状態で「完成」しているか。

最適なプロダクトバックログの見本を見せるのは難しい

チームによる。「スクラムチームが経験を積むと、バックログは雑になってくることも」という話もあって、わかるーと思いつつもそれを言い訳にするのは良くないなとも思った。

スプリントゼロについて

スプリントを回し始める前の準備期間を便宜上スプリントゼロと呼ぶ人がいる。これはスクラム公式の用語ではないことに注意。これも流派はあるが、講師の原田さんとしてはインクリメントがないのにそれをスプリントと呼称するのは違和感があるのでスプリントゼロという言葉は使わない方が良いという立場。

ただ、スプリントを回し始める前に準備をしっかりやったほうがその後が速いのが確かで、2スプリント期間を超えない範囲で準備期間を設けるのはアリ。

余談だが、デザインスプリントも混同されやすい言葉だが、これもスクラムのスプリントとは関係ないプロトタイピング手法なので注意。

使われてない機能は削る。そのために計測する。ドキュメントも同様

なかなかできないけどそうだよな、という感じ。面白かったのはドキュメントの閲覧数を見ると良いという話で、確かに見られていないドキュメントは消すなり、再確認するなりしたほうが良さそう

ハードウェア開発とスクラム

短いスプリント期間が切りづらく、リードタイムが長いものに対してどうするのか、という話。これもいろいろ実例があるけど、テストハーネスとシミュレーターを作り込んでそこでイテレーションを回すのが大事、という話だった。おっしゃる通りだけど、大変そうだな、とも思った。

医療の世界とスクラム

多くの事例が出てたけど、医療や製薬みたいなクリティカルな世界でも欧米ではかなりスクラム化が進んでいるようで驚いた。「多くの実験や検証が必要なのだから、スクラム的にやらないと無理だ」などとも言われていて、確かにおっしゃる通りだけど、なにか怖さを感じてしまう。これは僕のマインドチェンジが足りてないんだろうなー。

このあたりのマインドの話は他の参加者とも温度差を感じるところはあった。「納品したら別のチームが運用を引き継ぐ」「開発とインフラは別」みたいな前提からなかなか抜けられない人もいるようにも。

このあたりのスクラムに対する理解度により、それをどこまでの領域で適用できるかというところにも関わってくるのだろうと感じた。「チームでフルスタックになる」という言葉も講義で度々出てきて、そのとおりだと思った。

GoConでGoによるコマンド起動と停止について話してきました

嬉しいことに、Go Conference 2019 Springのプロポーザルが通ったので、自作のtimeoutパッケージを例にしながらGoからコマンドを起動して停止させる方法について話してきました。

https://junkyard.song.mu/slides/gocon2019-spring/#0

コマンド起動と停止というと簡単な話に聞こえるかも知れませんが、実はちゃんとやるためには考慮すべき事柄があります。そのあたり、GNU timeoutのソースコードも交えながら説明しました。結構面白い話ができたんじゃないかと思います。

github.com/Songmu/timeoutは単にコマンドをタイムアウトさせる目的だけではなく、contextでコマンドを正しく停止させるのにも有用なので是非お使いください。

プロセス停止に関しては大体以下のようなことをお話しました。

GoConは実践の話が多くて面白かった。システムプログラミング的なのは少なめだったので、また話す機会があればそういうことを話せれば良いかな、とも思っています。

GitHub Pagesを独自ドメインにしてhttps化した

資料置き場や雑多な画像やスクショ置き場などにGitHub Pagesを利用していたが、独自ドメイン配信にして、https化もした。GitHubのrepository上で作業して、ドメインのCNAME設定するだけですぐできた。httpsに関しては最初は証明書エラーがでてたけど30分くらい待ったら正常になった。

はてブに関しては、301かcanonicalが設定されていればそのうち統合されるようになったので、反映待ち。

コメント一覧ページを統合する(エントリー正規化機能)

外部サイトから画像やiframeがリンクされている場合に表示されない等あるかもしれませんので、その場合適宜調整いただけると助かります。

ghq v0.11.1 でGoの依存取得や一括アップデートが便利になりました

motemenにcollaboratorに追加してもらったので、滞留していたissue及びpull requestを大体さばきつつ、機能追加などをおこない、先程v0.11.1をリリースしました。GW中になんと45個のpull requestをマージしました。

今回の目玉は go get/import の機能追加です。具体的には、ghqで取り込んでいるリポジトリの一括アップデートや、Goの依存の一括取得が簡単になりました。

変更点

詳しくは、 v0.10.0以降のCHANGELOGを見てもらえればと思いますが、一部ピックアップして取り上げます。

ghq get/import への入力にホストも受け付け可能に

https://github.com/motemen/ghq/pull/119

実はこれまで以下のようにホスト名をつけられなかったのですが、それができるようになりました。ghq import への入力も同様です。

% ghq get github.com/motemen/ghq

go-import metaタグサポート

https://github.com/motemen/ghq/pull/120

go get がパッケージのリポジトリを探す時に、 meta name="go-import" というhtmlタグをヒントにするという仕様がありますが、これに準拠するようにしました。

Go固有の仕様なので、対応可否は微妙なラインですが、Goを書く身にとっては欲しい機能なので、入れることにしました。

これとホスト付加が可能になったことにより、以下のコマンドでGoのプロジェクトの依存の一括取得が可能になりました。

% go list -f '{{join .Deps "\n"}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | ghq import

これは、$GOPATH/src が廃止されるGo Modules時代に非常に便利でしょう。

go import --parallel/-Pオプション (Experimental)

https://github.com/motemen/ghq/pull/136

go import での並列取得が可能になりました。6並列決めうちにしています。多くのブラウザの同時接続数と同じなので、これくらいであれば多分お行儀も悪くないはず。

これにより、以下のコマンドで、手元のリポジトリの一括更新を高速にできるようになりました。

% ghq list | ghq import -u -P

ただ、以下のように xargs を使う場合に比べて速いわけでもないので、もしかしたらrevertするかも知れません。

% ghq list | xargs -L1 -P6 -I@ ghq get -s -u @

ghq get --vcs=

https://github.com/motemen/ghq/pull/72

ghq get 時にVCSを明示的に指定できるようになりました。

ghq get --look

https://github.com/motemen/ghq/pull/112

ghq get 直後にcloneしたrepositoryのディレクトリ配下に移動できるようになりました。

repository ownewの補完にユーザーを使わない設定を可能に (k0kubun++)

https://github.com/motemen/ghq/pull/118

#81:When there is no slash in the argument, complement URL as $USER/repo で、 ghq get hoge などとした時に、 https://github.com/$USER/hoge からリポジトリを取得するようになりましたが、元の挙動のほうが好みだという意見もあり、設定で切り替えられるようになりました。

% git config --global ghq.completeUser false

上記のように、ghq.completeUserfalse を設定しておくと、リポジトリ名をユーザー名の位置に補完してくれます。例えば、 ghq get peco とすると https://github.com/peco/peco を取得します。

ghq list --vcs= (msh5++)

https://github.com/motemen/ghq/pull/155

ghq list --vcs オプションにより、VCSによる絞り込みが可能になりました。例えば以下のように一括git gcできるので便利です。

% ghq list --full-path --vcs=git | xargs -I@ git -C @ gc --aggressive --prune=now

bazaar(shigemk2++), fossilサポート

これで、go get が対応しているVCSをghqも一通りサポートしました。めでたい。

その他

まとめ

ということで是非ご利用ください。だいぶメンテして、テストも追加されて触りやすくなっているので、pull requestもお待ちしています。

今後はもう少しテスト追加するのと、チューニングなどに取り組みたい。具体的には ghq listをもう少し速くしたい。これはどなたか取り組んでくれても嬉しいです。