Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDF版の自動更新 #241

Open
y-yu opened this issue Jan 24, 2017 · 18 comments
Open

PDF版の自動更新 #241

y-yu opened this issue Jan 24, 2017 · 18 comments
Assignees

Comments

@y-yu
Copy link
Member

y-yu commented Jan 24, 2017

こちらのリポジトリでCIが動作して成功した場合、PDF版を自動で更新したいと思っています(現在は私が適当なタイミングで手動により更新しています)。そのため、Circle CIの管理者に追加していただくか、すでにCircle CIに秘密鍵が登録されている場合はその公開鍵を教えていただきたいと思います。

@tatsuya6502
Copy link
Member

tatsuya6502 commented Jan 24, 2017

@y-yu PDF版の更新、いつもありがとうございます。

Circle CI ですが、調べてみたところ、follow という概念しかなく、管理者という概念はないようです。(y-yu さんは、すでに Circle CI 上の the-rust-programming-language-ja を follow されているようです。リンク

Circle CI から GitHub のレポジトリに SSH キーや web hook を登録する際は、GitHub リポジトリ側の管理者権限が必要になります(参考)。そこで、trpl-admin という管理者チームを作って、y-yu さんを登録しました。

Circle CI に秘密鍵が登録されている場合はその公開鍵を教えていただきたいと思います。

Circle CI に登録された SSH 秘密鍵の一覧(fingerprint のみ表示)は、こちらにあります。
https://circleci.com/gh/rust-lang-ja/the-rust-programming-language-ja/edit#ssh

現状は、github.com 向けのものだけが登録されています。この鍵は私が管理してますので、公開鍵を教えることはできます。ただ、今回連携したい先は、GitHub ではなくて、Travis でしょうか? だとすると、新たに、Travis 向けのキーを作成して、登録することになるのかもしれません。(よく分かってなくて、すみません。)

@tatsuya6502
Copy link
Member

現状は、github.com 向けのものだけが登録されています。この鍵は私が管理してますので、公開鍵を教えることはできます。

公開鍵ですが、こちらに置きました。

finderprint:

% ssh-keygen -l -E md5 -f $HOME/.ssh/trpl_circleci_rsa.pub 
4096 MD5:6c:8f:02:77:31:a0:9b:e5:5f:ef:78:11:54:36:8c:34 [email protected] (RSA)

@y-yu
Copy link
Member Author

y-yu commented Jan 24, 2017

@tatsuya6502 さん。

trpl-ja-pdf にいただいた公開鍵を登録しようとしたのですが、次のようなエラーが出てしまってだめのようにです。

Key is already in use

つまり、GitHubはあるリポジトリにデプロイキーとして登録されている公開鍵を別のリポジトリのデプロイキーとして登録できないようです。
そうなるとちょっと困った問題として、Circle CIは github.com として秘密鍵を登録していますから、PDF版のリポジトリ用のデプロイキーをどのように登録しようか考える必要がありそうです……。

@tatsuya6502
Copy link
Member

tatsuya6502 commented Jan 24, 2017

GitHub の別のリポジトリでしたか。

Circle CI の web API を使うと、CI から別の CI を起動できるようです(参考)。ということは、もし、Circle CI に trpl-ja-pdf の CI を作成したなら、そこに登録したそれ専用のデプロイキー(trpl-ja で使っているものとは別のもの)を使って GitHub trpl-ja-pdf に連携できそうです。

流れ:

  1. trpl-ja の CI がビルドに成功。
  2. trpl-ja の CI の deployment ステップが、web API 経由で trpl-ja-pdf の CI を起動。
  3. trpl-ja-pdf の CI が、自身専用のデプロイキーを使って、GitHub trpl-ja-pdf へ連携。

@y-yu
Copy link
Member Author

y-yu commented Jan 24, 2017

  1. trpl-ja の CI がビルドに成功。
  2. trpl-ja の CI の deployment ステップが、web API 経由で trpl-ja-pdf の CI を起動。
  3. trpl-ja-pdf の CI が、自身専用のデプロイキーを使って、GitHub trpl-ja-pdf へ連携。

ちょっと試していないので確実ではないですが、実はtrpl-ja-pdfはtrpl-jaリポジトリをサブモジュールで管理していますので、その関係でCIがややこしい(何度も実行されたりする)ことになりそうな予感がします。
ですので、やや強引ですが次のような方法ではどうでしょうか。

方法

  1. trpl-ja-pdf専用の公開鍵・秘密鍵のペアを作成する

  2. 秘密鍵を下記のようなランダムな文字列で暗号化する

    $ password=`cat /dev/urandom | head -c 10000 | openssl sha1`
    $ openssl aes-256-cbc -k "$password" -in deploy_key -out deploy_key.enc -a
    
  3. 秘密鍵をtrpl-jaのリポジトリに追加する

  4. ランダムな文字列をtrpl-jaのCircle CIのEnvironment Variablesとして登録する

    • この値は一般のユーザーが知ることはできないようです
  5. trpl-jaにtrpl-ja-pdfへ自動コミットするスクリプトを追加する

    • このスクリプトの中で、(4)のランダムな文字列を用いて(3)の暗号化された秘密鍵を復号し、それをコマンドで強引に~/.sshディレクトリに配置し、~/.ssh/configを編集する

という手順でいってはどうかと思います。けっこう強引な方法なのですが、どうでしょうか。

参考

@tatsuya6502
Copy link
Member

tatsuya6502 commented Jan 25, 2017

@y-yu さんの案(trpl-ja の CI の途中で deploy key を入れ替えて、trpl-ja から trpl-ja-pdf へ自動コミットする)も、たしかに動くと思います。しかし、これは最後の手段としてとっておいて、この自動コミットは、trpl-ja-pdf の CI で行わせた方がよさそうに感じます。

理由は、trpl-ja の CI と trpl-ja-pdf の CI をできる限り疎結合にしたいからです。そうすることで以下のような利点があります。

  • trpl-ja-pdf に関すること(deploy key の設定や自動コミットのスクリプト)が、その中で完結するので、メンテナンスや変更管理がしやすくなる。
  • trpl-ja の CI に持たせる権限を最小にできる。(trpl-ja-pdf master ブランチへのコミット権限はできるだけ持たせたくない)

また、別の理由として、この仕組みが壊れやすそうなこともあります。

  • 本来 Circle CI が自動的にやってくれる部分(deploy keyの配置やリポジトリのチェックアウト)を使わずに、スクリプトで対応することになるので、複雑さが増す。Circle CI の仕様が変わった時に、動かなくなる可能性がある。
  • trpl-ja の master ブランチの CI では、HTML を生成して、trpl-ja master 自身に対して自動コミットしているので、これと trpl-ja-pdf master への自動コミットとの順番に注意する必要がある。(前者は Circle CI が配置する deploy key を使用し、後者はスクリプトで配置する deploy key を使用する)

もう少し調べたところ、Travis CI でも web API 経由で CI を起動できることがわかりました。

そこで、trpl-ja の CI は、この API を経由して、trpl-ja-pdf の既存の Travis CI による CI を起動するだけにして、残り、というか、メインの作業、つまり、サブモジュールの更新と trpl-ja-pdf への自動コミットは trpl-ja-pdf の既存の CI に行わせてはどうでしょうか? そこでは、すでに deploy key がセットアップされていて、gh-pages ブランチへの自動コミットを行っていますので、少ない修正で実現できそうです。

自動コミットにより CI が何度も実行されてしまう問題については、自動コミットのメッセージに [ci skip] と入れることで回避できます。これは、Travis CI、Circle CI 共通の方法で、trpl-ja の CI でも使っています。(参考:CIサービスの自動ビルドをスキップする方法まとめ

流れ

  1. trpl-ja の CI(Circle CI):もしビルドに成功したら、web API 経由で trpl-ja-pdf の CI(Travis CI)を起動
  2. trpl-ja-pdf の CI:サブモジュールを更新
    • (cd the-rust-programming-language-ja; git pull origin master) かな?
  3. trpl-ja-pdf の CI:PDF を生成
  4. 生成に成功したら、
    4.1. trpl-ja-pdf の CI:サブモジュールのリビジョンが変わっていたら、master ブランチへ自動コミット
    4.2. trpl-ja-pdf の CI:PDF を gh-pages ブランチへ自動コミット

ステップ 4.1 は、trpl-ja の自動コミットのスクリプトが参考になるかもしれません。コミットするものがあるときだけ、コミットするしくみになっています。

@tatsuya6502
Copy link
Member

メモ:

trpl-ja の最新版を pull する前に、/1.9/ja/book に変更があるかを確認するコマンド。

$ pwd
... /trpl-ja-pdf
$ (cd the-rust-programming-language-ja; git fetch origin && git diff --stat HEAD..origin/master -- 1.9/ja/book | grep -q 'files changed'; echo $?)

結果が 0 なら変更あり。1 なら変更なし。それ以外はエラー。

@tatsuya6502
Copy link
Member

#241 (comment)

trpl-ja の CI は、この API を経由して、trpl-ja-pdf の既存の Travis CI による CI を起動するだけにして、残り、というか、メインの作業、つまり、サブモジュールの更新と trpl-ja-pdf への自動コミットは trpl-ja-pdf の既存の CI に行わせてはどうでしょうか?

この方法で構わなければ、私の方で実装してみようと思います。ちょっと時間がかかるかもしれませんが、完成したら、trpl-ja-pdf と trpl-ja に、順に pull request を上げます。

  • 第1段階:trpl-ja-pdf の既存の CI(Travis CI)に、git サブモジュールの更新と自動コミットを追加する。
  • 第2段階:trpl-ja の既存の CI(Circle CI)に、trpl-ja-pdf の CI を起動するための Travis CI API コールを追加する。

@y-yu
Copy link
Member Author

y-yu commented Jan 27, 2017

うーん、ちょっと見てみないとわからないのですが、trpl-ja-pdfのCIの挙動が次のような二つになりそうな予感がします。

  • Circle CIによりキックされ、trpl-ja-pdfのmasterブランチを更新する
  • trpl-ja-pdfのmaster更新によりキックされ、trpl-ja-pdfのgh-pagesブランチを更新する

すると、条件文を次のように書くことになる気がします。

if trpl-ja-pdfのsubmoduleに変更がある then
  # この場合、trpl-jaのCircle CIにより起動されたといえる
  submoduleをアップデート
  git push origin master
else
  # trpl-ja-pdfのsubmoduleにアップデートがないのに起動された場合、
  # trpl-ja-pdfのCIが自らを更新したものであると言える
  ビルドを実行
  git push origin gh-pages
fi

こんな感じになるでしょうか。(ちょっと複雑で、僕もうまく状況が掴めていないかもしれないので、確認させてほしいと思います)

@tatsuya6502
Copy link
Member

tatsuya6502 commented Jan 27, 2017

ちょっと見てみないとわからないのですが、trpl-ja-pdfのCIの挙動が次のような二つになりそうな予感がします。

説明不足ですみません。
CI がどうやって起動されたかに関係なく、1回の実行で十分です。

TRPL ← ./the-rust-programming-language-ja

# trpl-jaに変更があったかに関係なく、ローカルのsubmoduleのアップデートを試みる。
(cd $TRPL; git fetch origin && git pull origin master)

PDFのビルドを実行

# ローカルのsubmoduleがアップデートされているかをチェックする。
st ← (git status $TRPL | grep -q 'modified'; echo $?)

# YESならmasterへコミットする。
if st == 0 then
  git add $TRPL
  # コミットメッセージに `[ci skip]` を含めることで、このコミットをきっかけにCIが走ることを防ぐ。
  git commit -m "... [ci skip]"
  git push origin master
fi

# gh-pagesへPDFをコミットする。
git checkout gh-pages
...
git push origin gh-pages

例:

trpl-ja の Circle CI によりキックされた場合

  1. ローカルの submodule のアップデートを試みる
  2. PDF のビルドを実行する
  3. submodule がアップデートされているかチェックする → YES
  4. trpl-ja-pdf の master ブランチを更新する([ci skip]
  5. trpl-ja-pdf の gh-pages ブランチを更新する

trpl-ja-pdf の master 更新によりキックされた場合

  1. ローカルの submodule をアップデート試みる → なにも起こらない
  2. PDF のビルドを実行する
  3. submodule がアップデートされているかチェックする → NO
  4. trpl-ja-pdf の gh-pages ブランチを更新する

この方法の利点は、PDF のビルドに成功しない限り、trpl-ja-pdf の master ブランチの submodule が更新されないことです。もし trpl-ja でなにか breaking な変更(例えば /1.9/ja/book のデレクトリ構造を /1.9/book に変更した)があって、そのままでは PDF のビルドが通らなくなったとしたら。そういう場合は、trpl-ja-pdf の master ブランチの submodule は、PDF のビルドが通るリビジョンがキープされます。

もう少し複雑な判断をさせたい場合

trpl-ja-pdf は trpl-ja の /1.9/ja/book ディレクトリの内容だけに依存しています。そこに変更があったときだけ、submodule を更新することもできます。

この場合は、Circle CI によって起動されたかどうかも判断したほうがよさそうです。Travis CI の API をコールする際に、任意の環境変数を設定できますので、それで判断しましょう。仮にその環境変数を、TRPL_JA_NEW_COMMIT とします。

  • trpl-ja の Circle CI によりキックされた場合 → TRPL_JA_NEW_COMMIT は 1
  • trpl-ja-pdf の master 更新によりキックされた場合 → TRPL_JA_NEW_COMMIT は未定義
TRPL ← ./the-rust-programming-language-ja
TRPL_JA_BOOK_UPDATED ← /tmp/tprl-ja-book-updated

# trpl-jaの/1.9/ja/bookに変更があるかチェックする。
st ← (cd $TRPL; \
      git fetch origin && \
      git diff --stat HEAD..origin/master -- 1.9/ja/book | grep -q 'files changed'; \
      echo $?)

# YESなら、ローカルのsubmoduleをアップデートし、さらに、TRPL_JA_BOOK_UPDATEDファイルを作成する。
if st == 0 then
  (cd $TRPL; git pull origin master)
  touch $TRPL_JA_BOOK_UPDATED
else
  rm -f $TRPL_JA_BOOK_UPDATED
fi

PDFのビルドを実行

if TRPL_JA_BOOK_UPDATEDファイルが存在する then
  git add $TRPL
  # コミットメッセージに `[ci skip]` を含めることで、このコミットをきっかけにCIが走ることを防ぐ。
  git commit -m "... [ci skip]"
  git push origin master
fi

if TRPL_JA_NEW_COMMITが未定義 or TRPL_JA_BOOK_UPDATEDファイルが存在する then
  # gh-pagesへPDF をコミットする。
  git checkout gh-pages
  ...
  git push origin gh-pages
fi

@y-yu
Copy link
Member Author

y-yu commented Jan 28, 2017

なるほど。詳細な説明をありがとうございます。これでよさそうに感じました。複雑な方法はとりあえずは使わずに、trpl-jaの方に変更があれば常にtrpl-ja-pdfを更新するという方針でよいと思います。

この方法で構わなければ、私の方で実装してみようと思います。ちょっと時間がかかるかもしれませんが、完成したら、trpl-ja-pdf と trpl-ja に、順に pull request を上げます。

もし、お忙しいようでしたら引き継ぎますので、気軽におねがいします。

@tatsuya6502
Copy link
Member

納得していただけたようで、よかったです。

複雑な方法はとりあえずは使わずに、trpl-jaの方に変更があれば常にtrpl-ja-pdfを更新するという方針でよいと思います。

了解です。これで進めますね。

@tatsuya6502 tatsuya6502 self-assigned this Feb 1, 2017
@y-yu
Copy link
Member Author

y-yu commented Jun 19, 2017

@tatsuya6502 さん。

この件ですが、お忙しいようでしたら私の方でやってみましょうか?

@tatsuya6502
Copy link
Member

@y-yu さん、お待たせしてすみません。Travisにテスト用の環境を用意した時点で、作業が止まってました...。今日、続きの作業をしますね。

@tatsuya6502
Copy link
Member

本日、作業してます。お待たせして本当にすみません。

@tatsuya6502
Copy link
Member

@tatsuya6502
Copy link
Member

  • the-rust-programming-language-ja の Circle CI 側
    • 数日中に PR を上げることを目標にしてます。

PR #278 をオープンしました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants