T-DASH×GitHubActions×DockerでCICD完全攻略

## はじめに
エンドユーザーに**高品質で価値のあるソフトウェアを効率的に素早く提供**していくためには、**CICD環境**の適切な運用が不可欠です。
テスト自動化ツールの**T-DASH**にコマンドライン実行機能が実装されたため、T-DASH、GitHubActions、Docker、Slackなどのツールを連携させてCICD環境を構築しました。
本記事では、**T-DASHのCICD連携**に焦点を絞って記載をしたいと思います。
(本記事は、Qiita Engineer Festa 2023「コマンドライン実行機能が実装される「T-DASH」を使って、CI/CD連携をしてみよう！」への投稿記事になります)

https://qiita.com/official-events/7fec21cc6f0e98587570

## CICD想定要件
今回構築するCICD環境の想定要件を定義しました。(要件は、ソフトウェアの規模や開発体制、方針によって変わるので、柔軟に対応してください)
1. T-DASHのテスト実行を自動で行うことができる
2. T-DASHのテスト実行結果の通知を受けることができる
3. T-DASHのテスト実行環境構成をバージョン管理することができる
4. 自動でT-DASHテスト実行環境を作成することができる
5. T-DASHテスト実行環境に変更があった場合は、ソフトウェア開発者に通知することができる 

## 構築環境
想定要件をもとに構築した環境について説明します。
### システム全体図
構築したシステムの全体図を下記に示します。
![tdash_cicd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/00c5cc2d-b166-575c-3ce8-3a5130506341.png)
**アクター**
ソフトウェア開発者：テストケースの作成およびテストの実行、テスト結果の管理をする責務を持つ
インフラ開発者：テスト環境を構築し、テスト環境を管理する責務を持つ

**上図システム各工程詳細**
1. Docker file登録：インフラ開発者が、テスト実行に必要な環境(T-DASHやgoogle chromeなど)のバージョン変更や新たなソフトウェアをインストールする場合に、Docker fileを更新したうえでGitHubの環境ファイル登録リポジトリにpushする
2. trigger create-docker-image workglow：docker imageを作成するGitHub actionsのworkflow(create-docker-image.yml)をキックする
3. docker build:登録されたDocker fileをもとにdocker imageを作成する
4. docker push:作成したdocker imageをdocker hubにpushする
5. 環境変更通知：テスト環境がUpdateされたことをソフトウェア開発者に通知する
6. Export:ソフトウェア開発者が、T-DASHを用いてブラウザ上で作成したテストシナリオ、テストケースを出力する
7. テストファイル登録：ソフトウェア開発者が、出力したテストシナリオ、テストケースをテストファイル登録リポジトリにpushする
8. trigger tdash-test workflow:テストを実行するGitHub actionsのworkflow(tdash-selfhosted-workflow.yml)をキックする
9. docker pull:docker hubからテスト環境のdocker imageをpullする
10. テスト実行:テストをコマンドライン実行する
11. テスト完了通知:テストが完了した旨をソフトウェア開発者に通知する


**各ツールスペック**
今回使用した各ツールのスペックです。
- T-DASH：Ver3.2.000b
- selfhosted-runner：windows11(バージョン22H2)
- docker engine(for windows)：24.0.2

## 環境詳細
- **事前準備**



- **環境ファイル登録リポジトリ**

**フォルダ構成**
```file structure
|--.github
|  |--workflows
|  |  |--create-docker-image.yml
|--README.md
|--tools
|  |--Dockerfile
|  |--tdashbeta
|  |  |--tdashbeta.zip.001
```
**create-docker-image.yml**
Dockerfileからdocker imageを作成するためのworkflow定義ファイルです。
Docker registoryとしてDockerHubを利用しています。
DockerBuildして作成したdocker imageをDockerHubにpushしています。
```create-docker-image.yml
---
name: create-docker-image
on:
  push:
  workflow_dispatch:

jobs:
  create-docker-image:
    runs-on: [self-hosted, Windows, X64]
    steps:
    - name: Checkout
      uses: actions/checkout@v3.5.2

    - name: Login to Docker Hub
      run: |
        docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}

    - name: docker-build
      run: |
        docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/t-dash-sample:latest -f ./tools/Dockerfile .

    - name: docker-push
      run: |
        docker push ${{ secrets.DOCKERHUB_USERNAME }}/t-dash-sample:latest
```

**Dockerfile**
テスト環境となるdockerimageの作成手順を記載しています。
T-DASHやgooglechromeのインストール手順を記載します。
Windowsパッケージマネジメントツールのchocolateyを利用して、各種ツールをインストールしています。
```Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2022

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

#chrome setup
RUN echo 'install choco'
RUN Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
RUN echo 'install chrome via choco'
RUN choco install -y googlechrome

#T-dash Install
RUN choco install -y 7zip
COPY ./tools/tdashbeta/ C:/work/tdashbeta/
RUN 7z x -oC:/work C:/work/tdashbeta/tdashbeta.zip.001
RUN New-Item -Path C:/Users/ContainerAdministrator/AppData/Local/Programs/T-DASH -ItemType Directory
RUN Move-Item "C:/work/tdashbeta.exe" C:/Users/ContainerAdministrator/AppData/Local/Programs/T-DASH/tdash.exe
WORKDIR C:/Users/ContainerAdministrator/AppData/Local/Programs/T-DASH
RUN Start-Process -FilePath C:/Users/ContainerAdministrator/AppData/Local/Programs/T-DASH/tdash.exe -ArgumentList "setup","--silent" -NoNewWindow -Wait
```

