debexpoをnハックするには¶ ↑
: subtitle
How to hack mentors.d.n
: author
Kentaro Hayashi
: institution
ClearCode Inc.
: content-source
TokyoDebian, 140th
: date
2016-06-25
: allotted-time
40m
: theme
.
自己紹介(1)¶ ↑
# image # relative-height = 40 # src = https://pbs.twimg.com/profile_images/2290018079/cvcy12slbeva80jboxzf_400x400.png
-
Twitter/GitHub: @kenhys
-
所属: ((*トラックポイント・ソフトドーム派*))
自己紹介(2)¶ ↑
# image # relative-height = 60 # src = images/track-points.png
-
トラックポイント・ソフトドーム派
参考画像の出典¶ ↑
# image # relative-height = 80 # src = images/irasutoya.png
閑話休題¶ ↑
そろそろ本題へ
今日の話¶ ↑
-
debexpoとは?
-
なぜdebexpoをハックする必要が?
-
どうやってハックしたのか?
今日の話¶ ↑
-
((*debexpoとは?*))
-
なぜdebexpoをハックする必要が?
-
どうやってハックしたのか?
debexpoとは?¶ ↑
-
mentors.d.nを支えるウェブアプリケーション
-
リポジトリ名がdebexpo
mentors.d.nとは?¶ ↑
# image # relative-height = 80 # src = images/mentors.d.n.png
debexpoの由来¶ ↑
# blockquote # title = https://workaround.org/project/debexpo The new project was called "debexpo" because it was supposed to become an ((*expo*))sition for ((*Deb*))ian packages.
ゆるキャラも¶ ↑
# image # relative-height = 80 # src = images/debexpo-mascot-zoom.png
-
名前は不明。知っていたら教えてください。
debexpo概要¶ ↑
-
Python製
-
Pylonsフレームワーク採用
-
テンプレートエンジンはMako
Pylonsn((‘note:www.pylonsproject.org/’))¶ ↑
-
Railsっぽいフレームワーク
-
2011年にメンテナンスモード入り
-
後継はPyramidに
debexpoの歴史(1)¶ ↑
-
2003年
-
最初はPerlで書かれていた
-
-
その後、Pythonで書き直し
debexpoの歴史(2)¶ ↑
-
2008年
-
Google SoCで開発が進む
-
-
2009-2010年
-
expo.debian.net/ 運用開始
-
-
2011年 そしてmentors.d.nへ
debexpoの役割¶ ↑
-
ITP,RFSのためのアップロード先
-
non-DDはパッケージを直接アップロードできない
-
スポンサーが必要
-
ITP,RFSのおさらい¶ ↑
mentors.d.nの使いかた ITP編/RFS編
mentors.d.nのn使いかた ITP編(1)¶ ↑
-
パッケージをDebianにもっていきたい
-
ITPのメールをsubmit@bugs.d.oへ
-
パッケージをmentors.d.nにdput
mentors.d.nのn使いかた ITP編(2)¶ ↑
-
RFSのメールをsubmit@bugs.d.oへ
-
レビュー & 修正 & dput
-
DDによるupload
mentors.d.nのn使いかた RFS編(1)¶ ↑
-
upstreamの新リリース
-
追従してパッケージをdput
-
RFSのメールをsubmit@bugs.d.oへ
mentors.d.nのn使いかた RFS編(2)¶ ↑
-
レビュー & 修正 & dput
-
DDによるupload
mentors.d.nオススメ¶ ↑
-
パッケージのチェックもしてくれる
-
RFSのテンプレートも生成してくれる
mentors.d.nオススメ¶ ↑
-
((*パッケージのチェックもしてくれる*))
-
RFSのテンプレートも生成してくれる
チェック結果がみれる¶ ↑
# image # relative-height = 80 # src = images/qa-information.png
-
lintianの警告とか
mentors.d.nオススメ¶ ↑
-
パッケージのチェックもしてくれる
-
((*RFSのテンプレートも生成してくれる*))
RFSのテンプレート生成¶ ↑
# image # relative-height = 80 # src = images/view-rfs-template.png
-
あとはメールするだけ(※)
今日の話¶ ↑
-
debexpoとは?
-
((*なぜdebexpoをハックする必要が?*))
-
どうやってハックしたのか?
mentors.d.nがnオススメな理由¶ ↑
(再)mentors.d.nがnオススメな理由¶ ↑
-
RFSテンプレート生成
-
あとはメールを出すだけ
(再)mentors.d.nがnオススメな理由¶ ↑
-
RFSテンプレート生成
-
あとはメールを出すだけ
-
((*と言ったが、あれは嘘だ*))
論より証拠¶ ↑
実際のRFS templateをお見せしよう
証拠物件(1)¶ ↑
# image # relative-height = 80 # src = images/rfs-template-pithole.png
-
[fill in]の文字がちらほら
証拠物件(2)¶ ↑
# image # relative-height = 70 # src = images/rfs-template-pithole2.png
-
ほかにも穴埋めが必要
編集すべき箇所¶ ↑
-
いくつかあるので紹介
編集すべき箇所(1)¶ ↑
# image # relative-width = 100 # src = images/rfs-template-fill-in1.png
-
Subject:に種別を書け
編集すべき箇所(2)¶ ↑
# image # relative-width = 100 # src = images/rfs-template-fill-in2.png
-
Severity:を書け
編集すべき箇所(3)¶ ↑
# image # relative-width = 100 # src = images/rfs-template-fill-in3.png
-
Upstream,URL,License:を書け
編集すべき箇所(4)¶ ↑
# image # relative-width = 100 # src = images/rfs-template-fill-in4.png
-
Changelogを書け
これで終わり?¶ ↑
編集すべき箇所(5)¶ ↑
# image # relative-width = 100 # src = images/rfs-template-fill-in5.png
-
さりげなく埋めこまれたhelloとexample.com
これでメールが出せる¶ ↑
先頭に埋めこまれたnスペース2つ¶ ↑
# image # relative-width = 100 # src = images/rfs-template-pithole3.png
-
コマンドメールであることを思いだそう
-
((‘wait’))((*もちろんエラーになります*))
Q. なぜdebexpoをnハックするのか?¶ ↑
-
RFSテンプレートの残念っぷりをどうにかしたい
-
同じ思いの人はいた¶ ↑
# image # relative-width = 100 # src = images/alioth-debexpo-313593-request.png
-
Aliothのtrackerで4年も前に通った道
今日の話¶ ↑
-
debexpoとは?
-
なぜdebexpoをハックする必要が?
-
((*どうやってハックしたのか?*))
あらすじ¶ ↑
-
upstream探し
-
ドキュメント探し
-
まずは動かしてみる
-
あたりをつけて修正
-
そしてPRへ
特別なことは何も¶ ↑
よくあるフリーソフトウェアの修正
あらすじ¶ ↑
-
((*upstream探し*))
-
ドキュメント探し
-
まずは動かしてみる
-
あたりをつけて修正
-
そしてPRへ
upstream探し(1)¶ ↑
# image # relative-width = 100 # src = images/source-code-and-bugs.png
-
mentors.d.n下部にリンクがきちんとある
-
aliothをみればいいとわかる
upstream探し(2)¶ ↑
# image # relative-height = 80 # src = images/last-change-on-alioth.png
-
最近はコミットがない
ちょっと不安に¶ ↑
-
よく使われているならそこそこメンテされているイメージ
-
実際にはそうでもなかった
upstream探し(3)¶ ↑
# image # relative-height = 70 # src = images/last-change-on-github.png
-
GitHubのほうが実は新しい
-
((‘tag:x-small’))github.com/debexpo/debexpo
-
upstream探し(4)¶ ↑
-
aliothがmaster
-
GitHubのをマージという運用
あらすじ¶ ↑
-
upstream探し
-
((*ドキュメント探し*))
-
まずは動かしてみる
-
あたりをつけて修正
-
そしてPRへ
ドキュメント探し¶ ↑
-
docs/*にドキュメントが整備
-
docs/installing.rstを参照
-
リンク先が404なこともあるので注意
-
あらすじ¶ ↑
-
upstream探し
-
ドキュメント探し
-
((*まずは動かしてみる*))
-
あたりをつけて修正
-
そしてPRへ
まずは動かしてみる¶ ↑
-
セットアップ方法は3種
-
既存システムにインストール
-
virtualenvでインストール
-
VirtualBoxでインストール
-
まずはVirtualBoxで¶ ↑
-
環境を分けたいのでVirtualBoxを選択
Vagrantfileがアレ¶ ↑
# Every Vagrant virtual environment requires a box to build off of. config.vm.box = "chef/debian-7.6"
-
Debian 7.6 (2014年7月12日)?
-
Debian 7.10でてるよ?
vagrant upしてみると¶ ↑
% vagrant up Bringing machine 'default' up with 'virtualbox' provider... ==> default: Box 'chef/debian-7.6' could not be found. Attempting to find and install... default: Box Provider: virtualbox default: Box Version: >= 0 The box 'chef/debian-7.6' could not be found or could not be accessed in the remote catalog. If this is a private box on HashiCorp's Atlas, please verify you're logged in via `vagrant login`. Also, please double-check the name. The expanded URL and error message are shown below: URL: ["https://atlas.hashicorp.com/chef/debian-7.6"] Error: The requested URL returned error: 404 Not Found
-
boxが見つからなくてコケる
PR#32で修正¶ ↑
# image # relative-width = 100 # src = images/debexpo-pr32-use-latest-wheezy.png
-
Bento projectに移行していたせいだった
起動してログインするまで¶ ↑
$ vagrant up --provision $ vagrant ssh
-
よくあるやりかた
vagrant sshしてnサーバーを起動¶ ↑
$ cd debexpo $ . venv/bin/activate $ paster serve development.ini
5000ポートでサーバー起動¶ ↑
# image # relative-height = 80 # src = images/debexpo-on-localhost.png
-
ブラウザでアクセス可能に
ユーザーの追加(1)¶ ↑
-
方法は2つある
-
ブラウザ経由で追加
-
JSONで追加
-
ユーザーの追加(2)¶ ↑
# image # relative-height = 80 # src = images/debexpo-sign-me-up.png
-
ブラウザ経由で追加
ユーザーの追加(3)¶ ↑
-
JSONで追加するなら
# enscript javascript { "realname":"Hayashi Kentaro", "password":"password", "email":"hayashi@clear-code.com" }
ユーザーの追加(4)¶ ↑
-
追加用のスクリプトを利用
$ python ./bin/user_importer.py \ -i development.ini -u user.json
アカウントの有効化¶ ↑
-
verification (ログインに必要)
-
dmup (アップロードに必要)
verificationの設定¶ ↑
# image # relative-width = 90 # src = images/update-verification.png
-
verificationを空にする
-
メールの確認をバイパス
-
DMUP?¶ ↑
# image # relative-width = 50 # src = images/debexpo-dmup.png
-
マシン使用ポリシーのこと
dmupの設定¶ ↑
# image # relative-width = 90 # src = images/update-dmup.png
-
dmupフィールドを更新
-
同意したことにする
-
.dput.cfの設定をする¶ ↑
[debexpo] fqdn = localhost:5000 incoming = /upload/kenhys@gmail.com/password method = http allow_unsigned_uploads = 0
-
アップロードの準備をする
試しにパッケージをnアップロード¶ ↑
Uploading to debexpo (via http to localhost:5000): Uploading groonga_6.0.2-1.dsc: Upload failed: 500 Internal Server Error
-
((*500 Internal Server Error*))
さっそくバグを踏む¶ ↑
# image # relative-width = 90 # src = images/find-a-debexpo-bug.png
-
あるべきディレクトリがないというオチ
PR#34で修正¶ ↑
# image # relative-width = 100 # src = images/debexpo-pr34-incoming-directory.png
-
ちゃんとディレクトリを作る
PR出して気づいた怖い話¶ ↑
# image # relative-width = 100 # src = images/broken-ci-since-8month-ago.png
-
最後にテストが通ったの((*8ヶ月前*))
なぜか?¶ ↑
-
Travis-CIの環境の変化
-
しばらくコミットされてないので誰も気づかない
PR#38で修正¶ ↑
# image # relative-width = 100 # src = images/debexpo-pr38-broken-ci.png
-
テストが通るように
PR#37で修正¶ ↑
# image # relative-width = 100 # src = images/debexpo-pr37-drop-py26.png
-
Python2.6でCIはもういいんじゃ
パッケージのとりこみ¶ ↑
$ ./bin/debexpo_importer.py \ -c /tmp/debexpo/growl-for-linux_0.8.5-1_source.changes \ -i development.ini --skip-gpg-check --skip-email
-
インポートスクリプト実行
とりこみできずにnTraceback¶ ↑
Traceback (most recent call last): File "./bin/debexpo_importer.py", line 60, in i.main() File "/home/vagrant/debexpo/debexpo/importer/importer.py", line 473, in main gpg = get_gnupg() File "/home/vagrant/debexpo/debexpo/lib/utils.py", line 119, in get_gnupg return gnupg.GnuPG(config['debexpo.gpg_path'], File "/home/vagrant/debexpo/venv/local/lib/python2.7/site-packages/paste/registry.py", line 146, in getitem return self._current_obj()[key] KeyError: 'debexpo.gpg_path'
PR#39で修正¶ ↑
# image # relative-width = 100 # src = images/debexpo-pr39-skip-gpg.png
-
オプションを正しく解釈するように
パッケージリスト¶ ↑
# image # relative-width = 80 # src = images/debexpo-package-list.png
-
リストアップされるように
あらすじ¶ ↑
-
upstream探し
-
ドキュメント探し
-
まずは動かしてみる
-
((*あたりをつけて修正*))
-
そしてPRへ
ディレクトリ構成¶ ↑
config controllers cronjobs importer i18n lib model plugins public templates tests
手がかりはURL¶ ↑
# image # relative-height = 80 # src = images/debexpo-investigate-rfs-template-link.png
-
知りたいのはこのリンク
こんなリンク先¶ ↑
コントローラを探す¶ ↑
# enscript python def rfs_howto(self, packagename = None): c.package = None c.package_dir = None if packagename: package = meta.session.query(Package) .filter_by(name=packagename).first() if package: c.package = package c.package_dir = get_package_dir(package.name) return render('/sponsor/rfs_howto.mako')
-
controllers/sponsor.py
テンプレートを見る¶ ↑
Package: sponsorship-requests Severity: normal [important for RC bugs, wishlist for new packages] Dear mentors, %if c.package: I am looking for a sponsor for my package "${ c.package.name }" %else: I am looking for a sponsor for my package "hello": %endif
-
templates/sponsor/rfs_howto.mako
やりたいこと¶ ↑
-
RFSテンプレートから
-
[fill in]撲滅
-
mailto:リンクの生成
-
当初の目論見¶ ↑
-
${ c.package.name }とかあるぞ
-
テンプレートを書き換えればいいのでは?
無理でした¶ ↑
なぜか?¶ ↑
-
必要なメタ情報を保持していない
-
持ってないものは表示できない orz…
-
ないならかき集めればいいじゃない
-
収集するにはどうすればいいか¶ ↑
-
インポートの処理の流れを把握する
-
どのタイミングで収集すべきか知る
-
不足している情報は何かを知る
インポート処理の流れ(1)¶ ↑
-
dputでmentors.d.nへアップロード
-
インポート前処理
-
パッケージのインポート処理
インポート処理の流れ(2)¶ ↑
-
もう少し詳しく言うと
-
dputしたファイルは/tmp/debexpo/pubへ保存
-
インポート前処理で/tmp/debexpoヘ移動
-
orig.tar.gzがなかったりするとrejectメール
-
-
インポート処理の流れ(3)¶ ↑
-
もう少し詳しく言うと
-
インポート処理で/tmp/debexpo/filesへ移動
-
/tmp/debexpo/files以下
-
pool
-
dist
-
git
-
-
収集すべきデータは?¶ ↑
-
現状、メタ情報はどう保持されているのかを把握する
-
テーブルを覗いてみよう
-
主要なテーブル¶ ↑
-
主なものは3つ
-
packages
-
package_versions
-
package_info
-
packagesテーブル¶ ↑
-
パッケージのマスターテーブル
-
名前や説明などのメタ情報を保持
packagesテーブル¶ ↑
# enscript sql sqlite> .schema packages CREATE TABLE packages ( id INTEGER NOT NULL, name TEXT NOT NULL, user_id INTEGER, description TEXT, watch_counter INTEGER, download_counter INTEGER, needs_sponsor INTEGER NOT NULL, PRIMARY KEY (id), FOREIGN KEY(user_id) REFERENCES users (id) );
package_versionsnテーブル¶ ↑
-
パッケージの版管理
-
何度もアップロードすると増加
package_versionsnテーブル¶ ↑
# enscript sql sqlite> .schema package_versions CREATE TABLE package_versions ( id INTEGER NOT NULL, package_id INTEGER, version TEXT NOT NULL, maintainer TEXT NOT NULL, section TEXT NOT NULL, distribution TEXT NOT NULL, qa_status INTEGER NOT NULL, component TEXT NOT NULL, priority TEXT, closes TEXT, uploaded DATETIME NOT NULL, PRIMARY KEY (id), FOREIGN KEY(package_id) REFERENCES packages (id) );
package_infoテーブル¶ ↑
-
プラグインの適用結果を管理
-
メタ情報を保持
package_infoテーブル¶ ↑
# enscript sql sqlite> .schema package_info CREATE TABLE package_info ( id INTEGER NOT NULL, package_version_id INTEGER, from_plugin VARCHAR(200) NOT NULL, outcome VARCHAR(200) NOT NULL, data TEXT, severity INTEGER NOT NULL, PRIMARY KEY (id), FOREIGN KEY(package_version_id) REFERENCES package_versions (id) );
package_infoテーブル¶ ↑
* from_plugin * どのプラグインか * outcome * 説明文(エラーメッセージ) * data * JSONデータ
package_infoの例¶ ↑
# enscript sql sqlite> select * from package_info; 1|1|native|Package is not native|{"native": false}|1 2|1|maintaineremail|"Maintainer" email is the same as the uploader|{ "user-email": "hayashi@clear-code.com", "uploader-emails": [], "maintainer-email": "hayashi@clear-code.com", "user-is-maintainer": true }|1 3|1|debianqa|Package is already in Debian|{ "nmu": false, "in-debian": true, "is-debian-maintainer": true }|1
やりたいこと¶ ↑
-
RFSテンプレートから
-
[fill in]撲滅
-
mailto:リンクの生成
-
修正方針¶ ↑
-
プラグインで追加のメタ情報を収集
-
メール用のテンプレート追加
-
詳細ページでメタ情報を表示しつつmailto:リンク生成
プラグイン?¶ ↑
-
debexpoはプラグインで機能拡張する
-
パッケージのチェックもプラグインを組み合わせて実現
プラグインの作り方¶ ↑
-
docs/writing_plugins.rst
プラグインの雛形¶ ↑
# enscript python class FooPlugin(BasePlugin): def test_xxx(self): self.passed(outcome, data, severity) or self.failed(outcome, data, severity) plugin = FooPlugin
-
debexpo/plugins/foo.py
プラグインいろいろ¶ ↑
% wc -l debexpo/plugins/*.py 99 debexpo/plugins/buildsystem.py 67 debexpo/plugins/changeslist.py 141 debexpo/plugins/closedbugs.py 85 debexpo/plugins/controlfields.py 185 debexpo/plugins/debianqa.py 85 debexpo/plugins/diffclean.py 63 debexpo/plugins/distribution.py 123 debexpo/plugins/getorigtarball.py 116 debexpo/plugins/lintian.py 100 debexpo/plugins/maintaineremail.py 69 debexpo/plugins/native.py 77 debexpo/plugins/notuploader.py 86 debexpo/plugins/removepackage.py 60 debexpo/plugins/ubuntuversion.py 110 debexpo/plugins/watchfile.py
プラグインの適用方法¶ ↑
-
設定ファイル(.ini)で制御
-
インポート前処理
-
QA処理
-
Debian入りした時
-
インポート処理後
-
プラグインを設定(1)¶ ↑
-
debexpo.plugins.post_upload
-
インポート前処理で適用
-
getorigtarballプラグイン
-
プラグインを設定(2)¶ ↑
-
debexpo.plugins.qa
-
QA処理で適用
-
lintianプラグイン
-
プラグインを設定(3)¶ ↑
-
debexpo.plugins.post_upload_to_debian
-
パッケージがDebian入りしたときに適用
-
removepackageプラグイン
-
プラグインを設定(4)¶ ↑
-
debexpo.plugins.post_successful_upload
-
インポート処理後に適用
-
changeslistプラグイン
-
プラグインの書きかた¶ ↑
なんとなくわかったのでいざ実践へ
やったこと¶ ↑
-
プラグインの処理を実装
-
プラグインを適用
-
mailto用テンプレート追加
-
rfstemplateのデータを表示
プラグインの処理を実装¶ ↑
-
debexpo/plugins/rfstemplate.pyを実装
-
実質100行ないくらい
-
debian/changelogやdebian/controlから抽出
-
deb822, copyrightモジュールを活用
-
プラグインを適用¶ ↑
debexpo.plugins.qa = ... rfstemplate ...
-
development.iniに設定
mailto用テンプレート追加¶ ↑
%if c.rfstemplate: Upstream Author : ${ c.rfstemplate['upstream-author'] } * URL : ${ c.rfstemplate['upstream-url'] } * License : ${ c.rfstemplate['upstream-license'] } %else: Upstream Author : [fill in name and email of upstream] * URL : [fill in URL of upstreams web site] * License : [fill in] %endif
-
debexpo/templates/sponsor/rfs_template.mako
rfstemplateのnデータを表示¶ ↑
# enscript python if latest: rfstemplate = meta.session.query(PackageInfo) .filter_by(package_version_id=latest.id) .filter_by(from_plugin='rfstemplate').first() if rfstemplate: c.rfstemplate = json.loads(rfstemplate.data) c.mailbody = render('/sponsor/rfs_template.mako') return render('/sponsor/rfs_howto.mako')
-
debexpo/controllers/sponsor.py
実際にデモ¶ ↑
成果物をPR#35で出した¶ ↑
# image # relative-width = 60 # src = images/debexpo-pr35.png
((‘tag:x-small’))github.com/debexpo/debexpo/pull/35
PR#35の経過(1)¶ ↑
-
May 4
-
@olasdさんから好意的な反応
-
-
May 14
-
どうなった?とつついてみるも反応なし
-
PR#35の経過(2)¶ ↑
-
May 21
-
Debian勉強会でまだマージされてない話をする
-
あれやこれやでしばし放置
-
PR#35の経過(3)¶ ↑
-
June 19
-
@paulproteusさんをつついてみる
-
-
June 19
-
20日にみれるかもと@paulproteusさんから反応あり
-
PR#35の経過(4)¶ ↑
# image # relative-width = 100 # src = images/debexpo-pr35-paulproteus.png
-
どうもDebConf16待ち
まとめ¶ ↑
-
debexpoとはmentors.d.nのこと
-
RFSテンプレートが残念だったので改善した
-
そのうちマージされる(多分)ので乞御期待
補足¶ ↑
-
マージへ向けた懸念事項
-
mentors.d.nは運用環境がwheezyらしい
-
wheezyのままならrejectされるかも
-
実装したプラグインがwheezyでは動かない(0.1.23以降が必要)
-
wheezyではpython-debianが古い(0.1.21)
-
jessieなら0.1.27なので動作する
-
-