オフトゥン大好き。

惰眠系プログラマの作業ログで( ˘ω˘ ) スヤァ…

homebrew-caskの書き方とpull-requestの出し方

GitHub - caskroom/homebrew-cask: A CLI workflow for the administration of Mac applications distributed as binaries

Mac使いならほとんどの人がお世話になっているHomebrew。 その拡張であるHomebrew Caskは以前なら別途インストールする必要があったが、色々ゴタゴタがあった末に本体に統合された模様。

僕は環境構築をできる限り自動化していてMacのプロビジョニングを行うにあたってはこれがないと結構面倒だ。もしHomebrew Caskのリポジトリに必要なCaskがなければ自分で作ってプルリクを出したら他にも幸せになる人がいるかもしれない。今回Windowsで使っていた3DモデリングソフトがいつのまにかMacに対応していたのでCaskに固めてみた次第。

Caskを作成する

まず最新のHomebrewが導入された状態で次のコマンドを実行する。hogehogeは作成するCaskの名前に読み替えてほしい。

$ brew cask create hogehoge

するとhogehoge.rbができるのでこれに必要な情報を書き加えていく。

cask 'hogehoge' do
  version ''
  sha256 ''

  url ''
  name ''
  homepage ''

  app ''
end
項目 内容
version アプリケーションのバージョンを指定する
sha256 改ざんや破損検知のためSHA256でイメージやアーカイブチェックサムを取る場合、ここにハッシュを入れておく。スキップする場合は:no_checkシンボルを指定する。
url ダウンロードするファイルのURL。CDNなどを利用していてhomepageで指定するドメインと異なる場合は# <ダウンロード先のドメイン> was verified as official when first introduced to the caskというコメントを一行上につけないとLintで弾かれる。
name アプリケーションの名前を指定する。
homepage アプリケーションのホームページを指定する。多くの場合はコーポレートサイトの製品ページなど。
app .appファイルの名前を書いておくと.dmgがマウントされた後にこれが/Applicationにコピーされる。

Macのアプリケーションは様々なインストール手段があるので、appでは対応できないことがある。例えば.dmgの中身が.pkg形式のインストーラだった場合。appではなくpkgを使用する。

また、この場合uninstallの項目にベンダーのIDを指定する必要があるが、これはhomebrew-caskのリポジトリにあるスクリプトで確認できる。

$ ./developer/bin/list_recent_pkg_ids
com.tetraface.Metasequoia.pkg
com.microsoft.OneDrive-mac
com.autodesk.mas.123ddesign
com.agilebits.onepassword-osx
com.microsoft.office.all.core.pkg.14.6.8.update
com.microsoft.office.all.dcc.pkg.14.6.8.update
com.microsoft.office.all.excel.pkg.14.6.8.update
com.microsoft.office.all.fix_permissions.pkg.14.6.8
com.microsoft.office.all.outlook.pkg.14.6.8.update
com.microsoft.office.all.powerpoint.pkg.14.6.8.update

最終的には以下のような状態になる。

cask 'hogehoge' do
  version '1.0.0'
  sha256 '0cd88d99379bdf8dfa42fd13ee970d8921f6d5eb3d892f76e4a7c76d68dc9e6d'

  # cdn.hogehoge.net was verified as official when first introduced to the cask
  url "https://cdn.hogehoge.net/download/Hogehoge-#{version}-Installer.dmg"
  name 'Hogehoge'
  homepage 'https://www.hogehoge.com/'

  pkg "Hogehoge-#{version}-Installer.pkg"

  uninstall pkgutil: 'com.pkg.hogehoge'
end

プルリクを出す

結構ガイドラインが細かったりするので目を通しておいた方がいいが、プルリク時のテンプレートにチェックボックスが用意されていて基本的にはこれを満たしていれば問題ない。

  • brew cask audit --download {{cask_file}}でエラーが出ないかどうか
  • brew cask style --fix {{cask_file}}でエラーが出ないかどうか
  • コミットメッセージにCaskの名前とバージョンを記載しているか
  • token referenceに沿って名前を付けているか
  • brew cask install {{cask_file}}でエラーが出ないかどうか
  • brew cask uninstall {{cask_file}}が正常に動くかどうか
  • すでに同じアプリケーションのプルリクが出ていたり過去に却下されていないか

本体のリポジトリにマージされるとbrew cask install hogehogeでインストールできるようになるので、ansibleのplaybookには

homebrew_cask_packages:
  - { name: hogehoge }

とか書いておくと新型に買い換えたときの環境構築で幸せになれる。

Facebookが公開した新しいJavaScriptパッケージマネージャ: Yarn

元記事:

素敵やーん。

日本時間で12日、ちょうど日付が変わったくらいにFacebookが前述の記事を公開した。内容は「JavaScriptコミュニティで圧倒的に力を持っているnpmの代替となる新しいパッケージマネージャ、Yarnを作ったぜ!」というもの。代替といってもYarnはnpmクライアントを完全に置き換えるものではなくて、上位互換を持ったものらしい。

npmに対して、Facebookはかなり前から依存パッケージのインストールにかかる時間を問題視していたみたいだ。これは僕や周囲のエンジニアの反応とも一致するし極めて妥当な感じがする。今回のYarn開発に関するモチベーションはそれだけではなく、同社のJavaScriptコードベースがエンジニアの数と共に肥大化していったことも述べていて、開発にグーグルが協力していることからも大規模サービスにおいてコード管理がいかに負担になっているかを物語っていると思う。

アーキテクチャ

Yarnは3つのステップで依存パッケージのインストールを行う。グローバルキャッシュを用意してそこにパッケージを保存しておくのが従来のnpmクライアントとの違い。

  1. Resolution:
    npmレジストリへのリクエストによってそれぞれの依存関係を再帰的に解決していく。

  2. Fetching:
    次に、ダウンロードすべきパッケージがすでにグローバルキャッシュに存在しているかを確認し、もしなければtarballをグローバルキャッシュに保存する。これによってこのパッケージはオフラインでも利用可能になり、再びダウンロードする必要がなくなる。

  3. Linking:
    最後にYarnは必要なファイルをグローバルキャッシュからnode_modulesディレクトリにコピーする。

なるほど、という感じだ。

インストール

npmでインストールできる。

$ npm install -g yarn

使い方

次のようにnpmのサブコマンドに対応するらしい。個人的には、ここはあえて変えずにそのまま置き換えられるようにして欲しかった。

  • npm installyarn

  • npm install --save <name>yarn add <name>

速度比較

適当に選んだ自作nodeプロジェクトの依存項目のみ抜粋したものがこちら。

{
  "dependencies": {
    "es6-promise": "^4.0.5",
    "isomorphic-fetch": "^2.2.1",
    "qs": "^6.2.1"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.16.0",
    "chai": "^3.5.0",
    "karma": "^1.3.0",
    "karma-babel-preprocessor": "^6.0.1",
    "karma-chai": "^0.1.0",
    "karma-mocha": "^1.2.0",
    "karma-mocha-reporter": "^2.2.0",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-sinon-chai": "^1.2.4",
    "karma-webpack": "^1.8.0",
    "mocha": "^3.1.0",
    "phantomjs-prebuilt": "^2.1.12",
    "sinon": "^1.17.6",
    "sinon-chai": "^2.8.0",
    "ts-loader": "^0.8.2",
    "tslint": "^3.15.1",
    "typedoc": "^0.4.5",
    "typescript": "^2.0.3",
    "typings": "^1.4.0",
    "webpack": "^1.13.2"
  }
}

これをnpmとYarnで比較してみる。Yarnはキャッシュの効果も知りたいので1回目でコピーされたnode_modulesを削除してもう一度実行した結果もみる。

manager time result
npm npm install 44.20s user 11.06s system 28% cpu 3:11.75 total
Yarn (1回目) yarn 38.63s user 19.57s system 98% cpu 59.047 total
Yarn (2回目) yarn 23.46s user 11.32s system 116% cpu 29.961 total

Yarnはとにかく速い。そして、Yarnは2回目でダウンロードの時間が省けるのでさらに速くなる。ちなみにキャッシュは~/.yarn-cache/に保存されるようだ。

感想

速度が向上するのはいいことだけど、僕としてはオフラインでも作業できるようになるのが一番のメリットだと思う。 一度ローカルにnpmをミラーしようとして挫折したことがある。

とにかくYarn素敵。使わない理由はない。

GitHub - yarnpkg/yarn: 📦🐈 Fast, reliable, and secure dependency management for JavaScript.

関連記事

CPANにPerlモジュールを公開するまでの手順

CPANにAuthor登録してモジュールを公開したので、やったことを書いていく。個人的な覚書の側面が強いのであまりまとまってないかも。

ちゃんとした手順が知りたい人はQiitaとかで記事を探したほうがいいと思う。

