GitHubアクションを使用した継続的インテグレーションテストワークフローの作成

公開: 2022-03-10
クイックサマリー↬このチュートリアルを使用すると、GitHubアクションを使用してNode JS REST APIの継続的インテグレーションワークフローを作成する方法と、Coverallsを使用してテストカバレッジをレポートする方法を学ぶことができます。

GitHubやBitbucketなどのバージョン管理プラットフォームでプロジェクトに貢献する場合、慣例として、機能コードベースを含むメインブランチがあります。 次に、複数の開発者がメインのコピーを操作して、新しい機能を追加したり、バグを修正したりできる他のブランチがあります。 入ってくる変更が既存のコードに与える影響の種類を監視することがより簡単になるので、それは非常に理にかなっています。 エラーが発生した場合は、変更をメインブランチに統合する前に、簡単に追跡して修正できます。 小さなプロジェクトであっても、コードのすべての行を手動で調べてエラーやバグを探すのは時間がかかる場合があります。 そこで、継続的インテグレーションが登場します。

継続的インテグレーション(CI)とは何ですか?

「継続的インテグレーション(CI)は、複数の貢献者からのコード変更の単一のソフトウェアプロジェクトへの統合を自動化する手法です。」

— Atlassian.com

継続的インテグレーション(CI)の背後にある一般的な考え方は、プロジェクトに加えられた変更が「ビルドを壊さない」、つまり既存のコードベースを台無しにしないようにすることです。 ワークフローの設定方法に応じて、プロジェクトに継続的インテグレーションを実装すると、誰かがリポジトリに変更を加えるたびにビルドが作成されます。

それで、ビルドとは何ですか?

ビルド(このコンテキストでは)は、ソースコードを実行可能形式にコンパイルすることです。 それが成功した場合、それは入ってくる変更がコードベースに悪影響を及ぼさないことを意味し、それらはうまくいきます。 ただし、ビルドが失敗した場合は、変更を再評価する必要があります。 そのため、メインコードベースに組み込む前に、別のブランチでプロジェクトのコピーを操作してプロジェクトに変更を加えることをお勧めします。 このように、ビルドが壊れた場合、エラーがどこから来ているのかを簡単に把握でき、メインのソースコードにも影響しません。

「欠陥を早期に発見すればするほど、修正するのに費用がかかりません。」

— David Farley、継続的デリバリー:ビルド、テスト、および展開の自動化による信頼性の高いソフトウェアリリース

プロジェクトの継続的インテグレーションの作成に役立つツールがいくつかあります。 これらには、Jenkins、TravisCI、CircleCI、GitLab CI、GitHubアクションなどが含まれます。このチュートリアルでは、GitHubアクションを使用します。

継続的インテグレーションのためのGitHubアクション

CIアクションはGitHubのかなり新しい機能であり、プロジェクトのビルドとテストを自動的に実行するワークフローの作成を可能にします。 ワークフローには、イベントが発生したときにアクティブ化できる1つ以上のジョブが含まれています。 このイベントは、リポジトリ上の任意のブランチへのプッシュまたはプルリクエストの作成である可能性があります。 先に進むにつれて、これらの用語について詳しく説明します。

始めましょう!

前提条件

これは初心者向けのチュートリアルなので、主にGitHub ActionsCIについて表面レベルで説明します。 読者は、PostgreSQLデータベースを使用したNode JS REST APIの作成、ORMの続編、およびMochaとChaiを使用したテストの作成に既に精通している必要があります。

また、マシンに次のものがインストールされている必要があります。

  • NodeJS、
  • PostgreSQL、
  • NPM、
  • VSCode(または任意のエディターとターミナル)。

すでに作成したcountries-info-apiというRESTAPIを利用します。 これは、役割ベースの承認がない単純なAPIです(このチュートリアルを書いている時点で)。 これは、誰でも国の詳細を追加、削除、および/または更新できることを意味します。 各国には、ID(自動生成されたUUID)、名前、首都、および人口があります。 これを実現するために、データベースにNode js、express jsフレームワーク、Postgresqlを使用しました。

テストカバレッジのテストと継続的インテグレーションのワークフローファイルの作成を開始する前に、サーバーとデータベースのセットアップ方法について簡単に説明します。

独自のAPIをフォロースルーまたは作成するために、 countries-info-apiリポジトリのクローンを作成できます。

使用したテクノロジーNode Js、NPM(Javascriptのパッケージマネージャー)、Postgresqlデータベース、続編ORM、Babel。

ジャンプした後もっと! 以下を読み続けてください↓

サーバーのセットアップ

サーバーをセットアップする前に、npmからいくつかの依存関係をインストールしました。

 npm install express dotenv cors npm install --save-dev @babel/core @babel/cli @babel/preset-env nodemon

Expressフレームワークを使用してES6形式で記述しているので、コードをコンパイルするにはBabeljsが必要です。 公式ドキュメントを読んで、それがどのように機能し、プロジェクトに合わせて構成するかについて詳しく知ることができます。 Nodemonは、コードに加えられた変更を検出し、サーバーを自動的に再起動します。

