Umi Uyuraのブログ

プログラミング関連の作業ログ

GitHub/Bitbucketなどで使うSSHキーを複数アカウントで使い分ける

個人でもGitHubやBitbucketのアカウントを持っている場合に、会社や別の会社のリポジトリにも同じサービスのアカウントを作ることになると、SSHキーをそれぞれに用意する必要がでてきます。

その際のconfigの書き方を毎回調べているので、自分用にメモ。

なお、環境はMacです。

SSHキーの生成

ssh-keygen コマンドを使ってSSHキーを生成します。

$ ssh-keygen -t rsa -C '<アカウント名やメールアドレスなど>' -f ~/.ssh/<ファイル名>

実行するとパスフレーズを求められるので、設定します。

ファイル名を分けておくことで、同一サービスに複数のファイル(アカウント)で利用することができます。

SSH公開鍵をサービスへ登録

SSH公開鍵をクリップボードへコピー

$ pbcopy < ~/.ssh/<ファイル名>.pub

GitHubへの登録

Bitbucketへの登録

SSH configの設定

同一サービスを複数のアカウントで利用する場合、 github.combitbucket.org へのリクエストがどのアカウント(つまりどのSSHキー)のものか区別できなくなってしまいます。

そこでSSHの設定ファイルで、複数アカウント用にエイリアスを作成します。

個人用のSSH configは ~/.ssh/config に作成します。

Host github.com
    HostName        github.com
    IdentityFile    ~/.ssh/github_rsa
    IdentitiesOnly  yes

Host hoge-github.com
    HostName        github.com
    IdentityFile    ~/.ssh/hoge_github_rsa
    IdentitiesOnly  yes

Host bitbucket.org
    HostName        bitbucket.org
    IdentityFile    ~/.ssh/bitbucket_rsa
    IdentitiesOnly  yes

Host fuga-bitbucket.org
    HostName       bitbucket.org
    IdentityFile   ~/.ssh/fuga_bitbucket_rsa
    IdentitiesOnly  yes

IdentitiesOnly は、その Host へ接続する際に指定した IdentityFile だけを使うという設定です。

これを付けておかないと、後述する接続確認の際、すでに同一の HostName へ接続したアカウントがあった場合、そのSSHキーを利用してしまうようなので、厳密にするために付けています。

接続確認

SSH configが正しく設定できたかどうか、各サービスへSSHで接続できるか確認します。

GitHubの場合

$ ssh -T git@hoge-github.com
Hi <ユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.

Bitbucketの場合

$ ssh -T git@fuga-bitbucket.org
logged in as <ユーザー名>.

You can use git or hg to connect to Bitbucket. Shell access is disabled.

上記 ユーザー名 の部分に、保有している別のアカウント名が表示された場合は、すでに認証した別のアカウントのSSHキーが使われている状態です。

上記のSSH configの設定を見なおして、該当 Host の設定に IdentitiesOnly を付けて再実行することで、本来のアカウントで接続確認することができます。

cloneの方法 / 既存リポジトリの変更

~/.ssh/configHost を元ドメイン以外にしたものをcloneする場合は、通常であれば以下のように実行するところを、

$ git clone git@github.com:hoge/hoge-example.git
$ git clone git@bitbucket.org:fuga/fuga-example.git

ホスト名部分を設定した Host に合わせて変更して実行します。

$ git clone git@hoge-github.com:hoge/hoge-example.git
$ git clone git@fuga-bitbucket.org:fuga/fuga-example.git

既存リポジトリ

<プロジェクト>/.git/config を編集します。

...

[remote "origin"]
    url = git@github.com:hoge/hoge-example.git

...

を、

...

[remote "origin"]
    url = git@hoge-github.com:hoge/hoge-example.git

...

のように書き換えることで対応できるもよう。(試していない)

参考

Flycheckのエラーリストのフォーマットが変わっていた

Emacsの静的解析にはFlycheckを使っていますが、発生しているエラーの一覧を表示する flycheck-list-errors の各フィールドの幅が微妙に見難かったので、ちょっとフォーマットを変更して使っていました。

umi-uyura.hatenablog.com

