静的サイトジェネレータとGitHub Pagesを使っていると、Travis-CIでHTMLを生成してコミットを行い、masterを自動で更新して欲しいですね。

普通なら下記の記事の方法で充分でした。

しかし、 Organization のリポジトリに対してこの方法を使うとメンバーが私個人のリポジトリを操作ができる気がする。 仕方ないので別の方法を模索してみた。

GitHub には、リポジトリごとに公開鍵を追加する機能があったのでこれを使ってみました。

考えないといけないことは、秘密鍵をどうやってTarvisへもっていくかです。 秘密鍵を共通鍵で暗号化して、リポジトリに追加する方法を選んでみました。 共通鍵を .travis.yml の中に暗号化してに保存しておきます。 この共通鍵の復号は Travis 側で自動的にされます。この共通鍵を使い Travis 側でリポジトリに含まれる秘密鍵を復号します。

秘密鍵さえ手に入れば GitHub に push できます。

やることを整理します。

  • Travis-CI の設定
  • 秘密鍵と公開鍵の作成
  • 秘密鍵を暗号化するための共通鍵の生成
  • 秘密鍵の暗号化してリポジトリに追加
  • GitHub のリポジトリに公開鍵を追加
  • .travis.yml へ暗号化した共通鍵を設定
  • .travis.yml にGitHubへ pushする処理などを記述

Travis-CIの設定

割愛します。

ログインして、設定したいリポジトリをONにします。

秘密鍵と公開鍵の作成

ssh-gen コマンドを使います。 作る鍵を deploy_key として進めます。

$ ssh-keygen -f deploy_key

deploy_keydeploy_key.pub が生成されます。

秘密鍵を暗号化するための共通鍵の生成

適当につくります。shell変数 password に保存しておく例を書いておきます。

$ password=`cat /dev/urandom | head -c 10000 | openssl sha1`

秘密鍵の暗号化してリポジトリに追加

さっき作成した共通鍵で deploy_key を暗号化して deploy_key.encを作成します。

$ openssl aes-256-cbc -k "$password" -in deploy_key -out deploy_key.enc -a

あとは適当にコミットします。 deploy_key をコミットしないように気をつけてください。

$ git add deploy_key.enc
$ git commit -m 'Add deploy key'

GitHub のリポジトリに公開鍵を追加

deploy_key.pub をGitHubに登録します。

GitHubのリポジトリのページを表示して、設定 > Deploy keys > Add deploy key で登録できます。区別がつくように名前は好きにつけましょう。

.travis.yml へ暗号化した共通鍵を設定

travis gem をインストールしていない場合はインストールしましょう。

$ gem install travis

travis encrypt コマンドを使用します。

$ travis encrypt -r [ユーザ名や組織名]/[リポジトリ名] "SERVER_KEY=$password" -a

.travis.yml の env.global へ情報が記録されます。

すごい広島を例にすると、こんな感じになります。

$ travis encrypt -r great-h/great-h.github.io "SERVER_KEY=$password" -a

.travis.yml にGitHubへ pushする処理などを記述

.tarvis.ymlafter_success にやりたいことを書きましょう。

鍵の設定の部分はこんな感じ。

after_success:
  - echo -e "Host github.com\n\tStrictHostKeyChecking no\nIdentityFile ~/.ssh/deploy.key\n" >> ~/.ssh/config
  - openssl aes-256-cbc -k "$SERVER_KEY" -in .travis/deploy_key.enc -d -a -out deploy.key
  - cp deploy.key ~/.ssh/
  - chmod 600 ~/.ssh/deploy.key

あとは煮るなり焼くなり。

すごい広島での例を上げておきます。 _site にファイルが生成されているので、それを master ブランチにコミットしてプッシュしています。

language: ruby
rvm:
  - 2.1.0
after_success:
  - echo -e "Host github.com\n\tStrictHostKeyChecking no\nIdentityFile ~/.ssh/deploy.key\n" >> ~/.ssh/config
  - openssl aes-256-cbc -k "$secret" -in .travis/deploy_key.enc -d -a -out deploy.key
  - cp deploy.key ~/.ssh/
  - chmod 600 ~/.ssh/deploy.key
  - git clone git@github.com:great-h/great-h.github.io.git -b master
  - cd great-h.github.io
  - cp -a ../_site/ .
  - git add --all
  - 'git commit -m "Generate Travis JOB $TRAVIS_JOB_NUMBER

https://travis-ci.org/great-h/great-h.github.io/builds/$TRAVIS_BUILD_ID"'
  - '[ "x$TRAVIS_BRANCH" == "xsource" ] && git push origin master'
branches:
  except:
    - master
env:
  global:
    - secure: "gIC6PLCnYmO29FiGqA1ZpVFsGBWbbdkZJGcBwYL2kyav3fPwdxRe6+RG3WEUfY2qwFnI52Br7pQ4ZClaBD76abObmYFW8Qkd13bgxgYMHFFzDh6ACMoY/JvRu4SXZcqiSi2QzeDTRk8Q825kGNY3QJXb4NiZ9gj8uAR9bNpnqnc="

まとめ?

暗号の強度して十分なのか検証していない。復号できたとしても、できることは限られてるので、とりあえず、妥協している。

そういえば、master に作成したファイルをコミットしているのですが、master を push した際に travis が走るというバグに悩まされました。 .travis.yml には以下のように書いておけば master は無視されます。

branches:
  except:
    - master

実は master には .travis.yml を置いていないのが原因でした。

Travisの設定で .travis.yml が無ければ動かさないという設定もできますし、適当に master に .travis.yml を置いておくのも良いと思います。

他にも .travis.yml に秘密鍵を保存する手法をいくつかみかけました。 長さが足りないので分割して保存して、Travis側で結合して使うようです。

参考文献

関連