git-archive を使うと worktree に変更があるかどうか (dirty かどうか) を気にしなくてよくて便利。
上記のようなことをやってみた例:
git-archive を使うと worktree に変更があるかどうか (dirty かどうか) を気にしなくてよくて便利。
上記のようなことをやってみた例:
http://JENKINS_HOST/job/JOB_ID/api/json
http://JENKINS_HOST/overallLoad/api/json
http://JENKINS_HOST/load-statistics
で見えるのと同じ?GitHub の Deployments API を使うと Web アプリケーションのリリース (デプロイ) に関わるワークフローをより便利にできそうだったので、試したことを記録する。
すべてドキュメントに書いてあるが、かいつまむと:
……という具合である。
つまり GitHub の API は具体的なデプロイのタスクについて責務を負うことはなく、「デプロイ」というイベントをリポジトリにアーカイブしそれらを通知する責務のみを負う、ということになる。Webhook のひとつと言い換えてもよい。
Deployments を作成する時に required_contexts
というパラメータを渡すことができる。
ドキュメントには:
By default, commit statuses for every submitted context must be in a ‘success’ state. The required_contexts parameter allows you to specify a subset of contexts that must be “success”, or to specify contexts that have not yet been submitted. You are not required to use commit statuses to deploy. If you do not require any contexts or create any commit statuses, the deployment will always succeed.
……とある。
つまり、これから作成する Deployments が参照しているコミットの Status について、required_contexts
で指定して context に対応する Status が成功した状態であることを求める、ということになる。
context については、Commit Status API において:
Statuses can include a context to indicate what service is providing that status. For example, you may have your continuous integration service push statuses with a context of ci, and a security audit tool push statuses with a context of security. You can then use the combined status endpoint to retrieve the whole status for a commit.
……とある。
たとえば Jenkins でのビルド状態を表す ci/jenkins
であるとか、ステージング環境におけるチェックを表す check/staging
などが、考えられる。
実際には、これら2つの API を組み合わせて、たとえば次のようなワークフローが考えられるかもしれない:
ci/jenkins
が成功したとラベル付けされるcheck/staging
が成功したとラベル付けされるstaging でのチェックが進行中で、大安を待つことは既に成功している、ということが伺える。
staging のチェックも完了した。"Caution to Merge" も消えている。
Deployments API と Commit Status API を組み合わせると、手動のオペレーションを含むデプロイの自動化ができそう
Release 2015-01-15 20:57:44 +0900 by aereal · Pull Request #4 · aereal/playground-github-api · GitHub - 実際に Deployments API を試した Pull Request
aereal/gulp-handlebars-playground · GitHub
HTML を出力するためのタスクを用意してみた。
……を使った。
role で使う変数の名前が衝突しないよう配慮すると、素朴に辞書を定義して名前空間を導入したいと考えると思う:
--- # roles/mackerel-agent/defaults/main.yml mackerel_agent: pid_file: '...' id: '...'
ところが Ansible の Variables は辞書の deep merge を行ってくれないので、デフォルト値の一部上書きができない:
--- # host_vars/app001.yml mackerel_agent: id: '...' # !!! mackerel_agent.pid_file が未定義になる !!!
なので辞書を用いて衝突を回避するのは諦めて、気をつけるしかなさそう:
--- # roles/mackerel-agent/defaults/main.yml mackerel_agent_pid_file: '...' mackerel_agent_id: '...'
ソフトウェア開発におけるテストは仕様の表現のひとつという風にも扱われるなど、重要な役割を担う一方で、テスト自体の妥当性の検証や保証は少なくて、こういう不安定な土台の上でいろいろやっていいのか、という気がする。
レビューする時には、まずテストコードを眺めて、大抵が自然文で表現された仕様と照らし合わせながら、矛盾がないかとか足りないテストケースがないか、とか考える。
ソフトウェアテストについてちゃんと勉強していけば、どういうテストケースが必要か *1 とかどういう風に表現すればよいか *2 はわかってくると思う。けど、人間の知識や理解に委ねられている、というのはどうにも不安に思える。
テストに対するテスト、メタテストみたいなのがあって、こういうテストケースが足りていない、とかわかるとよいと思う。
今思ったけど、カバレッジとかがそれにあたるのではないか、と思った。
今のチームでは一日に一回、カバレッジをとっていて、たまに眺める、という風になっている。本当はトピックブランチなどでテストの追加・削除を行ったらその都度カバレッジの変化が見れるとよいのだろうと思う。
タイトルにあることを Ruby でやる実装を書いた:
aereal/module-requirement · GitHub
Swift / Objective-C の protocol は具象クラスがメソッドを実装していることを要求できるので、Ruby でも似たようなことをやってみる、というコンセプト。
require 'module/requirement' module Iterable include Module::Requirement include Enumerable requires :each end class List include Iterable # => Module::Requirement::Error::NotMeetRequirements List must implement required methods: each end
Iterable
という each
メソッドが定義されていることを期待するモジュールを定義して、List
というクラスは Iterable
を include
しようとするけど要求されている each
メソッドの定義を持っていないので例外が発生する、という様子。
Ruby はコアに Enumerable
や Comperable
といった「要求されるメソッドさえ定義しておけば、後はいい感じに便利なメソッドを使える、というモジュールが用意されている。
そのようなモジュールを自分で定義して提供するときに、要求する実装 (= メソッド) を宣言的に書けて、あまつさえ (実行時でも) 検証してくれるので便利。
Module::Requirement
を include
したモジュールを include
する時点で構造を検証するので、次のように書いてもエラーになる:
class List include Iterable def each # ... end end
静的検査に近づこうというコンセプトなので、仕方がないと思いつつ、どうにかなるとよいと思う。
include
すると要求するメソッドのボディを raise NotImplementedError
と定義する、というのはありかもしれない。
public/
ディレクトリがある場合cd my_repo ln -sfv $PWD/public ~/.pow/my_repo
public/
ディレクトリが無い場合 (ディレクトリ直下を ServerRoot にしたい)mkdir -p ~/.pow/my_repo ln -sfv $PWD ~/.pow/my_repo/public
ServerRoot が ~/.pow/$vhost/public
になるように symlink を貼ればよい。
以前に書いた AquaSKK をインストールする Cask を書いた - Sexual Knowing の続き。
brew tap aereal/homebrew-aereal_casks
brew install aquaskk
Homebrew Cask 0.40.0 で DSL の語彙が変更された。0.40.0 以降で brew cask install aquaskk
が失敗するようになっていたので修正した。
OS X Yosemite で動作するよう修正が加えられている fork より AquaSKK 4.2.1 が配布されているのでこちらをインストールするようにした。
テンプレートエンジンNight というイベントで Text::Xslate を使ってテンプレートの静的解析とリファクタリングを行った知見について発表した。
テンプレートエンジンを使ってこういうことができる、というような内容から、テンプレートエンジン作った・作ってますというような内容まで、トークの内容に幅があっておもしろかった。
正規表現です。
変数として定義することも考えられるし、実際にそうすることも考えてみた。
[% SET INHERITED_VARS = ['post'] %]
しかし既にあるコメントによる宣言を書き換える手間や、現状を把握したいという目的からは逸れてしまうことから見送った。
早すぎた抽象化という問題がある (あった) ということは認識しているし、今が最高の状態だと思っているわけではない。
既存のテンプレートのコードを書き換える前に現状を把握するために静的解析を行おう、というモチベーションがあってトークの内容に繋がる、というかんじです。
最近、MacBook の SSD の空き容量がいつの間にか無くなっていて、スワップを作れなくなった結果、フリーズするということがあって反省したのでちゃんと管理しようという気持ちになった。
ひとまず家にある中で壊れたりトラブルが起きると一番困るのは QNAP なので、これを監視することにした。
Mackerel は Go で書かれた agent を入れるだけでよい割にアラートの閾値をいい感じに定義することができるので便利。
僕の持っている QNAP は TS-220 というモデルで CPU は ARM v5 で OS は Linux ベースらしい。
mackerel-agent は最近の CentOS と Debian しか動作することを保証されていない:
For now, mackerel-agent is guaranteed to run only on CentOS 5/6 and Debian 6/7.
https://github.com/mackerelio/mackerel-agent#readme
とはいえ Go で書かれているし Linux ベースなら取り付く島が無いなんてことはないだろうと思ってちょっと試したら動いた。
テストは書いていないしかなりいい加減だがこれで動いた。
uname
は -o
(Operating System) をサポートしていない
"Linux"
とするdf
は -P
オプションをサポートしていないし出力の形式が少し違う
1024-block
が 1k-block
だったmackerel-agent は OS X ではビルドに失敗するので Docker を使うことにした。
Dockerfile:
FROM golang:cross RUN mkdir -p /go/src/github.com/mackerelio ADD ./mackerel-agent /go/src/github.com/mackerelio/mackerel-agent WORKDIR /go/src/github.com/mackerelio/mackerel-agent RUN make deps CMD bash -c "GOOS=linux GOARCH=arm GOARM=5 CGO_ENABLED=0 make build && cp ./build/mackerel-agent /host/_mackerel-agent"
これで docker build -t mackerel-agent . && docker run -v "$(pwd)":/host mackerel-agent
とすると _mackerel-agent
が作られる。
Docker Hub Registry には golang が登録されているが、そのうちクロスコンパイルするための環境がセットアップされているタグを選ぶ。最新 (1.3) でよければ cross
.
ビルドの際に指定している環境変数は Optional environment variables
を参照した。
また GOARM
変数については GoArm - go-wiki が詳しい。
ビルドはできたものの実行時エラーが出る:
x509: failed to load system roots and no roots provided
意味がわからなかったが調べたところ x509 は SSL 通信のために使われているらしい。“roots” がよくわからなかったがルート証明書のことらしい。
ルート証明書が無いなら配置すればよいかと思ったもののどこに配置すればよいのかわからない。
Go において CertPool
は参照すべき証明書を保持するオブジェクトの型で、SSL 通信などを扱うライブラリ (e.g. net/http
) ではデフォルトではシステムの証明書を参照するようだった。
ではシステムの証明書の配置場所はどこかというと root_unix.go というファイルに定義されている。
var certFiles = []string{ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL "/etc/ssl/ca-bundle.pem", // OpenSUSE "/etc/ssl/cert.pem", // OpenBSD "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly }
QNAP では /etc/ssl/certs/myroots.crt
に配置されていたので symlink を作った。
これで QNAP 上で mackerel-agent を動かすことができるようになったはず。
あとは init スクリプトを書いたりしてデーモン化しておけばよい。
ディスク容量だけではなく netin/netout や CPU 使用状況も見れるので並列にコピーを走らせて無茶を走らせているときなど、余裕があるかなど見れて便利。
だいたい普通の Linux という感じでかなり手軽に運用できるので、次は nasne あたりも監視したい。
Text::Xslate::Parser が返す AST を文字通り「歩きまわる」ためのモジュールです。
0.01 現在では条件に一致するノードのみを返すメソッド (#search_descendants
) が実装されています。
SYNOPSIS より:
use Text::Xslate::Parser; use Text::Xslate::AST::Walker; my $template = <<EOF; : my $first_name = 'Hanae'; Hello, <: $last_name :>, <: $first_name :>. EOF my $parser = Text::Xslate::Parser->new; my $nodes = $parser->parse($template); my $tw = Text::Xslate::AST::Walker->new(nodes => $nodes); my $undeclared_vars = $tw->search_descendants(sub { my ($node) = @_; ($node->arity eq 'variable') && !$node->is_defined && !$node->is_reserved; }); printf "Undeclared var: %s @ Line %d\n", $_->id, $_->line for @$undeclared_vars;
簡単ですね。
#search_descendants
に渡すサブルーチンには Text::Xslate::Symbol
のインスタンスが渡されます。
上記例のように未定義の変数を列挙することなどができます。
Text::Xslate は高速なテンプレートエンジンとして既に有名で実績がありますが、一方で構文を選ぶことのできる柔軟性も持ち合わせています。
構文それぞれについて Parser が用意されており、抽象構文木を得ることができます。
GitHub で開発しているので Issues or Pull Request をお待ちしております。
cpanm Text::Xslate::AST::Walker
HTML::Selector::XPath@0.16 は CSS における class セレクタと等価な XPath を出力しない - Sexual Knowing
Normalize space characters of the class attribute by aereal · Pull Request #5 · Corion/HTML-Selector-XPath · GitHub がマージされた 0.17 がリリースされた。
0.17 以降に更新すると @normalize-space()@ を使うようになっているので、class 属性値の中に改行などの空白 (U+0020) 以外の空白文字が含まれていても正しくマッチするようになった。
めでたい。
class 属性の値は:
The attribute, if specified, must have a value that is a set of space-separated tokens representing the various classes that the element belongs to.
HTML Standard
とあるように、a set of space-separated tokens
と定義されている。
では a set of space-separated tokens
の定義を参照すると:
A set of space-separated tokens is a string containing zero or more words (known as tokens) separated by one or more space characters, where words consist of any string of one or more characters, none of which are space characters.
HTML Standard
とある。
space characters
について合意を持たないといけなさそう。
The space characters, for the purposes of this specification, are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF), U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN (CR).
HTML Standard
とある。つまり改行 (line feed, carriage return) は「空白文字」として定義されている。
class 属性の値の前後に空白 (U+0020 SPACE) を追加して contains()
関数でマッチするか試しているが、前述の通り class 属性の値は U+0020 以外の文字も空白文字として許容する。
たとえば改行 (U+000A LINE FEED) があった場合には contains()
関数は偽を返すので、CSS における class セレクタと等価ではない。
XPath には normalize-space()
関数がある。この関数は、連続する空白文字をひとつの空白 (U+0020) に置き換える。
この Pull Request では normalize-space()
を使うよう変更している。
プログラマブル Mac OS X - YAPC::Asia Tokyo 2014
「プログラマブル Mac OS X」というタイトルで YAPC::Asia Tokyo 2014 のトークに応募した。
ひとつの仕事をうまくやるプログラムの組み合わせでより大きな仕事をこなす、という UNIX 的な考え方は Mac OS X にも継承されており、設定を取得・変更したり普段 GUI から操作する機能と同等の仕事をこなすコマンドが種々用意されている。
pkgutil, defaults, launchctl といったツールおよびそれらの背後にある技術 (e.g. Property List, launchd, Installer Package) についての簡単な紹介や実際にそれらのツールを組み合わせた簡単なスクリプトの紹介をする予定。
Mac OS X ユーザがより効率的に「大きな仕事」をこなす助けとなればよいと思う。