**slack通知**
slack通知に関してはいくつか方法がありますが、今回はGithubとSlackを連携させるAppを用いて通知を行います。
メッセージをカスタマイズしたい場合は、slackに通知するアクションを作成することが可能です。(一般に公開されているactionもありますが、windowsをサポートしてない場合が多かったです。。。)

https://github.com/integrations/slack#actions-workflow-notifications


- **テストファイル登録リポジトリ**

**フォルダ構成**
```file structure
|--.github
|  |--workflows
|  |  |--tdash-selfhosted-workflow.yml
|--README.md
|--tools
|  |--run-tdash.ps1
|--sync
|  -- ......(T-DASHからexportしたsyncファイル(省略)).....
```

**tdash-selfhosted-workflow.yml**
作成したDocker imageの環境をもとに、T-DASHのテストを実行するためのworkflow定義ファイルです。
T-DASH等の必要なツールのインストールはdocker build時に実行されているため、ここではテストの実行のみになります。

```tdash-selfhosted-workflow.yml
name: T-DASH Docker

on:
  workflow_dispatch:
  push:

jobs:
  container-job:
    runs-on: [self-hosted, Windows, X64]
    steps:
    
    - name: Checkout
      uses: actions/checkout@v3.5.2

    - name: Docker start
      run: |
        mkdir ${{ github.workspace }}/reports
        $NAMES = docker ps -a | Select-String -Pattern "t-dash"
        if([string]::IsNullOrEmpty($NAMES)){
            docker run -dit --name t-dash -v ${{ github.workspace }}:C:\work ${{ secrets.DOCKERHUB_USERNAME }}/t-dash-sample:latest powershell
        }
        else{
            docker stop t-dash
            docker rm t-dash
            docker run -dit --name t-dash -v ${{ github.workspace }}:C:\work ${{ secrets.DOCKERHUB_USERNAME }}/t-dash-sample:latest powershell 
        }

    - name: Docker exec
      run: |
        docker exec t-dash powershell C:\work\tools\run-tdash.ps1

    - name: Save results to artifacts
      uses: actions/upload-artifact@v3.1.2
      with:
        name: results
        path: ${{ github.workspace }}/reports
```

**run-tdash.ps1**
テスト実行時のpowershellのスクリプトです。
GitHubに登録されたテストケースを実行フォルダに移動してから実行しています。

```run-tdash.ps1
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit }

# コマンドライン実行するテスト実行環境のsyncフォルダパス
$destinationPath = 'C:\Users\ContainerAdministrator\AppData\Local\Programs\T-DASH\projects\commandlinetestrun\sync'

# コマンドライン実行するテスト実行結果パス
$reportsPath = 'C:\Users\ContainerAdministrator\AppData\Local\Programs\T-DASH\projects\commandlinetestrun\reports'

# 共有フォルダが既に存在する場合は一度フォルダごと削除する
if (Test-Path $destinationPath) {
    Remove-Item $destinationPath -Recurse -Force
}

# 共有フォルダが既に存在する場合は一度フォルダごと削除する
if (Test-Path $reportsPath) {
    Remove-Item $reportsPath -Recurse -Force
}

# リポジトリのsyncをコマンドライン実行テスト環境のsyncへコピー
Copy-Item C:\work\sync "C:\Users\ContainerAdministrator\AppData\Local\Programs\T-DASH\projects\commandlinetestrun\" -Recurse -Force
cd C:\Users\ContainerAdministrator\AppData\Local\Programs\T-DASH

# テスト実行
Start-Process -FilePath C:\Users\ContainerAdministrator\AppData\Local\Programs\T-DASH\tdash.exe -ArgumentList "testrun","sample","--background" -NoNewWindow -Wait

# 結果移動
Copy-Item $reportsPath "C:\work\" -Recurse -Force
```
**slack通知**
slack通知に関しては、**環境ファイル登録リポジトリ**と同様の設定を行います。

## 実行結果
それでは、システム全体図で示した各工程をもとに、実際のユースケースに従ってCI/CDの各工程の実行結果を見ていきます。
**1.Docker file登録** 
インフラ開発者：「T-DASHの機能拡充によりバージョンをUpdateしたいから、テスト環境のdocker imageを更新しよう！」
インフラ開発者はDockerfileを更新し、環境ファイル登録リポジトリにpushを行います。
```
$ git add .
$ git commit -m "test-docker build"
$ git push origin main
```

**2. trigger create-docker-image workglow**
環境ファイル登録リポジトリへのpushを契機に、docker imageを作成するGitHub actionsのworkflow(create-docker-image.yml)が実行されます。
![trigger-workflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/76b9ed68-661d-72a8-0b67-bb42a5889b8f.png)

