Skip to content

Commit c24bc53

Browse files
committed
docs: count desktop .dmg and .exe downloads per platform
shields.io cannot split downloads by asset: its wildcards silently report 0 (a tag whose .dmg had 39,877 downloads returns 0 for *.dmg), exact asset names embed the version so they break every release, and dynamic/json rejects every filter expression. A daily workflow sums the counts from the desktop releases repo and publishes them as shields endpoint documents on the orphan badges branch, which main's protection rules do not block. The badges move into the hero row in for-the-badge style, matching the rest of that row rather than adding a fourth style to the README.
1 parent ce744d9 commit c24bc53

2 files changed

Lines changed: 84 additions & 4 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Refreshes the per-platform desktop download counters behind the README badges.
2+
#
3+
# shields.io cannot do this on its own: its asset wildcards silently report 0
4+
# (a tag whose .dmg had 39,877 downloads returns 0 for `*.dmg`), exact asset
5+
# names embed the version so they break on every release, and `dynamic/json`
6+
# rejects every filter expression. So we sum the counts here and publish them
7+
# as shields `endpoint` documents.
8+
#
9+
# The documents land on the orphan `badges` branch, never on `main` — `main` is
10+
# protected and rejects pushes from everyone, CI included.
11+
name: Desktop Download Badges
12+
13+
on:
14+
schedule:
15+
# Once a day is plenty; the counters move slowly and the API is rate-limited.
16+
- cron: '17 4 * * *'
17+
workflow_dispatch: {}
18+
19+
permissions:
20+
contents: write
21+
22+
concurrency:
23+
group: desktop-download-badges
24+
cancel-in-progress: true
25+
26+
jobs:
27+
refresh:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout the badges branch
31+
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # pinned from v4
32+
with:
33+
ref: badges
34+
persist-credentials: true
35+
36+
- name: Sum the .dmg and .exe download counts
37+
env:
38+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39+
RELEASES_REPO: PyModel/pythinker-desktop-releases
40+
run: |
41+
set -euo pipefail
42+
43+
# --paginate walks every release, so the totals cover the whole
44+
# history rather than just the latest tag.
45+
gh api --paginate "repos/${RELEASES_REPO}/releases" > releases.json
46+
47+
write_badge() {
48+
local suffix="$1" label="$2" out="$3"
49+
local total
50+
total="$(jq --arg s "$suffix" '
51+
[ .[].assets[]
52+
| select(.name | ascii_downcase | endswith($s))
53+
| .download_count
54+
] | add // 0
55+
' releases.json)"
56+
jq -n --arg label "$label" --arg message "$total" '{
57+
schemaVersion: 1,
58+
label: $label,
59+
message: $message,
60+
color: "4D6BFE"
61+
}' > "$out"
62+
echo "${label}: ${total}"
63+
}
64+
65+
write_badge '.dmg' 'macOS .dmg' desktop-dmg.json
66+
write_badge '.exe' 'Windows .exe' desktop-exe.json
67+
68+
rm -f releases.json
69+
70+
- name: Publish if the counts moved
71+
run: |
72+
set -euo pipefail
73+
if git diff --quiet -- desktop-dmg.json desktop-exe.json; then
74+
echo 'Counts unchanged; nothing to publish.'
75+
exit 0
76+
fi
77+
git config user.name 'github-actions[bot]'
78+
git config user.email 'github-actions[bot]@users.noreply.github.com'
79+
git add desktop-dmg.json desktop-exe.json
80+
git commit -m 'chore: refresh desktop download counts'
81+
git push origin badges

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
[![npm version](https://img.shields.io/npm/v/@pymodel/pythinker-code?style=for-the-badge&logo=npm&logoColor=white&color=CB3837&label=pythinker-code)](https://www.npmjs.com/package/@pymodel/pythinker-code)
1313
[![Downloads](https://img.shields.io/npm/dm/@pymodel/pythinker-code?style=for-the-badge&logo=npm&logoColor=white&color=2b89ff&label=downloads)](https://www.npmjs.com/package/@pymodel/pythinker-code)
14+
[![Desktop downloads](https://img.shields.io/github/downloads/PyModel/pythinker-desktop-releases/total?style=for-the-badge&logo=github&logoColor=white&label=desktop&color=4D6BFE)](https://github.com/PyModel/pythinker-desktop-releases/releases)
15+
[![macOS .dmg](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FPyModel%2Fpythinker-code%2Fbadges%2Fdesktop-dmg.json&style=for-the-badge&logo=apple&logoColor=white)](https://github.com/PyModel/pythinker-desktop-releases/releases/latest)
16+
[![Windows .exe](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FPyModel%2Fpythinker-code%2Fbadges%2Fdesktop-exe.json&style=for-the-badge&logo=windows&logoColor=white)](https://github.com/PyModel/pythinker-desktop-releases/releases/latest)
1417
[![Node.js](https://img.shields.io/badge/Node.js-26%2B-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)](https://github.com/PyModel/pythinker-code/blob/main/package.json)
1518
[![License: MIT](https://img.shields.io/badge/License-MIT-16a34a.svg?style=for-the-badge)](https://github.com/PyModel/pythinker-code/blob/main/LICENSE)
1619
[![CI](https://img.shields.io/github/actions/workflow/status/PyModel/pythinker-code/ci.yml?branch=main&label=CI&style=for-the-badge&logo=githubactions&logoColor=white)](https://github.com/PyModel/pythinker-code/actions/workflows/ci.yml?query=branch%3Amain)
@@ -21,10 +24,6 @@
2124
[![Docs](https://img.shields.io/badge/docs-online-0284c7.svg?style=flat-square)](https://pymodel.github.io/pythinker-code/)
2225
[![Homepage](https://img.shields.io/badge/home-code.pythinker.com-ec4899.svg?style=flat-square)](https://code.pythinker.com)
2326

24-
<a href="https://github.com/PyModel/pythinker-desktop-releases/releases"><img src="https://img.shields.io/github/downloads/PyModel/pythinker-desktop-releases/total?style=flat&label=desktop%20downloads&color=4D6BFE" alt="Total desktop downloads"></a>
25-
<a href="https://github.com/PyModel/pythinker-desktop-releases/releases/latest"><img src="https://img.shields.io/badge/macOS-.dmg-4D6BFE?style=flat&logo=apple&logoColor=white" alt="Download the macOS .dmg"></a>
26-
<a href="https://github.com/PyModel/pythinker-desktop-releases/releases/latest"><img src="https://img.shields.io/badge/Windows-.exe-4D6BFE?style=flat&logo=windows&logoColor=white" alt="Download the Windows .exe"></a>
27-
2827
<br />
2928

3029
<a href="https://code.pythinker.com">Website</a> &nbsp;·&nbsp;

0 commit comments

Comments
 (0)