既にローカルでgit管理しているものをgithubにpushする

想定している状況

  • とりあえず、ローカルで開発をしていた
  • もちろん、git initして、作業毎にgit commitをしている
  • ブランチは切ってなくて、masterブランチで作業している
  • 一通り実装したので、githubに公開しようと思った
  • githubリポジトリを作ったけど、どうやってpushしていいかわからん
  • githubリポジトリを作った時の、LICENSEやらREADME.mdは残しておきたい*1

手順

github上でSSHのclone URLをコピーしてきます。
例:git@github.com:noboru-i/irkit.git

git管理しているディレクトリにて、下記のコマンドを実行します。

git remote add origin git@github.com:noboru-i/irkit.git
git fetch

これにより、origin/masterとして、github上のmasterブランチを参照できるようになりました。

なので、origin/masterを、ローカルのmasterにリベースします。*2(masterブランチをチェックアウトしている前提)

git rebase origin/master

これで、ローカルのmasterブランチはLICENSEやらREADME.mdが存在している状態になります。

なので、これをpushします。

git push origin master

f:id:suzaku114:20140505154842p:plain

一本道になりました。
一番左のコミットがgithubで自動的にコミットされたもので、それ以降のものがローカルでコミットしていたものです。
時系列はひっくり返ってしまいますが、意味的にはこんな感じでいいんじゃないでしょうか?

ちなみに、mergeしたらこんな感じに、入り口2つになったので、なんか微妙だなーと。

f:id:suzaku114:20140505154025p:plain

もっといいやり方があるような気はします。

余談

マージしてpushしちゃったあとの復旧方法は下記の通りです。

git reset --hard c62d6a3
git co -b o_master
git reset --hard e14b7566ca35c5910dd0769d3bdadb59f1499231
git push -f origin o_master:master
git co master
git b -d o_master
  • c62d6a3:1個前(margeする前)のコミット
  • e14b7566ca35c5910dd0769d3bdadb59f1499231:githubの初期コミット

なにをやっているかというと、下記のような感じ。

  • masterのマージコミットを破棄
  • o_masterブランチにて、元のorigin/master を再現し、強制push
  • masterをチェックアウトしなおし、不要になったo_masterブランチを削除

開発効率をUPする Git逆引き入門

開発効率をUPする Git逆引き入門

  • 作者: 松下雅和,船ヶ山慶,平木聡,土橋林太郎,三上丈晴
  • 出版社/メーカー: シーアンドアール研究所
  • 発売日: 2014/04/09
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (4件) を見る

GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)

GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)

*1:別に、LICENSEやらを破棄していいのなら、force pushしちゃえばいいと思う

*2:日本語あってるかな?

Play framework 2でinMemory以外のDBでテストを行う

下記を買って、Play Framework 2を使っています。

テストを書こうと思って、Chapter7のFakeAppをコピーしてやってみました。

で、実行してみたところ、PostGIS関連の特殊カラム関係でエラーになってしまいました。

そのため、inMemoryDatabaseをやめて、実際のPostgreSQLを利用しようと思って、ハマりまくりました。

あと、GlobalSettingsを継承したクラスでDBアクセスしてたので、さらにわけのわからんエラーが出ました。

まず、startAppでFakeApplicationを作成。

@BeforeClass
public static void startApp() throws IOException {
    Map<String, Object> map = new HashMap<>();
    map.put("db.default.url",
            "jdbc:postgresql://127.0.0.1:5432/sample_db");
    map.put("db.default.user", "web_dev");
    map.put("db.default.password", "password");

    app = fakeApplication(map, new GlobalSettings());
    start(app);
    String evolutionContent = FileUtils.readFileToString(app
            .getWrappedApplication().getFile(
                    "conf/evolutions/default/1.sql"));
    String[] splitEvolutionContent = evolutionContent.split("# --- !Ups");
    String[] upsDowns = splitEvolutionContent[1].split("# --- !Downs");
    createDdl = upsDowns[0];
    dropDdl = upsDowns[1];
}

これで、リクエスト時のDBはPostgreSQLに向く。

あと、DDL文を実行し、テーブルを作成。

