めりーくりすます。Red Hatのさいとうです。この記事はAnsible 2 Advent Calendarの12月25日のエントリです。 前回の記事に引き続き、2回めの今回は、実際にAWXのコードを修正して規定のテストを実施し、アップストリームのAWXプロジェクトにPull Requestを作成するまでの流れを紹介します。
※前回同様、開発環境上での作業はプロンプトに [host] を、開発環境上に起動させた開発用のコンテナ上で作業する作業は [container] と明記しますので、実際に作業する環境に注意して読んでください。
AWXの開発用コンテナ群が起動していることを確認する
How to contribute - AWX(1)にしたがって、すでに開発用のコンテナ群が起動しており、管理ユーザ(awx)が作成されていることを確認します。
tools_awx_1, tools_rabbitmq_1, tools_postgres_1 そして tools_memcached_1 という4つのコンテナが起動しているはずです:
[host]$ docker ps --format "table {{.ID}}\t{{.Names}}\t{{ .Ports }}" CONTAINER ID NAMES PORTS 210c423c473c tools_awx_1 0.0.0.0:6899->6899/tcp, 0.0.0.0:7899-7999->7899-7999/tcp, 0.0.0.0:8013->8013/tcp, 0.0.0.0:8043->8043/tcp, 0.0.0.0:8080->8080/tcp, 22/tcp, 0.0.0.0:8888->8888/tcp 5226b93ab835 tools_rabbitmq_1 4369/tcp, 5671-5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp 82c29aab2d47 tools_postgres_1 0.0.0.0:5432->5432/tcp 7cb708df7506 tools_memcached_1 0.0.0.0:11211->11211/tcp
AWXのダッシュボードやジョブ実行の機能を提供しているのが tools_awx_1 です。このコンテナは、開発環境にチェックアウトしたawxリポジトリをマウントしています。
[host]$ docker inspect tools_awx_1 -f "{{ .Mounts }}" [{bind /home/ansible/work/src/awx /awx_devel rw true rprivate} {bind /home/ansible/work/src/awx/awx/projects /var/lib/awx/projects rw true rprivate}]
つまり、コードの修正は開発環境上で実施すればOKです。ただし、フロントエンドのJavaScriptのコードを修正する場合は、修正を反映するために:
- tools_awx_1コンテナの停止(make docker-composeで起動しているはずなのでCTRL+Cで停止)
- make clean && make languages && make ui-devel の実施
- make docker-composeで再度起動
が必要になるので注意してください。
コードの修正
それでは、実際にコードを修正してから、規定のテストを実施してみましょう。サンプルとしてダッシュボードへのログイン時に出力されるログを修正してみます。
[修正前] awx_1 | 2019-12-21 02:51:51,354 INFO awx.api.generics User awx logged in from N.N.N.N [修正後] awx_1 | 2019-12-21 02:51:51,354 INFO awx.api.generics Welcome to Ansible AWX! User awx logged in from N.N.N.N
以下のようにログ出力メッセージを修正してみました。
[host]$ git diff awx/api/generics.py diff --git a/awx/api/generics.py b/awx/api/generics.py index 37ca8bef4..eb8de518c 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -92,7 +92,7 @@ class LoggedLoginView(auth_views.LoginView): ret = super(LoggedLoginView, self).post(request, *args, **kwargs) current_user = getattr(request, 'user', None) if request.user.is_authenticated: - logger.info(smart_text(u"User {} logged in from {}".format(self.request.user.username,request.META.get('REMOTE_ADDR', None)))) + logger.info(smart_text(u"Welcome to Ansible AWX! User {} logged in from {}".format(self.request.user.username,request.META.get('REMOTE_ADDR', None)))) ret.set_cookie('userLoggedIn', 'true') current_user = UserSerializer(self.request.user) current_user = smart_text(JSONRenderer().render(current_user.data))
DjangoアプリケーションのPythonコードに対する修正ですから、コンテナをリスタートすることなく make docker-compose を実行しているコンソールのログには、ダッシュボードからのログイン時に修正されたログが出力されるはずです。
規定のテストを実施する
実際に動作確認して、動作確認できたらcommit&pushしてPRを作成し、あとはアップストリーム側のCIテストにおまかせしてしまう...という手もありますが、本家のお作法にしたがって、手元でテストを実施してからPull Requestを作成します。
まずはflake8(make flake8)でPythonコードの書式のチェックです:
[container]$ make flake8 ./awx/api/generics.py:95:161: E501 line too long (162 > 160 characters) make: *** [Makefile:342: flake8] Error 1
長い...しまった...修正した行が長すぎた...では怒られないような書式に修正します:
[host]$ git diff awx/api/generics.py diff --git a/awx/api/generics.py b/awx/api/generics.py index 37ca8bef4..642c761b3 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -92,7 +92,8 @@ class LoggedLoginView(auth_views.LoginView): ret = super(LoggedLoginView, self).post(request, *args, **kwargs) current_user = getattr(request, 'user', None) if request.user.is_authenticated: - logger.info(smart_text(u"User {} logged in from {}".format(self.request.user.username,request.META.get('REMOTE_ADDR', None)))) + logger.info( smart_text( + u"Welcome to Ansible AWX! User {} logged in from {}".format(self.request.user.username,request.META.get('REMOTE_ADDR', None)))) ret.set_cookie('userLoggedIn', 'true') current_user = UserSerializer(self.request.user) current_user = smart_text(JSONRenderer().render(current_user.data))
これでよかろう:
[container]$ make flake8 [container]$
問題が報告されることなく無事に通過しました。続いてJavaScriptコードは修正していませんが、念の為 JSHint(make jshint)も実施しておきます:
[container]$ make jshint ... Running "jshint:source" (jshint) task ✔ No problems ...
コードの書式的には、これで問題ないようです。次に、テストフレームワーク(pytestとJasmine)を利用したテストを実施します。まずはpytest(make test)から:
[container]$ make test ====================================== test session starts ======================================= platform linux -- Python 3.6.8, pytest-3.6.0, py-1.8.0, pluggy-0.6.0 Django settings: awx.settings.development (from ini file) rootdir: /awx_devel, inifile: pytest.ini plugins: xdist-1.27.0, timeout-1.3.3, pythonpath-0.7.3, mock-1.11.1, forked-1.1.3, django-3.7.0, cov-2.8.1, celery-4.3.0 gw0 [2572] / gw1 [2572] / gw2 [2572] / gw3 [2572] .....................................................................................................................................................s [ 5%] ... .................... [100%] ========================================================= 2562 passed, 10 skipped in 388.78 seconds ========================================================== cd awxkit && /venv/awx/bin/tox -re py2,py3 GLOB sdist-make: /awx_devel/awxkit/setup.py py2 create: /awx_devel/awxkit/.tox/py2 ... py2: commands succeeded py3: commands succeeded congratulations :) awx-manage check_migrations --dry-run --check -n 'vNNN_missing_migration_file' No changes detected
エラーで失敗するようであれば、コードに問題がある可能性が高い(テスト自体の問題である場合ありますが、経験上その可能性は非常に低いです)ので、修正したコードを見直してからmake testを再実行しましょう。
続いてUIのテストです。make ui-test-ciは、Chromeをヘッドレスモードで起動してUIテストを実施してくれます。
[container]$ make ui-test-ci npm --prefix awx/ui run test:ci ... HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 4 of 41 (skipped 1) SUCCESS (0 secs / 0.254 secs) HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 6 of 41 (skipped 1) SUCCESS (0 secs / 0.45 secs) HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 8 of 41 (skipped 1) SUCCESS (0 secs / 0.656 secs) HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 11 of 41 (skipped 1) SUCCESS (0 secs / 0.885 secs) HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 13 of 41 (skipped 1) SUCCESS (0 secs / 1.008 secs) HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 14 of 41 (skipped 1) SUCCESS (0 secs / 1.185 secs) HeadlessChrome 71.0.3542 (Linux 0.0.0): Executed 38 of 41 (skipped 3) SUCCESS (1.967 secs / 1.753 secs)
無事にパスすればテスト完了です。
commit & push そしてPull Request
git commit --signoff でサインして適切なコメントをつけて修正コードをcommit & pushしましょう。
[host]$ git add awx/api/generics.py [host]$ git commit --signoff [host]$ git push --set-upstream origin PR/adc20191204
最後に、GithubサイトでPull Requestを作成してください。
以上、AWXのアップストリームプロジェクトにコードをコントリビュートするためのオーソドックスな方法について紹介しました。AWXプロジェクトにコードをコントリビュートしたいと考えている「みなさん」の参考になりますように :)