fix(contributors): use table layout for HTML format to prevent vertic… #1
Workflow file for this run
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: Update Contributors | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| output-format: | ||
| description: 'Output format: html (enforces image size) or markdown' | ||
| required: false | ||
| type: string | ||
| default: 'markdown' | ||
| jobs: | ||
| contributors: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| token: ${{ secrets.CONTRIBUTORS_TOKEN }} | ||
| - name: Update contributors | ||
| env: | ||
| GH_TOKEN: ${{ secrets.CONTRIBUTORS_TOKEN }} | ||
| OUTPUT_FORMAT: ${{ inputs.output-format }} | ||
| run: | | ||
| # Fetch code contributors (exclude bots) | ||
| code_contributors=$(gh api repos/${{ github.repository }}/contributors --paginate --jq '.[] | select(.type != "Bot") | select(.login | test("\\[bot\\]$") | not) | .login') | ||
| # Fetch closed issues and check if they were closed by a merged PR | ||
| issue_authors="" | ||
| closed_issues=$(gh api "repos/${{ github.repository }}/issues?state=closed" --paginate -q '.[] | select(.pull_request == null) | {number, login: .user.login}') | ||
| for row in $(echo "$closed_issues" | jq -c '.'); do | ||
| issue_num=$(echo "$row" | jq -r '.number') | ||
| login=$(echo "$row" | jq -r '.login') | ||
| # Check timeline for cross-referenced merged PR that closed this issue | ||
| closed_by_pr=$(gh api repos/${{ github.repository }}/issues/$issue_num/timeline --jq ' | ||
| [.[] | select(.event == "cross-referenced") | | ||
| select(.source.issue.pull_request.merged_at)] | | ||
| .[0].source.issue.number // empty') | ||
| if [[ -n "$closed_by_pr" ]]; then | ||
| issue_authors="$issue_authors$login"$'\n' | ||
| fi | ||
| done | ||
| issue_authors=$(echo "$issue_authors" | sort -u) | ||
| # Fetch credited users from /credit commands in merged PR comments | ||
| credit_users="" | ||
| merged_prs=$(gh pr list --state merged --limit 100 --json number --jq '.[].number') | ||
| for pr_num in $merged_prs; do | ||
| credit_login=$(gh pr view "$pr_num" --json comments --jq '.comments[].body' 2>/dev/null | grep "^/credit @" | sed 's|^/credit @||' | tr -d '[:space:]' | head -1 || echo "") | ||
| if [[ -n "$credit_login" ]]; then | ||
| credit_users="$credit_users$credit_login"$'\n' | ||
| fi | ||
| done | ||
| credit_users=$(echo "$credit_users" | sort -u) | ||
| # Combine and deduplicate, ensuring CalvinAllen is always first | ||
| other_contributors=$(echo -e "$code_contributors\n$issue_authors\n$credit_users" | sort -u | grep -v '^$' | grep -v '^CalvinAllen$' || true) | ||
| all_contributors=$(echo -e "CalvinAllen\n$other_contributors" | grep -v '^$') | ||
| # Build output for each contributor | ||
| contributor_output="" | ||
| for login in $all_contributors; do | ||
| # Skip bots | ||
| if [[ "$login" == *"[bot]" ]]; then | ||
| continue | ||
| fi | ||
| # Get user info | ||
| user_info=$(gh api users/$login --jq '{avatar_url, html_url}') | ||
| avatar=$(echo "$user_info" | jq -r '.avatar_url') | ||
| url=$(echo "$user_info" | jq -r '.html_url') | ||
| if [[ "$OUTPUT_FORMAT" == "html" ]]; then | ||
| # HTML format with enforced size (table cells prevent GitHub's display:block from stacking images) | ||
| contributor_output="$contributor_output<td><a href=\"$url\"><img src=\"${avatar}&s=64\" width=\"64\" height=\"64\" alt=\"$login\"></a></td>" | ||
| else | ||
| # Markdown format (default) | ||
| contributor_output="$contributor_output[]($url) " | ||
| fi | ||
| done | ||
| # Build the contributors section | ||
| if [[ "$OUTPUT_FORMAT" == "html" ]]; then | ||
| contrib_section="<!-- readme: contributors -start --> | ||
| <table><tr>$contributor_output</tr></table> | ||
| <!-- readme: contributors -end -->" | ||
| else | ||
| contrib_section="<!-- readme: contributors -start --> | ||
| $contributor_output | ||
| <!-- readme: contributors -end -->" | ||
| fi | ||
| # Update README between the markers | ||
| awk -v contrib="$contrib_section" ' | ||
| /<!-- readme: contributors -start -->/{found=1; print contrib; next} | ||
| /<!-- readme: contributors -end -->/{found=0; next} | ||
| !found{print} | ||
| ' README.md > README.tmp && mv README.tmp README.md | ||
| - name: Commit and push | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add README.md | ||
| git diff --staged --quiet || (git commit -m "docs: update contributors" && git push) | ||