GitLab CI/CDを使ってビルドを自動化し、テストを高速化する

# 概要

GitLab CI/CDを使ってテストを行うまでの手順を紹介します。

CI/CDといえば自動テストをしてデプロイまで自動で行われるようなイメージがありますが(←私だけ？)、私の参画しているプロジェクト(レガシーなシステム)ではテストコードは無く、テストまで自動化することは安易にはできませんでした。
ですが、「テストコードが書けていないから自動化はムリ～！」と諦めてしまうのではなく、自動化できる部分(とりあえずビルドまで)を自動化しようというお話です。

# 前提条件

- この記事内ではビルド用のサーバでビルドを行い、ビルド後のリリース用資材をGitLabサーバ上に保管するところまでを対象とします。
- 開発に使用する言語はGoで(Goのソースについては深掘りしないため)HelloWorld程度のソースをビルドする前提とします
    - (`go build -o outfileName`でビルドを行います)
    - とりあえず何かしらのコミットがあったときにビルドが行われるものとし、他の条件(特定のブランチにコミットがあったときだけビルド)等は別記事に記載します。

# 導入することのメリット

- ビルドをが自動化されることで、テストまでの手順が減る
- リリース資材をGitLab上に一定期間保管することができるので、やり取りが楽になる
    - また、GitLab画面上からビルドの再実行も可能なため、保管期間を過ぎた後でもリリース資材を生成できる
- GitLab上のソースをベースにビルドが行われるため、ミスが減る

:::note
私の参画していたプロジェクトの話にはなりますが、
例えば開発メンバーの開発環境で改修を行って、その環境内でビルドを行い、自社内での動作確認「ヨシ！」→本番環境にリリースしてお客さん確認も「ヨシ！」

その後、実はコミット漏れがあって他の開発担当者が別の改修を行ったあとでリリースを行ったとき、その改修に関しては「ヨシ！」であっても、前の改修が何故か戻っている・・・

というような事故も防げるようになりました。
(ローカル開発環境そのままでビルドせずにせめてビルド用のディレクトリを切って、ビルド時にはgit上のものをベースにビルドしろ！とかそういう話ではあるんですが。。。)
:::


# 前提知識

2023/01/09 変更: 大まかな手順は下記のページに移動しました。

https://qiita.com/g-iki/items/3ea1890fc58110bd6de5


### ビルド用サーバにRunnerをインストールする場合のイメージ

![gitlab-ページ1.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/9000025e-d7f4-1c1b-ce07-9719e28ccf9f.png)

### 検証用サーバにRunnerをインストールする場合のイメージ

![gitlab-ページ1のコピー.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/bc4bf157-f302-b31e-63e0-9dd730d3e0bc.png)

### 開発用サーバにRunnerをインストールする場合のイメージ

![gitlab-ページ1のコピーのコピー.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/1d64d3e0-a4ae-64c0-73e0-b844b8b5e658.png)


※GitLab CE等をセルフマネージドでサーバ建てしている場合、GitLabServerにRunnerをインストールすることも可能です。

## リポジトリに`.gitlab-ci.yml`ファイルを作成する

リポジトリのホーム画面のファイルを追加からファイルを作成するか、`.gitlab-ci.yml`というファイルを作ってコミット(&プッシュ)します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/5dea494a-edc6-4fbf-32c6-1dc45357b73e.png)

gitlab上から作成する場合にはテンプレートが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/e159c079-3631-fd35-b72a-ff36ceb76f6e.png)


今回はGo言語でビルドを行うだけなので、以下のようなファイル内容としました。

### shellの場合

```yml
build:
    tags:
        - shell-executor # runner登録時に設定したタグ名
    script:
        - go build -o server  # ビルドコマンド `server`という名前でビルド
    artifacts:
        paths:
            - server # gitlabサーバに保管するファイル名
```


### Dockerの場合

```yml
image: golang:latest # ジョブを行うDockerのイメージ名

build:
    tags:
        - docker # runner登録時に設定したタグ名
    script:
        - go build -o server  # ビルドコマンド `server`という名前でビルド
    artifacts:
        paths:
            - server # gitlabサーバに保管するファイル名
```

タグは利用可能な Specific(Group) Runnerの箇所から確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/05a912d1-3860-1e6a-9c3e-3635f12c9254.png)


## GitLab上から動作確認

.gitlab-ci.ymlがある状態で、コミットが行われるとジョブが開始され、CI/CD > ジョブからジョブの実行内容が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/87f46173-face-da59-8b0a-1bbee5c05ea6.png)

一覧の中から状態(`成功`や`キャンセル`と書かれた箇所)か、ジョブ(#3009840154のような箇所)をクリックすると詳細が表示されます。

また、ビルド後の生成物は`アーティファクト`としてGitlabServerに保管することができ、Gitlabの画面上からダウンロードすることもできます。
(指定がなければ4週間保管(指定方法は別途記事化します。))

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/23848380-7232-8305-991b-057e1f3b35c4.png)


ただしアーティファクトは容量を圧迫していくため、適宜削除する必要があり、
右上のゴミ箱アイコンからアーティファクトの削除を行うことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/0c3da80d-5344-ea0d-c774-04d54c23ab70.png)

# 完成！

とりあえずここまでの手順がコミットしたら自動でビルドが行われ、リリース用の資材をGitLab上に保管する手順となります。

実際に業務で行った手順と違う内容であるため、内容が薄い部分がありますので、不足分は追記したり別記事で詳細なオプション等記載していこうと思いますので、ご意見等ありましたらコメント頂けると幸いです)

# おわりに

冒頭のメリットにも書きましたが、ソース管理ツールへのコミット漏れによる手戻りを防げるようになったこと、テストを行うまでの手順を減らすことができたことは私達のプロジェクトにとって大きな前進となりました。
全てを自動化する必要はなく、できるところから自動化していくことで少しでも業務の効率化を図り、バグの改修やリファクタリング等にかける時間を増やしていくことが、レガシーなシステムの改善、もしくはレガシーなシステムを生み出さないようにする一歩なのだと思いました。

(実際に業務上で作った環境は社内検証環境上にRunnerをインストールして、そのサーバ上でビルド(executor:shell)を行いデプロイ用の資材をそのサーバ上に保管とGitlabサーバ上にも保管、(複数人触る可能性のあった検証環境であったため)頃合いを見て手動デプロイを行うような手順としていました。

記事化する際に色々と調べていくうちにビルド用サーバ上でDockerを建ててその中でビルドしてみたり、ビルドサーバ上にRunnerをインストールしたDockerを建ててさらにそこからDockerを建ててそこでビルドしてみたりする方法があると分かり、自分の中でのベストプラクティスにたどり着けていないので、更に調査していこうと思います。