ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

Gitで大雑把にConflict解消

こんにちは。

Gitのコンフリクトの解消方法毎回忘れるのでメモしておきます。エディタで修正するのは手間でしたので・・・

$ git checkout --ours filepath   # 変更しない
$ git checkout --theirs filepath # マージ先のファイルで上書き
$ git checkout -m filepath       # よくわからなくなったので、コンフリクトが発生した直後の状態に戻す

まとめ

コンフリクトのdiffが読みにくすぎてやばいです。<<<<<<< HEADHEADとか書いてありますがだいたい文字とか見るの面倒なので、diffの囲み(<<<<<<< ... ======= ... >>>>>>>)の中にあるやつは上にあるのが僕らの、下にあるのが奴らのと覚えてます。

<<<<<<<
  ours(僕らの)
=======
  theirs(奴らの)
>>>>>>>

よくわからなくなったらgit checkout -m .でやり直しちゃえばいいかなと思います。

あと、個別のファイルに対して変更するかしないかを判断するのはかなりきついな。。。という感想を持ちました。

願わくばコンフリクトが起きない方がいいですが、コンフリクト恐れすぎるのも良くないので、mergetoolとか駆使していきたいです。(Gitはいくらでもやり直しがきくのでやってみてから考えるでいいかと思います)

参考: Gitコンフリクト解消ガイド(git mergetoolの使い方)

BitbucketのPipelinesでmasterブランチにPull Request後、自動デプロイ

いい加減デプロイ自動化しないといけない。

プライオリティ低くなってしまっていて放置気味でしたが、毎回サーバーに入ってgit pullすることに飽きてきました。

BitbucketのPipelinesについて調べたことを書いていきます。

無料で使用できますが月50分までの使用制限があるそうなので、そんなにがっつりは使えない気もします。(2017/10/31 時点)

また、この記事ではPipelinesを使いますが、他の選択肢としてはWebhookとかあります。 その場合サーバー側にエントリポイント作って、POST受け取ってあれこれするという風になるかと思います。 状況に応じてWebhookも検討してみると良いかもしれないです。

概要

BitbucketのPipelinesを使えばリポジトリごとに 特定のブランチへのコミットを検知したタイミング で行いたい処理、テスト実行とか通知とかデプロイスクリプト起動とか、を設定できます。

Pipelinesはコミット検知したら裏側でDocker立ち上げているので、私たちはコンテナ内で起動するコマンドを書いていく感じです。立ち上げるDockerイメージも指定できます。

Pipelinesの使い方は簡単で、 bitbucket-pipelines.ymlというYAMLファイルに記述してレポジトリルートにおいておくと勝手に読んでくれます。

プルリクエストのマージじゃなくて 特定のブランチへのコミットを検知したタイミング でいいの?

とか思ったのですがよく考えたら、デフォルトだとプルリクエストをマージするとマージコミットが生成されるため(fast-fowardでもコミット追加されますし)、 masterブランチの設定を記述しておけば、masterへのプルリクエストが閉じられたら本番環境にデプロイ、とか出来る様になります。なるはずです!

やること

  • Pipelinesの有効化とbitbucket-pipelines.ymlの記述
  • デプロイ用ユーザーを作成
  • deploy.shの記述

今回は最小限、デプロイだけです。テストとかロールバックとかについては考えてないので、お気をつけください。

Pipelinesの有効化とbitbucket-pipelines.ymlの記述

Bitbucketへ行き、対象のリポジトリ管理画面の「Settings > Pipelines > Settings」からPipelinesを有効化します。

(リファレンスは次です。参考ページ)

YAMLを書きます。私は次のように記述しました。Dockerイメージは現在使っているサーバーに合わせてcentosにしています。sshできるようにしてデプロイスクリプトを叩くだけです。スクリプトは後で書きます。

image: centos:latest

