RPAを検討する人に知ってもらいたい「JenkinsでのWindows自動化」

#はじめに
「RPA以外にも自動化の選択肢はあるんやで」という記事です。
世の中、RPAに代表されるようなノンプログラミングツールでの自動化が流行り初めていますが、その流れに逆らうように、プログラミングでの自動化について記載したのが本記事です。
Windows端末で諸々自動化したので、その際に作ったJenkins環境を忘れないように具体例を残しておきます。

**本記事のJenkinsが提供する機能**
以下の5つです。それ以外にもプラグインなどで拡張すればきっとだいたいできるっすよ。
（GUIのみのwindowsクライアントツールの自動化は苦手な気がするので、それはRPAの方が得意そうな気がする。）

- Excelマクロ操作
- ファイルサーバーへのアップロード/ダウンロード
- ブラウザ操作
- windows-linux間のファイル転送
- linuxサーバーでの処理

**イメージ図**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214587/d41589b5-c024-1fdb-3cb2-cdc33e8caaf1.png)

#環境構築編
##準備
3Stepなので、誰でも簡単！

1. JDKをインストール
    - 参考：[WindowsへのJDKインストール方法](https://qiita.com/ko2a/items/69fa8a5366d7449500ca)
2. jenkinsのwarをダウンロード
    - Downloadページ＞LTS＞Generic Java Package(.war)
3. jenkinsをjdkで起動する
    - 起動オプションについては、後述します。

**補足1:Javaのバージョン**
最新情報は以下で確認して欲しいですが、記事記載時点では、Java8です。最新のJava9だと動かないっす。
[Jenkins: Getting Started with the Guide](https://jenkins.io/doc/pipeline/tour/getting-started/)

**補足2：Windowsインストーラは使わない**
WEBブラウザの操作を自動化する際、serviceから起動していると、WEBdriverが起動しない。
ブラウザ操作の自動化が不要な場合は、インストーラーでも良いかも。
参考：[WindowsでJenkinsとWebDriverを動かそうとしてハマった](http://daipresents.com/2014/windows-webdriver/)

**補足3:JREではなくJDKからの起動**
この記事では記載しないですが、mavenでビルドする際に、jdkであることが要求されるので。
設定で後から追加もできますが、多少の手間も減らすため、JDKからの起動としています。

##初期設定
起動後、一番最初に以下にアクセスすると、初期設定を求められます。
http://localhost:8080/

基本的には画面に言われるがままにやれば良いです。
ここらへんは記事も多いと思うので、割愛。
参考：[[Jenkins] Windows7にJenkinsをインストールする方法まとめ](https://qiita.com/koara-local/items/5fea213a9cf7033a95c1)

#機能拡充編
##Excelマクロ
**事前準備**
1. [powershellプラグイン](https://wiki.jenkins.io/display/JENKINS/PowerShell+Plugin)を入れる

**ジョブの設定**
1. Jenkinsにて「ビルド手順の追加」で「Windows Powershell」を追加
2. 以下のコードを打ち込む
※「ビルドのパラメータ」で「xls_macro_file」と「xls_macro_function」を用意しています。
　Excelマクロに引数が引き渡せないですが、まぁひとまず十分な感じ。

```powershell:Jenkins側のpowershellコード
C:\rpawk\common\bin\execxlsmacro.ps1 $env:xls_macro_file $env:xls_macro_function
```

```powershell:execxlsmacro.ps1
Param( $macroBook, $procedureName ) # 引数の取得

# 起動するファイルを標準出力
$macroBook

# ファイルパスの取得
$macroBookFullPath = (ls $macroBook).FullName
$macroProcName = (ls $macroBook).Name + "!" + $procedureName

# 起動するマクロを標準出力
$macroProcName

# Excelの起動
$excelApp = New-Object -com "Excel.Application"

try {
  # マクロの起動
  $excelApp.DisplayAlerts = $false
  $excelApp.Workbooks.Open($macroBookFullPath)
  $excelApp.Run($macroProcName)
} finally {
  # Excelの終了
  $excelApp.EnableEvents = $false
  $excelApp.DisplayAlerts = $false
  $excelApp.Visible = $false
  $excelApp.Workbooks | % { $_.Close($false) }
  $excelApp.Quit()
}
```

**補足1：Excelマクロでのパラメータ（環境変数）の取得**
以下のようにすれば、「ビルドのパラメータ化」で指定したパラメータを取得できます。

```vb.net:Excelマクロ
environmentString = Environ("パラメータ名")
```

**補足2：引数を指定したい場合**

```powershell:Jenkins側のpowershellコード
$excelApp = New-Object -com "Excel.Application"
$macroBook = $excelApp.Workbooks.Open("マクロブックへの絶対パス")
try {
  $excelApp.Run("'$($macroBook.name)'!マクロ名", "引数1", "引数2")
} finally {
  $excelApp.EnableEvents = $false
  $excelApp.DisplayAlerts = $false
  $excelApp.Visible = $false
  $excelApp.Workbooks | % { $_.Close($false) }
  $excelApp.Quit()
}
```

参考：[JenkinsでVBAを動かす際のあれこれ](http://knjname.hateblo.jp/entry/2015/02/18/012005)
　→本記事で触れていない注意事項等も丁寧に記事化されていますので、ぜひご一読を。

##ファイルサーバーへの転送
**事前準備**

1. [powershellプラグイン](https://wiki.jenkins.io/display/JENKINS/PowerShell+Plugin)を入れる
2. 「Jenkinsの管理＞システム設定＞グローバル プロパティ＞環境変数」に以下パラメータを用意する
    - filesv_user：ファイルサーバーにログインする際のユーザー（ドメイン\ユーザー）
    - filesv_pass：ファイルサーバーにログインする際のパスワード
    - drivepath：ファイルサーバーの最初のディレクトリのフルパス（ネットワークドライブに指定するため）

**ジョブの設定**
1. 以下に記載した「local2server.ps1」および「server2local.ps1」をテキトーな場所に置く
2. Jenkinsにて「ビルド手順の追加」で「Windows Powershell」を追加
3. Jenkinsから以下コードを呼び出す。

※「ビルドのパラメータ」で「source 」と「destination」を用意しています。

###アップロード

```powershell:Jenkins側のpowershellコード
C:\rpawk\common\bin\local2server.ps1 $source $destination
```

```powershell:local2server.ps1
#引数取得
Param( $source, $filesv_copy_target )

# ユーザ名
$user = $env:filesv_user

# パスワード
$spass = ConvertTo-SecureString $env:filesv_pass -AsPlainText -Force

# PSCredential（資格情報）オブジェクトを作成
$cred = New-Object System.Management.Automation.PSCredential($user, $spass)

# PSCredentialオブジェクトを使ってこのスクリプトからアクセス可能なPSDriveを作成
New-PSDrive -Name Fsv -PSProvider FileSystem -Root $env:drivepath -Credential $cred

#PSDrive経由でのアクセス
if ($filesv_copy_target.Contains($env:drivepath)) {
  $destination = "Fsv:" + ($filesv_copy_target -replace [regex]::Escape($env:drivepath), "")
}

# コピーを実行
$outputs = Copy-Item -Path $source -Destination $destination -Force -PassThru

# コピーしたファイルと件数を表示
$outputs
$outputs.Count
```

###ダウンロード

```powershell:Jenkins側のpowershellコード
C:\rpawk\common\bin\server2local.ps1 $source $destination
```

```powershell:server2local.ps1
#引数取得
Param( $source, $destination )

# ユーザ名
$user = $env:filesv_user

# パスワード
$spass = ConvertTo-SecureString $env:filesv_pass -AsPlainText -Force

# PSCredential（資格情報）オブジェクトを作成
$cred = New-Object System.Management.Automation.PSCredential($user, $spass)

# PSCredentialオブジェクトを使ってこのスクリプトからアクセス可能なPSDriveを作成
New-PSDrive -Name Fsv -PSProvider FileSystem -Root $env:drivepath -Credential $cred

#PSDrive経由でのアクセス
if ($source.Contains($env:drivepath)) {
  $source_path = "Fsv:" + ($source -replace [regex]::Escape($env:drivepath), "")
}

# コピーを実行
$outputs = Copy-Item -Path $source_path -Destination $destination -Force -PassThru

# コピーしたファイルと件数を表示
$outputs
$outputs.Count
```

参考：[JenkinsでPowerShellを使ってリモートの（Windows, AD）サーバへファイルをコピーするには．スクリプト内で資格情報オブジェクトを作ってそれを使ってサーバにアクセスする．](https://gist.github.com/hidari/5396195)

##ブラウザ操作
**事前準備**
1. [pythonプラグイン](https://wiki.jenkins.io/display/JENKINS/Python+Plugin)を入れる
2. webdriverを入手する（参考：[Python で Selenium WebDriver を使ったブラウザテストをする方法](http://akiyoko.hatenablog.jp/entry/2014/04/29/231343)）
3. `pip install serenium`
※python for windows も必要かも。

**ジョブの設定**
1. Jenkinsにて「ビルド手順の追加」で「Execute python」を追加
2. 以下のコードを打ち込む

```py3:Jenkins側のpythonコード
#!/usr/bin/python
# coding: utf-8
import os
from selenium import webdriver
from selenium.webdriver.support.ui import Select

# 処理が早すぎて要素が取得できない場合、この数値を調整する。
sleeptime=5
dlsleeptime=30

# driver起動
driver_options = webdriver.ChromeOptions()
driver_options.add_argument('--no-sandbox')
driver = webdriver.Chrome("C:/rpawk/common/bin/chromedriver.exe", chrome_options=driver_options)
driver.implicitly_wait(10) # 要素が見つからなかった場合のポーリング期間（秒）

# 処理
# （割愛）

# 完了
driver.close()
```

参考：[Python3 と Selenium Webdriver に挑戦](https://qiita.com/silverskyvicto/items/e8e2fff0159952973e61)

**補足1：pythonでのパラメータ（環境変数）の取得**
以下のようにすれば、「ビルドのパラメータ化」で指定したパラメータを取得できます。

```python3:python
var=os.environ['パラメータ名']
```



##windows-linux間のファイル転送
**事前準備**
1. [WinSCP](https://winscp.net/eng/docs/lang:jp#winscp_%E3%81%AE%E5%8F%96%E5%BE%97%E3%81%A8%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)をインストールしておく
2. [pythonプラグイン](https://wiki.jenkins.io/display/JENKINS/Python+Plugin)を入れる
3. tereterm等で該当サーバーにアクセスしておいて、既知のホストに設定しておく。

**ジョブの設定**
1. 以下に記載した「local2server.winscp」および「server2local.winscp」をテキトーな場所に置く
2. Jenkinsにて「ビルド手順の追加」で「Windows Powershell」を追加
3. Jenkinsから以下コードを呼び出す。

###アップロード
```bat:Jenkins側のwindows.batコード
"C:\Program Files (x86)\WinSCP\WinSCP.exe" /console /script="C:\rpawk\common\scpscript\upload.txt" /parameter %upload_server% %source% %destination%
```

```:upload.txt
option batch on
option confirm off
open %1%
cd %3%
option transfer binary
put %2%
close
exit
```

###ダウンロード
```bat:Jenkins側のwindows.batコード
"C:\Program Files (x86)\WinSCP\WinSCP.exe" /console /script="C:\rpawk\common\scpscript\download.txt" /parameter %download_server% %source% %destination%
```

```:download.txt
option batch on
option confirm off
open %1%
lcd %3%
option transfer binary
get %2%
close
exit
```

補足1：server名
以下記載でログインできる。

```
user:password@hostname
```

補足2：「sudo を実行するには tty がなければいけません。すみません。」
ptyにチェックを入れましょう。
ただ、`sudo su -`は機能しません。（ログインし直すせい？）
`sudo su -`の実行に関しては、teretermマクロを起動するくらいしか、今のところは思いつきません。。。

```bat:Jenkins側のwindows.batコード
“%ProgramFiles(x86)%\teraterm\ttpmacro.exe” <tllマクロファイルフルパス> [引数] 
```

参考：[TeraTermマクロをバッチファイルから実行する方法](https://www.teraterm.jp/?p=348)
参考：[WinSCPとは](https://winscp.net/eng/docs/lang:jp)
参考：[WinSCPスクリプト入門：コマンドやバッチファイルとの連携による自動処理](https://mag.osdn.jp/10/04/20/1033216)
参考：[スクリプト機能 - WinSCP Wiki - WinSCP - OSDN](https://ja.osdn.net/projects/winscp/wiki/scripting)

##Linuxサーバーでの処理
ここはプラグインの機能そのままなので、あんま言うことはない。

**事前準備**
1. [SSH Plugin](https://wiki.jenkins.io/display/JENKINS/SSH+plugin)をインストールしておく
2. 接続設定をしておく（参考：[Jenkinsからリモートサーバーにsshする設定](https://tomokazu-kozuma.com/setting-to-ssh-from-jenkins-to-remote-server/)）
3. tereterm等で該当サーバーにアクセスしておいて、既知のホストに設定しておく。

**ジョブの設定**
1. Jenkinsにて「ビルド手順の追加」で「リモートホストでのシェル実行」を追加

補足1:暗号化強度について
「Teratermでは繋がるのにJenkinsでは繋がらない！」みたいな時です。
sshに関するログを見ると、以下のようなエラーが出ている場合は、参考情報にあるようにAES256を使用できるようにしてあげれば解決するはずです。
※

```:/var/log/secure（中身はJENKINS-36648から引用）
Jul 11 13:09:22 server auth|security:crit sshd[21561580]: fatal: no matching cipher found: client aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc server aes256-ctr,aes192-cbc,aes256-cbc [preauth]
```

参考：[[JENKINS-36648]SSH plugin : no matching cipher found - can't connect to server](https://issues.jenkins-ci.org/browse/JENKINS-36648)
参考：[JavaでAES256を使用できるようにする](https://qiita.com/mizuki_takahashi/items/cc26a7fd51aa04396e92)
参考：[sshdのログファイルの確認方法](http://www.yukun.info/blog/2008/06/sshd-log-file.html)

##通知
ネットワーク内にRocket.chatを立てているので、そこに通知を集約しています。

**OS起動・停止**
WindowsUpadteによる予期せぬ起動/停止や、管理者以外の人が勝手にOS起動/停止しちゃった場合に気づくため。

1. ファイル名を指定して実行＞`gpedit.msc`
2. ローカル コンピューター ポリシー＞コンピュータの構成＞Windows の設定＞スクリプト（スタートアップ/シャットダウン）
3. 通知処理を呼び出すように設定

```bat:起動時呼び出しコマンド
C:\rpatools\client_start.bat
```

```bat:停止時呼び出しコマンド
C:\rpatools\client_shutdown.bat
```

```bat:client_start.bat
python "C:\rpawk\common\bin\notificationToRocketChat.py" "client_start"
```

```bat:client_shutdown.bat
python "C:\rpawk\common\bin\notificationToRocketChat.py" "client_shutdown"
```

```python3:notificationToRocketChat.py
# encode: utf-8

#import
import requests
import json
import sys

def post_text(token, bodyText):
  h = {'Content-Type': 'application/json'}
  baseurl = "ロケットチャットのURL/hooks/"
  payload = {'text': bodyText}

  # debug用情報
  print("token:" + token)
  
  # post
  requests.post(baseurl + token, headers=h, data=json.dumps(payload))

def mainfuncion()
  args = sys.argv
  args_str = ','.join(args)
  
  # debug用情報
  print("args:" + args_str)
  
  # message処理のエラー
  token = "エラー通知する先のトークン"
  bodyText = ":question:typeが判別できませんでした。 args:" + args_str
  
  type = args[1]
  if type=="client_start":
    token = "起動通知する先のトークン"
    bodyText = ":thinking:jenkinsクライアント端末が起動しました。必要に応じて、ソフトを立ち上げてください。"
    
  elif type=="client_shutdown":
    token = "停止通知する先のトークン"
    bodyText = ":zzz:jenkinsクライアント端末をシャットダウンします。"
    
  # post
  post_text(token, bodyText)

if __name__ == "__main__":
  mainfuncion()
```

参考：[Windows、PC起動時に任意のバッチファイルを自動実行する](http://piyopiyocs.blog115.fc2.com/blog-entry-890.html)
参考：[[Jenkins][管理者向け] 起動時トリガージョブ](http://srz-zumix.blogspot.jp/2014/04/jenkins_28.html)

**定期的なエラーチェック**
以下を指定したジョブを5分おきに流しています。（rocket.chatプラグインありますが、なぜか動かないので、自作。）
こんな感じで通知してくれる。
「落ちてまっせ」の右側は、対象jenkinsのURL
その下は、ジョブ名が一覧になっており、「 -ジョブ名(ジョブのURL)」になっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214587/f14d6aa0-5552-267e-561e-0f7a8b5f9fe4.png)

```bat:Jenkins側のWindowsバッチスクリプト
python "C:\rpawk\common\bin\jenkinsErrorCheck.py" "rocket.chatのトークン" "サーバAのURL" "○○用jenkins"
python "C:\rpawk\common\bin\jenkinsErrorCheck.py" "rocket.chatのトークン" "サーバBのURL" "☓☓用jenkins"
```

```python3:errorCheck.py
#!/usr/bin/python
# coding: utf-8

import requests
import json
import sys
import os
sys.path.append("C:\\rpawk\\common\\bin")
import notificationToRocketChat
USERNAME="ユーザー名"
PASSWORD="パスワード"

def get_before_timestamp():
  jenkins_url = os.getenv("JENKINS_URL")
  
  # apiで取得
  p = {'depth': '2', 'tree': 'jobs[displayName,buildable,lastCompletedBuild[number,timestamp,result,url,duration]]'}
  r = requests.get(jenkins_url + "api/json", auth=(USERNAME, PASSWORD), params=p)
  print(str(r))
  # print(str(r.json()["jobs"]))
  
  beforetime = [i["lastCompletedBuild"]["timestamp"] for i in r.json()["jobs"] if i["displayName"]==os.getenv("JOB_NAME")][0]
  print("beforetime: " + str(beforetime))
  return beforetime

def get_builds(jenkins_url, beforetime):
  # apiで取得
  p = {'depth': '2', 'tree': 'jobs[displayName,buildable,lastUnsuccessfulBuild[number,timestamp,result,url,duration]]'}
  r = requests.get(jenkins_url + "api/json", auth=(USERNAME, PASSWORD), params=p)
  print(str(r))
  # print(str(r.json()["jobs"]))
  
  # 前回実行後にエラーになったものだけを抽出
  result_datas = [i for i in r.json()["jobs"] if i["lastUnsuccessfulBuild"] is not None and i["lastUnsuccessfulBuild"]["result"]!="SUCCESS" and int(i["lastUnsuccessfulBuild"]["timestamp"]) >= beforetime ]
  print("result: " + json.dumps(result_datas))
  return result_datas
  
def mainfunction(token, jenkins_url, server_name):
  builds_datas = get_builds(jenkins_url, get_before_timestamp())
  
  if builds_datas:
    print("Error!!!")
    joblist = "\n -" + "\n -".join([i["displayName"] + " ( " + jenkins_url + "job/" + i["displayName"] + " )" for i in builds_datas])
    textdata = u":rage:落ちてまっせ: " + jenkins_url + " (" + server_name + ")" + joblist
    notificationToRocketChat.post_text(token, textdata)
    
  else:
    print(u"Not Error. Luky!")
    
if __name__ == "__main__":
  argvs = sys.argv  # コマンドライン引数を格納したリストの取得
  argc = len(argvs)
  print(str(argvs))  # デバッグプリント
  print(str(argc))  # デバッグプリント
  if (argc != 4):   # 引数が適切でない場合は、その旨を表示
    print('Erro: invalid argument')
    print('Usage: python %s ROCKET_CHAT_TOKEN JENKINS_URL JENKINS_SERVER_NAME' % argvs[0])
    sys.exit(1)         # プログラムの終了

  mainfunction(argvs[1], argvs[2], argvs[3])
```

補足1：slackへの通知
slackへの通知は、[Jenkinsおじさんビルド結果Slackに通知して](https://qiita.com/ryuthky_github/items/c7e68fba13ddf230159a)を見ると良いかと。

##見栄え
いずれも、ログインした後の見た目が変わります。（ログイン画面変えたいけど、war弄るぐらいしか思いつかない。）

###テーマ
何はともあれ[SimpleThemePlugin](https://wiki.jenkins.io/display/JENKINS/Simple+Theme+Plugin)。

DLして使用する場合は、以下Step。
1. `%JENKINS_HOME%/userContent`に`theme.css`,`theme.js`,`icon.png`（名前はテキトー）を格納
2. Jenkinsの管理＞システム設定＞Themeで`/userContent/theme.css`と`/userContent/theme.js`を指定する。
3. Jenkinsの管理＞システム設定＞Faviconで`/userContent/icon.png`を指定する。

左上おじさんに関しては、`theme.css`に追記する。
タイトルに関しては`theme.js`を作成する。

```css:theme.css
#jenkins-head-icon {
content:url('/userContent/icon.png');
height:36px;
width:auto;
}
#jenkins-name-icon {
content:url('/userContent/logo.png');
height:36px;
width:auto;
}
```

```html:theme.js
window.addEventListener("load", function() {  
  var title = document.querySelector('title');
  title.innerHTML = title.innerHTML.replace(/\[Jenkins\]/, '[Shiro-iruka]');
}, false)
```

参考：[JenkinsのUIをカスタマイズする](https://84zume.wordpress.com/2013/12/23/customize-jenkins-ui/)
参考：[Jenkinsの左上のおじさんアイコンを変更する](https://qiita.com/74th/items/13ad068c8e2f68dc2727)
参考：[フリーフォントで簡単ロゴ作成](http://lightbox.on.coocan.jp/html/fontImage.php)

#運用編
##起動オプション

ご参考程度にどうぞ。
少なくともメモリは設定したほうが良いかと。1GBを超えると起動しなくなったので、1GBが限界？
セキュリティ的に推奨されない指定もしているので、各自ご調整ください。

```bat:jenkinsStart.bat
SET BASE=C:\rpatools\jenkins
C:\java\jdk\bin\java -Xrs -Xmx1024m -Xms1024m -XX:MaxMetaspaceSize=256m -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -verbose:gc -Xloggc:"gc.log" -XX:HeapDumpPath="heapdump.log" -XX:ErrorFile="javaerror.log" -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\jenkins.war" --httpPort=8080 --webroot="%BASE%\war" >> %JENKINS_HOME%\logs\jenkins.log 2>>&1
```

参考：[Jenkinsの起動オプションを細かく指定して起動](https://qiita.com/quattro_4/items/769f875baa17ce4725e8)


##起動・停止
手動で起動/停止でございます。batファイルでも作っておきましょう。
停止は、Ctrl+Cとか、タスクマネージャーからのプロセスダウンとかで。
SafeRestartは機能しません。。。

ちなみに、起動手段と、機能の使える使えないのマッピングはこんな感じ。

|起動手段|ブラウザ操作|Excelマクロ起動|
|:--|:--|:--|
|Service|:no_entry_sign:|:question:（試してない）|
|タスクスケジューラ|:thumbsup:|:no_entry_sign:|
|手動|:thumbsup:|:thumbsup:|

##アップデート
Jenkinsのバージョンを上げたいときは、WARを置き換えれば良いんやで。
不安なら`%JENKINS_HOME%`をバックアップしておきましょう。

#最後に
RPAのもっとも特徴的なポイントは**ノンプログラミングで**色々作れる点だと思います。
事務員さんが多い会社さんとか、プログラムの素養がある人が少ないところでは、今まで外注しないとできなかったことが自分で作れるツールなので、そこに非常に効果的なのでは？と感じています。
(他にも、自動化の実装が簡易とか、メリットは多いです。)

ただ、プログラマーの多い環境であれば、Jenkinsとかを用いて自動化を図ったほうが、コードに触れる機会が増えるので良いのでは？と思っています。
無償だし、並列実行もできるし、管理機能も充足しているし、情報もたくさん落ちているし、無料だし、無料だし、無料だし、文句なしだと思う。
（面倒な決済を取らなくて済むのが本当に嬉しい）

少し脱線しましたが、詰まるところ、自動化とか効率化のためのツール導入ってのは、「そのツールを誰が使うのか？」を中心にして、検討をしたほうが良いと思っています。
自動化する作業って、係数取得的なものが多かったりする気がするので、それをやる人は誰なんだろうか・・・って話ですね。
プログラマがそのツールを使うのであれば、RPAと合わせて、Jenkinsでの自動化も選択肢に入れてみてはいかがでしょうか。