@@ -2,7 +2,7 @@ name: GitHub Clone Count Update Everyday
22
33on :
44 schedule :
5- - cron : " 0 */24 * * *"
5+ - cron : " 0 0 * * *"
66 workflow_dispatch :
77
88jobs :
@@ -13,69 +13,131 @@ jobs:
1313
1414 steps :
1515 - uses : actions/checkout@v6
16-
16+
1717 - name : gh login
1818 run : echo "${{ secrets.SECRET_TOKEN }}" | gh auth login --with-token
1919
2020 - name : parse latest clone count
2121 run : |
22- curl --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \
22+ set -euo pipefail
23+ if ! curl -f --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \
2324 -H "Accept: application/vnd.github.v3+json" \
24- https://api.github.com/repos/${{ github.repository }}/traffic/clones \
25- > clone.json
25+ "https://api.github.com/repos/${{ github.repository }}/traffic/clones" \
26+ > clone.json; then
27+ echo "Error: Failed to fetch clone statistics"
28+ exit 1
29+ fi
2630 - name : create gist and download previous count
2731 id : set_id
2832 run : |
33+ set -euo pipefail
2934 if gh secret list | grep -q "GIST_ID"
3035 then
3136 echo "GIST_ID found"
3237 echo "GIST=${{ secrets.GIST_ID }}" >> $GITHUB_OUTPUT
33- curl https://gist.githubusercontent.com/${{ github.actor }}/${{ secrets.GIST_ID }}/raw/clone.json > clone_before.json
34- if cat clone_before.json | grep '404: Not Found'; then
38+ curl -f " https://gist.githubusercontent.com/${{ github.actor }}/${{ secrets.GIST_ID }}/raw/clone.json" > clone_before.json || true
39+ if grep -q '404: Not Found' clone_before.json 2>/dev/null || [ ! -s clone_before.json ] ; then
3540 echo "GIST_ID not valid anymore. Creating another gist..."
3641 gist_id=$(gh gist create clone.json | awk -F / '{print $NF}')
37- echo $gist_id | gh secret set GIST_ID
42+ if [ -z "$gist_id" ]; then
43+ echo "Error: Failed to create gist"
44+ exit 1
45+ fi
46+ echo "$gist_id" | gh secret set GIST_ID
3847 echo "GIST=$gist_id" >> $GITHUB_OUTPUT
3948 cp clone.json clone_before.json
40- git rm --ignore-unmatch CLONE.md
49+ git rm --ignore-unmatch CLONE.md || true
4150 fi
4251 else
4352 echo "GIST_ID not found. Creating a gist..."
4453 gist_id=$(gh gist create clone.json | awk -F / '{print $NF}')
45- echo $gist_id | gh secret set GIST_ID
54+ if [ -z "$gist_id" ]; then
55+ echo "Error: Failed to create gist"
56+ exit 1
57+ fi
58+ echo "$gist_id" | gh secret set GIST_ID
4659 echo "GIST=$gist_id" >> $GITHUB_OUTPUT
4760 cp clone.json clone_before.json
4861 fi
4962 - name : update clone.json
5063 run : |
51- curl https://raw.githubusercontent.com/nathanthaler/github-clone-count-badge/master/main.py > main.py
52- python3 main.py
64+ set -euo pipefail
65+ python3 << 'EOF'
66+ import json
67+
68+ # Read current clone data from GitHub API
69+ with open('clone.json', 'r') as fh:
70+ now = json.load(fh)
71+
72+ # Read previous accumulated data
73+ with open('clone_before.json', 'r') as fh:
74+ before = json.load(fh)
75+
76+ # Create timestamp index for efficient lookup
77+ timestamps = {before['clones'][i]['timestamp']: i for i in range(len(before['clones']))}
78+
79+ # Start with previous data and merge in new data
80+ latest = dict(before)
81+ for i in range(len(now['clones'])):
82+ timestamp = now['clones'][i]['timestamp']
83+ if timestamp in timestamps:
84+ # Update existing timestamp with new data
85+ latest['clones'][timestamps[timestamp]] = now['clones'][i]
86+ else:
87+ # Add new timestamp
88+ latest['clones'].append(now['clones'][i])
89+
90+ # Recalculate totals from all clones
91+ latest['count'] = sum(map(lambda x: int(x['count']), latest['clones']))
92+ latest['uniques'] = sum(map(lambda x: int(x['uniques']), latest['clones']))
93+
94+ # Aggregate old data by month if we have more than 100 timestamps
95+ if len(timestamps) > 100:
96+ remove_this = []
97+ clones = latest['clones']
98+ for i in range(len(timestamps) - 35):
99+ clones[i]['timestamp'] = clones[i]['timestamp'][:7] # Truncate to YYYY-MM
100+ if clones[i]['timestamp'] == clones[i+1]['timestamp'][:7]:
101+ clones[i+1]['count'] += clones[i]['count']
102+ clones[i+1]['uniques'] += clones[i]['uniques']
103+ remove_this.append(clones[i])
104+
105+ for item in remove_this:
106+ clones.remove(item)
107+
108+ # Write updated data back
109+ with open('clone.json', 'w', encoding='utf-8') as fh:
110+ json.dump(latest, fh, ensure_ascii=False, indent=4)
111+ EOF
53112 - name : Update gist with latest count
54113 run : |
114+ set -euo pipefail
55115 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')
56116 echo '{"description": "${{ github.repository }} clone statistics", "files": {"clone.json": {"content": "'"$content"'"}}}' > post_clone.json
57- curl -s -X PATCH \
117+ if ! curl -f -s -X PATCH \
58118 --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \
59119 -H "Content-Type: application/json" \
60- -d @post_clone.json https://api.github.com/gists/${{ steps.set_id.outputs.GIST }} > /dev/null 2>&1
120+ -d @post_clone.json "https://api.github.com/gists/${{ steps.set_id.outputs.GIST }}" > /dev/null; then
121+ echo "Error: Failed to update gist"
122+ exit 1
123+ fi
61124 if [ ! -f CLONE.md ]; then
62125 shields="https://img.shields.io/badge/dynamic/json?color=success&label=Clone&query=count&url="
63126 url="https://gist.githubusercontent.com/${{ github.actor }}/${{ steps.set_id.outputs.GIST }}/raw/clone.json"
64127 repo="https://gist.githubusercontent.com/${{ github.actor }}/${{ steps.set_id.outputs.GIST }}/raw/clone.json"
65- echo ''> CLONE.md
66- echo '
67- **Markdown**
68- ```markdown' >> CLONE.md
69- echo "[]($repo)" >> CLONE.md
70- echo ```' >> CLONE.md
71-
128+ echo '' > CLONE.md
129+ echo '**Markdown**' >> CLONE.md
130+ echo '```markdown' >> CLONE.md
131+ echo "[](${repo})" >> CLONE.md
132+ echo '```' >> CLONE.md
133+
72134 git add CLONE.md
73135 git config --global user.name "GitHub Action"
74136 git config --global user.email "action@github.com"
75137 git commit -m "create clone count badge"
76138 fi
77139 - name : Push
78- uses : ad-m/github-push-action@master
140+ uses : ad-m/github-push-action@v0.8.0
79141 with :
80142 github_token : ${{ secrets.GITHUB_TOKEN }}
81-
143+
0 commit comments