**3. docker build**
create-docker-image.ymlのworkflow内で、登録したDockerfileをもとにdocker imageが作成されます。
(初回実行時は時間がかかりますが、2回目以降キャッシュを利用すれば時間が短縮されます。)
![docker-build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/ff7a3e34-1837-8f76-5fd3-d081cfb5a57f.png)
実行サーバー上(self-hosted-runner上)で作成されたdocker image
```
docker images
REPOSITORY                             TAG        IMAGE ID       CREATED        SIZE
tomyamkung1206/t-dash-sample           latest     e518ef00b831   16 hours ago   5.71GB
```

**4. docker push**
create-docker-image.ymlのworkflow内で、作成されたdocker imageがDocker Hubにpushされます。
(初回実行時は時間がかかりますが、2回目以降キャッシュを利用すれば時間が短縮されます。)
![docker-push.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/939a0776-a567-a4a9-111b-1fabec7fad8d.png)
Docker Hub上で、imageがpushされたことも確認できます。
![docker-hub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/2a79a888-5e82-195d-cbb8-b4aacce62220.png)

**5. 環境変更通知**
各ソフトウェア開発者には、slackでテスト環境がバージョンアップされた旨の通知が来ます。
![docker-image-update.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/37646a57-5884-a70c-e9ac-0cd85737211b.png)

**6. Export**
ソフトウェア開発者：「よし、新機能をテストするために、テストシナリオとテストケースをアップデートするぞ！」
各ソフトウェア開発者は、T-DASHを用いてブラウザ上で作成したテストシナリオ、テストケースを出力します。
![export.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/41c97648-a57f-cb22-3006-dcc923f0ff17.png)

**7. テストファイル登録**
ソフトウェア開発者は、出力したテストシナリオ、テストケースをテストファイル登録リポジトリにpushします。
![sync-file.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/2c614566-617d-f656-97c1-dfb4a9dc6e6c.png)
```
$ git add .
$ git commit -m "container-test"
$ git push origin main
```

**8. trigger tdash-test workflow**
テストファイル登録リポジトリへのpushを契機に、T-DASHを利用したテストを実行するGitHub actionsのworkflow(tdash-selfhosted-workflow.yml)が実行されます。
![trigger-workflow-container.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/e90818e6-342e-dc21-c9a7-45a3ed9d66ea.png)

**9. docker pull**
tdash-selfhosted-workflow.ymlのworkflow内で、Docker Hubに登録されているテスト環境の最新のdocker imageをpullします。
docker imageをpullする際に初回はかなり時間がかかりますが、二度目からはt-dashや各種ツールのinstallの手順が短縮される分、workflow実行時間も短くなります
![docker-pull.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/f1e98797-1924-0e64-7d2d-5a3599c1bcab.png)


**10. テスト実行**
tdash-selfhosted-workflow.ymlのworkflow内でT-DASHを利用したテストをコマンドライン実行します。
![t-dash-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/add2a9f8-3e77-3627-4525-4294a57b354c.png)

テストが完了すると、結果がGitHubのArtifactsにUploadされます。
![artifacts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/0252b846-54e0-497a-aa78-e7be00e47c03.png)


**11. テスト完了通知**
テストが完了した旨が、slackでソフトウェア開発者に通知されます。
![slack-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2378598/0b245f94-632b-8ffc-6388-7a19843ff60a.png)

以上より、T-DASH、GitHubActions、Dockerを連携させたCI/CDシステムの導入を行うことができました。

## T-Dashを使ってみて
**良かった点**
- テストケースの作成は、ブラウザ上で視覚的にできるので非常にわかりやすいと思いました。
- マニュアルが豊富で、初心者でもすぐに試すことができるので学習コストが低いと思いました。
- GitHubActionsやJenkinsなど、幅広く使用されているCIツールと連携が可能なので、各社の様々な用途に合わせて活用ができると思いました。

**改善してほしい点**
- Ubuntu版のサポートもしていただけると助かります。普段Windows版を利用する機会が少ないので、powershellのコマンドなど調べながら構築しました。また、Docker Desktopの有料化の影響で、会社によっては利用するのに手続きなどが面倒な場合もあるので、フリーで利用できる環境が好まれます。GitHubActionsなどのCIツールもWindows版に対応していない公式Actionなども散見されるので、適応範囲を広げるという意味でもサポートしてほしいです。
- テスト失敗時にエラーコードをはかないようなので、設定などで変更できると良いと思います。出力結果を解析して、それによってslackに成功や失敗を伝達することもできますが、できればツール側の機能に織り込んでほしいです。

## おわりに
今回、主にCI/CD連携に焦点をあて、T-DASHと各ツールを連携させることで実運用を想定した環境を構築することができました。
T-DASHは、今回連携したツールの他にも、要件管理ツール、静的解析ツールなど幅広く連携をすることが可能だと思うので、CI/CDの観点でみてもソフトウェア開発の可能性を大きく広げていくと考えられます。
ぜひ皆様も活用を検討してみてはいかがでしょうか？