CPAN Author登録してもらう

モジュールを公開するにはPAUSE(Perl programming Authors Upload Server)というのに登録しなければいけない。

モジュールができてからでもいいけど、npmとかRubyGemsとは違って登録作業はCPANの中の人が手動でやってるっぽいので長くて1日くらいかかる。まだ、モジュールができてない状態でもこれからどんなモジュールを公開していきたいかという抱負だけで登録してもらえるので申請だけ出しておいたほうがよい。

ツールを揃える

perlplenv経由でインストールされている前提で書いている。揃えるべきツールは以下の3つ。

Name Description
cpanm Perlモジュールインストーラ
Carton モジュールプロジェクト下に依存モジュールをインストールするツール
Minilla モジュールの雛形を作るオーサリングツール
インストール手順
  1. plenvにはinstall-cpanmというコマンドが付属しているので、これを使ってまずはcpanmをインストールする
  2. Cartonをインストールする
  3. Minillaをインストールする
$ plenv install-cpanm # (1
$ cpanm carton        # (2
$ cpanm Minilla       # (3

モジュールの雛形を作る

Minillaでモジュールの雛形を作る。

$ minil new <module name>

モジュール名はハイフンが入るとそこでネームスペースが切られる。例えば、saiko-no-moduleとすると生成後の雛形はlib/saiko/no/module.pmという構造を持ち、公開後のモジュール名はSaiko::No::Moduleという名前になる。まあ、こんな名前をつけてはいけない。基本的にモジュール名はすでに公開されてるものを参考にしてつけるのが良い。迷ったらフォーラムで質問してもいい。Perl Mongerは優しい。

コードとモジュール情報を書く

メタ情報はMETA.jsonに書いてあるが、これはMinillaが自動で生成するので直接いじらない。Minillaはコードやcpanfileminil.tomlから必要な情報を集めてこれを出力する。README.mdもコードのpodドキュメントから生成されるのでいじらない。

テストを走らせるには次のようにする。

$ minil test

ただ、このコマンドではgitの管理下に追加されていないテストは実行されないので、.tファイルを追加したらまずgit addする。

公開する

PAUSEに登録され、コードを書いて、テストが通ったらいよいよ公開する。 公開にはPAUSEのサイトにtar.gzをアップロードするのがトラディショナルなやり方。でも、Minillaを使えばコマンドラインから公開できる。

$ minil release

その他

モジュールを公開したら、CPANのテストサーバからメールが来る。これはアップロードされたモジュールがテストを通過するかどうかを色々なプラットフォームでチェックしてくれているらしい。Travis CIとかCircle CIとかでアップロードする前にテストすることが望ましいけど、環境がubuntuのみだったりするのでBSDなんかでもテストしてくれるのはありがたい。落ちたテストレポートへのリンクが添付されているので修正に役立つ。

関連記事

nukosuke.hatenablog.jp

npm依存パッケージアップデートにgreenkeeper.ioが便利

Index | Greenkeeper

今までnpm-check-updateを使ってncu -aでアップデートをかけていたんだけど、依存を最新に保つためのgreenkeeperというサービスがあったので使ってみた。

$ npm install -g greenkeeper
$ greenkeeper login
$ cd ./node_project/
$ greenkeeper enable

アップデートするパッケージごとにPRを作ってくれて、そのパッケージの変更点をコメントに書いてくれる。

gyazo.com

ちなみにウェブインタフェースもあるらしくgreenkeeper web-appで起動できる。

無料プランではpublicリポジトリなら無制限、privateリポジトリは1つまで登録できるので積極的に使っていこう。

関連記事

nukosuke.hatenablog.jp

言語ごとのモジュール・エコシステム事情

ダンな言語には標準でパッケージマネージャが付属することが少なくない。 これは依存関係を洗い出して開発やランタイムに必要なパッケージを自動で補完してくれるうえ、自分が作成したライブラリやアプリケーションを公開する際にも便利なユーティリティとして機能する。

いつ頃からこのようなツール群が一般的になったのかはわからないが、最近触れる機会のある言語はもれなくこの恩恵に預かっていて、それぞれの言語についてエコシステム事情が気になったので調べてみた。 触ったことがあるもの以外はあまり詳しくは書けないし間違っているかもしれない。

Ruby: RubyGems

RubyGems.org | your community gem host

