main
GitHub Skill Tools
Custom tools for enhanced GitHub workflow automation.
Purpose
While gh CLI handles most GitHub operations, these tools provide enhanced functionality for:
- Complex PR status formatting and filtering
- Intelligent check restart logic
- Automated PR template filling
- Advanced workflow automation
Available Tools
Planned Tools
CheckPRStatus.sh
- Enhanced PR check status with color-coded output
- Automatic log fetching for failures
- Smart filtering (required checks, failed only, pending)
- Export to JSON/Markdown
- Notification integration
RestartFailedChecks.sh
- Detect flaky vs. code failures from logs
- Automatic retry for flaky tests (with configurable limits)
- Skip restart if same failure occurred multiple times
- Statistics tracking (success rate, retry count)
- Slack/email notifications
CreatePR.sh
- Auto-detect and parse PR templates
- Intelligently fill template sections based on commits
- Auto-check completed checklist items
- Detect PR type from branch name or commits
- Suggest reviewers based on file changes (git blame)
- Validate PR against project guidelines
PRSummary.py
- Generate comprehensive PR summaries
- Analyze code changes and generate description
- Extract key changes and impact
- Suggest labels and reviewers
- Integration with AI for smart summaries (complex logic warrants Python)
Tool Development Guidelines
Technology Stack
- Bash/Shell: Primary choice for most tools (simple, portable, direct
ghintegration) - Python with uv: For complex logic requiring data structures or libraries
- nix-shell: For shell scripts needing specific dependencies
Structure
Shell Script Example:
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p gh jq
# CheckPRStatus.sh - Enhanced PR check status viewer
set -euo pipefail
# Parse arguments
PR_NUMBER="${1:-}"
FILTER="${2:-all}" # all, failed, pending, required
if [ -z "$PR_NUMBER" ]; then
echo "Usage: $0 <pr-number> [filter]"
exit 1
fi
# Get PR checks
CHECKS=$(gh pr view "$PR_NUMBER" --json statusCheckRollup --jq '.statusCheckRollup')
# Filter and format
case "$FILTER" in
failed)
echo "$CHECKS" | jq -r '.[] | select(.conclusion == "failure") | "✗ \(.name)"'
;;
pending)
echo "$CHECKS" | jq -r '.[] | select(.status != "COMPLETED") | "⏳ \(.name)"'
;;
required)
echo "$CHECKS" | jq -r '.[] | select(.isRequired == true) | "\(.conclusion // .status) \(.name)"'
;;
*)
echo "$CHECKS" | jq -r '.[] | "\(.conclusion // .status) \(.name)"'
;;
esac
Python Script Example (for complex logic):
#!/usr/bin/env -S uv run --quiet --script
# /// script
# dependencies = ["click", "requests"]
# ///
"""
PRSummary.py - Generate intelligent PR summaries
"""
import click
import json
import subprocess
@click.command()
@click.option('--pr', required=True, help='PR number')
@click.option('--format', default='markdown', help='Output format')
def summarize_pr(pr: int, format: str):
"""Generate comprehensive PR summary"""
# Get PR data via gh
result = subprocess.run(
['gh', 'pr', 'view', str(pr), '--json', 'title,body,commits,files'],
capture_output=True,
text=True
)
data = json.loads(result.stdout)
# Analyze commits
commits = data['commits']
files_changed = len(data['files'])
# Generate summary
summary = f"""
# PR #{pr}: {data['title']}
## Changes
- {files_changed} files changed
- {len(commits)} commits
## Commit Summary
"""
for commit in commits:
summary += f"- {commit['messageHeadline']}\n"
click.echo(summary)
if __name__ == '__main__':
summarize_pr()
Best Practices
- Prefer shell scripts: Start with bash, only use Python if truly needed
- Use nix-shell shebang: For scripts with dependencies (jq, curl, etc.)
- Use uv for Python: Inline dependency management with
# /// script - Fail fast: Exit early with clear error messages (
set -euo pipefail) - Validate inputs: Check for required options and valid values
- Provide feedback: Show progress for long-running operations
- Handle errors gracefully: Don’t crash, provide actionable error messages
- Make it scriptable: Support JSON output for automation
- Add help text: Include usage message when called incorrectly
- Follow conventions: Use standard flags like
-v,--json,--dry-run
Dependencies
Shell Scripts:
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p gh jq curl fzf
# Script has access to: gh, jq, curl, fzf
Python Scripts:
#!/usr/bin/env -S uv run --quiet --script
# /// script
# dependencies = [
# "click>=8.0",
# "requests>=2.28",
# ]
# ///
Example: CheckPRStatus.sh
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p gh jq
# CheckPRStatus.sh - Enhanced PR check status viewer
# Usage: ./CheckPRStatus.sh <pr-number> [--filter failed|pending|required]
set -euo pipefail
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Parse arguments
PR_NUMBER="${1:-}"
FILTER_TYPE="${2:-all}"
show_usage() {
cat << EOF
Usage: $0 <pr-number> [--filter <type>]
Arguments:
pr-number PR number to check
Options:
--filter TYPE Filter checks (all|failed|pending|required)
--show-logs Show failure logs
--json Output as JSON
Examples:
$0 123 # Show all checks
$0 123 --filter failed # Show only failed checks
$0 123 --show-logs # Show failures with logs
EOF
}
if [ -z "$PR_NUMBER" ]; then
show_usage
exit 1
fi
# Get PR checks
CHECKS_JSON=$(gh pr view "$PR_NUMBER" --json statusCheckRollup --jq '.statusCheckRollup')
# Count statuses
TOTAL=$(echo "$CHECKS_JSON" | jq 'length')
PASSED=$(echo "$CHECKS_JSON" | jq '[.[] | select(.conclusion == "success")] | length')
FAILED=$(echo "$CHECKS_JSON" | jq '[.[] | select(.conclusion == "failure")] | length')
PENDING=$(echo "$CHECKS_JSON" | jq '[.[] | select(.status != "COMPLETED")] | length')
# Show summary
echo -e "\nPR #$PR_NUMBER Check Status"
echo "=============================="
echo -e "Total: $TOTAL | ${GREEN}Passed: $PASSED${NC} | ${RED}Failed: $FAILED${NC} | ${YELLOW}Pending: $PENDING${NC}\n"
# Filter and display
case "${FILTER_TYPE}" in
--filter)
case "${3:-all}" in
failed)
echo -e "${RED}Failed Checks:${NC}"
echo "$CHECKS_JSON" | jq -r '.[] | select(.conclusion == "failure") | " ✗ \(.name)\n → \(.detailsUrl)"'
;;
pending)
echo -e "${YELLOW}Pending Checks:${NC}"
echo "$CHECKS_JSON" | jq -r '.[] | select(.status != "COMPLETED") | " ⏳ \(.name)"'
;;
required)
echo -e "Required Checks:"
echo "$CHECKS_JSON" | jq -r '.[] | select(.isRequired == true) | " \(if .conclusion == "success" then "✓" elif .conclusion == "failure" then "✗" else "⏳" end) \(.name)"'
;;
all|*)
echo "$CHECKS_JSON" | jq -r '.[] | "\(if .conclusion == "success" then "✓" elif .conclusion == "failure" then "✗" else "⏳" end) \(.name)"'
;;
esac
;;
--show-logs)
echo -e "${RED}Failed Checks with Logs:${NC}\n"
# Get failed run IDs
BRANCH=$(gh pr view "$PR_NUMBER" --json headRefName --jq '.headRefName')
FAILED_RUNS=$(gh run list --branch="$BRANCH" --status=failure --json databaseId --jq '.[].databaseId' | head -3)
for run_id in $FAILED_RUNS; do
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
gh run view "$run_id" --log-failed | head -50
echo ""
done
;;
--json)
echo "$CHECKS_JSON" | jq '.'
;;
*)
# Default: show all
echo "$CHECKS_JSON" | jq -r '.[] | "\(if .conclusion == "success" then "✓" elif .conclusion == "failure" then "✗" else "⏳" end) \(.name)"'
;;
esac
Testing Tools
# Make executable
chmod +x tools/CheckPRStatus.sh
# Test (nix-shell will automatically provide dependencies)
./tools/CheckPRStatus.sh 123
# Test with filter
./tools/CheckPRStatus.sh 123 --filter failed
# Test with logs
./tools/CheckPRStatus.sh 123 --show-logs
Integration with Workflows
Tools are referenced in workflow files:
## Custom Tool: Enhanced Status Check
For complex formatting:
\`\`\`bash
./tools/CheckPRStatus.sh 123 --filter failed --show-logs
\`\`\`
Development Workflow
- Plan the tool: Define what it should do
- Check if gh can do it: Don’t duplicate existing functionality
- Choose language: Shell for simple, Python for complex
- Add dependencies: Use nix-shell or uv shebang
- Prototype: Write minimal version
- Test: Test with real PRs/repos
- Make executable:
chmod +x tools/ToolName.sh - Document: Add usage examples to workflow files
- Integrate: Reference in appropriate workflows
Future Tools
- PRMetrics.sh: Analyze PR size, complexity, review time
- AutoLabel.sh: Automatically suggest labels based on file changes
- ReviewReminder.sh: Notify reviewers of pending PRs
- MergeQueue.sh: Manage PR merge order with dependencies
- ChangelogGenerator.sh: Generate changelog from merged PRs
Contributing
When adding a new tool:
- Create script in
tools/(prefer.sh, use.pyonly if needed) - Add appropriate shebang (nix-shell or uv)
- Add usage/help message
- Make executable:
chmod +x - Document in this README
- Reference in relevant workflow files
- Add usage examples
- Test with real GitHub data