diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index f743ec5..50dc168 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -1,4 +1,4 @@ -name: Snapshot download metrics +name: Snapshot download & traffic metrics # GitHub は「今の累計」しか返さないので、定期的に撮って差分を残す。 # 手元の Mac が起動していなくても回るように Actions で撮る。 @@ -42,17 +42,25 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: OUT=.metrics/downloads.csv sh scripts/metrics_snapshot.sh + # Traffic API は Administration:read が要る。GITHUB_TOKEN では取れないことがある + # ので TRAFFIC_TOKEN を優先し、未設定なら GITHUB_TOKEN にフォールバックする + # (その場合 gh api が失敗し、スクリプトの安全策で CSV には触らず落ちるだけ)。 + - name: views/clones を追記 + env: + GH_TOKEN: ${{ secrets.TRAFFIC_TOKEN || secrets.GITHUB_TOKEN }} + run: OUT=.metrics/traffic.csv sh scripts/traffic_snapshot.sh + - name: 変化があれば metrics へコミット working-directory: .metrics run: | - if git diff --quiet -- downloads.csv; then + if git diff --quiet -- downloads.csv traffic.csv; then echo "変化なし。コミットしない。" exit 0 fi git config user.name 'github-actions[bot]' git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add downloads.csv - git commit -m "メトリクス: ダウンロード数のスナップショット ($(date -u +%Y-%m-%dT%H:%MZ))" + git add downloads.csv traffic.csv + git commit -m "メトリクス: ダウンロード数・トラフィックのスナップショット ($(date -u +%Y-%m-%dT%H:%MZ))" # 順番待ちの間に metrics が進んでいることがある。撮った行は捨てずに乗せ直す。 for i in 1 2 3; do git push origin HEAD:metrics && exit 0 diff --git a/scripts/traffic_snapshot.sh b/scripts/traffic_snapshot.sh new file mode 100644 index 0000000..995bf6d --- /dev/null +++ b/scripts/traffic_snapshot.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# GitHub Traffic API(views/clones)を、直近14日ローリング集計のスナップショットとして記録する。 +# +# downloads.csv(metrics_snapshot.sh)と違い、views/clones は「今の累計」ではなく +# 「直近14日間の集計」なので、前回より減っても異常ではない。よって減少チェックはしない。 +# 撮り続けること自体に意味がある(撮り漏らした日は API 側にも残らず復元できない)。 +# +# 正はブランチ `metrics`(main には無い。理由は metrics_snapshot.sh 参照)。 +# +# 使い方: +# sh scripts/traffic_snapshot.sh +# DRY_RUN=1 sh scripts/traffic_snapshot.sh # CSV に書かずに値だけ見る +# OUT=/tmp/x.csv sh scripts/traffic_snapshot.sh +# +# Traffic API は Administration:read 権限が要る。既定の GITHUB_TOKEN では取れないことが +# ある(MrkAppRelease で実際に token_required が発生した実績あり)ため、呼び出し側の +# ワークフローで secrets.TRAFFIC_TOKEN を優先し、無ければ GITHUB_TOKEN にフォールバックする。 +# +# 壊れた値を書かないための約束: +# - gh api が失敗したら書かない(パイプで握り潰さない)。 +set -eu + +REPO="${REPO:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}" +DATA_BRANCH="${DATA_BRANCH:-metrics}" +OUT="${OUT:-}" +DRY_RUN="${DRY_RUN:-}" + +# OUT が指定されていなければ、正(ブランチ metrics)を作業コピーへ引いてくる。 +if [ -z "$OUT" ]; then + OUT=".metrics/traffic.csv" + mkdir -p "$(dirname "$OUT")" + if git rev-parse --git-dir >/dev/null 2>&1; then + git fetch -q origin "$DATA_BRANCH" 2>/dev/null || true + if git cat-file -e "FETCH_HEAD:traffic.csv" 2>/dev/null; then + git show "FETCH_HEAD:traffic.csv" > "$OUT" + echo "ブランチ $DATA_BRANCH から $OUT へ引いた(手元の結果は push しない)" + fi + fi +fi +AT="${AT:-$(date -u +%Y-%m-%dT%H:%MZ)}" + +mkdir -p "$(dirname "$OUT")" +[ -f "$OUT" ] || printf 'taken_at,views_14d,unique_views_14d,clones_14d,unique_clones_14d\n' > "$OUT" + +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +if ! views_json="$(gh api "repos/$REPO/traffic/views" 2>"$WORK/err")"; then + echo "views の取得に失敗した。CSV は変更していない。" >&2 + cat "$WORK/err" >&2 + exit 1 +fi +if ! clones_json="$(gh api "repos/$REPO/traffic/clones" 2>"$WORK/err")"; then + echo "clones の取得に失敗した。CSV は変更していない。" >&2 + cat "$WORK/err" >&2 + exit 1 +fi + +views="$(printf '%s' "$views_json" | jq -r '.count')" +unique_views="$(printf '%s' "$views_json" | jq -r '.uniques')" +clones="$(printf '%s' "$clones_json" | jq -r '.count')" +unique_clones="$(printf '%s' "$clones_json" | jq -r '.uniques')" + +if [ -z "$DRY_RUN" ]; then + grep -v "^\"$AT\"," "$OUT" > "$WORK/out" 2>/dev/null || true + printf '"%s",%s,%s,%s,%s\n' "$AT" "$views" "$unique_views" "$clones" "$unique_clones" >> "$WORK/out" + mv "$WORK/out" "$OUT" +fi + +printf '%s views=%s(uniq %s) clones=%s(uniq %s)' "$AT" "$views" "$unique_views" "$clones" "$unique_clones" +if [ -n "$DRY_RUN" ]; then + printf ' [DRY_RUN: CSV は書いていない]' +fi +printf '\n'