opensouce COBOLとcircle ciによるCI/CD

# 概要

開発現場では効率、品質を向上させるため、DevOpsとCI/CDパイプラインを活用することが増えてきました。

そこで、CIの大手サービスである、circle ciでopensource COBOLの自動テストをしてみたいと思います。

# circle ciについて

circle ciではテストを実行する環境としてDockerコンテナを利用しています。
標準部品として、Javaなど主要な言語のテスト環境やWindows、Macなどが用意されていますが、さすがにCOBOL環境はありません。
このため、docker hubに公開されている、opensource COBOLのイメージを利用してテストを実行します。

# テスト対象

テスト対象のプログラムはいつものHELLO.cblを「コンパイル」、「実行」でテストします。
「実行」では、正しく標準出力が行えていることを確認します。

```cbl:HELLO.cbl
       IDENTIFICATION              DIVISION.
       PROGRAM-ID.                 HELLO.
       DATA                        DIVISION.
       WORKING-STORAGE             SECTION.
       PROCEDURE                   DIVISION.
       MAIN-RTN.
           DISPLAY "HELLO WORLD!".
       MAIN-EXT.
           STOP RUN.
```

# リポジトリ準備

まずはgithubにテスト用のリポジトリを作成します。
なんでもいいので、サクッと作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/b2820848-ac3f-3b32-a7f4-9b8d61ac775e.png)

そのままCOBOLソースをアップロードします。

最後に、circle ciでテストを実行するための定義ファイルとなる、`config.yml`をリポジトリに追加します。
circle ciでは、リポジトリ配下の`.circleci/config.yml`を参照し、テストを実行します。
`config.yml`の細かな書き方については[公式のドキュメント](https://circleci.com/docs/ja/2.0/configuration-reference/)を参照してください。

今回は以下のような設定を作成します。

```yml:config.yml
version: 2
jobs:
  compile:
    docker:
      - image: opensourcecobol/opensource-cobol
    steps:
      - checkout
      - run: cobc -m -o HELLO.so HELLO.cbl
  test:
    docker:
      - image: opensourcecobol/opensource-cobol
    steps:
      - checkout
      - run: cobc -m -o HELLO.so HELLO.cbl
      - run: cobcrun HELLO
      - run: test "`cobcrun  HELLO`" = 'HELLO WORLD!'
workflows:
  version: 2
  test:
    jobs:
      - compile
      - test
```

- `docker`タグ

テストの実行環境となるDockerコンテナのイメージを指定します。
dockerhubで公開されているopensource COBOLのイメージを利用することで、COBOLのコンパイル、実行を行えます。

- `checkout`

連携しているgithubのリポジトリからcheckoutを行います。
これにより、カレントに`HELLO.cbl`が配置されます。

- `compile`タグ

コンパイルが通るかをチェックするテストを実施します。

- `test`タグ

COBOLの実行までをテストします。
ここでは、testコマンドを利用して、標準出力が想定した文字列であるかも確認します。

# circle ci連携

続いてcircle ciを動かすため、githubとcircle ciを連携させます。
こちらは普通にcircle ci側からgithubアカウントでログインすることで、連携させることができるので、割愛します。

連携後、テストしたいリポジトリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/f9711e44-2794-2565-1cf2-514eeac7091d.png)

そのまま初回のテストが実行されます。
※ファイルの記述が間違っていて何回か失敗しました、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/b3105db1-1b7b-90b1-d4e6-a3759d3addae.png)

それぞれのテストの詳細を確認できます。

- コンパイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/82f3e46b-6b5b-304f-ab48-c81defcd5891.png)

- 実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/1fb7dc1f-d826-14b2-e594-7079da8b234e.png)

# 本題のCI

それでは本題のCIを実施していきます。
といっても、基本的にgithubのファイルを更新すると、自動でcircle ciでテストが走ってくれますので、特に操作はありません。

### コンパイルエラーの例

わざとコンパイルエラーにしてみます。

```cbl:HELLO.cbl
       IDENTIFICATION              DIVISION.
       PROGRAM-ID.                 HELLO.
       DATE                        DIVISION.
       WORKING-STORAGE             SECTION.
       PROCEDURE                   DIVISION.
       MAIN-RTN.
           DISPLAY "HELLO WORLD!".
       MAIN-EXT.
           STOP RUN.
```

`DATA DIVISION`が`DATE DIVISION`になっています。
早速このファイルをリポジトリにcommit&pushします。

するとテストが失敗になっており、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/6c40c408-1451-43b9-aa92-ff4a917f4c91.png)

詳細を見ると、コンパイルエラーのメッセージが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/e9b937ad-6599-3b61-4cd2-e7b410d3cc9b.png)

### 実行時エラーの例

次に実行時エラーにしてみます。
opensource COBOL最大のつまりポイント、PROGRAM-IDとsoファイル名が一致しない例です。

```cbl:HELLO.cbl
       IDENTIFICATION              DIVISION.
       PROGRAM-ID.                 HELL.
       DATA                        DIVISION.
       WORKING-STORAGE             SECTION.
       PROCEDURE                   DIVISION.
       MAIN-RTN.
           DISPLAY "HELLO WORLD!".
       MAIN-EXT.
           STOP RUN.
```

同様にファイルをcommit&pushします。
compileジョブは成功しましたが、testジョブで失敗してます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/a6e54e4d-a4bd-2fc5-78f5-c4a7038daa67.png)


詳細をみると予定通りのメッセージが見れました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/95a4a8fc-40fe-43bb-c894-4e450d0ef199.png)


### 出力文字列が違う場合

一応最後に出力文字列が変わってしまった場合も確認しておきます。

```cbl:HELLO.cbl
       IDENTIFICATION              DIVISION.
       PROGRAM-ID.                 HELLO.
       DATA                        DIVISION.
       WORKING-STORAGE             SECTION.
       PROCEDURE                   DIVISION.
       MAIN-RTN.
           DISPLAY "HELL WORLD!".
       MAIN-EXT.
           STOP RUN.
```

一文字間違っただけで地獄の世界になるのは怖いですね。

詳細を確認すると、実行は通っていますが、`test`コマンドがエラーになっています。
このように、exit codeで判別されるので、簡単にテストを作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/16f1993a-edc5-5d8a-b046-b4efecf3440a.png)

# 総評

このように、COBOLもCIに乗せることができました、といった感じです。
COBOLではCOPY句などで、複数のソースにまたがった記述も多々あるので、コンパイルだけでもテストすると便利になるかもしれません。

また、今回は単純なコンパイル、実行でしたが、makeやAutoTestなどと組み合わせることでより高機能なCIサイクルができそうです。

注意点として、テストが失敗すると、メール通知をしてくれます。
いろいろ試してたらメールボックスに失敗メールがいっぱいたまってたました。

# 参考等

今回利用したdockerイメージの配布は以下で行われています。
https://hub.docker.com/r/opensourcecobol/opensource-cobol

需要はないと思いますが、今回作成したリポジトリも公開してあります。
https://github.com/nor51010/cobol-ci