Skip to content

Daily Update

Daily Update #1415

name: Daily Update
# NOTE: GitHub Action's scheduler is always set to UTC+0. So 9am should be set at 0am for JST (UTC+9)
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule
# '0 23 * * *' == 8am in JST (UTC+9)
# '0 0 * * *' == 9am in JST (UTC+9)
# '0 1 * * *' == 10am in JST (UTC+9)
# '59 23 * * *' task will be completed after 9am in JST
on:
schedule:
- cron: '59 20 * * *'
# [DEBUG ONLY] Every 5 minutes
# https://github.blog/changelog/2019-11-01-github-actions-scheduled-jobs-maximum-frequency-is-changing
#- cron: '*/5 * * * *'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 📥 Download codes from GitHub
uses: actions/checkout@v7
with:
fetch-depth: 2
- name: 💎 Set up Ruby
uses: ruby/setup-ruby@v1
#with:
# bundler-cache: true
#ruby-version: 3.2 # Not necessary if .ruby-version is given
- name: 🧪 Install Ruby gems
run: |
bundle install
- name: 🌐 Fetch dojo data from Earth
run: |
bundle exec rake get_data_from_earth
if [ "`cat tmp/number_of_dojos`" -lt "1000" ] ; then
echo "ERROR: NUMBER_OF_DOJOS=`cat tmp/number_of_dojos`"
echo "This number should be 1000+. Something went wrong."
exit 1
fi
- name: 🗾 Fetch dojo/event data from Japan
run: |
bundle exec rake get_data_from_japan
# 日本のマーカーは global_club_id での突合に依存している。取得に失敗して
# 空や欠損のデータが入ると、海外のマーカーだけが残った地図がデプロイされる。
# Earth 側と同じく、入口で件数を確かめる
NUMBER_OF_DOJOS=$(ruby -rjson -e 'puts JSON.parse(File.read("_data/dojos_japan.json")).size')
if [ "$NUMBER_OF_DOJOS" -lt "300" ] ; then
echo "ERROR: NUMBER_OF_DOJOS=$NUMBER_OF_DOJOS"
echo "This number should be 300+. Something went wrong."
exit 1
fi
- name: 🔧 Build data to render DojoMap
run: |
# Jekyll plugin automatically runs upsert_dojos_geojson and compact_geojson
JEKYLL_ENV=production bundle exec jekyll build
- name: ✅ Test
run: |
# _site is already built in previous step
JEKYLL_ENV=production bundle exec jekyll doctor
SKIP_BUILD=true bundle exec rake test
- name: 🆙 Commit latest data to update DojoMap (if any)
run: |
if [ -n "$(git status --porcelain)" ]; then
git config --global user.name "Yohei Yasukawa"
git config --global user.email "yohei@yasslab.jp"
git checkout main
# Gems may update automatically
git add Gemfile.lock
# Cache responses from Japan/Clubs APIs
git add _data/*.json
# Save GeoJSON data to render DojoMap
git add dojos.geojson
# Commit changed files above
git commit -m '🤖 Upsert Earth/Japan data for DojoMap'
# Git pull/push the commit to deploy
git pull origin main
git push origin main
fi
env:
GITHUB_TOKEN:
# 地図に載らなかった active な Dojo を検知する。
#
# 意図的な設計:
# - デプロイの「後」に置く。1 つの Dojo が Clubs 側で消えただけで日次更新
# 全体を止めるのは割に合わない
# - continue-on-error でジョブ自体は失敗させない
# - 通知するのは uuid_not_in_clubs と no_uuid の 2 つ。
# uuid_not_in_clubs は Japan 側が UUID を持っているのに Clubs 側にその
# クラブが無い状態で、削除か UUID 変更が起きている。
# no_uuid は coderdojo.jp 側の spec が防いでいるはずの状態なので、ここに
# 出たら上流の保証が破れている。
# - club_excluded_by_status_or_coordinates は Clubs 側の登録内容の問題で、
# こちらからは直せないためログのみに留める
- name: 🔎 Check unmatched dojos
id: unmatched
continue-on-error: true
run: |
cat tmp/unmatched_dojos.json
ruby -rjson -e '
critical = JSON.parse(File.read("tmp/unmatched_dojos.json"))
.select { |d| %w[uuid_not_in_clubs no_uuid].include?(d["reason"]) }
exit 0 if critical.empty?
critical.each { |d| warn "#{d["name"]} (id=#{d["id"]}): #{d["reason"]} #{d["global_club_id"]}" }
exit 1
'
- name: 🔔 Notify unmatched dojos to Slack (if any)
if: steps.unmatched.outcome == 'failure'
uses: slackapi/slack-github-action@v3.0.5
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": "<@yasulab> 地図に載らなかった Dojo があります。",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<@yasulab> *地図に載らなかった Dojo があります。* coderdojo.jp 側の `global_club_id` が Clubs DB のクラブと結びついていません。提携先での削除・ID 変更か、`global_club_id` の未設定が考えられます。\n\n*対応:* `db/dojos.yml` の `global_club_id` を現在の値に更新してください。該当 Dojo 名と理由はログに出ています。\n\n<https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|» 詳細を見る (GitHub)>"
}
}
]
}
# This is NOT for security reason but for others, especially who fork,
# to easier find out which API key they need to replace with their own.
# Check out the official tutorial for details: https://docs.geolonia.com/tutorial
- name: 🔑 Pass Geolonia YOUR-API-KEY from secrets
env:
GEOLONIA_API_KEY: ${{ secrets.GEOLONIA_API_KEY }}
run: |
ruby -i -pe '$_.gsub!("geolonia-api-key=YOUR-API-KEY",
"geolonia-api-key=${{ env.GEOLONIA_API_KEY }}")' _site/index.html
ruby -i -pe '$_.gsub!("geolonia-api-key=YOUR-API-KEY",
"geolonia-api-key=${{ env.GEOLONIA_API_KEY }}")' _site/world.html
- name: 🚀 Deploy to GitHub Pages
if: github.ref == 'refs/heads/main' && job.status == 'success'
uses: peaceiris/actions-gh-pages@v4
with:
personal_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_site
# 地図の表示は Geolonia のサービスに依存している。過去2回、サイト自体は HTTP 200 を
# 返しているのに地図が表示されない状態が発生した。自サイトの死活監視では気づけないため、
# 依存先の応答を毎日確認する。
# 2026/06: スプライト サーバが 502 → マーカーが1件も描画されなかった
# 2026/07: 埋め込み v1 が参照する旧インフラの不具合 → 世界地図が描画されなかった
#
# 意図的な設計:
# - デプロイの「後」に置く。依存先に異常がある時こそ marker: default への切替を
# デプロイしたいので、外部要因でデプロイを止めてはならない
# - continue-on-error でジョブ自体は失敗させない(本体のビルド失敗と混同しないため)
# - always() でビルドが失敗した時も実行する(依存先の状態は常に知りたい)
- name: 🩺 Check map dependencies
id: geolonia
if: always()
continue-on-error: true
run: |
set -e
# 1. 埋め込みスクリプト (_config.yml で一元管理している URL を読む)
EMBED_URL=$(ruby -ryaml -e 'puts YAML.load_file("_config.yml")["geolonia_embed_url"]')
echo "Checking embed script: $EMBED_URL"
curl -sfL --retry 3 --retry-delay 30 --max-time 30 \
"$EMBED_URL?geolonia-api-key=YOUR-API-KEY" -o /tmp/embed.js
test -s /tmp/embed.js # 空でないこと(200 を返しても中身が空なら異常)
# 2. スプライト サーバ (マーカー描画に必須)
echo "Checking sprite server..."
ruby tests/sprite_status_test.rb # 標準ライブラリのみ。bundle install 不要
env:
GEOLONIA_API_KEY: ${{ secrets.GEOLONIA_API_KEY }}
- name: 🔔 Notify map dependency issue to Slack (if any)
if: always() && steps.geolonia.outcome == 'failure'
uses: slackapi/slack-github-action@v3.0.5
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": "<@yasulab> 地図の依存サービスから正常な応答が得られていません。地図が表示されない可能性があります。",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<@yasulab> *地図の依存サービス (Geolonia) から正常な応答が得られていません。* 地図が表示されない可能性があります。\n\n*暫定復旧の手順:* マーカーが表示されない場合、`_config.yml` の `marker: coderdojo` を `marker: default` に変更して再デプロイすると、スプライト サーバに依存しない circle マーカーに切り替わります。\n\n<https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|» 詳細を見る (GitHub)>"
}
}
]
}
- name: 🔔 Notify error to Slack (if any)
if: failure()
id: slack
uses: slackapi/slack-github-action@v3.0.5
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
# For posting a simple plain text message
payload: |
{
"text": "<@yasulab> Failed to build DojoMap. » 詳細を見る (GitHub)",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<@yasulab> Failed to build DojoMap. <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|» 詳細を見る (GitHub)>"
}
}
]
}