Skip to content

Commit 592aab6

Browse files
jeremyederclaude
andcommitted
feat: consolidate GitHub Actions workflows by purpose
PHASE 1 (completed earlier): - Delete 5 redundant workflows (tests, publish-pypi, docs-lint, 2× leaderboard) - Rename 3 workflows (ci, agentready-dev, update-docs-manual) - Add 3 new workflows (stale-issues, leaderboard, update-docs) - Optimize triggers for cost savings PHASE 2 (this commit): - Merge coverage-report.yml into ci.yml as new job - Create docs.yml combining link-check + future docs jobs - Fix actionlint issues (proper quoting, combined redirects) - Rename agentready-dev workflow - Add explicit @agentready-dev agent invocation in prompt - Update all GitHub Actions to latest versions (v6) - Delete update-docs-manual.yml (redundant with automated update-docs.yml) - Add GitHub Actions guidelines to CLAUDE.md - Reorganize README.md with TOC, research citations, expanded CLI reference NET RESULT: - 16 workflows → 13 workflows (-3 total) - Clear purpose-driven organization - 100% actionlint compliance for modified workflows - Improved maintainability All modified workflows validated with actionlint. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent ba795ca commit 592aab6

20 files changed

+778
-948
lines changed

.claude/agents/agentready-dev.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
---
2+
name: AgentReady Development
3+
description: Specialized agent with deep knowledge of the AgentReady codebase for development, testing, and maintenance
4+
tools: [Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch, TodoWrite]
5+
---
6+
17
# AgentReady Development Agent
28

39
**Purpose**: Specialized Claude Code agent with deep knowledge of the AgentReady codebase to assist with development, testing, and maintenance tasks.

.github/workflows/agentready-assessment.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121

2222
steps:
2323
- name: Post unauthorized message
24-
uses: actions/github-script@v7
24+
uses: actions/github-script@v8
2525
with:
2626
script: |
2727
const user = context.payload.comment.user.login;
@@ -126,7 +126,7 @@ jobs:
126126
127127
- name: Checkout current repository
128128
if: steps.parse.outputs.assess_current == 'true'
129-
uses: actions/checkout@v4
129+
uses: actions/checkout@v6
130130
with:
131131
ref: ${{ github.event.pull_request.head.ref || github.ref }}
132132

@@ -146,7 +146,7 @@ jobs:
146146
echo "✅ Repository cloned successfully"
147147
148148
- name: Set up Python
149-
uses: actions/setup-python@v5
149+
uses: actions/setup-python@v6
150150
with:
151151
python-version: '3.12'
152152

@@ -205,7 +205,7 @@ jobs:
205205
} >> "$GITHUB_OUTPUT"
206206
207207
- name: Upload Assessment Reports
208-
uses: actions/upload-artifact@v4
208+
uses: actions/upload-artifact@v5
209209
if: always()
210210
with:
211211
name: agentready-reports-${{ github.run_id }}
@@ -214,7 +214,7 @@ jobs:
214214

