Help us understand the problem. What is going on with this article?

オフラインで動作する祝日かどうかを判定してCIをスキップさせるPythonスクリプト

ローカルファイルに記載した日付と一致するかどうかを判定して、祝日などにCIをスキップできるシンプルなPythonスクリプトの実装方法と使用方法を記載します。

背景

現在CIで使用しているクラウドサービス上のVMは、稼働時間で課金されるため、休日や祝日などの使用しない日は起動させたくない。しかし、クラウドサービスで設定できるのは、土日などの決まった曜日だけなので、祝日や特定の日付などに起動をスキップできなかった。

内閣府のデータを使用して祝日かどうかを判定できるメンテナンスフリーなツールを公開してくださっている方がすでにいますが、会社独自の休日への対応や、外部のネットワークに依存せずに祝日を判定したかった。

そこで、オフラインで判定できるスクリプトを作成しました。

動作確認環境

  • python 2.6.6, 3.7.1
  • CentOS release 6.8
  • Windows 10 version 1809

実装方法

以下のisholiday.pyholidays.txtを同一ディレクトリに配置します。

isholiday.py
"""
Check whether holiday or not based on holidays.txt.
"""

import sys, os


def get_holidays_list():
    holidays_list = []
    target_path = os.path.join(os.path.dirname(__file__), 'holidays.txt')
    with open(target_path, 'r') as f:
        for row in f:
            holidays_list.append(row.strip())
    return holidays_list

def is_holiday(date):
    if date in get_holidays_list():
        return True
    else:
        return False


if __name__ == '__main__':
    if len(sys.argv) >= 2:
        if is_holiday(sys.argv[1]):
            print("It's a holiday!")
            sys.exit(0)
        else:
            print("It's a business day!")
            sys.exit(1)
    else:
        print('Usage: python isHoliday.py `date --iso-8601`')
        sys.exit(2)
holidays.txt
2018-07-16
2018-09-17
2018-09-24
2018-10-08
2018-11-23
2018-12-24
2018-12-31
2019-01-01
2019-01-02
2019-01-03
2019-01-14
2019-02-11
2019-03-21

使用方法

python isholiday.py <日付>

<日付>はYYYY-MM-DD形式で指定します。

例:

python isholiday.py `date --iso-8601`

実行した日がholidays.txtに含まれている場合は終了コード0を、
含まれていない場合は1を返します。

CIから呼び出す場合:

#!/bin/sh
python /path/to/isholiday.py `date --iso-8601`
if [ "$?" = "0" ]; then
  echo "Skip holiday!" 
  exit 0
fi

新しい祝日を追加する方法

holidays.txtにYYYY-MM-DD形式で追加してください。
不要な行は削除してしまって構いません。

注意: 2018-07-16の行は後述のテストで使っているため、削除してしまうと、テストが失敗します

テストの実行方法

python -m unittest tests.py

tests.py
import unittest
import isholiday

class TestGetHolidaysList(unittest.TestCase):
    def test_file_read(self):
        self.assertTrue(len(isholiday.get_holidays_list()) > 0)

class TestIsHoliday(unittest.TestCase):
    def test_holiday(self):
        self.assertTrue(isholiday.is_holiday('2018-07-16'))
    def test_not_holiday(self):
        self.assertFalse(isholiday.is_holiday('2018-07-17'))

if __name__ == '__main__':
    unittest.main()

問題点

この実装方法では、毎年holidays.txtを更新する必要があります。そのため、部署異動などでメンテナンスする人がいなくなったりすると、CIをスキップできなくなります。(可能な限りシンプルに実装していますので、後任の方への引き継ぎは比較的容易だと思います)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした