リポジトリをGitHubに変更してCircle CIで自動デプロイしようとしたら大ハマリした
今更ながらCircle CIを使ってみる
前から興味があったCircle CIでの自動デプロイを、機会があったので試してみました。
リポジトリをBitbucketからGitHubに変えて、Circle CIに登録してデプロイできるようになるまで8時間。。。
いい経験にはなりましたが大変でした。
構成
サービス稼働中のRailsアプリに対して、デプロイ方法のみを変更します。
変更前
- リポジトリ:Bitbucket
- 手動で
rake test
- Capistranoで手動デプロイ
変更後
作業内容
circle.yml追加
# circle.yml machine: timezone: Asia/Tokyo ruby: version: 2.1.7 deployment: master: branch: master commands: - bundle exec cap production deploy - bundle exec cap production deploy:restart
リポジトリの向き先を変更
$ git remote set-url origin git@github.com:zakihaya/sample_repo.git
GitHubにpushする
$ git push origin master
Circle CIにプロジェクト追加
普通に登録する。
その後、サーバにSSHで接続するための秘密鍵を追加しておく。
Project settings → Permissions → SSH Permissions
リポジトリを修正するところは1箇所ではなかった!
これで適当な修正を加えてpushしてみると、こんな感じのSSHエラーが。。
(Backtrace restricted to imported tasks) cap aborted! SSHKit::Runner::ExecuteError: Exception while executing as deploy@example.com: git exit status: 128 git stdout: Permission denied (publickey).
この調査で3時間くらいハマる。
やってみた事は
どれをやってもうまくいかない。。。
困ったのでもう一度最初からエラーを見直してみる。
+ bundle exec cap production deploy DEBUG [1562897d] Running /usr/bin/env [ -d ~/.rbenv/versions/2.1.7 ] as deploy@example.com DEBUG [1562897d] Command: [ -d ~/.rbenv/versions/2.1.7 ] DEBUG [1562897d] Finished in 2.463 seconds with exit status 0 (successful). INFO [addbc921] Running /usr/bin/env mkdir -p /tmp/sample-repo/ as deploy@example.com DEBUG [addbc921] Command: ( RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.7 /usr/bin/env mkdir -p /tmp/sample-repo/ ) INFO [addbc921] Finished in 0.386 seconds with exit status 0 (successful). DEBUG Uploading /tmp/sample-repo/git-ssh.sh 0.0% INFO Uploading /tmp/sample-repo/git-ssh.sh 100.0% INFO [edd74d42] Running /usr/bin/env chmod +x /tmp/sample-repo/git-ssh.sh as deploy@example.com DEBUG [edd74d42] Command: ( RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.7 /usr/bin/env chmod +x /tmp/sample-repo/git-ssh.sh ) INFO [edd74d42] Finished in 0.384 seconds with exit status 0 (successful). INFO [0101ca3e] Running /usr/bin/env git ls-remote --heads git@bitbucket.org:zakihaya/sample-repo.git as deploy@example.com DEBUG [0101ca3e] Command: ( RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.7 GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/sample-repo/git-ssh.sh /usr/bin/env git ls-remote --heads git@bitbucket.org:zakihaya/sample-repo.git ) DEBUG [0101ca3e] Permission denied (publickey).
なんと、 bitbucket
が残っているではないか!
Circle CIがソースを取りに行っている先がBitbucketのままになっているっぽい。
確認したところ、 config/deploy.rb
で repo_url
がBitbucketのままになっていた。。。
がっかりしながら修正
# config/deploy.rb # set :repo_url, 'git@bitbucket.org:zakihaya/sample-repo.git' ← 削除 set :repo_url, 'git@github.com:zakihaya/sample_repo.git'
リポジトリを修正するところは2箇所ではなかった!
これでイケるだろうと思いきや、もう1つハードルが。
今度はこんなエラーが出る。
DEBUG [83c5bd28] Command: if test ! -d /var/rails/sample-repo/repo; then echo "Directory does not exist '/var/rails/sample-repo/repo'" 1>&2; false; fi DEBUG [83c5bd28] Finished in 0.358 seconds with exit status 0 (successful). INFO [72e69c47] Running /usr/bin/env git remote update as deploy@example.com DEBUG [72e69c47] Command: cd /var/rails/sample-repo/repo && ( RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.7 GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/sample-repo/git-ssh.sh /usr/bin/env git remote update ) DEBUG [72e69c47] Fetching origin DEBUG [72e69c47] Permission denied (publickey). DEBUG [72e69c47] fatal: The remote end hung up unexpectedly DEBUG [72e69c47] error: Could not fetch origin (Backtrace restricted to imported tasks) cap aborted! SSHKit::Runner::ExecuteError: Exception while executing as deploy@example.com: git exit status: 1 git stdout: Fetching origin Permission denied (publickey). fatal: The remote end hung up unexpectedly
今度はちゃんとエラーを見ると、サーバで git remote update
をする時にエラーになっているっぽい。
なるほど、サーバ側のリポジトリの設定にもBitbucketが残っていたのか。。
/var/rails/sample-repo
にデプロイしていたので、
サーバにログインして、リポジトリの向き先を変える。
$ cd /var/rails/remple-repo/repo $ git remote set-url origin git@github.com:zakihaya/sample_repo.git
これで全てうまくいきました。
まとめ
Capistranoを使っていて、CIする直前にリポジトリを変えた場合は気をつけましょう。
haml使用時に値が無い属性(itemscope)などを追加する
<div itemscope>・・・</div>
のような感じで表示させたい場合は
%div{ itemscope: true }
とすればOK。
RubyのバッチでGoogleAnalyticsのデータを取得する(OAuth2利用)
Garbが使えなくなった・・・
もともとはGarbというgemを使ってアクセス数を取得するバッチを作っていたのですが、急にGoogleにログインができなくなってしまいました。。
いろいろと見てみると、Google APIがOAuth2以外の認証を受け付けなくなってしまった模様。
GarbでOAuth2を使うためにいろいろ試してみたのですがうまくいかず、Google謹製のgemに乗り換えました。
乗り換えたgemはこちら
google/google-api-ruby-client · GitHub
Google Developers Consoleで鍵ファイルを取得
まず準備として、Google Developers Consoleにアクセス。 https://console.developers.google.com
プロジェクトを作成していない場合は作成する。
プロジェクトを開いたら、
APIと認証 > 認証情報
を開き、新しいクライアントIDを作成する。
アプリケーションの種類は、「サービス アカウント」を選択する。
IDを作成したら、「新しい P12 キーを生成」をクリックして、鍵ファイルをダウンロードする。
作成したクライアントのメールアドレスに権限を設定する
Analyticsのデータが見れるように、権限を設定します。
自分はこれを忘れてだいぶハマりました。
Google Analyticsを開き、「アナリティクス設定」を選択します。
アカウント→プロパティ→ビュー の順に、取得したいサイトの項目を選択していきます。
ビューの下の「ユーザー管理」をクリックし、Google Developers ConsoleのクライアントIDの下に表示されているメールアドレスを追加してください。
権限は、自分は編集までにしましたが、もっと低くても大丈夫かもしれません。
この時、ビュー設定の「ビューID」をコピっておきます。
後で使用します。
Gemfile設定
# Gemfile gem 'google-api-client' gem 'signet'
を記入して、 bundle install
する。
OAuth2認証
client = Google::APIClient.new(:application_name => '') # 鍵ファイルの場所を指定 key = Google::APIClient::PKCS12.load_key(File.join(Rails.root, 'certificates', 'analytics.p12'), 'notasecret') client.authorization = Signet::OAuth2::Client.new( :token_credential_uri => 'https://accounts.google.com/o/oauth2/token', :audience => 'https://accounts.google.com/o/oauth2/token', :scope => 'https://www.googleapis.com/auth/analytics', :issuer => 'example@example.com', # Google Developers Consoleに表示されているメールアドレスを入力 :signing_key => key, ) client.authorization.fetch_access_token!
今回は鍵ファイルを、 RAILS_ROOT/certificates/analytics.p12
に配置しています。
鍵ファイルの場所は各自書き換えてください。
client.authorizationのパラメータ issuer
には、先程権限を追加したメールアドレスを入力してください。
Analytcsからデータを取得する
start_date = Date.today - 7 end_date = Date.today - 1 api_method = client.discovered_api('analytics','v3').data.ga.get results = client.execute(:api_method => api_method, :parameters => { 'ids' => 'ga:999999', # ビューIDを設定する 'start-date' => start_date.to_s, 'end-date' => end_date.to_s, 'dimensions' => 'ga:pagePath', 'metrics' => 'ga:pageviews' }).data.rows
パラメータ ids
には、権限追加時にコピーしておいたビューIDを入力します。
これを実行すると、
results => [["/", 10], ["page1.html", "5"], ["page2.html"], "8"]
のような形式でページビューが取得できます。
全体のソース
require 'google/api_client' require 'google/api_client/client_secrets' require 'google/api_client/auth/installed_app' module Google class Analytics def self.import start_date = Date.today - 7 end_date = Date.today - 1 # OAuth2認証 client = Google::APIClient.new(:application_name => '') key = Google::APIClient::PKCS12.load_key(File.join(Rails.root, 'certificates', 'analytics.p12'), 'notasecret') client.authorization = Signet::OAuth2::Client.new( :token_credential_uri => 'https://accounts.google.com/o/oauth2/token', :audience => 'https://accounts.google.com/o/oauth2/token', :scope => 'https://www.googleapis.com/auth/analytics', :issuer => 'example@example.com', :signing_key => key, ) client.authorization.fetch_access_token! # Analyticsからデータ取得 api_method = client.discovered_api('analytics','v3').data.ga.get results = client.execute(:api_method => api_method, :parameters => { 'ids' => 'ga:999999', 'start-date' => start_date.to_s, 'end-date' => end_date.to_s, 'dimensions' => 'ga:pagePath', 'metrics' => 'ga:pageviews' }).data.rows # resultsからデータを取得する処理 # ・ # ・ # ・ end end end
Railsでメールを送信する機能を実装する時はmailcatcherを使うと便利
Webアプリを作っていると、メールを送信する機能を作ることがよくあるかと思います。 そんな時はmailcatcherというgemを使うと、仮想SMTPのような形で使えるので便利です。
準備
Gemfileを更新して、 bundle install
します。
# Gemfile group :development do gem 'mailcatcher' end
設定ファイル記述
# config/environments/development.rb Rails.application.configure do ・ ・ ・ # 開発時のメール関連はMailCatcherを利用 # RAILS_ROOTでbundle exec mailcatcherを実行し、http://127.0.0.1:1080/でメールが確認できる config.action_mailer.default_url_options = { host: 'localhost:3000' } config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 } ・ ・ ・ end
送信されたメールを確認する
mailcatcherを起動します。
$ bundle exec mailcatcher Starting MailCatcher ==> smtp://127.0.0.1:1025 ==> http://127.0.0.1:1080
起動したら http://127.0.0.1:1080/
にアクセスすると、下のような画面が表示されます。
確認する
今回はconsoleからメールを送信して確認してみます。
# メール本文 mail = Mail.new do from 'test-from@example.net' to 'test-to@example.net' subject 'Test mail using mailcatcher' body 'There is a test mail.' end # SMTPの設定。ActionMailerに設定したのと同じもの。 mail.delivery_method :smtp, { :address => "localhost", :port => 1025 } # メール送信 mail.deliver!
http://127.0.0.1:1080/
にアクセスすると、メールが届いています。
あら便利。
bundlerを使ってGemを作成する
Gemの作り方を勉強するために、どうしようもないGemを作ってみます。
テストを作成し、Travis CIで自動テストができることが目標です。
ソースはこちら
zakihaya/hello-zakihaya · GitHub
Gemを作成する準備
Gemの雛形を作成する
$ bundle gem hello_zakihaya
gemspecファイルを編集する
# hello_zakihaya.gemspec # coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'hello_zakihaya/version' Gem::Specification.new do |spec| spec.name = "hello_zakihaya" spec.version = HelloZakihaya::VERSION spec.authors = ["hayazaki"] spec.email = ["toru.hayazaki@gmail.com"] spec.description = %q{greeting with zakihaya} spec.summary = %q{You can greet to zakihaya with modification whatever you want} spec.homepage = "https://github.com/zakihaya/hello-zakihaya" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" spec.add_development_dependency "rspec" spec.add_dependency "activesupport" end
編集したのは下の2点です。
- spec.description、spec.summaryの部分がTODOになっているので記述
- activesupportとrspecの依存関係を追加
Gemfileにはgemspecと書いてあるのでノータッチ。
Gemをインストール
$ bundle install
テストを実装する
ディレクトリとファイルの準備
テストコードを置くディレクトリを作成する
$ mkdir spec
spec_helper.rbを作成する
# spec/spec_helper.rb require 'rubygems' # rspecの設定など RSpec.configure do |config| end
テストの実装
# spec/hello_zakihaya_spec.rb require 'spec_helper' require 'hello_zakihaya' describe HelloZakihaya do describe "#say" do let(:hello_zakihaya) { HelloZakihaya.new } context "with modification" do it do expect(hello_zakihaya.say("small")).to eq "Hello small zakihaya" end end context "without modification" do it do expect(hello_zakihaya.say).to eq "Hello zakihaya" end end end end
テストを実行する時は
$ bundle exec rspec
Gemの中身を実装する
実行ファイルを編集
普通はこのファイルはmoduleにしておくそうなのですが、今回は1ファイルなのでclassにしちゃいました。
# lib/hello_zakihaya.rb require "hello_zakihaya/version" require "active_support/all" class HelloZakihaya def say(modifiation = nil) if modifiation.present? "Hello #{modifiation} zakihaya" else "Hello zakihaya" end end end
version.rbを編集
# lib/hello_zakihaya/version.rb class HelloZakihaya VERSION = "0.0.1" end
テストを実行
$ bundle exec rspec .. Finished in 0.00145 seconds (files took 0.31777 seconds to load) 2 examples, 0 failures
問題なさげ
試しに実行してみる
$ irb -I ./lib -rhello_zakihaya irb(main):001:0> hello_zakihaya = HelloZakihaya.new => #<HelloZakihaya:0x007f871a271430> irb(main):002:0> hello_zakihaya.say('small') => "Hello small zakihaya" irb(main):003:0> hello_zakihaya.say => "Hello zakihaya"
何やらいい感じ
Gemfileを使って実行してみる
Gemfileの準備
適当なディレクトリを作成して、Gemfileを置く
# Gemfile source 'https://rubygems.org' gem "hello_zakihaya", git: 'git@github.com:zakihaya/hello-zakihaya.git'
Gemをインストール
$ bundle install --path=./gems Fetching git@github.com:zakihaya/hello-zakihaya.git Cloning into bare repository '/path_to_dir/zakihaya/gems/ruby/2.0.0/cache/bundler/git/hello-zakihaya-ab6b21fa940a70b867b4448a34a700d718504fad'... remote: Counting objects: 32, done. remote: Compressing objects: 100% (22/22), done. remote: Total 32 (delta 8), reused 29 (delta 5) Receiving objects: 100% (32/32), 4.23 KiB | 0 bytes/s, done. Resolving deltas: 100% (8/8), done. Checking connectivity... done. Cloning into '/path_to_dir/zakihaya/gems/ruby/2.0.0/bundler/gems/hello-zakihaya-23604ae1e4df'... done. Fetching gem metadata from https://rubygems.org/......... Fetching gem metadata from https://rubygems.org/.. Resolving dependencies... Installing i18n (0.6.9) Installing json (1.8.1) Installing minitest (5.3.5) Installing thread_safe (0.3.4) Installing tzinfo (1.2.1) Installing activesupport (4.1.2) Using hello_zakihaya (0.0.1) from git@github.com:zakihaya/hello-zakihaya.git (at master) Using bundler (1.3.5) Your bundle is complete! It was installed into ./gems
問題ナッシング
irbで実行
$ bundle exec irb irb(main):001:0> require "hello_zakihaya" => true irb(main):002:0> hello_zakihaya = HelloZakihaya.new => #<HelloZakihaya:0x007ff6120ca638> irb(main):003:0> hello_zakihaya.say("small") => "Hello small zakihaya" irb(main):004:0> hello_zakihaya.say => "Hello zakihaya"
Travis CIで自動テストを行う
Travis CIと連携する
TravisにGithubのアカウントでログインし、連携をONにする
テスト結果をReadmeに表示
これを記述すればいいらしい
# README.md [![Build Status](https://travis-ci.org/[YOUR_GITHUB_USERNAME]/[YOUR_PROJECT_NAME].png)](https://travis-ci.org/[YOUR_GITHUB_USERNAME]/[YOUR_PROJECT_NAME])
.travis.ymlファイルを追加
# .travis.yml language: ruby rvm: - 2.0.0
rakeタスクを追加
# Rakefile require 'rspec/core/rake_task' task :default => :spec RSpec::Core::RakeTask.new
感想など
- Gemは意外と簡単に作れる。(今回のはブログ書きながらで2時間半くらい)
- Travis CIを初めて使ったのだが、これは便利。今後も積極的に使ってみたい。
ギモン
- hello_zakihaya.rbで
require "active_support/all"
の部分をrequire "active_support/core_ext"
にしてたら、Travisのテストが通らなかった。
ローカルではOK。なぜだろう。。。
〜参考にさせていただきました〜
MySQL varcharのlengthはバイト数ではなく文字数
varchar(255)だったら、全角でも255文字まで入る。
よく忘れるのでメモ。
エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド
- 作者: 奥野幹也
- 出版社/メーカー: 技術評論社
- 発売日: 2010/06/12
- メディア: 大型本
- 購入: 16人 クリック: 204回
- この商品を含むブログ (31件) を見る
Macで使う言語を英語にしたらgit logがおかしくなった
英語を勉強したいなーと思ってMacのシステム言語をEnglishに変更しました。
そうしたらgit logが<A0>みたいな文字列になってしまったので、その対処法。
〜参考にさせて頂きました
How to fix locale issues in Mac OS X Lion terminal (Mountain Lion has the same issue) | Development as a lifestyle
どうもターミナルの文字コードの設定を変えればいいらしい。
.zshrcにこれを追記したら直りましたー。
export LC_CTYPE=en_US.UTF-8 export LC_ALL=en_US.UTF-8