📰

自分用の技術情報収集サイトをPerl + GitHub Actionsで作った

に公開

きっかけ

情報収集したいけど、アプリ使うとノイズがあるなぁという気持ちがあり、どうせならと、勉強もかねてRSS収集ツール作りました。

作ったもの

ZennやQiitaなどなどから、RSSやAPI情報から記事を収集して、静的HTMLを生成するツールです。

  • カテゴリ(Knowledge / Official / Security)ごとにタブ切り替えで閲覧
  • GitHub Actionsで1日3回自動実行 → GitHub Pagesに公開
  • DBなし。取得データはJSONで管理

こんな感じのファイルが生成されます。

docs/
  index.html              最新エディション
  archive.html            過去エディション一覧
  articles/
    YYYYMMDDHHmmss.html   エディション本体

JSON ファイルは data/ に残るので、あとからレイアウトを変えることも考慮しました。

構成

Perl で書きました。深い意味は特にないです。

bin/
  generate.pl       メインスクリプト
lib/
  Util.pm           HTML エスケープ・日付変換・JSON IO
  Fetcher.pm        HTTP フェッチ・RSS/API パース
  Source.pm         ソース設定のパース
  Catalog.pm        カテゴリ定義・グルーピング
  Renderer.pm       HTML 生成・CSS

ソース設定

取得元は環境変数で管理しています。
追加変更するときに、いちいちソースをいじりなくないなと思いまして。
1行1ソース、| 区切りで id|name|url|color|icon_url|category を書く形式にしました。

export RSS_SOURCES='
id|name|url|color|icon_url|category
'

export API_SOURCES='
id|name|kind|url_or_endpoint|color|icon_url|category
'

カテゴリは3種類準備しました。

カテゴリ 内容
knowledge 技術ブログ・企業テックブログ・エンジニア向けニュース
official 主要サービス・企業の公式情報
security セキュリティ情報・脆弱性・アドバイザリ

既読管理

state/seen.jsonに取得済み記事のキー(URLベースのSHA256)を記録しておくことで、次回実行時に重複を弾きます。
SINCE_DATETIME 環境変数を指定すると、既読でも指定日時以降の記事を再取得できます。

パスワード保護

VIEW_PASSWORDを設定すると全ページにクライアントサイドのパスワードゲートが付きます。
公開リポジトリに上げつつ、自分以外には見せたくない場合に使っています。
(とはいえ、簡単に突破できる程度のもの。)

つまづいたところ

GitHub Actionsのcronがうまく走らなかったという問題が起きました。

on:
  schedule:
    - cron: "40 22 * * *"
    - cron: "40 8 * * *"

と設定したのに、全然実行されない。
無課金なのが1番の理由だとは思うけれどもお金を払う気がなかった私は調べました。

解決策:外部cronからworkflow_dispatchを叩く

この記事で紹介されている方法を採用しました。

https://zenn.dev/ytkdm/articles/github-actions-cron-unreliable

  1. ワークフローにworkflow_dispatchトリガーを追加する
  2. GitHubのFine-grained Personal Access Token を作成
  3. 外部の無料 cron サービス(cron-job.org)から GitHub API の workflow_dispatch エンドポイントを定期的に POST する
on:
  workflow_dispatch:
  schedule:
    - cron: "40 22 * * *"
    - cron: "40 8 * * *"

scheduleの記述も保険的に残しておきます。
また、cron-job.org側では、指定した間隔で以下のエンドポイントにPOSTするだけです。

POST https://api.github.com/repos/{owner}/{repo}/actions/workflows/generate.yml/dispatches
Authorization: Bearer {PAT}
Content-Type: application/json

{"ref": "main"}

これで、外部から確実にトリガーをかけられるので、GitHub側のscheduleが発火しなくても問題なくなりました。

使ってみて

毎日朝・昼・夕に自動で記事が集まった状態でGitHub Pagesが更新されるようになりました。
自分用なので公開するかは未定ですが、楽しかったです。

GitHubで編集を提案

Discussion