Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ CI is the one check that can't be skipped. Pre-commit hooks can be bypassed; CI
The assessor scores on a 100-point scale:

- **CI config exists** (50 pts): A workflow file in `.github/workflows/`, `.gitlab-ci.yml`, `.tekton` or similar
- **Quality gates present** (30 pts): lint, type-check, and test steps detected in CI config
- **Quality gates present** (30 pts): lint, type-check, and test steps detected in CI config. For compiled languages (Go, Rust), the build step (`go build`, `make build`, `cargo build`) counts as the type-check gate since the compiler is the type checker. `golangci-lint` also satisfies the type-check gate as it bundles type-checking linters.
- **Config quality** (15 pts): PR trigger configured, fail-fast enabled
- **Best practices** (5 pts): matrix testing, caching, or other optimizations

Expand Down
5 changes: 5 additions & 0 deletions src/agentready/assessors/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ def _assess_quality_gates(self, ci_configs: list) -> tuple:
r"(?:eslint|ruff|pylint|flake8|rubocop|golangci-lint|black|isort|prettier|stylelint)\b",
r"\blint\b",
r"\bformatting?\b",
r"\bcargo\s+clippy\b",
]
test_patterns = [
r"\bpytest\b",
Expand All @@ -1135,6 +1136,10 @@ def _assess_quality_gates(self, ci_configs: list) -> tuple:
r"\btsc\b",
r"\btype[_-]?check\b",
r"\bgo\s+vet\b",
r"(?:\bgo|\$\(GO\))\s+build\b",
r"\bmake\s+build\b",
r"\bgolangci-lint\b",
r"\bcargo\s+build\b",
]

found_lint = False
Expand Down
114 changes: 114 additions & 0 deletions tests/unit/test_assessors_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,120 @@ def test_config_quality_adds_score(self, tmp_path):
# 50 (CI) + 30 (all gates) + config quality bonus
assert finding.score > 80

# --- Compiled-language type-check gate tests (#473) ---

def test_go_build_detected_as_typecheck(self, tmp_path):
"""Test that 'go build' is recognized as a type-check gate for Go repos."""
workflows_dir = tmp_path / ".github" / "workflows"
workflows_dir.mkdir(parents=True)
(workflows_dir / "ci.yml").write_text(
"name: CI\n"
"on: [push, pull_request]\n"
"jobs:\n"
" lint:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: golangci-lint run\n"
" test:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: go test ./...\n"
" build:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: go build ./...\n"
)

repo = _make_repo(tmp_path)
assessor = CIQualityGatesAssessor()
finding = assessor.assess(repo)

assert finding.status == "pass"
assert any("Type-check gate detected" in e for e in finding.evidence)

def test_make_build_detected_as_typecheck(self, tmp_path):
"""Test that 'make build' is recognized as a type-check gate."""
workflows_dir = tmp_path / ".github" / "workflows"
workflows_dir.mkdir(parents=True)
(workflows_dir / "ci.yml").write_text(
"name: CI\n"
"on: [push, pull_request]\n"
"jobs:\n"
" lint:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: golangci-lint run\n"
" test:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: make test\n"
" build:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: make build\n"
)

repo = _make_repo(tmp_path)
assessor = CIQualityGatesAssessor()
finding = assessor.assess(repo)

assert finding.status == "pass"
assert any("Type-check gate detected" in e for e in finding.evidence)

def test_golangci_lint_detected_as_typecheck(self, tmp_path):
"""Test that golangci-lint is recognized as a type-check gate."""
workflows_dir = tmp_path / ".github" / "workflows"
workflows_dir.mkdir(parents=True)
(workflows_dir / "ci.yml").write_text(
"name: CI\n"
"on: [push, pull_request]\n"
"jobs:\n"
" lint:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - uses: golangci/golangci-lint-action@v6\n"
" test:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: go test ./...\n"
)

repo = _make_repo(tmp_path)
assessor = CIQualityGatesAssessor()
finding = assessor.assess(repo)

assert finding.status == "pass"
assert any("Type-check gate detected" in e for e in finding.evidence)

def test_cargo_build_detected_as_typecheck(self, tmp_path):
"""Test that 'cargo build' is recognized as a type-check gate for Rust repos."""
workflows_dir = tmp_path / ".github" / "workflows"
workflows_dir.mkdir(parents=True)
(workflows_dir / "ci.yml").write_text(
"name: CI\n"
"on: [push, pull_request]\n"
"jobs:\n"
" lint:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: cargo clippy\n"
" test:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: cargo test\n"
" build:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - run: cargo build\n"
)

repo = _make_repo(tmp_path)
assessor = CIQualityGatesAssessor()
finding = assessor.assess(repo)

assert finding.status == "pass"
assert any("Type-check gate detected" in e for e in finding.evidence)

# --- Tekton Pipelines as Code tests ---

def test_tekton_on_event_simple_pull_request(self, tmp_path):
Expand Down
Loading