-save --save-devフラグを使用してインストールされたNpmパッケージは、開発段階でのみ必要であり、 package.jsonファイルのdevDependenciesの下に表示されます。

index.jsファイルに以下を追加しました。

 import express from "express"; import bodyParser from "body-parser"; import cors from "cors"; import "dotenv/config"; const app = express(); const port = process.env.PORT; app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); app.get("/", (req, res) => { res.send({message: "Welcome to the homepage!"}) }) app.listen(port, () => { console.log(`Server is running on ${port}...`) })

これにより、 .envファイルのPORT変数に割り当てられているものすべてで実行されるようにAPIが設定されます。 これは、他の人が簡単にアクセスできないようにする変数を宣言する場所でもあります。 dotenv npmパッケージは、 .envから環境変数をロードします。

ターミナルでnpm run startと、次のようになります。

実行中のサーバー
サーバーはポート3000で稼働しています。(大きなプレビュー)

ご覧のとおり、サーバーは稼働しています。 わーい!

Webブラウザのこのリンクhttps://127.0.0.1:your_port_number/は、ウェルカムメッセージを返す必要があります。 つまり、サーバーが実行されている限りです。

ブラウザ
ホームページ。 (大プレビュー)

次は、データベースとモデルです。

Sequelizeを使用して国モデルを作成し、Postgresデータベースに接続しました。 SequelizeはNodejsのORMです。 主な利点は、生のSQLクエリを作成する時間を節約できることです。

Postgresqlを使用しているため、 CREATE DATABASE database_nameコマンドを使用してpsqlコマンドラインからデータベースを作成できます。 これは端末でも実行できますが、私はPSQLシェルを好みます。

envファイルでは、以下の形式に従って、データベースの接続文字列を設定します。

 TEST_DATABASE_URL = postgres://<db_username>:<db_password>@127.0.0.1:5432/<database_name>

私のモデルでは、この続編のチュートリアルに従いました。 わかりやすく、Sequelizeの設定に関するすべてを説明しています。

次に、作成したモデルのテストを作成し、Coverallでカバレッジを設定します。

テストの作成とカバレッジの報告

なぜテストを書くのですか? 個人的には、テストを書くことは、ブレーンストーミングプロセスであるため、開発者がソフトウェアがユーザーの手にどのように機能することが期待されるかをよりよく理解するのに役立つと思います。 また、時間どおりにバグを発見するのにも役立ちます。

テスト:

ソフトウェアのテスト方法はさまざまですが、このチュートリアルでは、ユニットテストとエンドツーエンドテストを使用しました。

MochaテストフレームワークとChaiアサーションライブラリを使用してテストを作成しました。 また、 sequelize.defineを使用して作成したモデルのテストを支援するために、 sequelize-test-helpersをインストールしました。

テストカバレッジ:

テストケースが実際にコードをカバーしているかどうか、およびテストケースを実行するときに使用されるコードの量が結果に示されるため、テストカバレッジを確認することをお勧めします。

イスタンブール(テストカバレッジツール)、nyc(InstabulのCLIクライアント)、およびCoverallsを使用しました。

ドキュメントによると、IstanbulはES5およびES2015 + JavaScriptコードをラインカウンターで計測しているため、単体テストでコードベースがどの程度うまく機能しているかを追跡できます。

私のpackage.jsonファイルでは、テストスクリプトがテストを実行し、レポートを生成します。

 { "scripts": { "test": "nyc --reporter=lcov --reporter=text mocha -r @babel/register ./src/test/index.js" } }

その過程で、生のカバレッジ情報を含む.nyc_outputフォルダーと、カバレッジレポートファイルを含むcoverageフォルダーが作成されます。 両方のファイルは私のリポジトリには必要ないので、 .gitignoreファイルに配置しました。

レポートを生成したので、それをCoverallsに送信する必要があります。 Coveralls(および他のカバレッジツールだと思います)の優れた点の1つは、テストカバレッジを報告する方法です。 カバレッジはファイルごとに分類され、関連するカバレッジ、カバーされた行と欠落した行、およびビルドカバレッジで何が変更されたかを確認できます。

開始するには、coverallsnpmパッケージをインストールします。 また、カバーオールにサインインして、リポジトリを追加する必要があります。

つなぎ服レポ
カバーオールに接続されたレポ。 (大プレビュー)

次に、ルートディレクトリにcoveralls.ymlファイルを作成して、javascriptプロジェクトのカバーオールを設定します。 このファイルには、カバーオールのレポジトリの設定セクションから取得したrepo-tokenが保持されます。

package.jsonファイルに必要なもう1つのスクリプトは、カバレッジスクリプトです。 このスクリプトは、アクションを介してビルドを作成するときに役立ちます。

 { "scripts": { "coverage": "nyc npm run test && nyc report --reporter=text-lcov --reporter=lcov | node ./node_modules/coveralls/bin/coveralls.js --verbose" } }

基本的に、テストを実行し、レポートを取得して、分析のためにカバーオールに送信します。

ここで、このチュートリアルの要点に移ります。

ノードJSワークフローファイルの作成