@Before
public void createCleanDb() {
    final DataSourceConfig dataSourceConfig = new DataSourceConfig(){{
        setDriver("org.postgresql.Driver");
        setUrl("jdbc:postgresql://127.0.0.1:5432/sample_db");
        setUsername("web_dev");
        setPassword("password");
    }};
    ServerConfig serverConfig = new ServerConfig(){{
        setName("test");
        setDataSourceConfig(dataSourceConfig);
        setRegister(false);
        setDdlRun(false);
        setDdlGenerate(false);
        setDefaultServer(false);
    }};

    // transactionで囲み、commitしないと反映されなかった
    EbeanServer ebeanServer = EbeanServerFactory.create(serverConfig);
    ebeanServer.beginTransaction();
    ebeanServer.execute(ebeanServer.createCallableSql(dropDdl));
    ebeanServer.execute(ebeanServer.createCallableSql("commit;"));
    ebeanServer.execute(ebeanServer.createCallableSql(createDdl));
    ebeanServer.execute(ebeanServer.createCallableSql("commit;"));
    ebeanServer.commitTransaction();
}

DROP文→CREATE文をとりあえず投げておけばOKかと思ったら、コメントで書いてあるように、transactionで囲んでそれぞれcommitしないとうまく動かなかった。

もっと普通のやり方があってもいいと思うけど、調べててもなかなか出てこなくて困った。

Play Framework自体あんまり情報が見つからないイメージ。しかも、バージョンごとに結構違ってて困る。

公式を探すしか無い印象。

テストのやり方とか、Ruby on Railsほど整ってない感じ。

とはいえ、Rubyの開発者よりはJavaの開発者の方が調達しやすいとかの関係で、Javaの案件もやらざるを得ない感じ。 (PHPは個人的に好きでない。。。)

Springもそのうちまともにやってみたいとは思うけど、「Play」だったり「Spring」だったり、なんでこんなにググラビリティの悪いものが多いんだろう。。。

chefでデータベースとかユーザとか作りたい

Vagrantで開発環境を共有したりしているのですが、

  • データベースの作成
  • ユーザの作成

とかってどこでやるべきなんでしょう?

「本来ここでやるべき」とか知ってる人がいたら教えて下さい。

とりあえず現状は、MySQLのインストールとかをchefでやっているので、ついでにchefでやってしまおうと思います。

knife cookbook create database-prepare -o site-cookbooks/
vim site-cookbooks/database-prepare/recipes/default.rb

mysql-clientのインストールと、SQL文の実行を記述しておきます。

package 'mysql-client-5.5' do
    action :upgrade
end

package 'libmysqlclient-dev' do
    action :upgrade
end

template '/tmp/mysql-schema.sql' do
    source 'mysql-schema.sql.erb'
end

bash 'apply schema' do
    code "mysql -uroot -h#{node[:database][:host]} #{"-p" + node[:database][:password] if node[:database][:host] != 'localhost'} < /tmp/mysql-schema.sql"
end

templateは下記のように。

<%
host = node[:database][:host]
name = node[:database][:name]
user = node[:database][:user]
password = node[:database][:password]
%>
<% if host == 'localhost' %>
CREATE DATABASE IF NOT EXISTS `<%= name %>` DEFAULT CHARACTER SET utf8;

CREATE DATABASE IF NOT EXISTS `<%= name %>_test` DEFAULT CHARACTER SET utf8;
GRANT ALL PRIVILEGES ON `<%= name %>_test`.* TO <%= user %>@localhost IDENTIFIED BY '<%= password %>';
GRANT ALL PRIVILEGES ON `<%= name %>_test`.* TO <%= user %>@"%" IDENTIFIED BY '<%= password %>';
<% end %>

GRANT ALL PRIVILEGES ON `<%= name %>`.* TO <%= user %>@localhost IDENTIFIED BY '<%= password %>';
GRANT ALL PRIVILEGES ON `<%= name %>`.* TO <%= user %>@"%" IDENTIFIED BY '<%= password %>';
FLUSH PRIVILEGES;

localhost の場合のみ"CREATE DATABASE"を行っているのは、RDSだと勝手に作られるから。 あと、"_test"ってのを作ってるのも、ローカルでのみテストを行うから。 そのへんはプロジェクト・案件によって変わってくるのかなー、と。

で、MySQLはこんな感じで簡単に出来たんだけど、PostgreSQL が面倒だった。

  • "IF EXISTS"的なものが見つからない。
  • 同じようにSQLファイルを用意しても、エラーになってしまった。

というわけで、毎回コマンドを発行することに。

package 'postgresql-client-common' do
    action :upgrade
end

execute "create-role" do
    exists = <<-EOH
        su - postgres -c "psql -c\\"SELECT * FROM pg_user WHERE usename='#{node[:database][:user]}'\\" | grep -c #{node[:database][:user]}"
    EOH
    command <<-EOC
        su - postgres -c "psql -c\\"CREATE ROLE #{node[:database][:user]} WITH LOGIN PASSWORD '#{node[:database][:password]}';\\""
    EOC
    not_if exists 
end

execute "create-database" do
    exists = <<-EOH
        su - postgres -c "psql -c\\"SELECT * FROM pg_database WHERE datname = '#{node[:database][:name]}'\\" | grep -c #{node[:database][:name]}"
    EOH
    command <<-EOC
        su - postgres -c "psql -c\\"CREATE DATABASE #{node[:database][:name]} OWNER #{node[:database][:user]} ENCODING 'UTF8' LC_CTYPE 'en_US.UTF-8' LC_COLLATE 'en_US.UTF-8' TEMPLATE template0;\\""
        su - postgres -c "psql -d #{node[:database][:name]} -f /usr/share/postgresql/9.3/extension/postgis--2.1.2.sql"
    EOC
    not_if exists 
end

ちなみに、Vagrantfileにはパラメータを設定しておく。

chef.json = {
  :database => {
  #  :type => "mysql",
    :type => "postgresql",
    :host => "localhost",
    :name => "sample_db",
    :user => "web",
    :password => "password"
  }
}

入門Chef Solo - Infrastructure as Code

入門Chef Solo - Infrastructure as Code

chefで頑張って冪等性を確保する

packageリソースなどは、勝手に冪等になってくれるけど、executeとかは自分で冪等になるように書かないといけない。

特定の文字列を、ファイルの末尾に追記したい場合

例:/etc/resolv.conf に 'options single-request-reopen' を追加する。 二重に追加されないように not_if で制限する。

execute 'add single-request-reopen' do
    command "echo 'options single-request-reopen' >> /etc/resolv.conf"
    not_if "cat /etc/resolv.conf | grep 'options single-request-reopen'"
end

パスを通す場合

例:rbenvコマンドにパスを通す。 パスが通っている場合は not_if で制限する。

user = 'vagrant'
home_dir = "/home/#{user}"
execute 'export path' do
    not_if 'which rbenv'
    user user
    group user
    command <<-EOC
        echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> #{home_dir}/.bash_profile
        echo 'eval "$(rbenv init -)"' >> #{home_dir}/.bash_profile
    EOC
end

とりあえず、このへんを知っておくと、たいていは冪等に書けるんじゃないかと。

久しぶりにiOSアプリをビルドしようとしたらエラー

ビルドしようとしたら下記のエラー。

No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=i386).

ググったら、こんなん http://stackoverflow.com/questions/22328882/xcode-5-1-no-architectures-to-compile-for-only-active-arch-yes-active-arch-x 出てきた。

なので、言われたとおり、

  • Xcode上でPodsプロジェクトを右クリック→Delete→Remove Reference
  • Xcodeを終了
  • コマンドラインから pod install
  • .xcworkspace を再度開く
  • Podsプロジェクトを選択し、Build Settings→Build Active Architecture Only をNOに (debugがYESになってた)
  • 同じく、自分のプロジェクトのBuild Active Architecture Only もNOに (debugがYESになってた)

したら、iOSシミュレータで動くようになった。よかった。

久しぶりにpod installしたらエラー

rubyのバージョン変えてたので、まずはgemのインストール

gem install cocoapods
rbenv rehash

で、

pod install

すると、エラーが出てくる。 こんなの

Psych::SyntaxError - (/Users/〜〜〜/.cocoapods/repos/master/CocoaPods-version.yml): mapping values are not allowed in this context at line 3 column 4

ググったら、 https://github.com/CocoaPods/CocoaPods/issues/1853 こんなのが出てきたので、書いてあったコマンドを実行

rm -rf ~/.cocoapods/repos/master
pod setup

で、再度

pod install

すると正常に動いた模様。

Vagrantをprovisionしたときにディレクトリを作る

メモ:

ステージング・本番ではcapistranoでデプロイするけど、 ローカルのVagrantではそんなことしないので、 pidを格納するディレクトリが無くて困った。
(nginxで見に行く先を変えればいいけど、そんな部分のchefをいじるのも面倒。。。)

んで、Vagrantfileのsynced_folderとして、テキトーなディレクトリを指定したけど、 sockファイルを作ろうとして、エラーになった。

http://stackoverflow.com/questions/16388342/unicorn-fails-to-start-on-vagrant-box-due-to-errnoeperm
synced_folderしたディレクトリには作れないっぽい。

