社内ではプロジェクトの管理をGitlabで行っていますが、このGitlabにはテストを実行するGitlab-CIという機能があります。
これは、TravisCIやCircleCIと類似のCIツールでDockerを使ったテストなどを行うことができます。
テストの実際の処理はGitlab runnerと呼ばれるテスト実行するノードで行います。このRunnerは手軽に構築でき適宜増やすことができます。
このGitlab-CIはとても便利なのですが、HTMLとして生成したテスト結果やカバレッジのレポートをブラウザ上で表示できないという問題があります。
テストで生成したファイルを保存しておくartifacts
という機能はあるのですが、これで保持したファイルのなかでhtmlやtext形式などのファイルは直接見ることができません。
そこで、GitlabのReview Appを使って生成したHTMLを表示できるようにする方法を考えました。
- Introducing Review Apps | GitLab
実現方法
具体的な環境の構築方法や使い方は以下の通りです。
Webサーバー環境構築
- レポート結果のHTMLを提供するためのサーバーを用意する
- そのサーバー上にnginxで提供ファイルを配置するディレクトリをドキュメントルートとしたhttpサーバーを構築する
- そのサーバー上にshellのgitlab runnerを構築する
- nginxのドキュメントルートにGitlab runnerのユーザ(デフォルトでgitlab-runnerユーザ)で書き込みできるようにする
Gitlab-CIのジョブ定義
Gitlab-CIはyamlでテストの処理内容を定義します。
テスト結果をwebで公開するには以下のようなジョブの定義にします。
stages:
- test
- deploy_report
test:
stage: test
script:
# テストを実行
- do some test
artifacts:
paths:
# テスト結果ファイルのあるディレクトリをartifactとして保存するように指示
- target/test-reports/
# テストレポートを公開場所にデプロイするタスク
deploy_test_report:
stage: deploy_report
variables:
# artifactsしか使わないのでgitリポジトリのcloneをしないように設定
GIT_STRATEGY: none
script:
# testジョブで保存したartifactsがカレントディレクトリにすでにある
# ファイルを公開ようにフォルダ整理
- mv target/test-reports/ ./test-reports
# テスト結果をweb公開ディレクトリに移す
- rsync -av --delete ./test-reports /srv/nginx/pages/$CI_BUILD_REF_NAME
environment:
name: review/$CI_BUILD_REF_NAME
url: http://$CI_BUILD_REF_NAME.$APPS_DOMAIN
on_stop: stop_review
# 公開したファイルを破棄するタスク
undeploy_test_report:
stage: deploy_report
variables:
GIT_STRATEGY: none
script:
# 公開ディレクトリのファイルを削除
- rm -rf public /srv/nginx/pages/$CI_BUILD_REF_NAME
when: manual
environment:
name: review/$CI_BUILD_REF_NAME
action: stop
上記のようにすることでテスト実行後に、nginxサーバーにテストレポートのファイルがコピーされます。
あとはそこで公開されているファイルをブラウザから閲覧することができるようになります。
公開ファイルのアクセス制限
前述の方法でテストレポートをブラウザから参照できるようになったのですが、1つ問題があります。
上記のwebサーバーには何らアクセス制限などがかけられておらず、URLがわかればだれでも閲覧できてしまいます。
そこで、このwebサーバーの閲覧をGitlabの各プロジェクトのアクセス権限と同じレベルで制限できる仕組みを作りました。
- m3dev/gitlab-access-controlled-server
大まかな仕組み
GitlabはOAuth2プロバイダーサーバーとして認証機能を提供する機能があります。
この仕組みは、nginx + oauth2_proxy + 自作pythonスクリプトの組み合わせでOAuth2認証付きのサーバーとして動作します。
nginxがhttpサーバーとして動作し、リクエストをoauth2_proxyにproxyします。
oauth2_proxyは、Gitlabを使ったOAuth2認証を行い、Gitlabで認証できた場合にのみ自作pythonスクリプトでのサーバーにさらにproxyします。
自作pythonスクリプトはwebサーバーとて動作し、その中でoauth2_proxyから受け取ったOAuth2のアクセストークンを使ってGitlab APIにアクセスします。Gitlab APIで対象プロジェクトにアクセスできるかどうかを確認できれば、指定されたディレクトリかのファイルをレスポンスします。
プロジェクト判定方法
この仕組みの中で問題になるのが、アクセスしようとしてるURLがどのプロジェクトに属したリソースであるかを判別する方法です。
はじめはURL中にプロジェクトIDを含めることを考えたのですがそれだと汎用性が低い感じがあったので、公開したいファイルのディレクトリに .gitlab-info.json
というファイルを配置し、その中にプロジェクトIDなどを定義するようにしました。
動きとしては、自作pythonスクリプトサーバーはアクセスされたURLのパスに対応するフォルダから上記のファイルを探します。もしなければ、ドキュメントルートまで上位階層へ登りながらこのファイルを探します。
ファイルを見つけたらその中身のJSONからプロジェクトIDや権限設定を取得します。
構築方法
この認証機能付きサーバーの構築方法は、プロジェクト内にDockerでの構築方法を用意しているのでそれを参考にしてください。
Dockerをそのまま使うこともできると思います。
使い方
Gitlab-CIでのテストの使い方は、基本的には前述の内容と同じです。
違うところは、ファイルをデプロイするときに.gitlab-info.json
ファイルを作成することを追加した点です。
# テストレポートを公開場所にデプロイするタスク
deploy_test_report:
stage: deploy_report
variables:
# artifactsしか使わないのでgitリポジトリのcloneをしないように設定
GIT_STRATEGY: none
script:
# testジョブで保存したartifactsがカレントディレクトリにすでにある
# ファイルを公開ようにフォルダ整理
- mv target/test-reports/ ./test-reports
# .gitlab-info.jsonを作る
+ - echo "{\"project_id\": $CI_PROJECT_ID, \"requires_access_to_code\": false}" > public/.gitlab-info.json
# テスト結果をweb公開ディレクトリに移す
- rsync -av --delete ./test-reports /srv/nginx/pages/$CI_BUILD_REF_NAME
environment:
name: review/$CI_BUILD_REF_NAME
url: http://$CI_BUILD_REF_NAME.$APPS_DOMAIN
on_stop: stop_review
補足
このGitlab-CIでのテスト結果の閲覧に関しては、Gitlabの開発コミュニティ上でも対応が検討されているようです。