pipelines:
  branches:
    master:
      - step:
          name: Deploy
          script:
            - yum -y install openssh-clients
            - ssh -p $SERVER_PORT $DEPLOY_USER@$SERVER_IP bash < deploy.sh

$SERVER_PORT, $DEPLOY_USER, $SERVER_IPなどの環境変数を、 「Settings > Pipelines > Environment variables」 から設定します。参考

作成したYAMLファイルをどうにかmasterに取り込んでください。好きな方法でいいです。add, commit, pushとか。

デプロイ用ユーザーを作成

デプロイサーバー -> Bitbucket

デプロイサーバーからBitbucketのリポジトリにアクセスするユーザーを作成します。サーバーに接続してbitbucketユーザーを作成します。($DEPLOY_USERと同じもの)

次に新しいユーザーのSSHキーペアを作成してください、これはBitbucketからgit pullするときに使用します。参考: Creating SSH keys

Bitbucketのサイトから作成した公開鍵を、リポジトリのデプロイキーに設定します。

このユーザーでリモートリポジトリにアクセス(fetchとか)できたら成功です。

Pipelines -> デプロイサーバー

PipelinesのDockerコンテナからデプロイサーバーにssh接続するために、BitbucketからSSHキーペアを作成します。参考: Use SSH keys in Bitbucket Pipelines

「Settings > Pipelines > SSH keys」 からキーペアを作成してください。

サーバーに戻り、先ほど作ったユーザーの~/.ssh/authorized_keysに公開鍵を貼り付けます。

またsshが困らないように、この画面の下部にある Known hosts の追加も行っておきましょう。(ポート付きの場合XXX.XXX.XXX.XXX:PORT)

deploy.shの記述

#!/bin/bash

REPOSITORY_PATH=/repository/path # 適当に変えてください

cd $REPOSITORY_PATH
git pull

リポジトリパスに移動してgit pullするだけのスクリプトです。注意としては、リポジトリのブランチが常にmasterになっていないと予期せぬ挙動が起こると思います。

完了

適当にブランチ切って修正してコミットしてプッシュしてプルリクエストしてマージして、Pipelinesメニューからタスクが実行されているのが確認できるかと思います。

一旦流れを作っておけば、後からテストを追加とかもできるはずなので、一歩前進というところです。

内容に関して何かございましたらお知らせいただきたいです。こっちの方がいい、ここ間違っている、これめっちゃ危ない、根本的に勘違いしている、ちゃんとリファレンス読みなさい、など指摘いただけると大変助かります。

ハマった

  • リポジトリの権限
    • 私のケースではサーバーに、すでに別ユーザーでクローンしたリポジトリがあったため、新しいユーザーでは更新系のgit操作ができない状態になってました。今回はオーナーを再帰的に変更して誤魔化しました。
  • Permission denied
    • ssh-agentが止まっているとか
    • ~/.ssh周りの権限とか所有者が適切ではなかったり
    • どの時点での権限不足なのか、サーバー3つ(Pipelines, Deploy, Bitbucket)なのでわかりにくかった
  • Pipelinesを使い始める順番
    • Bitbucketサイトからアクティベートしないと使えない
    • メニュー直下のPipelinesはチュートリアル形式で混乱したので、設定以下のPipelinesで普通にアクティベートした
    • 環境変数などもアクティベート後から設定可能になる

React NativeでARを体感する、Introducing Expo AR

 9月末にExpoがアップデートされてiOSAR Kit対応が行われました。チュートリアルが公開されたのでちょっと手を出してみました。使用する要素としては、

  • expo
  • three
  • expo-three

のみです。3Dオブジェクトの生成はThree.jsレンダリングExpoExpo Threeという構成になっています。

Introducing Expo AR: Three.js on ARKit

デモ


Introducing Expo AR #1