どうせなので、provision時のshellを使ってみた。

  $script = <<SCRIPT
mkdir -p /srv/web/shared/pids
chown vagrant:vagrant -R /srv/web/shared
SCRIPT
  config.vm.provision "shell", inline: $script

単純にmkdirすると、root権限で作られたので、chownでログインユーザのものに変更。

無事、sockファイルが作れて、nginx -> unicornでページが表示された。

メモ:rspecで変更が無いことをテストする

自分用メモ

expect{hoge}.not_to change{fuga}

で変更が無いことをテストできる

Rank.get_rank_id では、パラメータによって次のランクが返却されるイメージ User#calc_rank!では、Rank.get_rank_id を呼び出し、その結果をDBに保存するイメージ

require 'spec_helper'

describe User do
  describe '#calc_rank!' do
    let!(:user) { FactoryGirl.create(:user, rank_id: 2) }
    it do
      Rank.stub(:get_rank_id).and_return(2)
      expect{user.calc_rank!}.not_to change{User.find(user.id).rank_id}
    end
  end
end

Alfred workflowで新規ウィンドウを開く

最近、Alfredを使い始めました。

どうせなら、ということでPowerPackも買って、workflowを使えるようにしました。

とか入れてます。

で、それなりに便利に使ってたんですが、FinderとかiTerm2を起動しようとして、別のデスクトップに起動してたのがアクティブになるのが不便。。。

というわけで、下記を追加してみた。

Finderを新規に起動する

  • Alfredの設定画面を開く
  • Workflowsタブを開く
  • 左ペインの右下にある"+"を押す
  • Templates -> Essentials -> Keyword to AppleScript を選択する
  • keywordをダブルクリックする
    • Keywordに"nfinder"を入力
    • No Argumentを選択
    • titleに"new finder"とかを入力
  • Run NSAppleScriptをダブルクリックする
on alfred_script(q)
  tell application "Finder"
    make new Finder window
    set frontmost to true
  end tell
end alfred_script

上記手順により、Alfred呼び出し -> "nfin"とか入力 -> Enter でFinderが新規に起動します。

iTerm2を新規に起動する

Finderの時と手順は同様。
keywordは"niterm"にしました。
AppleScriptは下記の通り。

on alfred_script(q)
    if application "iTerm2" is running or application "iTerm" is running then
        run script "
          on run {q}
              tell application \":Applications:iTerm.app\"
                  create window with default profile
                  select first window
                  tell the first window
                      if onlywindow is false then
                          create tab with default profile
                      end if
                      tell current session to write text q
                  end tell
              end tell
          end run
      " with parameters {q}
    else
        run script "
          on run {q}
              tell application \":Applications:iTerm.app\"
                  activate
                  try
                      select first window
                  on error
                      create window with default profile
                      select first window
                  end try
                  tell the first window
                      tell current session to write text q
                  end tell
              end tell
          end run
      " with parameters {q}
    end if
end alfred_script

これも、Alfred呼び出し -> "nit"とか入力 -> Enter でiTerm2が新規に起動します。
https://gist.github.com/reyjrar/1769355 を参考にしたのですが、zshを利用していたので書き換えました。

アイコンとかサクッと作れれば、フツーに公開するんだけどな。。。

KFCocoaPodsPlugin をインストールしてみる

前に iOSアプリ開発が捗るXcodeプラグイン - Qiita [キータ]ricobeck/KFCocoaPodsPlugin · GitHub というプラグインが紹介されていました。

便利そうだなーと思いつつ、放置していたのですが、年末年始で少し時間が出来たので、導入してみました。

ただし、githubの説明が

Clone this repo or download the zip, run 'pod install' in the terminal, open the workspace file in Xcode and compile. After a restart of Xcode you have a 'CocoaPods' Menu Item in the Products menu.

しか無かったので、念のためメモ。
※cocoapodsはインストール済みの前提

手順

今回、 ~/bin に入れておくとします。

cd ~/bin
git clone git@github.com:ricobeck/KFCocoaPodsPlugin.git
cd KFCocoaPodsPlugin
pod install
open KFCocoaPodsPlugin.xcworkspace

Xcodeが開くので、Product -> Buildとし、Xcodeを一旦完全に終了させ、再度起動。

すると、公式のgithubにあるように、Productメニュー無いにCocoaPodsが表示されます。
これで入力補完も効くし、黒い画面が無くてもpod install が出来ます。