Skip to content

README: Microsoft Store downloads badge from Partner Center analytics - #192

Open
Twest2 wants to merge 1 commit into
mainfrom
feat/store-downloads-badge
Open

Twest2 wants to merge 1 commit into
mainfrom
feat/store-downloads-badge

Conversation

@Twest2

@Twest2 Twest2 commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Adds a Microsoft Store downloads badge to the README, next to the GitHub, APT, Chocolatey and DNF badges. It's sorted with them by count.

How the count gets there

Microsoft publishes no public download count, so the README can't fetch one live the way the other badges do.

  1. Sort download badges gets a first job, microsoft-store. It signs in with the Entra app the release already uses (MICROSOFT_STORE_TENANT_ID, MICROSOFT_STORE_CLIENT_ID, MICROSOFT_STORE_CLIENT_SECRET). It then reads StepForge's acquisitions from Partner Center's app acquisitions API: monthly rows from 2026-01-01 to today, all pages, summed. This is scripts/microsoft-store-downloads.js.
  2. It writes a shields.io endpoint badge file to a badges branch. The README badge is img.shields.io/endpoint?url=…/badges/microsoft-store-downloads.json.
  3. The sort job reads that count through the GitHub contents API, which isn't cached the way raw.githubusercontent.com is, and sorts all five badges.

The badges branch recreates itself

  • Every update is a single parentless commit, holding the JSON and a short README, force-pushed to badges. The branch never grows history.
  • When the count hasn't changed, nothing is pushed.
  • If the branch is deleted, the next run sees it's missing and pushes it again. That's the next daily run at 06:23 UTC, or straight away with Run workflow.

I tested the publish step against a local bare remote: first run creates the branch, an unchanged count is skipped, a new count stays one commit, and a deleted branch is recreated.

When Partner Center can't be read

The microsoft-store job fails, so the run shows red. The sort job still runs (if: !cancelled()), using the last count on the branch. If there's no branch and no count, the sort aborts rather than guessing zero, consistent with how unreadable ProGet feeds are handled.

Caveats

  • It counts acquisitions, meaning each Get on a Microsoft account, not every install on every PC.
  • Partner Center analytics lag a day or two.

Testing

  • npm test: 1130 pass, 0 fail. New tests/unit/microsoft-store-downloads.test.js covers the token request, the acquisition query and paging, the error messages (which never include the secret), the badge JSON, the README badge URL and the workflow wiring. download-badges.test.js covers the new count source.
  • actionlint (with shellcheck) is clean.
  • The analytics call itself can only run in Actions with the real keys. I'll trigger the workflow from this branch to confirm it before merge.

Microsoft publishes no public download count, so the daily Sort
download badges workflow gains a first job that reads StepForge's total
Store acquisitions from Partner Center's analytics API, with the Entra
app the release already uses (scripts/microsoft-store-downloads.js),
and writes a shields.io endpoint file to a badges branch.

The branch is always one parentless commit, rebuilt and force-pushed
only when the count changes, so it never grows and comes back on the
next run if it is deleted. The sort job reads the count from that
branch through the contents API and still runs, with the last published
count, when Partner Center can't be read.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant