Help us understand the problem. What is going on with this article?

Hiki on VPS から Gollum on heroku sync with BitBucket へ移行した話

More than 3 years have passed since last update.

ずっと使ってるHikiがあるけど、いい加減、Hiki記法を忘れてるので、Markdownなwikiに移行することにした。Markdownだとdlの対応がないから本当はAsciiDocのほうがいいんだけど、マイナーなマークアップに移るんならHikiのままでいいやとなったので、GollumとGithub Flavored Markdownを選択。

tl;dr

shrkw/gollum-auto-backupにもろもろソースコードを置いたので動かすのに何が必要かわかるはず。

やったこと

  • Localで動かす
    • 普通に動く
    • Basic認証かける
    • Hookでgit pushする
    • BitBucketにpushする
  • Github Flavored Markdownを使う
  • Herokuで動かす
    • git pushもちゃんと動くこと
  • hikiのデータをmarkdownにコンバート

Localで動かす

準備

$ mkdir Desktop/shr-gollum
$ cat Gemfile
source 'https://rubygems.org'
ruby '2.2.2'
gem 'gollum', '~> 4.0.1'
gem 'github-markdown', '~> 0.6.9'
$ bundle install --path=vendor/bundle

起動

$ cd /tmp
$ git clone git@github.com:shrkw/gollumwiki.git
$ bundle exec gollum /tmp/gollumwiki

確認

$ cd /tmp/gollumwiki/
$ git log
commit f201b8be8803d0fc29f78b2308825baa6ef6710c
Author: shrkw <shrkwh@gmail.com>
Date:   Thu Dec 24 23:21:14 2015 +0900

    Created foo (markdown)

commit 4e10983baad0c3c6183aa6972c9b64f102008fbd
Author: shrkw <shrkwh@gmail.com>
Date:   Thu Dec 24 23:21:02 2015 +0900

    Created Home (markdown)

Basic認証かける

gollum-on-heroku/precious.rb at master · naoa/gollum-on-herokuをパクって認証かける。

#!/usr/bin/env ruby
require 'rubygems'
require 'gollum/app'

module Precious
  class App < Sinatra::Base
    basic_auth_username = ENV['BASIC_AUTH_USERNAME']
    basic_auth_password = ENV['BASIC_AUTH_PASSWORD']
    if basic_auth_username && basic_auth_password
      before do
        authorize
      end
    end

    private
    def authorize
      response['WWW-Authenticate'] = %(Basic realm="Restricted area.")
      throw(:halt, [401, "Not authorized\n"]) unless authorized?
    end

    def authorized?
      basic_auth_username = ENV['BASIC_AUTH_USERNAME']
      basic_auth_password = ENV['BASIC_AUTH_PASSWORD']

      @auth ||=  Rack::Auth::Basic::Request.new(request.env)
      @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [basic_auth_username, basic_auth_password]
    end
  end
end

Hookでgit pushする

naoa/gollum-on-heroku がすごく参考になった。
Hookが使えるとか、gollum/gollum-libにしか書いてないのに使っててすごい。

wiki = Gollum::Wiki.new(gollum_path)
Gollum::Hook.register(:post_commit, :hook_id) do |committer, sha1|
#  wiki.repo.git.pull("origin", "master")
  wiki.repo.git.push("origin", "master")
end

BitBucketにpushする

すごいめんどくさい。なぜならBitBucketのOAuth Access Tokenは1時間で失効してしまうから [OAuth on Bitbucket Cloud - Atlassian Documentation]。
なので、こんなプロセスが毎時で必要になる。

  1. refresh_tokenのAPI叩いて新しいAccess Tokenを取得
    • curl -X POST -u "client_id:secret" https://bitbucket.org/site/oauth2/access_token -d grant_type=refresh_token -d refresh_token={refresh_token}
  2. configのurlを更新
    • git remote set-url origin https://x-token-auth:{access_token}@bitbucket.org/shrkwh/gollumwiki.git

もしくは、これ用のsshキーを登録しておいて、sshプライベートキーを環境変数に渡して、dyno起動のたびにファイルに出力する、とか。それもイヤだけど。

non-expiringなAPI tokenも検討してはいるらしい [comment from Atlassian guy]。一応、Bitbucketのissue trackerにも追加しておいた [site / master / issues / #12186 - non-expiring auth access tokens (BB-15425) — Bitbucket]。

もしくは、dynoの起動時にアクセストークン取得する

  1. OAuth2キーとシークレットを環境変数で登録
  2. dyno起動時にアクセストークン取得
  3. それを使ってBitBucketからclone
  4. dyno起動中はそれでpushする

dynoは毎日rebootしてるみたいだし、これでいいか。なんかうまくいかなかったらまた考えよう。

require 'net/http'
require 'uri'
require 'openssl'
require 'json'
require 'logger'

def fetch_access_token(key, secret)
  logger = Logger.new(STDERR)
  url = URI.parse('https://bitbucket.org/site/oauth2/access_token')
  req = Net::HTTP::Post.new(url.path)

  req.basic_auth key, secret
  req.set_form_data({'grant_type'=>'client_credentials'}, ';')
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  #http.set_debug_output $stderr
  res = http.start {|http| http.request(req) }
  case res
  when Net::HTTPSuccess, Net::HTTPRedirection
    logger.info('Fetching Access Token Succeed')
    js = JSON.parse(res.body)
    js['access_token']
  else
    raise StandardError, 'Fetching Access Token Failed'
  end
end

gollum-auto-backup/bitbucket.rb at master · shrkw/gollum-auto-backup

Github Flavored Markdownを使う

もともとgithub-markdownに対応してた [gollum/README.md at master · gollum/gollum]。Gemfileに書けばOK。

gem 'github-markdown'

Herokuで動かす

buildpack-multi使うと.buildpacksファイルで複数のbuildpackが指定できるようになるのね。で、Heorku Deployボタんからの起動ならapp.jsonに指定できるけど、コマンドからなら、以下で指定。

heroku buildpacks:set https://github.com/heroku/heroku-buildpack-multi.git

その他のconfigも適宜指定。

heroku config:add GIT_REPO_PATH="shrkw/gollumwiki"
heroku config:add OAUTH_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXX

git pushもちゃんと動くこと

https://x-token-auth:{access_token}@bitbucket.org/shrkwh/gollumwiki.gitでcloneできてれば、上記のhookでちゃんとpushできる。

HikiのデータをMarkdownにコンバート

masasuzu/p5-App-hiki2mdがあったので使う。と思ったら微妙に空白の対応が期待してたのと違う。ので、folk [shrkw/p5-App-hiki2md] して、ついでにテーブルにざっくり対応させた。

perlの書き方とか動かし方全くもって忘れてた。

export PERL5LIB=/Users/shrkw/.ghq/github.com/shrkw/p5-App-hiki2md/lib
perl ./bin/hiki2md Src > Dest

できたファイルをgitのリポジトリにコミットしてpushして終わり。

まとめ

というわけでBitBucketとsyncするgollumがHerokuに建てられました。サクッと終わると思ってたけど毎日少しずつ進めてたら冬休み中かかってしまった。

Markdownでtodoリスト作って進めると、進捗がわかりやすくて助かった。

参考

shrkw
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away