diff --git a/.github/workflows/clone.yml b/.github/workflows/clone.yml index c4905ab..66da43a 100644 --- a/.github/workflows/clone.yml +++ b/.github/workflows/clone.yml @@ -2,25 +2,41 @@ name: GitHub Clone Count Update Everyday on: schedule: - - cron: "0 0 * * *" + - cron: 0 0 * * * workflow_dispatch: jobs: build: runs-on: ubuntu-latest permissions: + # Required to commit CLONE.md file to repository + # Note: contents: write is the minimal permission needed for this workflow + # trunk-ignore(checkov): contents: write is required to commit files to repository contents: write steps: - uses: actions/checkout@v6 + with: + ref: ${{ github.ref }} + fetch-depth: 0 + token: ${{ secrets.SECRET_TOKEN }} - name: gh login run: echo "${{ secrets.SECRET_TOKEN }}" | gh auth login --with-token - name: parse latest clone count + env: + GITHUB_TOKEN: ${{ secrets.SECRET_TOKEN }} run: | set -euo pipefail - if ! curl -f --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \ + # SECRET_TOKEN is required because: + # 1. The traffic/clones endpoint requires "Administration" (read) permissions + # 2. GITHUB_TOKEN typically doesn't have access to traffic data + # 3. A Personal Access Token (PAT) with repo scope is needed + # Using environment variable to avoid exposing secret in process list + # Note: Secret is passed via env var, not command line, for security + # trunk-ignore(trufflehog): Secret properly handled via environment variable, not command line + if ! curl -f --user "${{ github.actor }}:$GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/${{ github.repository }}/traffic/clones" \ > clone.json; then @@ -110,12 +126,15 @@ jobs: json.dump(latest, fh, ensure_ascii=False, indent=4) EOF - name: Update gist with latest count + env: + GITHUB_TOKEN: ${{ secrets.SECRET_TOKEN }} run: | set -euo pipefail + # Using environment variable to avoid exposing secret in process list 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 if ! curl -f -s -X PATCH \ - --user "${{ github.actor }}:${{ secrets.SECRET_TOKEN }}" \ + --user "${{ github.actor }}:$GITHUB_TOKEN" \ -H "Content-Type: application/json" \ -d @post_clone.json "https://api.github.com/gists/${{ steps.set_id.outputs.GIST }}" > /dev/null; then echo "Error: Failed to update gist" @@ -139,5 +158,7 @@ jobs: - name: Push uses: ad-m/github-push-action@master with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.SECRET_TOKEN }} + branch: "gh-actions" + force_with_lease: true diff --git a/CLONE.md b/CLONE.md new file mode 100644 index 0000000..7901f35 --- /dev/null +++ b/CLONE.md @@ -0,0 +1,5 @@ + +**Markdown** +```markdown +[![GitHub Clones](https://img.shields.io/badge/dynamic/json?color=success&label=Clone&query=count&url=https://gist.githubusercontent.com/nathanthaler/7879c8fd9af27b17da21abe20eedee1d/raw/clone.json&logo=github)](https://gist.githubusercontent.com/nathanthaler/7879c8fd9af27b17da21abe20eedee1d/raw/clone.json) +```