Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/package-stats.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
run: |
set -euo pipefail
files=(
docs/assets/package-downloads-monthly.svg
docs/assets/package-downloads-daily.svg
docs/assets/package-downloads.md
docs/assets/package-downloads-history.jsonl
)
Expand Down Expand Up @@ -82,6 +82,10 @@ jobs:
done

git add "${files[@]}"
# Drop superseded monthly chart so the data branch does not keep a stale SVG.
if [ -f docs/assets/package-downloads-monthly.svg ]; then
git rm -f docs/assets/package-downloads-monthly.svg
fi
if git diff --cached --quiet; then
echo "Package stats already up to date."
exit 0
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ separately from standalone release downloads. Charts refresh daily via
[`package-stats.yml`](.github/workflows/package-stats.yml). Exact numbers:
[package-downloads.md](https://github.com/bitdynamics-ab/canton-devkit/blob/release-stats-data/docs/assets/package-downloads.md).

![Monthly DPM package downloads](https://raw.githubusercontent.com/bitdynamics-ab/canton-devkit/release-stats-data/docs/assets/package-downloads-monthly.svg)
![Daily DPM package downloads](https://raw.githubusercontent.com/bitdynamics-ab/canton-devkit/release-stats-data/docs/assets/package-downloads-daily.svg)

## Contributing

Expand Down
11 changes: 11 additions & 0 deletions scripts/package-stats-daily.jq
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Daily download counts from cumulative daily snapshots.
#
# Input: JSON array of { date, total, ... } (use jq -s on a JSONL history file).
# Output: [ { date: "YYYY-MM-DD", downloads: N }, ... ] oldest first.
# The first snapshot is baseline only and contributes no delta. Negative steps clamp to 0.

sort_by(.date)
| . as $rows
| [ range(1; length)
| { date: $rows[.].date,
downloads: ([($rows[.].total - $rows[.-1].total), 0] | max) } ]
37 changes: 0 additions & 37 deletions scripts/package-stats-monthly.jq

This file was deleted.

32 changes: 17 additions & 15 deletions scripts/package-stats.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# https://github.com/bitdynamics-ab/canton-devkit/pkgs/container/canton-devkit
#
# Outputs (into docs/assets/):
# package-downloads-monthly.svg — new downloads per calendar month (line; last 6 months)
# package-downloads.md — total + monthly summary table
# package-downloads-daily.svg — new downloads per day (line; last 30 days)
# package-downloads.md — total + daily summary table (last 30 days)
# package-downloads-history.jsonl — appended daily snapshot (total + last30Days)
#
# Environment:
Expand Down Expand Up @@ -188,7 +188,7 @@ snapshot_date="${SNAPSHOT_DATE:-$(date -u +%Y-%m-%d)}"
touch "${HISTORY_FILE}"
history_len="$(jq -s 'length' "${HISTORY_FILE}" 2>/dev/null || echo 0)"

# Backfill when history has fewer than 2 rows so monthly deltas are possible
# Backfill when history has fewer than 2 rows so daily deltas are possible
# immediately from the page sparkline.
if [ "${history_len}" -lt 2 ]; then
echo "seeding history from sparkline (history_len=${history_len})" >&2
Expand Down Expand Up @@ -221,19 +221,21 @@ today_row="$(jq -nc --arg d "${snapshot_date}" --argjson total "${total}" --argj
mv "${HISTORY_FILE}.tmp" "${HISTORY_FILE}"
echo "updated ${HISTORY_FILE} (snapshot ${snapshot_date})"

# --- Monthly chart from history deltas ------------------------------------
monthly_rows="$(jq -s -f "${script_dir}/package-stats-monthly.jq" "${HISTORY_FILE}")"
# --- Daily chart from history deltas --------------------------------------
# GitHub only exposes a cumulative total. Diff consecutive snapshots, clamp
# negatives, then chart the trailing window so x-axis labels stay readable.
daily_rows="$(jq -s -f "${script_dir}/package-stats-daily.jq" "${HISTORY_FILE}")"

by_month_data="$(printf '%s' "${monthly_rows}" | jq '
.[-6:] as $months
| { labels: [ $months[].month ],
by_day_data="$(printf '%s' "${daily_rows}" | jq '
.[-30:] as $days
| { labels: [ $days[].date[5:] ],
series: [ { name: "Downloads",
color: "#2563eb",
values: [ $months[].downloads ] } ]
values: [ $days[].downloads ] } ]
}
')"
render_line_chart "${OUT_DIR}/package-downloads-monthly.svg" \
"Monthly DPM package downloads (last 6 months)" "Month (oldest -> newest)" "${by_month_data}"
render_line_chart "${OUT_DIR}/package-downloads-daily.svg" \
"Daily DPM package downloads (last 30 days)" "Day (oldest -> newest)" "${by_day_data}"

# --- Markdown summary -----------------------------------------------------
{
Expand All @@ -244,14 +246,14 @@ render_line_chart "${OUT_DIR}/package-downloads-monthly.svg" \
printf '**Last 30 days (page sparkline):** %s.\n\n' "${last30}"
echo "Source: [GitHub Packages](${PACKAGE_URL})."
echo
echo "### Monthly downloads"
echo "### Daily downloads (last 30 days)"
echo
echo "| Month | Downloads |"
echo "| Date | Downloads |"
echo "|---|---|"
if [ "$(printf '%s' "${monthly_rows}" | jq 'length')" -eq 0 ]; then
if [ "$(printf '%s' "${daily_rows}" | jq 'length')" -eq 0 ]; then
echo "| — | 0 (need at least two daily snapshots) |"
else
printf '%s' "${monthly_rows}" | jq -r 'reverse[] | "| \(.month) | \(.downloads) |"'
printf '%s' "${daily_rows}" | jq -r '.[-30:] | reverse[] | "| \(.date) | \(.downloads) |"'
fi
echo
} > "${OUT_DIR}/package-downloads.md"
Expand Down
39 changes: 18 additions & 21 deletions scripts/package-stats_test.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env bash
# Regression checks for scripts/package-stats.sh and package-stats-monthly.jq.
# Regression checks for scripts/package-stats.sh and package-stats-daily.jq.
set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
jq_filter="${script_dir}/package-stats-monthly.jq"
jq_filter="${script_dir}/package-stats-daily.jq"
fixture="${script_dir}/testdata/package-stats-page.html"
tmp="$(mktemp -d)"
trap 'rm -rf "${tmp}"' EXIT
Expand All @@ -28,25 +28,16 @@ assert_file_contains() {
fi
}

# --- Monthly jq (same contract as release-stats-monthly.jq) ----------------
# --- Daily jq -------------------------------------------------------------
cat > "${tmp}/history.jsonl" <<'EOF'
{"date":"2026-07-06","total":10}
{"date":"2026-07-20","total":12}
{"date":"2026-07-28","total":15}
{"date":"2026-08-05","total":18}
{"date":"2026-07-07","total":12}
{"date":"2026-07-08","total":15}
{"date":"2026-07-09","total":18}
EOF
assert_eq "monthly aggregation" \
assert_eq "daily aggregation" \
"$(jq -s -f "${jq_filter}" "${tmp}/history.jsonl")" \
'[{"month":"2026-07","downloads":5},{"month":"2026-08","downloads":3}]'

cat > "${tmp}/history-gap.jsonl" <<'EOF'
{"date":"2026-07-06","total":10}
{"date":"2026-07-10","total":14}
{"date":"2026-09-02","total":20}
EOF
assert_eq "gap fill" \
"$(jq -s -f "${jq_filter}" "${tmp}/history-gap.jsonl")" \
'[{"month":"2026-07","downloads":4},{"month":"2026-08","downloads":0},{"month":"2026-09","downloads":6}]'
'[{"date":"2026-07-07","downloads":2},{"date":"2026-07-08","downloads":3},{"date":"2026-07-09","downloads":3}]'

cat > "${tmp}/history-clamp.jsonl" <<'EOF'
{"date":"2026-08-03","total":20}
Expand All @@ -55,13 +46,19 @@ cat > "${tmp}/history-clamp.jsonl" <<'EOF'
EOF
assert_eq "negative delta clamp" \
"$(jq -s -f "${jq_filter}" "${tmp}/history-clamp.jsonl")" \
'[{"month":"2026-08","downloads":2}]'
'[{"date":"2026-08-04","downloads":0},{"date":"2026-08-05","downloads":2}]'

printf '%s\n' '{"date":"2026-08-03","total":20}' > "${tmp}/history-one.jsonl"
assert_eq "single snapshot" \
"$(jq -s -f "${jq_filter}" "${tmp}/history-one.jsonl")" \
'[]'

# Chart window: last 30 days only (full series may be longer).
window="$(printf '%s' "$(jq -n '[range(1;41) | {date: ("2026-01-" + (if . < 10 then "0\(.)" else "\(.)" end)), downloads: .}]')" | jq -c '.[-30:] | { labels: [.[].date[5:]], values: [.[].downloads] }')"
assert_eq "chart last-30 window length" \
"$(printf '%s' "${window}" | jq '.labels | length')" \
'30'

# --- End-to-end against HTML fixture --------------------------------------
out="${tmp}/out"
mkdir -p "${out}"
Expand All @@ -72,7 +69,7 @@ OUT_DIR="${out}" \

history="${out}/package-downloads-history.jsonl"
md="${out}/package-downloads.md"
svg="${out}/package-downloads-monthly.svg"
svg="${out}/package-downloads-daily.svg"

[ -f "${history}" ] || { echo "FAIL: missing history" >&2; exit 1; }
[ -f "${md}" ] || { echo "FAIL: missing markdown" >&2; exit 1; }
Expand All @@ -92,8 +89,8 @@ assert_eq "first seeded row" \
'{"date":"2026-08-01","total":10,"last30Days":null}'

assert_file_contains "md total" "${md}" "**Total downloads:** 100"
assert_file_contains "md month" "${md}" "| 2026-10 | 50 |"
assert_file_contains "svg title" "${svg}" "Monthly DPM package downloads"
assert_file_contains "md day" "${md}" "| 2026-10-20 | 20 |"
assert_file_contains "svg title" "${svg}" "Daily DPM package downloads"

# Idempotent same-day re-run must not duplicate rows.
OUT_DIR="${out}" \
Expand Down