OITA: Oika's Information Technological Activities

@oika 情報技術的活動日誌。

Travis CI Cron Jobs で .NET Core アプリを定期実行

GitHubと連携して使える CI サービス Travis CIには、ビルドタスクを定期実行させられる Cron Jobs という機能がある。

実行間隔は daily / weekly / monthly というレベルでしか指定できないので利用ケースは限られるが、これを使えば CI 的な用途に限らず、1日1回の cron的な処理を無料の環境で動かせるということだ。

Travis CI は .NET Core のビルドに対応しているので、C# でかいた簡単なアプリを動かしてみる。

なお .NET Core のみならず mono も対応してるっぽかったので、.NET Framework のアプリもそれなりに動きそうではある。

GitHub と Travis の連携

このへんの説明は割愛する。

Travis でアカウントを作って、GitHub のアカウントと紐づけておく必要がある。

.NET Core を Travis でビルドする

GitHub上で公開リポジトリを作り、そこに .NET Core アプリをコミットしておく。

まずはコンソールに 時間を出力するだけのもの。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($"{DateTime.Now} Executed.");
    }
}

.NET Core 2.2 をターゲットとした。

リポジトリ構成は以下のとおり。

/root/
  ├ src/
  │  ├ TravisCronJobsDotNetCoreSample/
  │  │  ├ Program.cs
  │  │  └ TravisCronJobsDotNetCoreSample.csproj
  │  └ TravisCronJobsDotNetCoreSample.sln
  ├ .gitignore
  └ .travis.yml

このリポジトリを、Travis 側の画面で「My Repositories」に追加しておく。

.travis.ymlドキュメントを参考に、以下のように記載。

language: csharp
mono: none
dotnet: 2.2
sudo: required
dist: xenial
script:
 - dotnet run -c Release -p src/TravisCronJobsDotNetCoreSample/TravisCronJobsDotNetCoreSample.csproj

dotnet には .NET Core SDK のバージョンを定義する。

バージョン番号は Download .NET Core 2.2のページで確認できるが、ビルドバージョンまで書かなくても、「2.2」とだけ書けば勝手に最新版(現時点では 2.2.203)を使ってくれるようだった。

あと大事な点として、 dist を指定しないと以下のようなログでビルドが失敗した。

Preparing to unpack .../dotnet-sdk-2.2_2.2.203-1_amd64.deb ...
Unpacking dotnet-sdk-2.2 (2.2.203-1) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Errors were encountered while processing:
 /var/cache/apt/archives/aspnetcore-runtime-2.2_2.2.4-1_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
The command "sudo apt-get install -qq dotnet-sdk-2.2" failed and exited with 100 during .

Your build has been stopped.

ここよくわからないんだけれど、Travis のフォーラムに同じような報告があって、dist を xenial にしろと書いてあったのでそのようにしたら動いた。

ここまでやれば、リポジトリにコミットがある度に Travis でビルドが走る。Travis のリポジトリページでコンソールに時刻が出力されているのを確認できるはず。

アプリから IFTTT をトリガする

これだけだとつまらないので、おまけとして IFTTT の WebHook をたたくアプリにしてみる。

IFTTT で WebHook を利用するあたりの詳細は以前書いた IFTTT 自作アプリからHTTPリクエストでスマホへプッシュ通知 を参照されたし。

CI で動かす場合の注意点としては、WebHook の URL になる IFTTT アカウントの Key を公開リポジトリにコミットしたくないよねっていうところ。

Key は Travis の環境変数として埋め込むようにする。

環境変数は、暗号化した状態で .travis.yml に書いちゃう方法もあるようだが、ここでは Travis の Settings 画面から設定する。

利用コードはこんな感じ。

class Program
{
    static void Main(string[] args)
    {
        var iftttId = Environment.GetEnvironmentVariable("IFTTT_ID");
        if (iftttId == null)
        {
            Console.WriteLine("ifttt id not defined.");
        }
        else
        {
            // 'ci' は IFTTTのイベント名
            var url = "https://maker.ifttt.com/trigger/ci/with/key/" + iftttId;

            //値を渡す場合(今回は未使用)
            var values = new Dictionary<string, string>  
            {  
                { "value1", "testtest" },  
            };

            using (var client = new HttpClient())  
            {
                client.PostAsync(url, new FormUrlEncodedContent(values)).Wait();
            }
        }
    }
}

これで IFTTT の通知がトリガされる。

Travis の Cron Jobs で動かす

あとは Cron Jobs に登録して、定期実行されるようにする。

同じく Travis の Settings ページ「Cron Jobs」から。ブランチ単位で登録できる。

実行時間を自分で指定することはできないっぽいが、次に実行される時刻は登録後に確認できる。

Cron Jobsでのみ実行されるようにしたい(コミット時に実行したくない)場合、 .travis.yml の先頭に以下の条件を追加する。

if: type = cron

CI タスクの中に、 cron だけで実行したいものとコミットでも実行したいものが混在する場合、stage や job ごとに条件を定義することができる。
詳細はこちらを参照。

また、タスクの条件として指定できる項目の詳細はこちらを参照。