github-metrics #109
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: github-metrics | |
| on: | |
| schedule: | |
| - cron: '15 0 * * *' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| metrics: | |
| name: Generate issue and PR activity SVG | |
| if: github.repository == 'nexu-io/open-design' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6.0.2 | |
| - name: Generate Open Design bot token | |
| id: open-design-bot-token | |
| uses: actions/create-github-app-token@v3.2.0 | |
| with: | |
| client-id: ${{ secrets.BOT_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }} | |
| owner: nexu-io | |
| repositories: open-design | |
| permission-administration: read | |
| permission-contents: read | |
| permission-issues: read | |
| permission-pull-requests: read | |
| - name: Generate issue and PR activity | |
| uses: lowlighter/metrics@latest | |
| with: | |
| # Render into the action workspace only. The upload step publishes the | |
| # SVG to repository-assets R2 so generated metrics never write back to | |
| # the git history. | |
| filename: github-metrics.svg | |
| # Auth: use the Open Design GitHub App for follow-up metrics | |
| # that need private repository API access, but do not grant write | |
| # permissions because this workflow publishes to R2 instead of git. | |
| token: ${{ steps.open-design-bot-token.outputs.token }} | |
| output_action: none | |
| # Use the repository template (per-repo metrics, not user metrics). | |
| # Organization-owned repositories must be targeted explicitly, otherwise | |
| # lowlighter/metrics infers the token owner and treats the target as an org. | |
| template: repository | |
| base: '' | |
| user: nexu-io | |
| repo: open-design | |
| # Keep this README image focused on the maintenance signal that is not | |
| # covered elsewhere: issue and PR follow-up status. Contributors and | |
| # star history have dedicated README sections, and languages are | |
| # already summarized by GitHub. | |
| plugin_followup: yes | |
| plugin_followup_sections: pr, issue | |
| config_timezone: Asia/Shanghai | |
| config_display: large | |
| - name: Normalize activity SVG layout | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| raw_svg="/metrics_renders/github-metrics.svg" | |
| svg="$RUNNER_TEMP/github-metrics.svg" | |
| if [ ! -s "$raw_svg" ]; then | |
| echo "Expected metrics SVG not found at $raw_svg" >&2 | |
| exit 1 | |
| fi | |
| cp "$raw_svg" "$svg" | |
| SVG_PATH="$svg" node <<'NODE' | |
| const fs = require('node:fs'); | |
| const svg = process.env.SVG_PATH; | |
| if (!svg) throw new Error('SVG_PATH is required'); | |
| let content = fs.readFileSync(svg, 'utf8'); | |
| content = content.replace( | |
| /<svg xmlns="http:\/\/www\.w3\.org\/2000\/svg" width="[^"]+" height="[^"]+"([^>]*)>/, | |
| '<svg xmlns="http://www.w3.org/2000/svg" width="720" height="110" viewBox="0 0 720 110"$1>' | |
| ); | |
| content = content.replace( | |
| '<span class="followup-title">Overall issues and pull requests status</span>', | |
| '<span class="followup-title">Issue and pull request status</span>' | |
| ); | |
| const layoutCss = [ | |
| 'foreignObject>div{width:100%;display:flex;flex-direction:column;align-items:center;transform:scale(1.1);transform-origin:top center}', | |
| '.field{justify-content:center}', | |
| '.followup-title{text-align:center}', | |
| 'svg.large .largeable{width:520px}', | |
| 'svg.large .chart.largeable{width:504px}' | |
| ].join(''); | |
| content = content.replace('</style>', `${layoutCss}</style>`); | |
| fs.writeFileSync(svg, content); | |
| NODE | |
| - name: Publish metrics SVG to repository assets | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_REPOSITORY_ASSETS_AK }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_REPOSITORY_ASSETS_SK }} | |
| AWS_DEFAULT_REGION: auto | |
| AWS_EC2_METADATA_DISABLED: "true" | |
| CLOUDFLARE_R2_REPOSITORY_ASSETS_BUCKET: ${{ secrets.CLOUDFLARE_R2_REPOSITORY_ASSETS_BUCKET }} | |
| CLOUDFLARE_R2_REPOSITORY_ASSETS_PUBLIC_ORIGIN: ${{ vars.CLOUDFLARE_R2_REPOSITORY_ASSETS_PUBLIC_ORIGIN }} | |
| CLOUDFLARE_R2_REPOSITORY_ASSETS_URL: ${{ secrets.CLOUDFLARE_R2_REPOSITORY_ASSETS_URL }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| svg="$RUNNER_TEMP/github-metrics.svg" | |
| if [ ! -s "$svg" ]; then | |
| echo "Expected metrics SVG not found at $svg" >&2 | |
| exit 1 | |
| fi | |
| key="resources/images/github-metrics.svg" | |
| node --experimental-strip-types .github/scripts/r2.ts put-object \ | |
| --endpoint "$CLOUDFLARE_R2_REPOSITORY_ASSETS_URL" \ | |
| --bucket "$CLOUDFLARE_R2_REPOSITORY_ASSETS_BUCKET" \ | |
| --key "$key" \ | |
| --file "$svg" \ | |
| --content-type "image/svg+xml" \ | |
| --cache-control "public, max-age=300" \ | |
| --public-origin "$CLOUDFLARE_R2_REPOSITORY_ASSETS_PUBLIC_ORIGIN" |