最近Pythonを触り始めてから、どうもFlycheckのエラーリストが1行しか出ないなーと思ったら、いつの間にかエラー一覧のフォーマットが若干変わっていました。

当初は以下のようなフォーマットにしていましたが、

(defconst flycheck-error-list-format [("Line" 4 flycheck-error-list-entry-< :right-align t)
                                      ("Col" 3 nil :right-align t)
                                      ("Level" 8 flycheck-error-list-entry-level-<)
                                      ("ID" 20 t)
                                      ("Message" 0 t)
                                      (" (Checker)" 8 t)])

この時点の最新版では、最後の "Message""(Checker)" が1フィールドにまとめられた形になっていましたので、それに合わせて設定も変更。

(defconst flycheck-error-list-format [("Line" 4 flycheck-error-list-entry-< :right-align t)
                                      ("Col" 3 nil :right-align t)
                                      ("Level" 8 flycheck-error-list-entry-level-<)
                                      ("ID" 20 t)
                                      ("Message (Checker)" 0 t)])

デフォルトの感じから、

f:id:umi-uyura:20160514234740p:plain

こんな感じで、 "ID" の部分を読み取れる程度に広げています。

f:id:umi-uyura:20160514234754p:plain

ふだん書いているJavaScript + ESLintでチェックしているときは大丈夫だったので、チェッカーの実装の違いによるものでしょうか。

そんな感じで、タプルなる存在に翻弄されている今日このごろです。

MacとEmacsのPython開発環境について調べてみた

Python使えると年収が高くなるかもしれないので、触っておくことにしました。

プログラマー年収ランキング2016!言語別、第1位はPythonの651万円 | みんなのスタンバイ

というわけで、まずはMac上に開発環境を整えることに。

Pythonバージョン管理

Macは標準でPythonがインストールされているものの、そのバージョンは2.7系。(El Capitanでは2.7.11が入っていました)

メジャーバージョンは今の時点で3.5まで上がっているものの、どうやら2.7系もまだまだ現役なようなので、用途に応じて切り替えられるように、バージョン管理ツールを導入しておくことに。

NodeやRubyなどのバージョン管理にanyenvを使っているので、その流れでpyenvを使います。

$ anyenv install pyenv
$ exec $SHELL -l
$ pyenv install 3.5.1

これで3.x系も触ってみたいときに切り替えられます。

$ pyenv global 3.5.1
$ python --version
Python 3.5.1

$ pyenv global system
$ python --version
Python 2.7.11

Python界隈では、異なるバージョンのPythonを扱うときにvirtualenvなる仕組みなどもあるみたいなので、いちおうインストールしておく。

$ pip install virtualenv

Pythonパッケージ管理

Node.jsで言うところのnpmのようなパッケージ管理ツールとしては、 pipデファクトな模様。

以前は別途インストールが必要だったようですが、El Capitan上のPyhtonにはpipもプリインストールされていたので、そのまま利用できます。

あとで使いそうな機能として、Brewfileなどのように必要なパッケージのリストを用意しておいて、そこから一括してインストールする機能があるみたい。

$ pip freeze > Pyfile
$ pip install -r Pyfile

これを使えば、自分の環境構築リポジトリ に簡単に含められるかなと思ったのですが、ちょっと試してみたところ、Homebrewなどで入れてしまっているPython系のツールなども含まれてしまっているので、そのままだと二重管理のような状態になりそう。

当面は pip install を羅列したシェルスクリプトで管理しておいて、Python活用するなら改めて検討することに。

Emacs用開発環境

自分のメインエディタであるEmacsでの開発環境について。

メジャーモード

Python用のメジャーモードとしては、どうやら2種類あるもよう。

いずれpython.el側にpython-modeの機能を取り込んでいくような計画があるようですが、そういった意味でpython-modeの方が活発に開発されているようなので、こちらを採用することにしました。

MELPAで公開されていたので list-packagespython-modeを選択してインストール。

そのままでは標準添付のpython.elが優先されてしまうようだったので、以下の設定を追加。

(autoload 'python-mode "python-mode" "Python Mode." t)
(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
(add-to-list 'interpreter-mode-alist '("python" . python-mode))

なんか色々できるみたいだけど、ひとまずインストールしておいて、使い方は勉強しながらつかんで行く。

静的解析

Python用の静的解析ツールを探すに当たり、Flycheckが対応していないか確認してみました。

Supported Languages — Flycheck 26-cvs documentation

FlycheckがサポートしているPython用の静的解析ツールとしては、flake8、Pylint、Pythonコンパイラを使うpycompileなどがあるみたい。

とりあえず守備範囲が広そうな印象のPylintを使うことにしました。

さっそく pip でインストール。

$ pip install pylint

設定ファイルは以下の方法で初期テンプレートを生成できるもよう。

$ pylint --generate-rcfile > ~/.pylintrc

とりあえず何が重要なのかわからないので、まずはデフォルトで運用してみて、適宜いじっていくことに。

軽く書いただけでやたらと出てきた C0111 だけ disable に追加。

オートコンプリート

オートコンプリート系としては、Jedi というEmacs用のオートコンプリートツールが便利なようなので導入。

まずはMELPAからjediをインストール後、init.elに設定を追加。

(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)

その後、Emacs上で M+x jedi:install-server を実行します。

このとき、内部的にvirtualenvでJedi用の環境が作られるのですが、自分の場合 ~/.emacs.d/.python-environments/default という場所に作られてしまいました。

そこで、init.elに jedi:environment-root を追加して、環境が作られる先を設定しました。

(setq jedi:environment-root "~/.emacs.d/var/jedi/env")

勉強

日本語のドキュメントとしては Python 2.7.x ドキュメント が良いらしい。

この中の Python チュートリアル あたりが一通り押さえられるらしいほか、 オンライン ドキュメント からはPDFでのダウンロードできるサイトもあったので、とてもありがたい。

Pythonチュートリアル 第3版

Pythonチュートリアル 第3版

TitaniumのiBeaconモジュール検証アプリ作成中

前回調べた情報をもとに、とりあえずiOS/AndroidでiBeaconを検出するところまでできたので、途中経過のまとめ。

umi-uyura.hatenablog.com

進捗

現時点のアプリのソースは umi-uyura/TiBeaconExam にあります。

できること

iOS/Androidともに基本的な機能は同じです。

メインの操作は、iOSは右上のActionアイコンで表示するAction Sheet、AndroidはActionBarに表示するメニューから行います。

f:id:umi-uyura:20160420214734p:plain f:id:umi-uyura:20160420214744p:plain

Actionは以下のとおり。

Action 意味
Start Scan 周辺のiBeaconの測定を開始する
Stop Scan 周辺のiBeaconの測定を停止する
Clear Beacon / Events タブのログをクリアする
Settings(iOSは左上の歯車アイコン) 設定画面を開く

※Start ScanとStop Scanは測定状態に応じて切り替わります。

Beaconタブ

Beaconタブには、iBeaconとの距離が測定できたときに発生する beaconProximity イベントログを表示。

こちらは、検知したiBeaconのMajar、Minor、Proximityといった測定値を整理して表示しています。

f:id:umi-uyura:20160420214803p:plain f:id:umi-uyura:20160420214817p:plain

Eventsタブ

Eventsタブには、測定に関連するイベント(enteredRegionexitedRegiondeterminedRegionStatebeaconRangesbeaconProximity )のログを表示します。

こちらは、イベントの発生パターンや取得できるデータの違いなどを検証するために、各イベントから取得できた情報をそのままダンプする形にしています。

上部にある検索窓にイベント名を入力することで、絞り込むことができます。

f:id:umi-uyura:20160420214831p:plain f:id:umi-uyura:20160420214840p:plain

設定画面

設定画面では、測定対象とするiBeaconのUUID/Major(オプション)/Minor(オプション)を登録できます。設定内容は画面を閉じると保存します。

f:id:umi-uyura:20160420214853p:plain f:id:umi-uyura:20160420214901p:plain

現状の制限

現状は、アプリがフロントにいる間だけiBeaconの検出をします。

iBeaconモジュールラッパーを作った

前回、iOS用とAndroid用のそれぞれのiBeaconモジュールのAPIを比較して、主要なものはほぼ同じものがあるようだったので、ひとまずモジュールの呼び出しを共通化するために、ラッパーを作りました。

app/lib/tibeaconwrapper.js

単純にプラットフォームに合わせたモジュールを呼び出して、存在しないAPIを使うときは警告を出力するようにしているだけです。

...

var tibeacon = null;

if (!tibeacon) {
  if (OS_IOS) {
    tibeacon = require('org.beuckman.tibeacons');
  } else if (OS_ANDROID) {
    tibeacon = require('com.drtech.altbeacon');
  }
}

...

exports.startMonitoringForRegion = function(region) {
  Ti.API.debug('TiBeaconWrapper.startMonitoringForRegion() - ' + JSON.stringify(region));
  tibeacon.startMonitoringForRegion(region);
};

exports.stopMonitoringAllRegions = function() {
  Ti.API.debug('TiBeaconWrapper.stopMonitoringAllRegions()');
  tibeacon.stopMonitoringAllRegions();
};

...

exports.checkAvailability = function() {
  Ti.API.debug('TiBeaconWrapper.checkAvailability()');

  if (OS_ANDROID) {
    return tibeacon.checkAvailability();
  } else {
    warningNotSupport('TiBeaconWrapper.checkAvailability()');
  }
};

...

権限関連はTitanium SDK 5.1.0サンプルアプリを参考に

iBeaconを取り扱う場合、iOS/Androidともに位置情報関連の権限を取得する必要があります。

特にAndroidは6.0になって新しい権限設定方法になっていたりするのを考慮したりしなくてはならないわけですが、ここは Titanium SDK 5.1.0のサンプルアプリ が参考になりました。

サンプルアプリの中の app/controllers/permissions.js に、Ti.Geolocation の他にも、Ti.CalendarTi.ContactsTi.Media などの権限の取得方法に関してのコードがあります。

iOS/AndroidのiBeacon関連イベントの違い

先に書いたように、現状はアプリ起動状態でのみiBeaconの検出ができます。

で、実際に動かしてみたところ、iOSAndroidでイベントの発生パターンに違いがあることがわかりました。この辺りは、特にAndroid側のモジュールの使い方なども関係しているかもしれないので、もう少し検証が必要な感じです。

今後の課題

次のステップとしては、アプリがバックグラウンドの状態でもiBeaconの検出ができるようにしたいと思います。

iOSAndroidも、バックグラウンドで検知できるようにするにはサービスを作らないといけないのかも、というあたりがわかっていないので、まだまだ検証が必要そう。

Asana用BitBarプラグインを作ってみた

少し前から、個人プロジェクト用に Asana というプロジェクト管理サービスを試しています。

お仕事では Backlog を使っていて、こちらはタスク管理やWiki、ファイル管理にバージョン管理と、プロジェクト管理に必要な機能を全て備えていると言っても過言ではない素晴らしいサービスなのですが、その分お値段もそれなりにすることもあり、個人で使うには敷居が高いです。

Asanaはタスク管理の機能がメインにはなりますが、プロジェクトに参加するメンバーが15名以下なら無料で使えるのが個人用途としては嬉しいところ。

多少クセはあるものの充分に使えそうという印象なので、継続して使っていこうと思っていますが、1つ不満なところは、全体的に若干重たいところでしょうか。

自分としては、その日以降のタスクを時系列順に確認することが多々あるのですが、一覧を表示するのにわりと時間がかかるので、そこが少々ネックです。

自分がふだんのタスク管理として使っているTodoistのように、Chrome拡張などがあると便利だったのですが、AsanaのChrome拡張は見た感じ登録専用のような感じだったので、使っていません。

そこで最近話題になった、Macのメニューバーにいろいろな情報を表示することができるBitBar向けに、Asanaのタスクを表示するプラグインを作ってみました。

できること

こんな感じです。

f:id:umi-uyura:20160410235221p:plain

Asanaは、まずワークスペースという単位があり、その中に複数のプロジェクトを設置することができます。ワークスペース複数作ることができるので、組織やチームなどで割り当てるのだと思います。

このプラグインでは、あるワークスペースワークスペース内で自分が担当に割り当てられている、かつ期限が設定されているタスクを日付順に表示しています。

ワークスペース表示

この部分を押すとワークスペースをブラウザで開きます。

Asanaのカレンダービューは個人的に気に入っている機能なので、このページを開く機能も付けました。

また、個別のプロジェクトを選ぶと、それぞれのページをブラウザで開きます。

タスク表示

タスクは期限、タスク名、プロジェクトを表示しています。

個々のタスクを選択すると、各タスクのページをブラウザで開きます。

期限が当日までのタスクを赤字で表示しています。

また、個人的にその週に実施するタスクというのを把握したかったので、締め切りがその週の週末(日曜日)までのタスク分で境界を入れています。

使い方

ソースはGitHubにあります。

umi-uyura/node-bitbar-asana: BitBar plugin for Asana

前提

動作はNode v4.4.2で確認しています。

インストール

理由は後述しますが、なんかBitBarプラグインとして微妙な作りにしてしまった気がするので、npmにはあげずにGitHubからインストールします。

$ [sudo] npm i -g umi-uyura/node-bitbar-asana

Personal Access Tokenの取得と設定

AsanaのAPIを使うために、アカウントの Personal Access Token というものが必要になります。

Asanaのヘルプ を見ると、 My Profile Settings という画面内に発行するUIがありそうですが、なくなっています。

新しい発行画面は以下のスクリーンショットのように、 Manage Developer Apps のリンクを選択して、

f:id:umi-uyura:20160410235241p:plain

移動した先の画面で Create New Personal Access Token をクリックします。

f:id:umi-uyura:20160410235258p:plain

Personal Access Tokenは生成直後だけ表示されて、その後見ることができなくなるので、メモっておくのを忘れないようにしてください。

Assignee IDとWorkspace IDの取得と設定

AsanaのAPIを使う際に必要な情報として、誰に割り当てられたタスクなのか(Assignee ID)と、どのワークスペースのタスクを表示するのか(Workspace ID)というものがあります。

これをあらかじめ取得しておくために、 bitbar-asana-me コマンドを実行します。

$ bitbar-asana-me
ID of your name (dummy@example.com) is <assignee id>.
Workspace that belongs is as follows.
  Test workspace (<workspace id>)
  Lab workspace (<workspace id>)

すると上記のように、自分のAssignee IDと、所属しているワークスペースのWorkspace IDが表示されます。

これを、設定ファイルに記載します。

設定ファイルは、GitHubリポジトリexample/bitbar_asana を落としてきて、 $HOME/.bitbar_asana として配置します。

設定ファイルには以下のキーが用意されているので、Assignee IDとWorkspace ID、それとPersonal Access Tokenを該当する箇所に記載してください。

Key Value
BITBAR_ASANA_ACCESSTOKEN Personal Access Token
BITBAR_ASANA_WORKSPACEID Workspace ID
BITBAR_ASANA_ASSIGNEE_ID Assignee ID
BITBAR_ASANA_LANGUAGE (optional) 曜日表示部の言語指定
ja を指定すれば月・火・水…で表示されます
BITBAR_ASANA_MENUBARICON (optional) メニューバーに表示するアイコンイメージ
Base64エンコードした画像データ

BitBarプラグインの設置

GitHubリポジトリexample/asana.10m.sh をBitBarプラグインフォルダにコピーするだけです。

設定が問題なければ、指定したワークスペースのタスクが表示されると思います。

複数ワークスペースで使う

設定ファイル( example/bitbar_asana )を別のファイル名で用意し、プラグインスクリプト内で bitbar-asana の引数としてファイルパスを渡すことで、複数設置することができます。

f:id:umi-uyura:20160410235314p:plain

例としては example/asana_other.10m.sh を参考にしてください。

感想

で、作ってから気付いたのですが、Nodeというか、npmで入れるパッケージにしてしまうと、BitBarプラグインとしては若干ポータビリティが悪いですね。

他のスクリプトを見ても、せいぜい外部のコマンドを叩くくらいにして、基本的にプラグインスクリプト単独でまとめている感じ。

それを考えると、そもそもNodeってMac標準で入っていないこともあるので、汎用性を考慮するならRubyなどで作ったほうが良かったかも…

とりあえず、自分の目的は達成できているので、気が向いたら作りなおすことにします。

マンガでわかるプロジェクトマネジメント

マンガでわかるプロジェクトマネジメント

iOS/AndroidでiBeaconを扱うTitaniumモジュールについて調べてみた

Titaniumで、iOSAndroid両方でiBeaconを扱うアプリを作ってみようかと思い、それらしいモジュールを探してみました。

さらに、どうせTitaniumでやるのであれば、なるべく処理を共通化できると良いなということで、まずはそれぞれで提供されているAPIを比較してみることに。

対象モジュール

今回使おうとしているのは以下のモジュールです。

プラットフォーム モジュール バージョン オリジナル
iOS Sensimity/TiBeacons 0.11.1 jbeuckm/TiBeacons
Android Sensimity/android-altbeacon-module 1.4.0 dwk5123/android-altbeacon-module

探していたところ、どちらも Sensimity というBeacon Management Systemのサービスを提供している会社の GitHub で公開されているものに行き着きました。

どちらのモジュールもオリジナルは別の人が開発したものなのですが、それらをフォークして改善が加わっているバージョンが公開されていて、さらにBeacon Managementしている会社のものであれば信頼性も高いのではということで、これを使ってみることにしました。

APIを比較

それぞれのモジュールに用意されているAPIを比較。

主要なAPIは同じ構成になっているので、挙動の差異が少なければ、共通化できそう。

それ以外は、直接iBeaconを扱えないAndroid用モジュールに、そのあたりをカバーするためのAPIが用意されている感じ。

API TiBeacons android-altbeacon-module 関連イベント
アドバタイズ開始 TiBeacons.startAdvertisingBeacon() Altbeacon.startBeaconAdvertisement() ※1 advertisingStatus
アドバタイズ停止 TiBeacons.stopAdvertisingBeacon() Altbeacon.stopBeaconAdvertisement() ※1 -
モニタリング開始 TiBeacons.startMonitoringForRegion() Altbeacon.startMonitoringForRegion() enteredRegion, exitedRegion, determinedRegionState
全てのモニタリング停止 TiBeacons.stopMonitoringAllRegions() Altbeacon.stopMonitoringAllRegions() -
ビーコンとの距離測定 TiBeacons.startRangingForBeacons() Altbeacon.startRangingForBeacons()
(Altbeacon.startRangingForRegion())
beaconRanges, beaconProximity
全ての距離測定を停止 TiBeacons.stopRangingForAllBeacons() Altbeacon.stopRangingForAllBeacons() -
BLEサポート有無 TiBeacons.isBLESupported() Altbeacon.isBLESupported() -
BLE有効無効 - Altbeacon.checkAvailability() -
Bluetoothの状態確認 TiBeacons.requestBluetoothStatus() - bluetoothStatus
Beaconサービスへ接続 - Altbeacon.bindBeaconService() -
Beaconサービスへの接続を解除 - Altbeacon.unbindBeaconService() -
Beaconサービスとの接続状態確認 - Altbeacon.beaconServiceIsBound() -
バックグラウンド動作設定 - Altbeacon.setBackgroundMode() -
ビーコンレイアウト追加 - Altbeacon.addBeaconLayout() -
ビーコンレイアウト削除 - Altbeacon.removeBeaconLayout() -
距離測定間隔設定 - Altbeacon.setProximityBounds() -
自動測定を有効化 ※2 Altbeacon.enableAutoRanging() -
自動測定を無効化 ※2 Altbeacon.disableAutoRanging() -
自動測定の有効無効 - Altbeacon.setAutoRange(boolean autoRange) -
サービス内動作設定 - Altbeacon.setRunInService(boolean runInService) -
サービス内動作確認 - Altbeacon.isRunInService() -
測定間隔の設定 - Altbeacon.setScanPeriods(scanPeriods) -

補足

  • ※1 Altbeacon.start(stop)BeaconAdvertisement() は完全にテストされていないもよう
  • ※2 TiBeacons.enable(disable)AutoRanging() はあったが0.8で廃止されたもよう(APIだけ残っている)

イベント

iBeaconを扱う際に発生するイベントは以下のとおり。

イベント名は双方同じものを使っているようなので、この点も挙動の差異次第で共通化できそう。

イベント 内容
advertisingStatus アドバタイズ状態
bluetoothStatus iOSのみ。Bluetooth状態
enteredRegion 領域侵入
exitedRegion 領域退出
determinedRegionState 領域状態を測定
beaconRanges 領域検出
beaconProximity ビーコンとの距離測定結果
changeAuthorizationStatus iOSのみ。パーミッション状態の変化

まとめ

当然細かい挙動は違ってくるのだと思いますが、API構成などはほぼ同じようなので、基本的な流れは共通化できそうな印象。

次は実際に組み込んでみて検証してみる予定。

iBeacon ハンドブック

iBeacon ハンドブック

BacklogのSubversionリポジトリをバックアップ

お仕事ではプロジェクト管理ツールとして Backlog を使っています。

年度末ということもあってプロジェクトの整理をしていたところ、過去に使っていたSubversionリポジトリをバックアップする必要がでてきたので、やり方を調べてみました。

リポジトリをエクスポート

いくつかやり方はあるなかで、もっとも一般的と思われる svnadmin dump をしてみようと思ったのですが。

$ svnadmin dump <REPO_PATH> > <DUMP_FILE>

ひとつ問題があり、それは svnadmin dump 時に指定するエクスポート元のリポジトリは、ローカルのパスでないとダメだということ。

数が多くなければそれでも良いのですが、やはり複数リポジトリをチェックアウトしてダンプして…というのを繰り返すのは面倒なので、できればBacklog上のリポジトリURL( https://<SPACE_KEY>.backlog.jp/subversion/<PROJECT_KEY> )からエクスポートしたいところです。

そこで、Backlogでエクスポートする機能などないのかな、と思って調べてみたところ、それ自体はないものの、FAQでバックアップ方法について紹介されているのを発見しました。

Subversionのリポジトリのエクスポートサービスはありますか? | FAQ | Backlog [バックログ]

紹介されているスクリプトを使うと、内部的に svnsync というミラーリングツールを使って、リポジトリの複製を作ってくれます。

作られた複製はリポジトリのフォルダ構造が再現されている状態なので、そのフォルダをリポジトリパスとして指定することで、 svnadmin dump にてダンプファイルにまとめることもできました。

リポジトリのインポート

念のため、ダンプファイルからの復元手順も確認。

svnadmin create で新しいリポジトリを用意し、 svnadmin load でダンプファイルからインポートすることで、ローカルにリポジトリを復元することができました。

$ svnadmin create <NEW_REPO>                    # リポジトリを作成
$ svnadmin load <NEW_REPO> < <DUMP_FILE>        # ダンプファイルからインポート

ただし、この方法は通常Subversionサーバー上で実施するらしく、少し調べてみましたが、例えばBacklogのような公開されているSubversionリポジトリへ直接インポートする方法は見つけられませんでした。

Backlogでは有料(税抜き30,000円)にてSubversionリポジトリをインポートするオプションを提供しているので、やはりそういった手段はなさそうな印象。

まあ今後はGitを主流に使うでしょうし、バックアップしたSubversionリポジトリは何か合ったときに参照に使う程度なので、今のところ、自分的には問題はなさそうです。

スクリプトをちょっと改良

というわけで、紹介されていたスクリプトをベースに、取り回ししやすいようにダンプファイルを出力して、念のためダンプファイルが読み込めるかを確認するために新しいローカルリポジトリを作成するという処理を追加してみました。

BacklogのSubversionリポジトリをバックアップする

引数にスペースIDとプロジェクトキーを指定して実行すると、ローカルに以下の3つを生成します。

  • <PROJECT_KEY> フォルダ ... svnsyncミラーリングしたSubversionリポジトリの複製
  • <PROJECT_KEY>.dump ファイル ... 上記をもとに出力したダンプファイル
  • <PROJECT_KEY>_CHECK フォルダ ... 上記ダンプファイルをインポートした新しいリポジトリ

<PROJECT_KEY>_CHECK フォルダをsvnXなどで開いてみると、履歴を読み込むことができたので、問題なさそう。

という感じで一通り必要なリポジトリはバックアップできました。

参考

チーム開発実践入門 ~共同作業を円滑に行うツール・メソッド (WEB+DB PRESS plus)

チーム開発実践入門 ~共同作業を円滑に行うツール・メソッド (WEB+DB PRESS plus)