この時点で、GitHubアクションで実行する必要なジョブを設定しました。 (「仕事」とはどういう意味か疑問に思いますか?読み続けてください。)

GitHubは、スターターテンプレートを提供することで、ワークフローファイルを簡単に作成できるようにしました。 [アクション]ページに示されているように、さまざまな目的に役立つワークフローテンプレートがいくつかあります。 このチュートリアルでは、Node.jsワークフロー(GitHubがすでに親切に提案している)を使用します。

アクションページ
GitHubアクションページ。 (大プレビュー)

ファイルはGitHubで直接編集できますが、ローカルリポジトリに手動で作成します。 node.js.ymlファイルを含むフォルダー.github/workflowsはルートディレクトリにあります。

このファイルにはすでにいくつかの基本的なコマンドが含まれており、最初のコメントはそれらが何をするかを説明しています。

 # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node

上記のコメントに加えて、カバレッジも実行されるように、いくつかの変更を加えます。

私の.node.js.ymlファイル:

 name: NodeJS CI on: ["push"] jobs: build: name: Build runs-on: windows-latest strategy: matrix: node-version: [12.x, 14.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm run build --if-present - run: npm run coverage - name: Coveralls uses: coverallsapp/github-action@master env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_GIT_BRANCH: ${{ github.ref }} with: github-token: ${{ secrets.GITHUB_TOKEN }}

これは何を意味するのでしょうか?

分解してみましょう。

  • name
    これはワークフロー(NodeJS CI)またはジョブ(ビルド)の名前になり、GitHubはそれをリポジトリのアクションページに表示します。
  • on
    これは、ワークフローをトリガーするイベントです。 私のファイルのその行は、基本的に、リポジトリにプッシュが行われるたびにワークフローをトリガーするようにGitHubに指示しています。
  • jobs
    ワークフローには少なくとも1つ以上のジョブを含めることができ、各ジョブはruns-on指定された環境で実行されます。 上記のファイルサンプルでは、​​ビルドとカバレッジを実行するジョブが1つだけあり、Windows環境で実行されます。 次のように、2つの異なるジョブに分けることもできます。

Node.ymlファイルを更新しました

name: NodeJS CI on: [push] jobs: build: name: Build runs-on: windows-latest strategy: matrix: node-version: [12.x, 14.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm run build --if-present - run: npm run test coverage: name: Coveralls runs-on: windows-latest strategy: matrix: node-version: [12.x, 14.x] steps: - uses: coverallsapp/github-action@master env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} with: github-token: ${{ secrets.GITHUB_TOKEN }}
  • env
    これには、ワークフローのすべてまたは特定のジョブとステップで使用できる環境変数が含まれています。 カバレッジジョブでは、環境変数が「非表示」になっていることがわかります。 それらは、設定の下のリポジトリのシークレットページにあります。
  • steps
    これは基本的に、そのジョブを実行するときに実行する手順のリストです。
  • buildジョブはいくつかのことを行います。
    • ワークフローからアクセスできるように、リポジトリを文字通りチェックアウトするチェックアウトアクション(v2はバージョンを示します)を使用します。
    • 使用するノード環境をセットアップするsetup-nodeアクションを使用します。
    • package.jsonファイルにあるインストール、ビルド、テストスクリプトを実行します。
  • coverage
    これは、分析のためにテストスイートのLCOVカバレッジデータをcoveralls.ioに投稿するcoverallsappアクションを使用します。
成功した仕事
すべてのジョブが正常に実行されます。 (大プレビュー)

最初にfeat-add-controllers-and-routeブランチをプッシュし、Coverallsから.coveralls.ymlファイルにrepo_tokenを追加するのを忘れたため、132行目に表示されるエラーが発生しました。

ビルドに失敗しました
coverallsの設定ファイルのエラーが原因でジョブが失敗しました。 (大プレビュー)
 Bad response: 422 {"message":"Couldn't find a repository matching this job.","error":true}

repo_tokenを追加すると、ビルドを正常に実行できました。 このトークンがないと、つなぎ服は私のテストカバレッジ分析を適切に報告できません。 GitHub Actions CIが、メインブランチにプッシュされる前にエラーを指摘したのは良いことです。

ビルドの成功
エラーが修正され、ジョブが成功しました。 わーい! (大プレビュー)

注意:これらは、私が仕事を2つの仕事に分ける前に取ったものです。 また、カバレッジスクリプトの最後に--verboseフラグを追加したため、端末でカバレッジの概要(およびエラーメッセージ)を確認できました。

結論

プロジェクトの継続的インテグレーションを設定する方法と、GitHubによって提供されるアクションを使用してテストカバレッジを統合する方法を確認できます。 プロジェクトのニーズに合わせてこれを調整できる方法は他にもたくさんあります。 このチュートリアルで使用されているサンプルリポジトリは非常にマイナーなプロジェクトですが、より大きなプロジェクトでも継続的インテグレーションがいかに重要であるかがわかります。 ジョブが正常に実行されたので、ブランチをメインブランチにマージできると確信しています。 それでも、実行のたびに手順の結果を読んで、完全に成功していることを確認することをお勧めします。