感想

 Expoの制限はあるもののARアプリをJavaScriptでかけるというのは前提となる知識量のハードルが下がるかと思います。

 チュートリアルやると満足感が得られてしまうのでやや危険ですね。色々いじってみるのは大切な一歩だと思いますが、一歩踏み出した後に自分の発想が広がっていかないのがなかなか辛いところです。

サービスがSSL化するとき

 ものすごく短い話ですが、サービスがSSL化するときの対応を想定してみました。近々知り合いのサイトにSSL入れられることになりそうなのが理由です。そういえばはてなブログSSL化するそうですね!

概要

 httphttpsに書き換えるの面倒ですよね。省略できた気がします。(確かにできるみたいです参考: リンクのhttp:https:を省略して現在のプロトコルでリンク先にアクセスさせる)。ただ参考リンクのタイトル通り、通信は現在のスキームになるのでほおっておくと 本来SSLが必要なページでもhttpで接続されてしまいます。というのはかなり問題だと思うので、移行するときは以下の切り分けをするかもしれないです。

  • リソースとかユーザーの情報を扱わないリンクに関しては、スキーム省略
  • 明示的にssl化したページはしっかりhttps書いておく
    • またはsslページにリダイレクトさせる

切り分け方法: 追記(2017年10月3日)

  • 内部
    • リソースとかユーザーの情報を扱わないリンクに関しては、スキーム省略
    • 明示的にssl化したページはしっかりhttps書いておく
  • 外部
    • リンク先に合わせたスキームを書く

感想

 でも切り分けるくらいならhttpsに置換しちゃったほうが早くない?というと、それもそうだと思います。前に、「画面動かない!直して!->ssl切れちゃってました」、というhttps -> http現象があったので対応減らせたらいいなと思った次第です。

 混在コンテンツ(Mixed Content)に対しても効果があるそうです。

配列でsplitもどき(JavaScriptメモ)

 JavaScriptに関するメモです。配列(Array)を適当な部分で分割したかったのでsplitもどきの関数を書きました。文字列のsplitをちゃんと配列版にしたわけではないので「もどき」と言っています。

function split(array, separator) {
  return array.reduce(function(p, n, i) {
    if (n !== separator) {
      p[p.length - 1].push(n);
    } else {
      if (i !== 0 && i !== array.length - 1 && array[i - 1] !== separator) p.push([]);
    }
    return p;
  }, [[]])
}
// 's'で分割する
split(['a', 'b', 's', 'c', 'd', 's', 'e'], 's')
=>
[
  ["a", "b"],
  ["c", "d"],
  ["e"]
]

// 配列の最初と最後に区切り文字があるときは、空配列を作らずに無視する
// 連続している区切り文字も1つとみなし、空配列は作らない
split([1,2,3,3,3,3,3,4,5,4,3,2,2,1,1,2,3,3,4,1], 1);
=>
[
  [2, 3, 3, 3, 3, 3, 4, 5, 4, 3, 2, 2],
  [2, 3, 3, 4]
]

// 区切り文字が配列に含まれていないときは、配列そのものを要素に持った配列を返す
split([1,2,3,3,3,3,3,4,5,4,3,2,2,1,1,2,3,3,4,1], 0)
=>
[[1, 2, 3, 3, 3, 3, 3, 4, 5, 4, 3, 2, 2, 1, 1, 2, 3, 3, 4, 1]]

感想

 必要に駆られて書いてみたので、文字列のsplitの配列版にはなっていないです。スプレッドシートExcel方眼紙状態になっていて、そこからデータを取得しなきゃいけない、というときに使用しました。

 配列版splitを作る場合、配列を区切り文字にして配列を分割できるようにするのが自然だと思います。文字列のsplitをうまく使って配列版をかけないか?と思ったのですが、空文字とかの扱いが微妙です。

 なんか圏論とか使うと整理できそうな気がしました。文字列対象から配列対象への射を、配列関手で写した先みたいな。全然よくわかっていないです。圏論ということはHaskellでの実装を見ると面白いかもしれないです。(多分split的なものがある?)