Skip to content
Merged
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
108 changes: 85 additions & 23 deletions .github/workflows/clone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: GitHub Clone Count Update Everyday

on:
schedule:
- cron: "0 */24 * * *"
- cron: "0 0 * * *"
workflow_dispatch:

jobs:
Expand All @@ -13,69 +13,131 @@ jobs:

steps:
- uses: actions/checkout@v6

- name: gh login
run: echo "${{ secrets.SECRET_TOKEN }}" | gh auth login --with-token

- name: parse latest clone count
run: |
curl --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \
set -euo pipefail
if ! curl -f --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/traffic/clones \
> clone.json
"https://api.github.com/repos/${{ github.repository }}/traffic/clones" \
> clone.json; then
echo "Error: Failed to fetch clone statistics"
exit 1
fi
- name: create gist and download previous count
id: set_id
run: |
set -euo pipefail
if gh secret list | grep -q "GIST_ID"
then
echo "GIST_ID found"
echo "GIST=${{ secrets.GIST_ID }}" >> $GITHUB_OUTPUT
curl https://gist.githubusercontent.com/${{ github.actor }}/${{ secrets.GIST_ID }}/raw/clone.json > clone_before.json
if cat clone_before.json | grep '404: Not Found'; then
curl -f "https://gist.githubusercontent.com/${{ github.actor }}/${{ secrets.GIST_ID }}/raw/clone.json" > clone_before.json || true
if grep -q '404: Not Found' clone_before.json 2>/dev/null || [ ! -s clone_before.json ]; then
echo "GIST_ID not valid anymore. Creating another gist..."
gist_id=$(gh gist create clone.json | awk -F / '{print $NF}')
echo $gist_id | gh secret set GIST_ID
if [ -z "$gist_id" ]; then
echo "Error: Failed to create gist"
exit 1
fi
echo "$gist_id" | gh secret set GIST_ID
echo "GIST=$gist_id" >> $GITHUB_OUTPUT
cp clone.json clone_before.json
git rm --ignore-unmatch CLONE.md
git rm --ignore-unmatch CLONE.md || true
fi
else
echo "GIST_ID not found. Creating a gist..."
gist_id=$(gh gist create clone.json | awk -F / '{print $NF}')
echo $gist_id | gh secret set GIST_ID
if [ -z "$gist_id" ]; then
echo "Error: Failed to create gist"
exit 1
fi
echo "$gist_id" | gh secret set GIST_ID
echo "GIST=$gist_id" >> $GITHUB_OUTPUT
cp clone.json clone_before.json
fi
- name: update clone.json
run: |
curl https://raw.githubusercontent.com/nathanthaler/github-clone-count-badge/master/main.py > main.py
python3 main.py
set -euo pipefail
python3 << 'EOF'
import json

# Read current clone data from GitHub API
with open('clone.json', 'r') as fh:
now = json.load(fh)

# Read previous accumulated data
with open('clone_before.json', 'r') as fh:
before = json.load(fh)

# Create timestamp index for efficient lookup
timestamps = {before['clones'][i]['timestamp']: i for i in range(len(before['clones']))}

# Start with previous data and merge in new data
latest = dict(before)
for i in range(len(now['clones'])):
timestamp = now['clones'][i]['timestamp']
if timestamp in timestamps:
# Update existing timestamp with new data
latest['clones'][timestamps[timestamp]] = now['clones'][i]
else:
# Add new timestamp
latest['clones'].append(now['clones'][i])

# Recalculate totals from all clones
latest['count'] = sum(map(lambda x: int(x['count']), latest['clones']))
latest['uniques'] = sum(map(lambda x: int(x['uniques']), latest['clones']))

# Aggregate old data by month if we have more than 100 timestamps
if len(timestamps) > 100:
remove_this = []
clones = latest['clones']
for i in range(len(timestamps) - 35):
clones[i]['timestamp'] = clones[i]['timestamp'][:7] # Truncate to YYYY-MM
if clones[i]['timestamp'] == clones[i+1]['timestamp'][:7]:
clones[i+1]['count'] += clones[i]['count']
clones[i+1]['uniques'] += clones[i]['uniques']
remove_this.append(clones[i])

for item in remove_this:
clones.remove(item)

# Write updated data back
with open('clone.json', 'w', encoding='utf-8') as fh:
json.dump(latest, fh, ensure_ascii=False, indent=4)
EOF
- name: Update gist with latest count
run: |
set -euo pipefail
content=$(sed -e 's/\\/\\\\/g' -e 's/\t/\\t/g' -e 's/\"/\\"/g' -e 's/\r//g' "clone.json" | sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g')
echo '{"description": "${{ github.repository }} clone statistics", "files": {"clone.json": {"content": "'"$content"'"}}}' > post_clone.json
curl -s -X PATCH \
if ! curl -f -s -X PATCH \
--user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \
-H "Content-Type: application/json" \
-d @post_clone.json https://api.github.com/gists/${{ steps.set_id.outputs.GIST }} > /dev/null 2>&1
-d @post_clone.json "https://api.github.com/gists/${{ steps.set_id.outputs.GIST }}" > /dev/null; then
echo "Error: Failed to update gist"
exit 1
fi
if [ ! -f CLONE.md ]; then
shields="https://img.shields.io/badge/dynamic/json?color=success&label=Clone&query=count&url="
url="https://gist.githubusercontent.com/${{ github.actor }}/${{ steps.set_id.outputs.GIST }}/raw/clone.json"
repo="https://gist.githubusercontent.com/${{ github.actor }}/${{ steps.set_id.outputs.GIST }}/raw/clone.json"
echo ''> CLONE.md
echo '
**Markdown**
```markdown' >> CLONE.md
echo "[![GitHub Clones]($shields$url&logo=github)]($repo)" >> CLONE.md
echo ```' >> CLONE.md

echo '' > CLONE.md
echo '**Markdown**' >> CLONE.md
echo '```markdown' >> CLONE.md
echo "[![GitHub Clones](${shields}${url}&logo=github)](${repo})" >> CLONE.md
echo '```' >> CLONE.md

git add CLONE.md
git config --global user.name "GitHub Action"
git config --global user.email "action@github.com"
git commit -m "create clone count badge"
fi
- name: Push
uses: ad-m/github-push-action@master
uses: ad-m/github-push-action@v0.8.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}