215215
- name: Post assessment results
216216
if: always()
217-
uses: actions/github-script@v7
217+
uses: actions/github-script@v8
218218
env:
219219
OUTPUT_DIR: ${{ steps.assessment.outputs.output_dir }}
220220
REPO_URL: ${{ steps.parse.outputs.repo_url }}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: Codebase Agent (agentready-dev)
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
issues:
9+
types: [opened, assigned]
10+
pull_request_review:
11+
types: [submitted]
12+
13+
permissions:
14+
contents: write
15+
pull-requests: write
16+
issues: write
17+
id-token: write
18+
actions: read
19+
20+
jobs:
21+
agentready-dev:
22+
# Trigger on @agentready-dev mentions in issues, PRs, and comments
23+
if: |
24+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@agentready-dev')) ||
25+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@agentready-dev')) ||
26+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@agentready-dev')) ||
27+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@agentready-dev') || contains(github.event.issue.title, '@agentready-dev')))
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Get PR info for fork support
31+
if: github.event.issue.pull_request
32+
id: pr-info
33+
env:
34+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
REPOSITORY: ${{ github.repository }}
36+
ISSUE_NUMBER: ${{ github.event.issue.number }}
37+
run: |
38+
PR_DATA=$(gh api "repos/$REPOSITORY/pulls/$ISSUE_NUMBER")
39+
{
40+
echo "pr_head_owner=$(echo "$PR_DATA" | jq -r '.head.repo.owner.login')"
41+
echo "pr_head_repo=$(echo "$PR_DATA" | jq -r '.head.repo.name')"
42+
echo "pr_head_ref=$(echo "$PR_DATA" | jq -r '.head.ref')"
43+
echo "is_fork=$(echo "$PR_DATA" | jq -r '.head.repo.fork')"
44+
} >> "$GITHUB_OUTPUT"
45+
46+
- name: Extract user request
47+
id: extract-request
48+
env:
49+
EVENT_NAME: ${{ github.event_name }}
50+
COMMENT_BODY: ${{ github.event.comment.body }}
51+
REVIEW_BODY: ${{ github.event.review.body }}
52+
ISSUE_BODY: ${{ github.event.issue.body }}
53+
run: |
54+
case "$EVENT_NAME" in
55+
issue_comment|pull_request_review_comment)
56+
REQUEST="$COMMENT_BODY"
57+
;;
58+
pull_request_review)
59+
REQUEST="$REVIEW_BODY"
60+
;;
61+
issues)
62+
REQUEST="$ISSUE_BODY"
63+
;;
64+
*)
65+
REQUEST="No request body found"
66+
;;
67+
esac
68+
69+
# Remove @agentready-dev mention from the request
70+
REQUEST=$(echo "$REQUEST" | sed 's/@agentready-dev//g' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
71+
72+
{
73+
echo "request<<EOF"
74+
echo "$REQUEST"
75+
echo "EOF"
76+
} >> "$GITHUB_OUTPUT"
77+
78+
- name: Checkout repository (fork-compatible)
79+
uses: actions/checkout@v6
80+
with:
81+
repository: ${{ github.event.issue.pull_request && steps.pr-info.outputs.is_fork == 'true' && format('{0}/{1}', steps.pr-info.outputs.pr_head_owner, steps.pr-info.outputs.pr_head_repo) || github.repository }}
82+
ref: ${{ github.event.issue.pull_request && steps.pr-info.outputs.pr_head_ref || github.ref }}
83+
fetch-depth: 0
84+
85+
- name: Claude Code Action
86+
uses: anthropics/claude-code-action@v1
87+
with:
88+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
89+
github_token: ${{ secrets.GITHUB_TOKEN }}
90+
prompt: |
91+
@agentready-dev ${{ steps.extract-request.outputs.request }}

.github/workflows/ci.yml

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
name: CI (Tests & Quality)
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main, master]
7+
workflow_dispatch:
8+
9+
jobs:
10+
# Combined blocking tests and linting in one job to reduce CI runtime
11+
blocking-checks:
12+
name: Blocking Tests & Quality Checks
13+
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
python-version: ['3.12', '3.13']
17+
18+
steps:
19+
- uses: actions/checkout@v6
20+
- uses: actions/setup-python@v6
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
24+
- name: Install dependencies
25+
run: |
26+
python -m pip install --upgrade pip
27+
pip install -e ".[dev]"
28+
29+
# Run code quality checks (only on one Python version to save time)
30+
- name: Code Quality Checks
31+
if: matrix.python-version == '3.13'
32+
run: |
33+
black --check .
34+
isort --check .
35+
ruff check .
36+
37+
# Run critical tests
38+
- name: Run Critical Tests
39+
run: |
40+
pytest tests/e2e/test_critical_paths.py tests/unit/cli/test_main.py tests/unit/test_models.py \
41+
-v --no-cov --tb=short
42+
timeout-minutes: 5
43+
44+
# Non-blocking comprehensive tests
45+
comprehensive-tests:
46+
name: Full Test Suite (Non-blocking)
47+
runs-on: ubuntu-latest
48+
continue-on-error: true # Don't fail CI
49+
50+
steps:
51+
- uses: actions/checkout@v6
52+
- uses: actions/setup-python@v6
53+
with:
54+
python-version: '3.13'
55+
56+
- name: Install dependencies
57+
run: |
58+
python -m pip install --upgrade pip
59+
pip install -e ".[dev]"
60+
61+
- name: Run all tests with coverage
62+
run: |
63+
pytest tests/unit/ --cov=src --cov-report=xml --cov-report=html --cov-report=term
64+
continue-on-error: true
65+
timeout-minutes: 20
66+
67+
- name: Upload coverage
68+
if: always()
69+
uses: actions/upload-artifact@v5
70+
with:
71+
name: coverage-report
72+
path: htmlcov/
73+
retention-days: 30
74+
75+
# Platform testing (simplified to single job)
76+
platform-test:
77+
name: macOS Compatibility
78+
runs-on: macos-latest
79+
continue-on-error: true
80+
81+
steps:
82+
- uses: actions/checkout@v6
83+
- uses: actions/setup-python@v6
84+
with:
85+
python-version: '3.13'
86+
87+
- name: Install and test
88+
run: |
89+
python -m pip install --upgrade pip
90+
pip install -e ".[dev]"
91+
pytest tests/e2e/test_critical_paths.py tests/unit/cli/test_main.py \
92+
-v --no-cov --tb=short || echo "Tests failed but continuing"
93+
timeout-minutes: 10
94+
95+
# Coverage reporting (PR only)
96+
coverage-report:
97+
name: Coverage Report
98+
if: github.event_name == 'pull_request'
99+
runs-on: ubuntu-latest
100+
permissions:
101+
contents: read
102+
pull-requests: write
103+
104+
steps:
105+
- name: Checkout PR branch
106+
uses: actions/checkout@v6
107+
108+
- name: Set up Python
109+
uses: actions/setup-python@v6
110+
with:
111+
python-version: '3.13'
112+
113+
- name: Install dependencies
114+
run: |
115+
python -m pip install --upgrade pip
116+
pip install -e ".[dev]"
117+
118+
- name: Run tests with coverage
119+
run: |
120+
pytest tests/unit/ --cov=src/agentready --cov-report=xml --cov-report=term
121+
continue-on-error: true
122+
123+
- name: Get coverage percentage
124+
id: coverage
125+
run: |
126+
COVERAGE=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); print(root.attrib['line-rate'])")
127+
COVERAGE_PCT=$(python -c "print(f'{float(\"$COVERAGE\") * 100:.1f}')")
128+
echo "coverage_pct=$COVERAGE_PCT" >> "$GITHUB_OUTPUT"
129+
130+
- name: Checkout main branch for comparison
131+
run: |
132+
git fetch origin main
133+
git checkout origin/main
134+
135+
- name: Run tests on main branch
136+
run: |
137+
pytest tests/unit/ --cov=src/agentready --cov-report=xml --cov-report=term
138+
continue-on-error: true
139+
140+
- name: Get main branch coverage
141+
id: main_coverage
142+
run: |
143+
MAIN_COVERAGE=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); print(root.attrib['line-rate'])")
144+
MAIN_COVERAGE_PCT=$(python -c "print(f'{float(\"$MAIN_COVERAGE\") * 100:.1f}')")
145+
echo "main_coverage_pct=$MAIN_COVERAGE_PCT" >> "$GITHUB_OUTPUT"
146+
147+
- name: Calculate diff
148+
id: diff
149+
env:
150+
PR_COVERAGE: ${{ steps.coverage.outputs.coverage_pct }}
151+
MAIN_COVERAGE: ${{ steps.main_coverage.outputs.main_coverage_pct }}
152+
run: |
153+
DIFF=$(python -c "print(f'{float(\"$PR_COVERAGE\") - float(\"$MAIN_COVERAGE\"):.1f}')")
154+
echo "diff=$DIFF" >> "$GITHUB_OUTPUT"
155+
156+
- name: Post coverage comment
157+
uses: actions/github-script@v8
158+
env:
159+
PR_COVERAGE: ${{ steps.coverage.outputs.coverage_pct }}
160+
MAIN_COVERAGE: ${{ steps.main_coverage.outputs.main_coverage_pct }}
161+
DIFF: ${{ steps.diff.outputs.diff }}
162+
with:
163+
script: |
164+
const prCoverage = process.env.PR_COVERAGE;
165+
const mainCoverage = process.env.MAIN_COVERAGE;
166+
const diff = parseFloat(process.env.DIFF);
167+
168+
const emoji = diff >= 0 ? '📈' : '📉';
169+
const diffText = diff >= 0 ? `+${diff}%` : `${diff}%`;
170+
const status = diff >= 0 ? '✅' : '⚠️';
171+
172+
const body = `## ${emoji} Test Coverage Report\n\n` +
173+
`| Branch | Coverage |\n` +
174+
`|--------|----------|\n` +
175+
`| **This PR** | ${prCoverage}% |\n` +
176+
`| Main | ${mainCoverage}% |\n` +
177+
`| **Diff** | ${status} ${diffText} |\n\n` +
178+
`---\n\n` +
179+
`*Coverage calculated from unit tests only*`;
180+
181+
const comments = await github.rest.issues.listComments({
182+
owner: context.repo.owner,
183+
repo: context.repo.repo,
184+
issue_number: context.issue.number,
185+
});
186+
187+
const existingComment = comments.data.find(comment =>
188+
comment.user.login === 'github-actions[bot]' &&
189+
comment.body.includes('Test Coverage Report')
190+
);
191+
192+
if (existingComment) {
193+
await github.rest.issues.updateComment({
194+
owner: context.repo.owner,
195+
repo: context.repo.repo,
196+
comment_id: existingComment.id,
197+
body: body
198+
});
199+
} else {
200+
await github.rest.issues.createComment({
201+
owner: context.repo.owner,
202+
repo: context.repo.repo,
203+
issue_number: context.issue.number,
204+
body: body
205+
});
206+
}

0 commit comments

Comments
 (0)