数多くの言語の中でも活発なコミュニティを有するRubyRubyGemsというエコシステムが存在する。gemやbundlerといったツールを用いて開発や実行に必要なパッケージをインストールする。依存するモジュールはGemfileというファイルに記述し、インストールするたび環境ごとの差異をなくすためGemfile.lockというファイルを生成してgemのバージョンや取得先を固定する。

JavaScript: npm

npm

Node.jsから生まれたモジュールシステムであり、当初はサーバサイドJavaScriptであるNode.js専用のパッケージマネージャだったため、フロント側では別にbowerというマネージャが発達していた。しかし、browserifyやwebpackなどのパッキングツールの発展、サーバとフロントの両方に対応したisomorphicなライブラリの増加で近年ではbowerを投げ捨てて、npmひとつで全てを完遂するのが主流になりつつある。

Perl: CPAN

CPANはComprehensive Perl Archive Networkの略でPerlのパッケージレジストリである。このレジストリ自体は現代的なエコシステムが発達する以前から存在しており、古くはtarアーカイブをダウンロードしてインストールしたり、OS標準のパッケージマネージャを使ってモジュールをインストールしたりしていた。今では言語用のモジュールシステムの流れに乗りCPANから依存モジュールを自動で展開するツールが公開されている。自作のモジュールを公開するにはPAUSEと呼ばれる開発者用のアップロードサーバに登録する必要がある。(しかしこのPAUSE、登録申請をどうやら人力で確認しているらしく時間がかかる)

Perl6: Perl 6 Modules

Perl 6 Modules Directory

まだ発展途上ではあるが、パッケージマネージャにはpandaというものがありmodule.perl6.orgに登録されているモジュールをインストールすることができる。 CPANのようなレジストリサーバは存在しておらずecosystem GitHubリポジトリに自らのモジュールリポジトリにあるメタデータファイルパスを追記することで公開される。

PHP: Packagist

Packagist

結構前にCakePHP 2.x系を使った開発案件に携わっていたことがあるが、その頃のPHPのパッケージ管理事情は酷いものだった。そもそもまともなパッケージマネージャは存在していなかったし、エラーの原因がパッケージのバージョンなのか言語のバージョンなのかも判別が難しい状態だった。今ではcomposerというパッケージマネージャを用いるのが主流になり、ようやくこうした状況も改善された。composerはPackagistというレジストリを参照しているため、公開する際はここにモジュールのURL(GitHubなど)をsubmitする。

Python: PyPI

PyPI - the Python Package Index : Python Package Index

PythonにはPyPIというリポジトリが存在していて、インストーラとしてはeasy_installとpipがよく使われるようだ。

参考記事:Python パッケージ管理技術まとめ (pip, setuptools, easy_install, etc) (16/10/8閲覧)

Go: gopkg.in, GitHub, BitBucket, ...

Go言語はバージョン管理システムリポジトリをそのままパッケージとして取り込むため、特定のモジュールレジストリは存在しない。そのためimportは標準ライブラリ以外は以下のような指定になる。

import (
  "github.com/hoge/huga"
  "bitbucket.org/hoge/huga"
)

go自体にパッケージマネージャは統合されているが、go getはデフォルトで最新のリビジョンを落としてくるため、バージョンを固定するには別途godepなどのツールを使用するかgopkg.inでバージョンを含んだURLを指定する必要がある。

Java: Maven

The Central Repository Search Engine

JavaにはMavenというツールがあり、Maven Central Repositoryというリポジトリからパッケージを取得している。最近ではGradleというビルドツールを使うことが増えているが、こちらでもMavenリポジトリを利用することができる。

Erlang, Elixir: hex

Hex

Erlangと同じくErlang VMで動作するElixirにはhexというモジュールシステムがある。Erlangではrebar, Elixirではmixというツールを用いてパッケージマネージングを行う。

その他

CやC++など古くから存在するネイティブ言語にもあるかと思って調べてみたら一応見つかった。

C/C++ Open Source Package Manager

認知度も低く、まだ流行っているとは言い難い状況だが、普及すれば特に複雑なC/C++のライブラリ依存解決も楽になりそうだ。

参考記事:C/C++ のパッケージマネージャーである conan を使ってみた - Secret Garden(Instrumental) (16/10/8閲覧)

まとめ

  • 企業が運営しているもの、コミュニティが運営しているもの、特定のレジストリを持たないものなどそれぞれ微妙に異なるが、言語ごとにエコシステムが存在している。
  • 古い言語でも後からパッケージマネージャが開発されており、以前の管理方法との統合が図られている。