chore: rename the project to ghglance

The Marketplace rejects ghstats as an action name, so the repo, Go module,
binary, and action share the name ghglance instead. The demo workflow keeps
reading the existing GHSTATS_TOKEN repo secret.
This commit is contained in:
tiennm99 committed 2026-10-03 13:38:15 +07:00
1 parent 8c1f139990
commit 3fc8a59de6
102 files changed
+238 -173

No files matched your search

+6 -6
View File
@@ -27,8 +27,8 @@ jobs:
go-version: "1.26" go-version: "1.26"
cache: true cache: true
- name: Build ghstats - name: Build ghglance
run: go build -trimpath -ldflags="-s -w" -o ghstats . run: go build -trimpath -ldflags="-s -w" -o ghglance .
- name: Render every card for every theme - name: Render every card for every theme
env: env:
@@ -36,7 +36,7 @@ jobs:
run: | run: |
rm -rf demo rm -rf demo
mkdir -p demo mkdir -p demo
./ghstats \ ./ghglance \
-user "${{ github.repository_owner }}" \ -user "${{ github.repository_owner }}" \
-themes all \ -themes all \
-tz Asia/Saigon \ -tz Asia/Saigon \
@@ -49,11 +49,11 @@ jobs:
OWNER: ${{ github.repository_owner }} OWNER: ${{ github.repository_owner }}
REPO: ${{ github.repository }} REPO: ${{ github.repository }}
run: | run: |
themes=$(./ghstats -list-themes) themes=$(./ghglance -list-themes)
# Lightweight index so readers don't have to load ~975 images at once. # Lightweight index so readers don't have to load ~975 images at once.
{ {
echo "# ghstats demo gallery" echo "# ghglance demo gallery"
echo echo
echo "Every card rendered for [\`$OWNER\`](https://github.com/$OWNER) in every supported theme. Click a theme to open its gallery page — each page embeds 16 SVGs, so only the theme you're reviewing is fetched." echo "Every card rendered for [\`$OWNER\`](https://github.com/$OWNER) in every supported theme. Click a theme to open its gallery page — each page embeds 16 SVGs, so only the theme you're reviewing is fetched."
echo echo
@@ -87,7 +87,7 @@ jobs:
printf '</tr>\n' printf '</tr>\n'
} }
{ {
printf '# ghstats — %s\n\n' "$theme" printf '# ghglance — %s\n\n' "$theme"
printf '[← back to index](../README.md)\n\n' printf '[← back to index](../README.md)\n\n'
printf 'Rendered for [`%s`](https://github.com/%s). 16 SVGs laid out to ' "$OWNER" "$OWNER" printf 'Rendered for [`%s`](https://github.com/%s). 16 SVGs laid out to ' "$OWNER" "$OWNER"
printf 'match the author profile README table.\n\n' printf 'match the author profile README table.\n\n'
+6 -6
View File
@@ -79,22 +79,22 @@ jobs:
GOARCH: ${{ matrix.goarch }} GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0" CGO_ENABLED: "0"
run: | run: |
bin=ghstats bin=ghglance
[ "$GOOS" = windows ] && bin=ghstats.exe [ "$GOOS" = windows ] && bin=ghglance.exe
mkdir -p dist mkdir -p dist
go build -trimpath -ldflags="-s -w" -o "dist/$bin" . go build -trimpath -ldflags="-s -w" -o "dist/$bin" .
cd dist cd dist
if [ "$GOOS" = windows ]; then if [ "$GOOS" = windows ]; then
zip "ghstats_${GOOS}_${GOARCH}.zip" "$bin" zip "ghglance_${GOOS}_${GOARCH}.zip" "$bin"
else else
tar -czf "ghstats_${GOOS}_${GOARCH}.tar.gz" "$bin" tar -czf "ghglance_${GOOS}_${GOARCH}.tar.gz" "$bin"
fi fi
- uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with: with:
files: dist/ghstats_*.* files: dist/ghglance_*.*
# Move the floating major-version tag (e.g. v1) to this release's commit so # Move the floating major-version tag (e.g. v1) to this release's commit so
# consumers using `uses: tiennm99/ghstats@v1` automatically pick up each new # consumers using `uses: tiennm99/ghglance@v1` automatically pick up each new
# minor/patch release. Force-push is expected here — that's the point of a # minor/patch release. Force-push is expected here — that's the point of a
# floating tag. # floating tag.
update-major-tag: update-major-tag:
+2 -2
View File
@@ -1,4 +1,4 @@
# ghstats # ghglance
Single-binary Go CLI that renders GitHub profile cards as SVG, wrapped by a Single-binary Go CLI that renders GitHub profile cards as SVG, wrapped by a
published GitHub Action. `main.go` parses flags → `internal/github` fetches → published GitHub Action. `main.go` parses flags → `internal/github` fetches →
@@ -15,7 +15,7 @@ them ships a half-wired feature or a README that lies:
3. `entrypoint.sh` — the `INPUT_*` → flag translation 3. `entrypoint.sh` — the `INPUT_*` → flag translation
4. `README.md` — **both** reference tables (Action inputs, CLI flags) **and 4. `README.md` — **both** reference tables (Action inputs, CLI flags) **and
the runnable examples**: the workflow YAML under "Use as a GitHub Action" the runnable examples**: the workflow YAML under "Use as a GitHub Action"
and the `ghstats …` command under "Use as a CLI" and the `ghglance …` command under "Use as a CLI"
5. `docs/system-architecture.md` — when the knob changes the fetch pipeline 5. `docs/system-architecture.md` — when the knob changes the fetch pipeline
or its query cost or its query cost
+2 -2
View File
@@ -3,11 +3,11 @@ WORKDIR /src
COPY go.mod ./ COPY go.mod ./
RUN go mod download || true RUN go mod download || true
COPY . . COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/ghstats . RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/ghglance .
FROM alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d FROM alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d
RUN apk add --no-cache ca-certificates tzdata git RUN apk add --no-cache ca-certificates tzdata git
COPY --from=build /out/ghstats /usr/local/bin/ghstats COPY --from=build /out/ghglance /usr/local/bin/ghglance
COPY entrypoint.sh /entrypoint.sh COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"] ENTRYPOINT ["/entrypoint.sh"]
+20 -20
View File
@@ -1,16 +1,16 @@
# ghstats # ghglance
> Generate SVG cards summarizing a GitHub user's profile — written in Go. > Generate SVG cards summarizing a GitHub user's profile — written in Go.
[![Marketplace](https://img.shields.io/badge/Marketplace-ghstats-2f81f7?logo=github)](https://github.com/marketplace/actions/ghstats) [![Marketplace](https://img.shields.io/badge/Marketplace-ghglance-2f81f7?logo=github)](https://github.com/marketplace/actions/ghglance)
[![Release](https://img.shields.io/github/v/release/tiennm99/ghstats?color=blue)](https://github.com/tiennm99/ghstats/releases/latest) [![Release](https://img.shields.io/github/v/release/tiennm99/ghglance?color=blue)](https://github.com/tiennm99/ghglance/releases/latest)
[![License](https://img.shields.io/github/license/tiennm99/ghstats?color=green)](./LICENSE) [![License](https://img.shields.io/github/license/tiennm99/ghglance?color=green)](./LICENSE)
`ghstats` is a single-binary CLI (and a GitHub Action wrapping it) that fetches `ghglance` is a single-binary CLI (and a GitHub Action wrapping it) that fetches
data for a GitHub user and writes a themed set of SVGs you can embed in your data for a GitHub user and writes a themed set of SVGs you can embed in your
profile README. profile README.
Marketplace listing: **[ghstats](https://github.com/marketplace/actions/ghstats)** · Source: [`tiennm99/ghstats`](https://github.com/tiennm99/ghstats) Marketplace listing: **[ghglance](https://github.com/marketplace/actions/ghglance)** · Source: [`tiennm99/ghglance`](https://github.com/tiennm99/ghglance)
Cards rendered: Cards rendered:
@@ -55,15 +55,15 @@ Live render against the author's profile, committed by [`.github/workflows/demo.
## In the wild ## In the wild
- [**tiennm99/tiennm99**](https://github.com/tiennm99/tiennm99) — author's profile README, refreshed daily via `tiennm99/ghstats@v1`. Two-per-row layout, dracula theme. - [**tiennm99/tiennm99**](https://github.com/tiennm99/tiennm99) — author's profile README, refreshed daily via `tiennm99/ghglance@v1`. Two-per-row layout, dracula theme.
## Use as a GitHub Action (recommended) ## Use as a GitHub Action (recommended)
Drop this in `.github/workflows/ghstats.yml` in your **profile repo** (the one Drop this in `.github/workflows/ghglance.yml` in your **profile repo** (the one
named after your username): named after your username):
```yaml ```yaml
name: ghstats name: ghglance
on: on:
schedule: schedule:
@@ -78,10 +78,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- uses: tiennm99/ghstats@v1 - uses: tiennm99/ghglance@v1
with: with:
user: ${{ github.repository_owner }} user: ${{ github.repository_owner }}
token: ${{ secrets.GHSTATS_TOKEN }} # classic PAT with read:user + repo token: ${{ secrets.GHGLANCE_TOKEN }} # classic PAT with read:user + repo
themes: dracula,github_dark,tokyonight themes: dracula,github_dark,tokyonight
tz: Asia/Saigon tz: Asia/Saigon
include_forks: "true" include_forks: "true"
@@ -127,7 +127,7 @@ Then embed the cards in your `README.md`:
| `include_private` | `true` | Include private repos (requires PAT with `repo` scope; silently no-op otherwise) | | `include_private` | `true` | Include private repos (requires PAT with `repo` scope; silently no-op otherwise) |
| `include_org_repos`| `false` | Count org-owned repos you administer toward stars, repo count, languages, top-starred (needs `read:org`) | | `include_org_repos`| `false` | Count org-owned repos you administer toward stars, repo count, languages, top-starred (needs `read:org`) |
| `commit_changes` | `false` | Commit generated cards back to the repo | | `commit_changes` | `false` | Commit generated cards back to the repo |
| `commit_message` | `chore: update ghstats cards` | Commit message | | `commit_message` | `chore: update ghglance cards` | Commit message |
| `commit_branch` | *(current ref)* | Target branch for auto-commit | | `commit_branch` | *(current ref)* | Target branch for auto-commit |
| `author_name` | `github-actions[bot]` | Commit author | | `author_name` | `github-actions[bot]` | Commit author |
| `author_email` | `…@users.noreply.github.com` | Commit email | | `author_email` | `…@users.noreply.github.com` | Commit email |
@@ -135,28 +135,28 @@ Then embed the cards in your `README.md`:
## Use as a CLI ## Use as a CLI
```sh ```sh
go install github.com/tiennm99/ghstats@latest go install github.com/tiennm99/ghglance@latest
``` ```
Or build from source: Or build from source:
```sh ```sh
git clone https://github.com/tiennm99/ghstats git clone https://github.com/tiennm99/ghglance
cd ghstats cd ghglance
go build -o ghstats . go build -o ghglance .
``` ```
Then: Then:
```sh ```sh
export GITHUB_TOKEN=ghp_xxx export GITHUB_TOKEN=ghp_xxx
ghstats -user tiennm99 -themes dracula,github_dark -tz Asia/Saigon -out output ghglance -user tiennm99 -themes dracula,github_dark -tz Asia/Saigon -out output
``` ```
Add `-include-org-repos` to also count org-owned repos you administer: Add `-include-org-repos` to also count org-owned repos you administer:
```sh ```sh
ghstats -user tiennm99 -themes dracula -include-org-repos -out output ghglance -user tiennm99 -themes dracula -include-org-repos -out output
``` ```
| Flag | Default | Description | | Flag | Default | Description |
@@ -191,7 +191,7 @@ ghstats -user tiennm99 -themes dracula -include-org-repos -out output
## Themes ## Themes
Run `ghstats -list-themes` for the full list (65 themes ported from Run `ghglance -list-themes` for the full list (65 themes ported from
github-profile-summary-cards). Built-ins include `default`, `dark`, `dracula`, github-profile-summary-cards). Built-ins include `default`, `dark`, `dracula`,
`github`, `github_dark`, `tokyonight`, `onedark`, `nord_dark`, `nord_bright`, `github`, `github_dark`, `tokyonight`, `onedark`, `nord_dark`, `nord_bright`,
`gruvbox`, `radical`, `synthwave`, `monokai`, `solarized`, `solarized_dark`, `gruvbox`, `radical`, `synthwave`, `monokai`, `solarized`, `solarized_dark`,
@@ -230,7 +230,7 @@ reference render of every card in every theme, see the CI-built
The default `${{ github.token }}` can read public user data but will not see The default `${{ github.token }}` can read public user data but will not see
your private-repo commits. For accurate stats, create a **classic** personal your private-repo commits. For accurate stats, create a **classic** personal
access token with `read:user` and `repo`, save it as a repo secret (e.g. access token with `read:user` and `repo`, save it as a repo secret (e.g.
`GHSTATS_TOKEN`), and pass it via the `token` input. `include_private` `GHGLANCE_TOKEN`), and pass it via the `token` input. `include_private`
defaults to `true` so those commits are counted automatically once the token defaults to `true` so those commits are counted automatically once the token
has `repo` scope; pass `include_private: "false"` if you want to keep private has `repo` scope; pass `include_private: "false"` if you want to keep private
work out of the rendered cards even when the token can see it. work out of the rendered cards even when the token can see it.
+2 -2
View File
@@ -1,4 +1,4 @@
name: ghstats name: ghglance
description: Generate GitHub profile summary SVG cards (profile, languages, stats, productive time, contributions) description: Generate GitHub profile summary SVG cards (profile, languages, stats, productive time, contributions)
author: tiennm99 author: tiennm99
branding: branding:
@@ -61,7 +61,7 @@ inputs:
commit_message: commit_message:
description: Commit message used when commit_changes is true description: Commit message used when commit_changes is true
required: false required: false
default: "chore: update ghstats cards" default: "chore: update ghglance cards"
commit_branch: commit_branch:
description: Branch to commit to (defaults to the current ref) description: Branch to commit to (defaults to the current ref)
required: false required: false
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — 2077 # ghglance — 2077
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats demo gallery # ghglance demo gallery
Every card rendered for [`tiennm99`](https://github.com/tiennm99) in every supported theme. Click a theme to open its gallery page — each page embeds 16 SVGs, so only the theme you're reviewing is fetched. Every card rendered for [`tiennm99`](https://github.com/tiennm99) in every supported theme. Click a theme to open its gallery page — each page embeds 16 SVGs, so only the theme you're reviewing is fetched.
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — algolia # ghglance — algolia
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — apprentice # ghglance — apprentice
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — aura # ghglance — aura
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — aura_dark # ghglance — aura_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — ayu_mirage # ghglance — ayu_mirage
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — bear # ghglance — bear
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — blue_green # ghglance — blue_green
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — blueberry # ghglance — blueberry
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — buefy # ghglance — buefy
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — calm # ghglance — calm
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — chartreuse_dark # ghglance — chartreuse_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — city_lights # ghglance — city_lights
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — cobalt # ghglance — cobalt
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — cobalt2 # ghglance — cobalt2
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — codeSTACKr # ghglance — codeSTACKr
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — darcula # ghglance — darcula
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — dark # ghglance — dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — date_night # ghglance — date_night
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — default # ghglance — default
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — discord_old_blurple # ghglance — discord_old_blurple
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — dracula # ghglance — dracula
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — flag_india # ghglance — flag_india
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — github # ghglance — github
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — github_dark # ghglance — github_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — gotham # ghglance — gotham
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — graywhite # ghglance — graywhite
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — great_gatsby # ghglance — great_gatsby
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — gruvbox # ghglance — gruvbox
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — highcontrast # ghglance — highcontrast
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — holi # ghglance — holi
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — jolly # ghglance — jolly
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — kacho_ga # ghglance — kacho_ga
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — maroongold # ghglance — maroongold
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — material_palenight # ghglance — material_palenight
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — merko # ghglance — merko
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — midnight_purple # ghglance — midnight_purple
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — moltack # ghglance — moltack
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — monokai # ghglance — monokai
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — moonlight # ghglance — moonlight
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — nightowl # ghglance — nightowl
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — noctis_minimus # ghglance — noctis_minimus
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — nord_bright # ghglance — nord_bright
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — nord_dark # ghglance — nord_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — ocean_dark # ghglance — ocean_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — omni # ghglance — omni
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — onedark # ghglance — onedark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — outrun # ghglance — outrun
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — panda # ghglance — panda
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — prussian # ghglance — prussian
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — radical # ghglance — radical
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — react # ghglance — react
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — rose_pine # ghglance — rose_pine
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — shades_of_purple # ghglance — shades_of_purple
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — slateorange # ghglance — slateorange
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — solarized # ghglance — solarized
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — solarized_dark # ghglance — solarized_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — swift # ghglance — swift
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — synthwave # ghglance — synthwave
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — tokyonight # ghglance — tokyonight
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — transparent # ghglance — transparent
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — vision_friendly_dark # ghglance — vision_friendly_dark
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — vue # ghglance — vue
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — yeblu # ghglance — yeblu
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -1,4 +1,4 @@
# ghstats — zenburn # ghglance — zenburn
[← back to index](../README.md) [← back to index](../README.md)
+1 -1
View File
@@ -66,7 +66,7 @@ Never write comments that describe what well-named code does (`// increment coun
## Testing ## Testing
- Unit tests in the same package, no mocking of http.Client — we test rendering and pure helpers. - Unit tests in the same package, no mocking of http.Client — we test rendering and pure helpers.
- Network tests are omitted; integration verification is manual (`./ghstats -token ...`). - Network tests are omitted; integration verification is manual (`./ghglance -token ...`).
- `go vet ./...` clean before every commit. - `go vet ./...` clean before every commit.
## Commit conventions ## Commit conventions
+1 -1
View File
@@ -3,7 +3,7 @@
## Layout ## Layout
``` ```
ghstats/ ghglance/
├── main.go # CLI entry point; wires flags → fetchers → renderers ├── main.go # CLI entry point; wires flags → fetchers → renderers
├── action.yml # GitHub Action metadata ├── action.yml # GitHub Action metadata
├── entrypoint.sh # Action runtime; maps INPUT_* env → CLI flags ├── entrypoint.sh # Action runtime; maps INPUT_* env → CLI flags
+13 -13
View File
@@ -6,10 +6,10 @@ Three consumption paths: **GitHub Action**, **prebuilt binaries**, **go install*
### Workflow template ### Workflow template
File: `.github/workflows/ghstats.yml` in your profile repo. File: `.github/workflows/ghglance.yml` in your profile repo.
```yaml ```yaml
name: ghstats name: ghglance
on: on:
schedule: schedule:
@@ -24,10 +24,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- uses: tiennm99/ghstats@v1 - uses: tiennm99/ghglance@v1
with: with:
user: ${{ github.repository_owner }} user: ${{ github.repository_owner }}
token: ${{ secrets.GHSTATS_TOKEN }} token: ${{ secrets.GHGLANCE_TOKEN }}
themes: dracula,github_dark,tokyonight themes: dracula,github_dark,tokyonight
tz: Asia/Saigon tz: Asia/Saigon
# start_of_week: monday # optional; default sunday — rotates heatmap rows + weekday bars # start_of_week: monday # optional; default sunday — rotates heatmap rows + weekday bars
@@ -38,7 +38,7 @@ jobs:
### Required secrets ### Required secrets
`GHSTATS_TOKEN`: a **classic** personal access token with at minimum: `GHGLANCE_TOKEN`: a **classic** personal access token with at minimum:
| Scope | Needed for | | Scope | Needed for |
| --- | --- | | --- | --- |
@@ -47,7 +47,7 @@ jobs:
Fine-grained PATs and the default `${{ github.token }}` lack the introspection scope for contribution calendars in many orgs, so a classic PAT is recommended. Fine-grained PATs and the default `${{ github.token }}` lack the introspection scope for contribution calendars in many orgs, so a classic PAT is recommended.
Create one at <https://github.com/settings/tokens> → "Generate new token (classic)" → select `read:user` (+ `repo` if needed) → save as repo secret `GHSTATS_TOKEN`. Create one at <https://github.com/settings/tokens> → "Generate new token (classic)" → select `read:user` (+ `repo` if needed) → save as repo secret `GHGLANCE_TOKEN`.
### Embedding in README ### Embedding in README
@@ -84,29 +84,29 @@ Install:
```sh ```sh
# Linux x86_64 example # Linux x86_64 example
curl -L https://github.com/tiennm99/ghstats/releases/latest/download/ghstats_linux_amd64.tar.gz \ curl -L https://github.com/tiennm99/ghglance/releases/latest/download/ghglance_linux_amd64.tar.gz \
| tar xz | tar xz
./ghstats -user YOUR_USERNAME ./ghglance -user YOUR_USERNAME
``` ```
## 3. go install ## 3. go install
```sh ```sh
go install github.com/tiennm99/ghstats@latest go install github.com/tiennm99/ghglance@latest
``` ```
Requires Go 1.26+. Puts the binary in `$(go env GOPATH)/bin`. Requires Go 1.26+. Puts the binary in `$(go env GOPATH)/bin`.
## Docker image ## Docker image
Published to `ghcr.io/tiennm99/ghstats:<tag>` on each `v*` release via `.github/workflows/release.yml` (buildx, multi-tag: exact version, major.minor, major, latest). Published to `ghcr.io/tiennm99/ghglance:<tag>` on each `v*` release via `.github/workflows/release.yml` (buildx, multi-tag: exact version, major.minor, major, latest).
The Action itself uses a runner-built image by default (`image: Dockerfile` in `action.yml`). To switch to the pre-built image for faster cold starts, edit `action.yml`: The Action itself uses a runner-built image by default (`image: Dockerfile` in `action.yml`). To switch to the pre-built image for faster cold starts, edit `action.yml`:
```yaml ```yaml
runs: runs:
using: docker using: docker
image: docker://ghcr.io/tiennm99/ghstats:v1 image: docker://ghcr.io/tiennm99/ghglance:v1
``` ```
## Release process ## Release process
@@ -117,12 +117,12 @@ runs:
3. On green, GHCR push + cross-platform binary artifacts happen automatically. 3. On green, GHCR push + cross-platform binary artifacts happen automatically.
4. The `update-major-tag` job force-moves the floating major tag (e.g. `v1`) 4. The `update-major-tag` job force-moves the floating major tag (e.g. `v1`)
to this release's commit after test + docker + binaries all pass. to this release's commit after test + docker + binaries all pass.
Consumers pinned to `tiennm99/ghstats@v1` pick up the release on their Consumers pinned to `tiennm99/ghglance@v1` pick up the release on their
next Action run without a workflow edit. next Action run without a workflow edit.
5. Docker base images and third-party actions are SHA-pinned (with version 5. Docker base images and third-party actions are SHA-pinned (with version
comments) so mutable-tag changes upstream can't rewrite a released image. comments) so mutable-tag changes upstream can't rewrite a released image.
6. **Marketplace:** the action is listed on the GitHub Marketplace as 6. **Marketplace:** the action is listed on the GitHub Marketplace as
[`ghstats`](https://github.com/marketplace/actions/ghstats); the listing [`ghglance`](https://github.com/marketplace/actions/ghglance); the listing
name comes from `name:` in `action.yml`. Publishing is a web-UI step — name comes from `name:` in `action.yml`. Publishing is a web-UI step —
edit the GitHub release and tick "Publish this Action to the GitHub edit the GitHub release and tick "Publish this Action to the GitHub
Marketplace" — since `action-gh-release` cannot publish it. Marketplace" — since `action-gh-release` cannot publish it.
+1 -1
View File
@@ -1,6 +1,6 @@
# Design Guidelines # Design Guidelines
Visual conventions for ghstats SVG cards. All cards share a single frame shape so they stack cleanly in a README — two cards sit side-by-side inside GitHub's ~816 px content column. Visual conventions for ghglance SVG cards. All cards share a single frame shape so they stack cleanly in a README — two cards sit side-by-side inside GitHub's ~816 px content column.
## Card frame ## Card frame
+3 -3
View File
@@ -1,4 +1,4 @@
# ghstats — Product Development Requirements # ghglance — Product Development Requirements
## One-liner ## One-liner
@@ -13,7 +13,7 @@ Single-binary Go CLI + GitHub Action that renders 15 themed SVG cards summarisin
- WakaTime-style editor telemetry. - WakaTime-style editor telemetry.
- Cloning repos or running linguist locally (lowlighter/metrics territory). A future `-accurate-languages` mode may add per-commit REST classification; clone-mode is out of scope for v1. - Cloning repos or running linguist locally (lowlighter/metrics territory). A future `-accurate-languages` mode may add per-commit REST classification; clone-mode is out of scope for v1.
- Real-time / per-request API server. ghstats is a scheduled batch renderer. - Real-time / per-request API server. ghglance is a scheduled batch renderer.
## Value proposition vs alternatives ## Value proposition vs alternatives
@@ -22,7 +22,7 @@ Single-binary Go CLI + GitHub Action that renders 15 themed SVG cards summarisin
| anuraghazra/github-readme-stats | JS | hosted service | No (byte-size only) | | anuraghazra/github-readme-stats | JS | hosted service | No (byte-size only) |
| vn7n24fzkq/github-profile-summary-cards | TS | Action + hosted | No (primary-language-per-repo) | | vn7n24fzkq/github-profile-summary-cards | TS | Action + hosted | No (primary-language-per-repo) |
| lowlighter/metrics (indepth) | JS | Action | Yes (clones + linguist-js) | | lowlighter/metrics (indepth) | JS | Action | Yes (clones + linguist-js) |
| **ghstats** | Go | Action + CLI | Partial (byte-weighted today; REST-per-commit planned) | | **ghglance** | Go | Action + CLI | Partial (byte-weighted today; REST-per-commit planned) |
Distinguishing traits: Distinguishing traits:
- **Single binary**: no Node, no Ruby, no Docker needed for CLI usage. - **Single binary**: no Node, no Ruby, no Docker needed for CLI usage.
+5 -5
View File
@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# Entrypoint for the ghstats GitHub Action. # Entrypoint for the ghglance GitHub Action.
# Inputs are passed via INPUT_* environment variables (set by the Action runtime). # Inputs are passed via INPUT_* environment variables (set by the Action runtime).
# This script translates them into ghstats CLI flags and optionally commits the # This script translates them into ghglance CLI flags and optionally commits the
# generated SVGs back to the repository. # generated SVGs back to the repository.
set -eu set -eu
@@ -18,7 +18,7 @@ include_forks="${INPUT_INCLUDE_FORKS:-true}"
include_private="${INPUT_INCLUDE_PRIVATE:-true}" include_private="${INPUT_INCLUDE_PRIVATE:-true}"
include_org_repos="${INPUT_INCLUDE_ORG_REPOS:-false}" include_org_repos="${INPUT_INCLUDE_ORG_REPOS:-false}"
commit_changes="${INPUT_COMMIT_CHANGES:-false}" commit_changes="${INPUT_COMMIT_CHANGES:-false}"
commit_message="${INPUT_COMMIT_MESSAGE:-chore: update ghstats cards}" commit_message="${INPUT_COMMIT_MESSAGE:-chore: update ghglance cards}"
commit_branch="${INPUT_COMMIT_BRANCH:-}" commit_branch="${INPUT_COMMIT_BRANCH:-}"
author_name="${INPUT_AUTHOR_NAME:-github-actions[bot]}" author_name="${INPUT_AUTHOR_NAME:-github-actions[bot]}"
author_email="${INPUT_AUTHOR_EMAIL:-41898282+github-actions[bot]@users.noreply.github.com}" author_email="${INPUT_AUTHOR_EMAIL:-41898282+github-actions[bot]@users.noreply.github.com}"
@@ -30,8 +30,8 @@ fi
mkdir -p "$out" mkdir -p "$out"
echo "Running ghstats for user=$user themes=$themes out=$out" echo "Running ghglance for user=$user themes=$themes out=$out"
ghstats \ ghglance \
-user "$user" \ -user "$user" \
-token "$token" \ -token "$token" \
-out "$out" \ -out "$out" \
+1 -1
View File
@@ -1,3 +1,3 @@
module github.com/tiennm99/ghstats module github.com/tiennm99/ghglance
go 1.26 go 1.26
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
// Card renders one SVG for a Profile under the given theme. // Card renders one SVG for a Profile under the given theme.
+3 -3
View File
@@ -9,8 +9,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
func TestRenderAll(t *testing.T) { func TestRenderAll(t *testing.T) {
@@ -35,7 +35,7 @@ func TestRenderAll(t *testing.T) {
{Name: "Python", Color: "#3572A5", Value: 150}, {Name: "Python", Color: "#3572A5", Value: 150},
}, },
TopRepos: []github.RepoInfo{ TopRepos: []github.RepoInfo{
{Owner: "tiennm99", Name: "ghstats", Stars: 42, PrimaryLanguage: "Go", PrimaryColor: "#00ADD8"}, {Owner: "tiennm99", Name: "ghglance", Stars: 42, PrimaryLanguage: "Go", PrimaryColor: "#00ADD8"},
{Owner: "tiennm99", Name: "some-app & <tool>", Stars: 17, PrimaryLanguage: "TypeScript", PrimaryColor: "#3178c6"}, {Owner: "tiennm99", Name: "some-app & <tool>", Stars: 17, PrimaryLanguage: "TypeScript", PrimaryColor: "#3178c6"},
{Owner: "tiennm99", Name: "fork-only", Stars: 99, IsFork: true}, {Owner: "tiennm99", Name: "fork-only", Stars: 99, IsFork: true},
}, },
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type contributionsCard struct{} type contributionsCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type contributionsByYearCard struct{} type contributionsByYearCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type contributionsHeatmapCard struct{} type contributionsHeatmapCard struct{}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
) )
// GitHub's contributionCalendar is week-aligned, so a "last year" series for a // GitHub's contributionCalendar is week-aligned, so a "last year" series for a
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"math" "math"
"strings" "strings"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
// renderDonutCard draws a donut chart with a left-side legend. Shared by the // renderDonutCard draws a donut chart with a left-side legend. Shared by the
+2 -2
View File
@@ -1,8 +1,8 @@
package card package card
import ( import (
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type mostCommitLanguageCard struct{} type mostCommitLanguageCard struct{}
@@ -1,8 +1,8 @@
package card package card
import ( import (
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type mostCommitLanguageAllTimeCard struct{} type mostCommitLanguageAllTimeCard struct{}
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type productiveCard struct{} type productiveCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type productiveWeekdayCard struct{} type productiveWeekdayCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type profileCard struct{} type profileCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type recordsCard struct{} type recordsCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
// dayAt is a tiny helper so fixtures stay readable. // dayAt is a tiny helper so fixtures stay readable.
+2 -2
View File
@@ -1,8 +1,8 @@
package card package card
import ( import (
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type reposPerLanguageCard struct{} type reposPerLanguageCard struct{}
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type statsCard struct{} type statsCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type streakCard struct{} type streakCard struct{}
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
type topStarredReposCard struct{} type topStarredReposCard struct{}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/tiennm99/ghstats/internal/github" "github.com/tiennm99/ghglance/internal/github"
"github.com/tiennm99/ghstats/internal/theme" "github.com/tiennm99/ghglance/internal/theme"
) )
// TestPadToWeekGridRotatesByWeekStart checks that the leading blank pad // TestPadToWeekGridRotatesByWeekStart checks that the leading blank pad
+1 -1
View File
@@ -69,7 +69,7 @@ func (c *Client) query(ctx context.Context, q string, vars map[string]any, out a
return fmt.Errorf("new request: %w", err) return fmt.Errorf("new request: %w", err)
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "ghstats") req.Header.Set("User-Agent", "ghglance")
if c.token != "" { if c.token != "" {
req.Header.Set("Authorization", "bearer "+c.token) req.Header.Set("Authorization", "bearer "+c.token)
} }
+1 -1
View File
@@ -59,7 +59,7 @@ func TestRepoAffiliationsAndOwnership(t *testing.T) {
orgWrite := orgAdmin orgWrite := orgAdmin
orgWrite.ViewerPermission = "WRITE" orgWrite.ViewerPermission = "WRITE"
own := repoNode{Name: "ghstats"} own := repoNode{Name: "ghglance"}
own.Owner = &struct { own.Owner = &struct {
Login string `json:"login"` Login string `json:"login"`
}{Login: "tiennm99"} }{Login: "tiennm99"}
Loaded 100 of 102 files, more files were not shown because too many files have changed in this diff. Show more