はじめに
リポジトリ内のURLを抽出し、指定されたステータスコードのURLを検知するGithub Actionsを作りました!!
リンク切れのURLを検知する使い方を想定しています。
on:
push:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: test
uses: PenguinCabinet/action-to-detect-404-URLs@v0.0.2
with:
working_directory: "./" # The directory path to check
filter_mode: "deny" # "allow" mode or "deny" mode
filter_status_code: "4.." # Detects URLs with status codes in the 400 range. Can be written using regular expressions.
detect_URLs_that_cannot_connect_to_the_server: true # Whether to detect when the server cannot be connected
wait_time: 1 # Request sending interval(second)
開発過程で困った点
三項式とlambda式の優先順位
filter_func=lambda a,b:re.match(b,a)==None if filter_mode == "allow" else lambda a,b:re.match(b,a)!=None
上記のコードは、三項式を使い、allowモードの場合合致しないものを検知し、denyモードの場合合致するものを検知することを意図しています。
しかし、これだとうまくいきません。
三項式の優先順位がlambda式より高いため、下記のような挙動になってしまうのです。
filter_func=lambda a,b:(re.match(b,a)==None if filter_mode == "allow" else lambda a,b:re.match(b,a)!=None)
そのため、意図するコードにしたい場合、下記のコードにします。
filter_func=(lambda a,b:re.match(b,a)==None) if filter_mode == "allow" else (lambda a,b:re.match(b,a)!=None)
URLを検知する方法
自前の正規表現で行うこともできるのですが、付け焼き刃で作るよりライブラリ化されたものを探したほうが信頼できるだろうということで、外部ライブラリを使用する方法を採用しました。
linkify-it-pyを使用しています。
最初、下記のようなコードを実装しました。
def search_urls(text: str) -> list[str]:
linkify = LinkifyIt()
matches = linkify.match(text)
if not matches:
return []
return [m.url for m in matches]
しかしこれだと、下記のスキーマのないURLやメールアドレスも検知してしまいます。
example.com
mailto:mail@example.com
そのため、LinkifyIt呼び出し時のコードを下記の通りに変更しました。
linkify = LinkifyIt(
schemas={
"ftp:": None,
"//": None,
"mailto:": None,
},
options={
"fuzzy_link": False,
"fuzzy_email": False,
"fuzzy_ip": False,
}
)
上記のテキストが検知されなくなり、意図した挙動になりました。