Gradle SSH Plugin 2.5.0 released
Gradle SSH Plugin 2.5.0、Groovy SSH 2.5.0をリリースしました。
2.4.1〜2.5.0の変更点
New feature
- Add timeout setting (2.5.0)
Bug fixes
- Fix executeSudo never finish if password is wrong (2.5.0)
- Fix closing gateway session (2.4.3)
- Update to JSch 0.1.53 (2.4.2)
- Fix remove() fails if recursively (2.4.1)
2.4系でバグが見つかったので2.4.1、2.4.2、2.4.3をリリースしました。いずれもユーザからIssueやPRをいただいて改修しました。ありがとうございます。
2.5.0ではConnection TimeoutやSocket Timeoutを指定する設定を追加しました。極端に遅いサーバがある場合に有用と思います。まあ、そういう状況ではSSHではなくcloud-initやSerfでデプロイする方がいい気もしますが、いろいろ事情があるでしょう。
振り返り
OS integration testで利用するサーバをEC2からCircle CI上のDockerに移行しました。これにより、開発環境でも手軽にOS integration testを実行できる、EC2の状態にテスト結果が左右されないというメリットがあります。その代わり、コンテナの立ち上げに20〜30秒かかるようになりました。
現状でCIに6〜7分かかっているため、せめて5分台に短縮したいです。Circle CIではなぜかGradle Daemonが効かない謎をどうにかしたい。あと、docker pullをバックグラウンドで実行すれば少しは時間を短縮できそう。
などと色々と改善したいことはありますが、プライベートで使える時間も限られているのでなるべくプロダクトコードを書いてユーザに価値を提供していきます。
Continuous deployment to App Engine from Circle CI by Gradle
Circle CIを利用して、JVMベースのアプリをGoogle App Engineにデプロイする作業を自動化してみました。
うれしいこと
- 誰でも簡単にデプロイできる
- CIやPull Requestレビューを通過したコードのみデプロイできるように制限できる
- ビルド環境の差異による影響を排除できる
基本的な考え方
ざっくりとした流れは以下になります。
- GitHubにmasterをpushする
- Circle CIでビルドが実行される
./gradlew build
でビルドする./gradlew appengineUpdate
でデプロイする
App Engine SDKはgradle-appengine-pluginが自動的にダウンロードするように設定します。また、デプロイにはService Accountを利用するため、あらかじめ https://console.cloud.google.com/iam-admin/serviceaccounts でService Accountを作成して鍵ファイルを取得しておきます。
実装
まず、Circle CIのYAMLを設定します。ポイントは以下になります。
- Java 7でビルドする
- Dependencies CacheにApp Engine SDKを含めてCI時間を短縮する
- 環境変数
APPENGINE_KEY
を経由してService Accountの鍵ファイルを渡す(あらかじめbase64でエンコードしておく)
circle.yml
は以下のようになります。
machine: java: version: openjdk7 environment: TERM: dumb GRADLE_OPTS: -Xmx1g -Xms1g dependencies: override: - ./gradlew testClasses appengineDownloadSdk test: override: - ./gradlew build deployment: production: branch: master commands: - echo "$APPENGINE_KEY" | base64 --decode > build/appengine-key.json - ./gradlew appengineUpdate
次に、Gradleを設定します。App Engine SDKを自動的にダウンロードするようにします。また、appcfgにService Accountの鍵ファイルを指定します。
appengine { downloadSdk = true appcfg { oauth2 = true if (file('build/appengine-key.json').exists()) { extraOptions << '--service_account_json_key_file=build/appengine-key.json' } } }
実装例
GaelykとReactのアプリをCircle CIからApp Engineにデプロイする例を下記に置いているので参考にどうぞ。
Circle CIでSSHサーバを利用する際の注意点
Circle CIでテストコードからローカルのSSHサーバを利用する際の注意点をメモします。
背景
SSHクライアントのテストでSSHサーバが必要なので、CI環境で用意したい。具体的には、Gradle SSH PluginのテストでCircle CIのSSHサーバを利用したい。
課題と対策
Circle CIではデフォルトでSSHサーバが起動しており、ubuntuユーザに対して公開鍵認証でログインできるようになっています。
私が試した範囲では以下の課題がありました。
- 一定時間ごとにホスト鍵が変わる
- ubuntuユーザへのログインに時間が掛かる
まず、一定時間(1〜2分?)ごとにSSHサーバのホスト鍵が変わるようです。これにより known_hosts
に書かれたホスト鍵が古くなるため、Host Key Checkingに失敗します。デフォルトで起動しているsshdに問題があるようなので、以下のように別のsshdを起動したら解決しました。
test: pre: - sudo /usr/sbin/sshd -D -e -p 8022: background: true
追記: 別のsshdを起動する方法でもホスト鍵が変わる場合があるようです。メモリを大量に使用した場合かもしれません。対策はまだ見つかっていません。
また、CIを実行しているユーザ(ubuntu)へのログインは異常に時間がかかるため、スローテストの原因になります。おそらくubuntuユーザのログイン時に何かやっているためと思われます。これは別のユーザを作成したら解決しました。
# configure public key authentication ssh-keygen -t rsa -N '' -f ~/.ssh/id_ext sudo useradd -m tester sudo -u tester -i mkdir -p -m 700 .ssh sudo -u tester -i tee .ssh/authorized_keys < ~/.ssh/id_ext.pub sudo -u tester -i chmod 600 .ssh/authorized_keys # configure sudo without password echo "tester ALL=(ALL) NOPASSWD: ALL" > /tmp/tester sudo chmod 440 /tmp/tester sudo chown 0.0 /tmp/tester sudo mv /tmp/tester /etc/sudoers.d
なお、2の解決策を実施することでCIの所要時間が約8分から約5分に短縮されました。あくまでもGradle SSH Pluginの例なので参考ですが。
別の選択肢
以下の選択肢もあります。
- Dockerコンテナでsshdを実行してログインする
- EC2などにログインする
1はdocker pullでやや時間がかかります。2はレイテンシの影響を受けます。