@bluefly/openstandardagents 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devfile.yaml +1 -1
- package/.env.example +1 -1
- package/.version.json +2 -2
- package/.wiki-config.json +24 -0
- package/CHANGELOG.md +11 -18
- package/CODEOWNERS +75 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +171 -243
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/repositories/schema.repository.d.ts +6 -1
- package/dist/repositories/schema.repository.d.ts.map +1 -1
- package/dist/repositories/schema.repository.js +49 -27
- package/dist/repositories/schema.repository.js.map +1 -1
- package/dist/services/migration.service.d.ts +4 -3
- package/dist/services/migration.service.d.ts.map +1 -1
- package/dist/services/migration.service.js +11 -10
- package/dist/services/migration.service.js.map +1 -1
- package/dist/services/release-automation/release.service.js +1 -1
- package/dist/services/release-automation/release.service.js.map +1 -1
- package/dist/services/release-automation/schemas/release.schema.js +1 -1
- package/dist/services/runtime/claude/claude-adapter.js +1 -1
- package/dist/services/runtime/claude/claude-adapter.js.map +1 -1
- package/dist/spec/v0.2.8/CHANGELOG.md +401 -0
- package/dist/spec/v0.2.8/README.md +72 -0
- package/dist/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/dist/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
- package/{spec/v0.2.6-dev/ossa-0.2.5.schema.json → dist/spec/v0.2.8/ossa-0.2.8.schema.json} +1509 -52
- package/dist/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/version.d.ts +68 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +156 -0
- package/dist/utils/version.js.map +1 -0
- package/eslint-report.json +1 -0
- package/examples/adk-integration/code-review-workflow.yml +1 -1
- package/examples/adk-integration/customer-support.yml +1 -1
- package/examples/adk-integration/data-pipeline.yml +1 -1
- package/examples/advanced/workflows/hybrid-model-strategy.yaml +1 -1
- package/examples/agent-manifests/critics/critic-agent.yaml +1 -1
- package/examples/agent-manifests/governors/governor-agent.yaml +1 -1
- package/examples/agent-manifests/integrators/integrator-agent.yaml +1 -1
- package/examples/agent-manifests/judges/judge-agent.yaml +1 -1
- package/examples/agent-manifests/monitors/monitor-agent.yaml +1 -1
- package/examples/agent-manifests/orchestrators/orchestrator-agent.yaml +1 -1
- package/examples/agent-manifests/sample-compliant-agent.yaml +1 -1
- package/examples/agent-manifests/workers/worker-agent.yaml +1 -1
- package/examples/anthropic/claude-assistant.ossa.json +1 -1
- package/examples/autogen/multi-agent.ossa.json +1 -1
- package/examples/claude-code/code-reviewer.ossa.yaml +78 -0
- package/examples/claude-code/ossa-validator.ossa.yaml +80 -0
- package/examples/common_npm/agent-router.ossa.yaml +1 -0
- package/examples/common_npm/agent-router.v0.2.2.ossa.yaml +1 -1
- package/examples/crewai/research-team.ossa.json +1 -1
- package/examples/cursor/code-review-agent.ossa.json +1 -1
- package/examples/drupal/gitlab-ml-recommender.ossa.yaml +1 -0
- package/examples/drupal/gitlab-ml-recommender.v0.2.2.ossa.yaml +1 -1
- package/examples/extensions/drupal-v1.yml +1 -1
- package/examples/extensions/kagent-v1.yml +1 -1
- package/examples/getting-started/hello-world-complete.ossa.yaml +1 -1
- package/examples/integration-patterns/agent-to-agent-orchestration.ossa.yaml +4 -4
- package/examples/kagent/compliance-validator.ossa.yaml +1 -1
- package/examples/kagent/cost-optimizer.ossa.yaml +1 -1
- package/examples/kagent/documentation-agent.ossa.yaml +1 -1
- package/examples/kagent/k8s-troubleshooter-v1.ossa.yaml +1 -0
- package/examples/kagent/k8s-troubleshooter-v1.v0.2.2.ossa.yaml +1 -1
- package/examples/kagent/k8s-troubleshooter.ossa.yaml +1 -1
- package/examples/kagent/security-scanner.ossa.yaml +1 -1
- package/examples/langchain/chain-agent.ossa.json +1 -1
- package/examples/langflow/workflow-agent.ossa.json +1 -1
- package/examples/langgraph/state-machine-agent.ossa.json +1 -1
- package/examples/llamaindex/rag-agent.ossa.json +1 -1
- package/examples/migration-guides/from-langchain-to-ossa.yaml +4 -4
- package/examples/multi-agent/README.md +74 -0
- package/examples/multi-agent/conditional-router.ossa.yaml +42 -0
- package/examples/multi-agent/parallel-execution.ossa.yaml +54 -0
- package/examples/multi-agent/sequential-pipeline.ossa.yaml +45 -0
- package/examples/openai/basic-agent.ossa.yaml +1 -1
- package/examples/openai/multi-tool-agent.ossa.json +1 -1
- package/examples/openai/swarm-agent.ossa.json +1 -1
- package/examples/production/document-analyzer-openai.yml +1 -1
- package/examples/quickstart/support-agent.ossa.yaml +1 -1
- package/examples/spec-examples/audit-agent.yml +1 -1
- package/examples/spec-examples/chat-agent.yml +1 -1
- package/examples/spec-examples/compliance-agent.yml +1 -1
- package/examples/spec-examples/monitoring-agent.yml +1 -1
- package/examples/spec-examples/workflow-agent.yml +1 -1
- package/examples/templates/ossa-compliance.yaml +1 -1
- package/examples/vercel/edge-agent.ossa.json +1 -1
- package/gl-code-quality-report.json +62 -0
- package/llms-ctx-full.txt +39 -0
- package/llms-ctx.txt +39 -0
- package/llms.txt +47 -0
- package/package.json +3 -2
- package/scripts/eslint-to-codequality.cjs +34 -0
- package/scripts/generate-llms-ctx.sh +17 -0
- package/scripts/generate-schema-docs.ts +31 -10
- package/scripts/sync-version.js +4 -12
- package/scripts/validate-schema.ts +2 -1
- package/spec/v0.2.8/CHANGELOG.md +401 -0
- package/spec/v0.2.8/README.md +72 -0
- package/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
- package/{dist/spec/v0.2.6-dev/ossa-0.2.5.schema.json → spec/v0.2.8/ossa-0.2.8.schema.json} +1509 -52
- package/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
- package/test-results/junit.xml +299 -0
- package/bin/validate-ossa-0.2.5-RC.ts +0 -244
- package/dist/spec/v0.2.6-dev/ossa-0.2.6-dev.schema.json +0 -1696
- package/scripts/lib/exec.ts +0 -37
- package/scripts/lib/file-ops.ts +0 -58
- package/scripts/lib/version.ts +0 -83
- package/spec/v0.2.6-dev/ossa-0.2.6-dev.schema.json +0 -1696
- package/website/.lighthouserc.ts +0 -24
- package/website/.prettierrc +0 -10
- package/website/DESIGN_SYSTEM_IMPLEMENTATION.md +0 -445
- package/website/Dockerfile +0 -30
- package/website/app/about/page.tsx +0 -304
- package/website/app/blog/[slug]/page.tsx +0 -208
- package/website/app/blog/page.tsx +0 -249
- package/website/app/design-guide/page.tsx +0 -511
- package/website/app/docs/[[...slug]]/page.tsx +0 -847
- package/website/app/docs/core-concepts/project-structure/page.tsx +0 -349
- package/website/app/ecosystem/page.tsx +0 -410
- package/website/app/examples/page.tsx +0 -133
- package/website/app/globals.scss +0 -370
- package/website/app/layout.tsx +0 -106
- package/website/app/license/page.tsx +0 -183
- package/website/app/not-found.tsx +0 -18
- package/website/app/page.tsx +0 -686
- package/website/app/page.tsx.bak +0 -679
- package/website/app/page.tsx.bak2 +0 -649
- package/website/app/playground/page.tsx +0 -487
- package/website/app/robots.ts +0 -19
- package/website/app/rss.xml/route.ts +0 -74
- package/website/app/schema/page.tsx +0 -1001
- package/website/app/sitemap.ts +0 -56
- package/website/app/specification/page.tsx +0 -287
- package/website/components/InstallCommand.tsx +0 -96
- package/website/components/Logo.tsx +0 -97
- package/website/components/StructuredData.tsx +0 -65
- package/website/components/docs/DocsSearch.tsx +0 -104
- package/website/components/docs/DocsSidebar.tsx +0 -155
- package/website/components/docs/MarkdownContent.tsx +0 -401
- package/website/components/docs/VersionSelector.tsx +0 -105
- package/website/components/examples/ExamplesViewer.tsx +0 -293
- package/website/components/layout/Footer.tsx +0 -116
- package/website/components/layout/Header.tsx +0 -172
- package/website/components/schema/SchemaComponentsAccordion.tsx +0 -84
- package/website/components/schema/SchemaExplorer.tsx +0 -213
- package/website/components/ui/Badge.tsx +0 -82
- package/website/components/ui/Button.tsx +0 -116
- package/website/components/ui/Card.tsx +0 -167
- package/website/components/ui/Checkbox.tsx +0 -141
- package/website/components/ui/Input.tsx +0 -169
- package/website/components/ui/Radio.tsx +0 -141
- package/website/components/ui/Select.tsx +0 -182
- package/website/components/ui/Tag.tsx +0 -158
- package/website/components/ui/Textarea.tsx +0 -195
- package/website/components/ui/index.ts +0 -11
- package/website/content/blog/OpenAPI-AI-Agents-Standard.md +0 -285
- package/website/content/blog/Why-Formal-Standards-Matter-Now.md +0 -198
- package/website/content/blog/gitlab-kubernetes-agent-ecosystem.md +0 -286
- package/website/content/blog/introducing-ossa-framework.md +0 -328
- package/website/content/blog/ossa-production-results.md +0 -279
- package/website/content/blog/welcome-to-ossa.md +0 -43
- package/website/content/blog/why-ai-agents-need-open-standard.md +0 -98
- package/website/content/docs/00-home.md +0 -153
- package/website/content/docs/adapters/openai-adapter.md +0 -693
- package/website/content/docs/agents/catalog.md +0 -28
- package/website/content/docs/aiflow-framework-integration-with-ossa.md +0 -107
- package/website/content/docs/api-reference/index.md +0 -38
- package/website/content/docs/api-reference/ossa-core-api.md +0 -634
- package/website/content/docs/api-reference/ossa-registry-api.md +0 -515
- package/website/content/docs/api-reference/unified-agent-gateway.md +0 -599
- package/website/content/docs/architecture/execution-flow.md +0 -335
- package/website/content/docs/architecture/multi-agent-systems.md +0 -737
- package/website/content/docs/architecture/overview.md +0 -121
- package/website/content/docs/architecture/stack-integration.md +0 -461
- package/website/content/docs/changelog.md +0 -246
- package/website/content/docs/cli-reference/index.md +0 -111
- package/website/content/docs/cli-reference/ossa-agents.md +0 -70
- package/website/content/docs/cli-reference/ossa-export.md +0 -56
- package/website/content/docs/cli-reference/ossa-generate.md +0 -66
- package/website/content/docs/cli-reference/ossa-gitlab-agent.md +0 -57
- package/website/content/docs/cli-reference/ossa-import.md +0 -56
- package/website/content/docs/cli-reference/ossa-init.md +0 -57
- package/website/content/docs/cli-reference/ossa-migrate.md +0 -62
- package/website/content/docs/cli-reference/ossa-run.md +0 -66
- package/website/content/docs/cli-reference/ossa-schema.md +0 -57
- package/website/content/docs/cli-reference/ossa-setup.md +0 -57
- package/website/content/docs/cli-reference/ossa-validate.md +0 -66
- package/website/content/docs/configuration/index.md +0 -97
- package/website/content/docs/contributing.md +0 -599
- package/website/content/docs/deployment/github-mirroring.md +0 -924
- package/website/content/docs/documentation.md +0 -100
- package/website/content/docs/ecosystem/framework-support.md +0 -1361
- package/website/content/docs/ecosystem/overview.md +0 -366
- package/website/content/docs/errors/index.md +0 -10
- package/website/content/docs/examples/aiflow-framework-integration-with-ossa.md +0 -107
- package/website/content/docs/examples/catalog.md +0 -300
- package/website/content/docs/for-audiences/students-researchers.md +0 -122
- package/website/content/docs/getting-started/index.md +0 -92
- package/website/content/docs/getting-started/installation.md +0 -155
- package/website/content/docs/getting-started/running-agents.md +0 -309
- package/website/content/docs/getting-started.md +0 -91
- package/website/content/docs/integrations/aiflow.md +0 -104
- package/website/content/docs/integrations/drupal.md +0 -105
- package/website/content/docs/migration-guides/agent-schema-comparison.md +0 -232
- package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +0 -1750
- package/website/content/docs/migration-guides/crewai-to-ossa.md +0 -274
- package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +0 -2017
- package/website/content/docs/migration-guides/general-agent-schema.yml +0 -247
- package/website/content/docs/migration-guides/index.md +0 -133
- package/website/content/docs/migration-guides/langchain-to-ossa.md +0 -1714
- package/website/content/docs/migration-guides/langflow-to-ossa.md +0 -2075
- package/website/content/docs/migration-guides/migration-manifest.json +0 -64
- package/website/content/docs/migration-guides/openai-to-ossa.md +0 -1202
- package/website/content/docs/openapi-extensions/examples.md +0 -550
- package/website/content/docs/openapi-extensions/index.md +0 -551
- package/website/content/docs/openapi-extensions/operation-extensions.md +0 -457
- package/website/content/docs/openapi-extensions/root-extensions.md +0 -410
- package/website/content/docs/ossa-compliant-badge.md +0 -251
- package/website/content/docs/pre-release/index.md +0 -175
- package/website/content/docs/quick-reference.md +0 -17
- package/website/content/docs/readme.md +0 -35
- package/website/content/docs/releases/v0.2.6.md +0 -99
- package/website/content/docs/schema-reference/agent-capabilities.md +0 -50
- package/website/content/docs/schema-reference/agent-id.md +0 -52
- package/website/content/docs/schema-reference/agent-name.md +0 -50
- package/website/content/docs/schema-reference/agent-role.md +0 -54
- package/website/content/docs/schema-reference/agent-spec.md +0 -406
- package/website/content/docs/schema-reference/agent-version.md +0 -50
- package/website/content/docs/schema-reference/autonomy.md +0 -568
- package/website/content/docs/schema-reference/constraints.md +0 -543
- package/website/content/docs/schema-reference/index.md +0 -45
- package/website/content/docs/schema-reference/llm-config.md +0 -445
- package/website/content/docs/schema-reference/observability.md +0 -654
- package/website/content/docs/schema-reference/ossa-manifest.md +0 -309
- package/website/content/docs/schema-reference/taxonomy.md +0 -509
- package/website/content/docs/schema-reference/tools.md +0 -628
- package/website/content/docs/templates/blog-post.md +0 -43
- package/website/content/docs/types-reference/index.md +0 -105
- package/website/content/docs/use-cases/00-index.md +0 -395
- package/website/content/docs/use-cases/cicd-code-review.md +0 -1236
- package/website/content/docs/use-cases/customer-support.md +0 -1234
- package/website/content/docs/use-cases/enterprise-compliance.md +0 -1208
- package/website/content/docs/use-cases/research-multi-agent.md +0 -1161
- package/website/content/docs/versioning.md +0 -288
- package/website/dev.sh +0 -53
- package/website/docker-compose.dev.yml +0 -36
- package/website/lib/version.ts +0 -35
- package/website/lib/versions.json +0 -103
- package/website/next.config.ts +0 -18
- package/website/nginx.conf +0 -32
- package/website/package-lock.json +0 -9679
- package/website/package.json +0 -59
- package/website/postcss.config.mjs +0 -9
- package/website/scripts/fetch-versions.js +0 -166
- package/website/scripts/generate-examples-index.js +0 -163
- package/website/scripts/merge-docs-to-wiki.ts +0 -207
- package/website/scripts/sync-version.js +0 -72
- package/website/scripts/sync-wiki.ts +0 -322
- package/website/scripts/upload-wiki.ts +0 -199
- package/website/styles/_spacing.scss +0 -453
- package/website/styles/_tokens.scss +0 -245
- package/website/styles/_typography.scss +0 -361
- package/website/styles/_variables.scss +0 -287
- package/website/tailwind.config.ts +0 -170
|
@@ -1,1236 +0,0 @@
|
|
|
1
|
-
# CI/CD Automated Code Review Agent
|
|
2
|
-
|
|
3
|
-
## Problem Statement
|
|
4
|
-
|
|
5
|
-
Modern development teams face code review bottlenecks:
|
|
6
|
-
- **Slow PR reviews**: Manual reviews take 1-3 days, blocking deployments
|
|
7
|
-
- **Inconsistent quality**: Different reviewers apply different standards
|
|
8
|
-
- **Missed issues**: Humans miss common bugs, security flaws, and style violations
|
|
9
|
-
- **Context switching**: Developers interrupted for trivial review comments
|
|
10
|
-
- **No 24/7 coverage**: PRs submitted outside business hours wait until next day
|
|
11
|
-
|
|
12
|
-
**Solution**: An OSSA-powered CI/CD agent that automatically reviews pull requests, runs linters, executes tests, checks security vulnerabilities, and provides actionable feedback in minutes—not days.
|
|
13
|
-
|
|
14
|
-
## Architecture Overview
|
|
15
|
-
|
|
16
|
-
```mermaid
|
|
17
|
-
graph TB
|
|
18
|
-
subgraph "CI/CD Pipeline"
|
|
19
|
-
PR[Pull Request Created]
|
|
20
|
-
Webhook[Git Webhook]
|
|
21
|
-
Agent[OSSA Code Review Agent]
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
subgraph "Analysis Tools"
|
|
25
|
-
Lint[ESLint/Prettier]
|
|
26
|
-
Test[Jest/Pytest]
|
|
27
|
-
Security[Snyk/Trivy]
|
|
28
|
-
Coverage[Coverage Report]
|
|
29
|
-
Complexity[Cyclomatic Complexity]
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
subgraph "AI Analysis"
|
|
33
|
-
LLM[GPT-4/Claude]
|
|
34
|
-
Patterns[Anti-Pattern Detection]
|
|
35
|
-
Suggestions[Improvement Suggestions]
|
|
36
|
-
Learning[Historical PR Analysis]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
subgraph "Outputs"
|
|
40
|
-
Comments[Inline PR Comments]
|
|
41
|
-
Status[CI Status Checks]
|
|
42
|
-
Report[Review Summary]
|
|
43
|
-
Metrics[Code Quality Metrics]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
PR --> Webhook
|
|
47
|
-
Webhook --> Agent
|
|
48
|
-
|
|
49
|
-
Agent --> Lint
|
|
50
|
-
Agent --> Test
|
|
51
|
-
Agent --> Security
|
|
52
|
-
Agent --> Coverage
|
|
53
|
-
Agent --> Complexity
|
|
54
|
-
|
|
55
|
-
Agent --> LLM
|
|
56
|
-
LLM --> Patterns
|
|
57
|
-
LLM --> Suggestions
|
|
58
|
-
LLM --> Learning
|
|
59
|
-
|
|
60
|
-
Agent --> Comments
|
|
61
|
-
Agent --> Status
|
|
62
|
-
Agent --> Report
|
|
63
|
-
Agent --> Metrics
|
|
64
|
-
|
|
65
|
-
Learning -.->|Feedback Loop| LLM
|
|
66
|
-
|
|
67
|
-
style Agent fill:#e1f5ff
|
|
68
|
-
style LLM fill:#ffe1f5
|
|
69
|
-
style Comments fill:#e1ffe1
|
|
70
|
-
style Security fill:#ffe1e1
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## OSSA Manifest
|
|
74
|
-
|
|
75
|
-
```yaml
|
|
76
|
-
apiVersion: ossa/v0.2.x
|
|
77
|
-
kind: Agent
|
|
78
|
-
metadata:
|
|
79
|
-
name: cicd-code-reviewer
|
|
80
|
-
namespace: ci-cd
|
|
81
|
-
labels:
|
|
82
|
-
app: code-review
|
|
83
|
-
tier: automation
|
|
84
|
-
integration: github-gitlab
|
|
85
|
-
annotations:
|
|
86
|
-
cicd.ossa.io/triggers: "pull_request,merge_request"
|
|
87
|
-
cicd.ossa.io/languages: "typescript,python,go,rust,java"
|
|
88
|
-
cost.ossa.io/budget-monthly: "200.00"
|
|
89
|
-
|
|
90
|
-
spec:
|
|
91
|
-
type: worker
|
|
92
|
-
description: |
|
|
93
|
-
Automated code review agent for CI/CD pipelines.
|
|
94
|
-
Performs linting, testing, security scanning, and AI-powered
|
|
95
|
-
code analysis on every pull request.
|
|
96
|
-
|
|
97
|
-
runtime:
|
|
98
|
-
type: docker
|
|
99
|
-
image: registry.example.com/agents/code-reviewer:3.0.0
|
|
100
|
-
command: ["/app/reviewer"]
|
|
101
|
-
args:
|
|
102
|
-
- "--mode=pr-review"
|
|
103
|
-
- "--auto-comment=true"
|
|
104
|
-
- "--auto-approve=false"
|
|
105
|
-
resources:
|
|
106
|
-
limits:
|
|
107
|
-
cpu: "4000m"
|
|
108
|
-
memory: "8Gi"
|
|
109
|
-
requests:
|
|
110
|
-
cpu: "1000m"
|
|
111
|
-
memory: "2Gi"
|
|
112
|
-
env:
|
|
113
|
-
- name: LOG_LEVEL
|
|
114
|
-
value: "info"
|
|
115
|
-
- name: SUPPORTED_LANGUAGES
|
|
116
|
-
value: "typescript,python,go,rust,java"
|
|
117
|
-
- name: AI_MODEL
|
|
118
|
-
value: "gpt-4-turbo-preview"
|
|
119
|
-
- name: MAX_PR_SIZE_FILES
|
|
120
|
-
value: "100"
|
|
121
|
-
- name: MAX_PR_SIZE_LINES
|
|
122
|
-
value: "5000"
|
|
123
|
-
- name: ENABLE_AUTO_FIX
|
|
124
|
-
value: "true"
|
|
125
|
-
|
|
126
|
-
capabilities:
|
|
127
|
-
- name: review_pull_request
|
|
128
|
-
description: |
|
|
129
|
-
Comprehensive pull request review including linting, testing,
|
|
130
|
-
security scanning, and AI-powered code analysis.
|
|
131
|
-
input_schema:
|
|
132
|
-
type: object
|
|
133
|
-
required: [repository, pr_number, base_branch, head_branch]
|
|
134
|
-
properties:
|
|
135
|
-
repository:
|
|
136
|
-
type: string
|
|
137
|
-
description: "Repository URL or identifier"
|
|
138
|
-
pr_number:
|
|
139
|
-
type: integer
|
|
140
|
-
description: "Pull request number"
|
|
141
|
-
base_branch:
|
|
142
|
-
type: string
|
|
143
|
-
description: "Target branch (e.g., main)"
|
|
144
|
-
head_branch:
|
|
145
|
-
type: string
|
|
146
|
-
description: "Source branch (e.g., feature/new-api)"
|
|
147
|
-
reviewers:
|
|
148
|
-
type: array
|
|
149
|
-
items:
|
|
150
|
-
type: string
|
|
151
|
-
description: "GitHub/GitLab usernames for notification"
|
|
152
|
-
auto_fix:
|
|
153
|
-
type: boolean
|
|
154
|
-
default: false
|
|
155
|
-
description: "Automatically commit fixes for trivial issues"
|
|
156
|
-
output_schema:
|
|
157
|
-
type: object
|
|
158
|
-
required: [review_id, status, summary]
|
|
159
|
-
properties:
|
|
160
|
-
review_id:
|
|
161
|
-
type: string
|
|
162
|
-
format: uuid
|
|
163
|
-
status:
|
|
164
|
-
type: string
|
|
165
|
-
enum: [approved, changes_requested, commented, error]
|
|
166
|
-
summary:
|
|
167
|
-
type: object
|
|
168
|
-
required: [total_files, total_issues, critical_issues]
|
|
169
|
-
properties:
|
|
170
|
-
total_files:
|
|
171
|
-
type: integer
|
|
172
|
-
total_lines_added:
|
|
173
|
-
type: integer
|
|
174
|
-
total_lines_deleted:
|
|
175
|
-
type: integer
|
|
176
|
-
total_issues:
|
|
177
|
-
type: integer
|
|
178
|
-
critical_issues:
|
|
179
|
-
type: integer
|
|
180
|
-
high_issues:
|
|
181
|
-
type: integer
|
|
182
|
-
medium_issues:
|
|
183
|
-
type: integer
|
|
184
|
-
low_issues:
|
|
185
|
-
type: integer
|
|
186
|
-
issues:
|
|
187
|
-
type: array
|
|
188
|
-
items:
|
|
189
|
-
type: object
|
|
190
|
-
required: [file, line, severity, category, message]
|
|
191
|
-
properties:
|
|
192
|
-
file:
|
|
193
|
-
type: string
|
|
194
|
-
line:
|
|
195
|
-
type: integer
|
|
196
|
-
severity:
|
|
197
|
-
type: string
|
|
198
|
-
enum: [critical, high, medium, low, info]
|
|
199
|
-
category:
|
|
200
|
-
type: string
|
|
201
|
-
enum: [bug, security, style, performance, best-practice, documentation]
|
|
202
|
-
message:
|
|
203
|
-
type: string
|
|
204
|
-
suggestion:
|
|
205
|
-
type: string
|
|
206
|
-
auto_fixable:
|
|
207
|
-
type: boolean
|
|
208
|
-
test_results:
|
|
209
|
-
type: object
|
|
210
|
-
properties:
|
|
211
|
-
passed:
|
|
212
|
-
type: boolean
|
|
213
|
-
total_tests:
|
|
214
|
-
type: integer
|
|
215
|
-
failed_tests:
|
|
216
|
-
type: integer
|
|
217
|
-
coverage_percent:
|
|
218
|
-
type: number
|
|
219
|
-
security_scan:
|
|
220
|
-
type: object
|
|
221
|
-
properties:
|
|
222
|
-
vulnerabilities_found:
|
|
223
|
-
type: integer
|
|
224
|
-
critical_vulnerabilities:
|
|
225
|
-
type: integer
|
|
226
|
-
dependencies_scanned:
|
|
227
|
-
type: integer
|
|
228
|
-
ai_analysis:
|
|
229
|
-
type: object
|
|
230
|
-
properties:
|
|
231
|
-
code_quality_score:
|
|
232
|
-
type: number
|
|
233
|
-
minimum: 0
|
|
234
|
-
maximum: 100
|
|
235
|
-
maintainability_index:
|
|
236
|
-
type: number
|
|
237
|
-
cognitive_complexity:
|
|
238
|
-
type: number
|
|
239
|
-
suggestions:
|
|
240
|
-
type: array
|
|
241
|
-
items:
|
|
242
|
-
type: string
|
|
243
|
-
timestamp:
|
|
244
|
-
type: string
|
|
245
|
-
format: date-time
|
|
246
|
-
|
|
247
|
-
- name: run_linters
|
|
248
|
-
description: |
|
|
249
|
-
Run configured linters (ESLint, Prettier, Black, Pylint, gofmt, etc.)
|
|
250
|
-
on changed files.
|
|
251
|
-
input_schema:
|
|
252
|
-
type: object
|
|
253
|
-
required: [files, language]
|
|
254
|
-
properties:
|
|
255
|
-
files:
|
|
256
|
-
type: array
|
|
257
|
-
items:
|
|
258
|
-
type: string
|
|
259
|
-
language:
|
|
260
|
-
type: string
|
|
261
|
-
enum: [typescript, javascript, python, go, rust, java]
|
|
262
|
-
fix:
|
|
263
|
-
type: boolean
|
|
264
|
-
default: false
|
|
265
|
-
output_schema:
|
|
266
|
-
type: object
|
|
267
|
-
properties:
|
|
268
|
-
issues:
|
|
269
|
-
type: array
|
|
270
|
-
items:
|
|
271
|
-
type: object
|
|
272
|
-
properties:
|
|
273
|
-
file: {type: string}
|
|
274
|
-
line: {type: integer}
|
|
275
|
-
column: {type: integer}
|
|
276
|
-
rule: {type: string}
|
|
277
|
-
message: {type: string}
|
|
278
|
-
severity: {type: string}
|
|
279
|
-
fixed:
|
|
280
|
-
type: boolean
|
|
281
|
-
fixes_applied:
|
|
282
|
-
type: array
|
|
283
|
-
items:
|
|
284
|
-
type: string
|
|
285
|
-
|
|
286
|
-
- name: run_tests
|
|
287
|
-
description: |
|
|
288
|
-
Execute test suite for changed code and collect coverage metrics.
|
|
289
|
-
input_schema:
|
|
290
|
-
type: object
|
|
291
|
-
required: [test_command, working_directory]
|
|
292
|
-
properties:
|
|
293
|
-
test_command:
|
|
294
|
-
type: string
|
|
295
|
-
description: "e.g., npm test, pytest, go test"
|
|
296
|
-
working_directory:
|
|
297
|
-
type: string
|
|
298
|
-
coverage:
|
|
299
|
-
type: boolean
|
|
300
|
-
default: true
|
|
301
|
-
timeout_seconds:
|
|
302
|
-
type: integer
|
|
303
|
-
default: 600
|
|
304
|
-
output_schema:
|
|
305
|
-
type: object
|
|
306
|
-
properties:
|
|
307
|
-
passed:
|
|
308
|
-
type: boolean
|
|
309
|
-
total:
|
|
310
|
-
type: integer
|
|
311
|
-
failed:
|
|
312
|
-
type: integer
|
|
313
|
-
skipped:
|
|
314
|
-
type: integer
|
|
315
|
-
duration_seconds:
|
|
316
|
-
type: number
|
|
317
|
-
coverage_percent:
|
|
318
|
-
type: number
|
|
319
|
-
failed_tests:
|
|
320
|
-
type: array
|
|
321
|
-
items:
|
|
322
|
-
type: object
|
|
323
|
-
properties:
|
|
324
|
-
name: {type: string}
|
|
325
|
-
error: {type: string}
|
|
326
|
-
|
|
327
|
-
- name: security_scan
|
|
328
|
-
description: |
|
|
329
|
-
Scan for security vulnerabilities in code and dependencies.
|
|
330
|
-
input_schema:
|
|
331
|
-
type: object
|
|
332
|
-
required: [directory]
|
|
333
|
-
properties:
|
|
334
|
-
directory:
|
|
335
|
-
type: string
|
|
336
|
-
scan_dependencies:
|
|
337
|
-
type: boolean
|
|
338
|
-
default: true
|
|
339
|
-
scan_code:
|
|
340
|
-
type: boolean
|
|
341
|
-
default: true
|
|
342
|
-
severity_threshold:
|
|
343
|
-
type: string
|
|
344
|
-
enum: [critical, high, medium, low]
|
|
345
|
-
default: medium
|
|
346
|
-
output_schema:
|
|
347
|
-
type: object
|
|
348
|
-
properties:
|
|
349
|
-
vulnerabilities:
|
|
350
|
-
type: array
|
|
351
|
-
items:
|
|
352
|
-
type: object
|
|
353
|
-
properties:
|
|
354
|
-
id: {type: string}
|
|
355
|
-
title: {type: string}
|
|
356
|
-
severity: {type: string}
|
|
357
|
-
package: {type: string}
|
|
358
|
-
version: {type: string}
|
|
359
|
-
fixed_in: {type: string}
|
|
360
|
-
description: {type: string}
|
|
361
|
-
total:
|
|
362
|
-
type: integer
|
|
363
|
-
by_severity:
|
|
364
|
-
type: object
|
|
365
|
-
properties:
|
|
366
|
-
critical: {type: integer}
|
|
367
|
-
high: {type: integer}
|
|
368
|
-
medium: {type: integer}
|
|
369
|
-
low: {type: integer}
|
|
370
|
-
|
|
371
|
-
- name: analyze_complexity
|
|
372
|
-
description: |
|
|
373
|
-
Analyze code complexity metrics (cyclomatic complexity,
|
|
374
|
-
cognitive complexity, maintainability index).
|
|
375
|
-
input_schema:
|
|
376
|
-
type: object
|
|
377
|
-
required: [files]
|
|
378
|
-
properties:
|
|
379
|
-
files:
|
|
380
|
-
type: array
|
|
381
|
-
items:
|
|
382
|
-
type: string
|
|
383
|
-
output_schema:
|
|
384
|
-
type: object
|
|
385
|
-
properties:
|
|
386
|
-
files:
|
|
387
|
-
type: array
|
|
388
|
-
items:
|
|
389
|
-
type: object
|
|
390
|
-
properties:
|
|
391
|
-
file: {type: string}
|
|
392
|
-
cyclomatic_complexity: {type: number}
|
|
393
|
-
cognitive_complexity: {type: number}
|
|
394
|
-
maintainability_index: {type: number}
|
|
395
|
-
functions:
|
|
396
|
-
type: array
|
|
397
|
-
items:
|
|
398
|
-
type: object
|
|
399
|
-
properties:
|
|
400
|
-
name: {type: string}
|
|
401
|
-
complexity: {type: number}
|
|
402
|
-
lines: {type: integer}
|
|
403
|
-
|
|
404
|
-
policies:
|
|
405
|
-
quality_gates:
|
|
406
|
-
min_test_coverage: 80
|
|
407
|
-
max_cyclomatic_complexity: 10
|
|
408
|
-
max_cognitive_complexity: 15
|
|
409
|
-
max_function_length: 50
|
|
410
|
-
max_file_length: 500
|
|
411
|
-
block_on_critical_security: true
|
|
412
|
-
block_on_failed_tests: true
|
|
413
|
-
|
|
414
|
-
auto_approval:
|
|
415
|
-
enabled: false # Require human approval
|
|
416
|
-
conditions:
|
|
417
|
-
- all_tests_pass: true
|
|
418
|
-
- no_security_issues: true
|
|
419
|
-
- no_linting_errors: true
|
|
420
|
-
- coverage_maintained: true
|
|
421
|
-
- max_files_changed: 5
|
|
422
|
-
- max_lines_changed: 200
|
|
423
|
-
|
|
424
|
-
auto_fix:
|
|
425
|
-
enabled: true
|
|
426
|
-
allowed_fixes:
|
|
427
|
-
- formatting
|
|
428
|
-
- import_sorting
|
|
429
|
-
- unused_imports
|
|
430
|
-
- trailing_whitespace
|
|
431
|
-
require_approval_for:
|
|
432
|
-
- logic_changes
|
|
433
|
-
- refactoring
|
|
434
|
-
|
|
435
|
-
cost_management:
|
|
436
|
-
budget:
|
|
437
|
-
monthly_limit_usd: 200.00
|
|
438
|
-
per_pr_limit_usd: 2.00
|
|
439
|
-
alert_threshold: 0.85
|
|
440
|
-
optimization:
|
|
441
|
-
cache_dependencies: true
|
|
442
|
-
skip_unchanged_files: true
|
|
443
|
-
parallel_analysis: true
|
|
444
|
-
|
|
445
|
-
integration:
|
|
446
|
-
protocol: webhook
|
|
447
|
-
api_version: v1
|
|
448
|
-
|
|
449
|
-
webhooks:
|
|
450
|
-
github:
|
|
451
|
-
events:
|
|
452
|
-
- pull_request.opened
|
|
453
|
-
- pull_request.synchronize
|
|
454
|
-
- pull_request.reopened
|
|
455
|
-
url: https://code-reviewer.example.com/webhooks/github
|
|
456
|
-
secret_env: GITHUB_WEBHOOK_SECRET
|
|
457
|
-
|
|
458
|
-
gitlab:
|
|
459
|
-
events:
|
|
460
|
-
- merge_request.open
|
|
461
|
-
- merge_request.update
|
|
462
|
-
url: https://code-reviewer.example.com/webhooks/gitlab
|
|
463
|
-
secret_env: GITLAB_WEBHOOK_SECRET
|
|
464
|
-
|
|
465
|
-
authentication:
|
|
466
|
-
github:
|
|
467
|
-
type: token
|
|
468
|
-
token_env: GITHUB_TOKEN
|
|
469
|
-
permissions:
|
|
470
|
-
- read:repo
|
|
471
|
-
- write:discussions
|
|
472
|
-
- read:packages
|
|
473
|
-
|
|
474
|
-
gitlab:
|
|
475
|
-
type: token
|
|
476
|
-
token_env: GITLAB_TOKEN
|
|
477
|
-
permissions:
|
|
478
|
-
- read_repository
|
|
479
|
-
- write_merge_request
|
|
480
|
-
|
|
481
|
-
endpoints:
|
|
482
|
-
review:
|
|
483
|
-
path: /v1/review/pull-request
|
|
484
|
-
method: POST
|
|
485
|
-
rate_limit: 1000/hour
|
|
486
|
-
|
|
487
|
-
status:
|
|
488
|
-
path: /v1/review/{review_id}/status
|
|
489
|
-
method: GET
|
|
490
|
-
rate_limit: 5000/hour
|
|
491
|
-
|
|
492
|
-
monitoring:
|
|
493
|
-
health_check:
|
|
494
|
-
endpoint: http://localhost:8080/health
|
|
495
|
-
interval_seconds: 15
|
|
496
|
-
timeout_seconds: 5
|
|
497
|
-
|
|
498
|
-
metrics:
|
|
499
|
-
enabled: true
|
|
500
|
-
exporter: prometheus
|
|
501
|
-
port: 9090
|
|
502
|
-
custom_metrics:
|
|
503
|
-
- prs_reviewed_total
|
|
504
|
-
- review_duration_seconds
|
|
505
|
-
- issues_found_total
|
|
506
|
-
- auto_fixes_applied_total
|
|
507
|
-
- tests_run_total
|
|
508
|
-
- security_vulnerabilities_found
|
|
509
|
-
|
|
510
|
-
traces:
|
|
511
|
-
enabled: true
|
|
512
|
-
exporter: jaeger
|
|
513
|
-
sample_rate: 0.2
|
|
514
|
-
|
|
515
|
-
logs:
|
|
516
|
-
level: info
|
|
517
|
-
format: json
|
|
518
|
-
output: stdout
|
|
519
|
-
|
|
520
|
-
metadata:
|
|
521
|
-
version: 3.0.0
|
|
522
|
-
author:
|
|
523
|
-
name: Engineering Team
|
|
524
|
-
email: eng@example.com
|
|
525
|
-
organization: Example Corp
|
|
526
|
-
license: MIT
|
|
527
|
-
tags:
|
|
528
|
-
- ci-cd
|
|
529
|
-
- code-review
|
|
530
|
-
- automation
|
|
531
|
-
- testing
|
|
532
|
-
- security
|
|
533
|
-
keywords:
|
|
534
|
-
- pull request review
|
|
535
|
-
- automated testing
|
|
536
|
-
- code quality
|
|
537
|
-
- security scanning
|
|
538
|
-
documentation_url: https://docs.example.com/agents/code-reviewer
|
|
539
|
-
source_repository: https://github.com/example/code-reviewer-agent
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
## Implementation (Python)
|
|
543
|
-
|
|
544
|
-
```python
|
|
545
|
-
"""
|
|
546
|
-
CI/CD Automated Code Review Agent
|
|
547
|
-
|
|
548
|
-
Production-ready OSSA agent for automated pull request reviews
|
|
549
|
-
with linting, testing, security scanning, and AI analysis.
|
|
550
|
-
"""
|
|
551
|
-
|
|
552
|
-
import asyncio
|
|
553
|
-
import json
|
|
554
|
-
import os
|
|
555
|
-
from dataclasses import dataclass, asdict
|
|
556
|
-
from datetime import datetime
|
|
557
|
-
from typing import List, Dict, Optional, Any
|
|
558
|
-
from enum import Enum
|
|
559
|
-
|
|
560
|
-
from ossa_runtime import Agent, OSSARuntime
|
|
561
|
-
from github import Github
|
|
562
|
-
from gitlab import Gitlab
|
|
563
|
-
import openai
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
class Severity(Enum):
|
|
567
|
-
CRITICAL = "critical"
|
|
568
|
-
HIGH = "high"
|
|
569
|
-
MEDIUM = "medium"
|
|
570
|
-
LOW = "low"
|
|
571
|
-
INFO = "info"
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
class Category(Enum):
|
|
575
|
-
BUG = "bug"
|
|
576
|
-
SECURITY = "security"
|
|
577
|
-
STYLE = "style"
|
|
578
|
-
PERFORMANCE = "performance"
|
|
579
|
-
BEST_PRACTICE = "best-practice"
|
|
580
|
-
DOCUMENTATION = "documentation"
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
@dataclass
|
|
584
|
-
class Issue:
|
|
585
|
-
file: str
|
|
586
|
-
line: int
|
|
587
|
-
severity: Severity
|
|
588
|
-
category: Category
|
|
589
|
-
message: str
|
|
590
|
-
suggestion: Optional[str] = None
|
|
591
|
-
auto_fixable: bool = False
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
@dataclass
|
|
595
|
-
class ReviewSummary:
|
|
596
|
-
total_files: int
|
|
597
|
-
total_lines_added: int
|
|
598
|
-
total_lines_deleted: int
|
|
599
|
-
total_issues: int
|
|
600
|
-
critical_issues: int
|
|
601
|
-
high_issues: int
|
|
602
|
-
medium_issues: int
|
|
603
|
-
low_issues: int
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
@dataclass
|
|
607
|
-
class TestResults:
|
|
608
|
-
passed: bool
|
|
609
|
-
total_tests: int
|
|
610
|
-
failed_tests: int
|
|
611
|
-
coverage_percent: float
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
@dataclass
|
|
615
|
-
class SecurityScan:
|
|
616
|
-
vulnerabilities_found: int
|
|
617
|
-
critical_vulnerabilities: int
|
|
618
|
-
dependencies_scanned: int
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
@dataclass
|
|
622
|
-
class AIAnalysis:
|
|
623
|
-
code_quality_score: float
|
|
624
|
-
maintainability_index: float
|
|
625
|
-
cognitive_complexity: float
|
|
626
|
-
suggestions: List[str]
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
@dataclass
|
|
630
|
-
class ReviewResult:
|
|
631
|
-
review_id: str
|
|
632
|
-
status: str # approved, changes_requested, commented, error
|
|
633
|
-
summary: ReviewSummary
|
|
634
|
-
issues: List[Issue]
|
|
635
|
-
test_results: Optional[TestResults]
|
|
636
|
-
security_scan: Optional[SecurityScan]
|
|
637
|
-
ai_analysis: Optional[AIAnalysis]
|
|
638
|
-
timestamp: datetime
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
class CodeReviewerAgent(Agent):
|
|
642
|
-
"""
|
|
643
|
-
OSSA agent for automated code review in CI/CD pipelines.
|
|
644
|
-
"""
|
|
645
|
-
|
|
646
|
-
def __init__(self, runtime: OSSARuntime):
|
|
647
|
-
super().__init__(runtime)
|
|
648
|
-
|
|
649
|
-
self.github_client = None
|
|
650
|
-
self.gitlab_client = None
|
|
651
|
-
self.openai_client = None
|
|
652
|
-
|
|
653
|
-
self._initialize_clients()
|
|
654
|
-
|
|
655
|
-
def _initialize_clients(self):
|
|
656
|
-
"""Initialize Git platform and AI clients."""
|
|
657
|
-
github_token = os.getenv("GITHUB_TOKEN")
|
|
658
|
-
if github_token:
|
|
659
|
-
self.github_client = Github(github_token)
|
|
660
|
-
|
|
661
|
-
gitlab_token = os.getenv("GITLAB_TOKEN")
|
|
662
|
-
if gitlab_token:
|
|
663
|
-
self.gitlab_client = Gitlab("https://gitlab.com", private_token=gitlab_token)
|
|
664
|
-
|
|
665
|
-
openai_api_key = os.getenv("OPENAI_API_KEY")
|
|
666
|
-
if openai_api_key:
|
|
667
|
-
openai.api_key = openai_api_key
|
|
668
|
-
self.openai_client = openai
|
|
669
|
-
|
|
670
|
-
async def review_pull_request(
|
|
671
|
-
self,
|
|
672
|
-
repository: str,
|
|
673
|
-
pr_number: int,
|
|
674
|
-
base_branch: str,
|
|
675
|
-
head_branch: str,
|
|
676
|
-
reviewers: Optional[List[str]] = None,
|
|
677
|
-
auto_fix: bool = False
|
|
678
|
-
) -> ReviewResult:
|
|
679
|
-
"""
|
|
680
|
-
Comprehensive pull request review.
|
|
681
|
-
|
|
682
|
-
Args:
|
|
683
|
-
repository: Repository URL or identifier
|
|
684
|
-
pr_number: Pull request number
|
|
685
|
-
base_branch: Target branch
|
|
686
|
-
head_branch: Source branch
|
|
687
|
-
reviewers: List of reviewers to notify
|
|
688
|
-
auto_fix: Automatically commit fixes for trivial issues
|
|
689
|
-
|
|
690
|
-
Returns:
|
|
691
|
-
ReviewResult with comprehensive analysis
|
|
692
|
-
"""
|
|
693
|
-
review_id = self._generate_review_id()
|
|
694
|
-
|
|
695
|
-
self.logger.info(f"Starting review {review_id} for PR #{pr_number}")
|
|
696
|
-
|
|
697
|
-
try:
|
|
698
|
-
# Fetch PR details
|
|
699
|
-
pr = await self._fetch_pull_request(repository, pr_number)
|
|
700
|
-
|
|
701
|
-
# Get changed files
|
|
702
|
-
changed_files = await self._get_changed_files(pr)
|
|
703
|
-
|
|
704
|
-
if len(changed_files) > int(os.getenv("MAX_PR_SIZE_FILES", "100")):
|
|
705
|
-
return ReviewResult(
|
|
706
|
-
review_id=review_id,
|
|
707
|
-
status="error",
|
|
708
|
-
summary=ReviewSummary(0, 0, 0, 0, 0, 0, 0, 0),
|
|
709
|
-
issues=[],
|
|
710
|
-
test_results=None,
|
|
711
|
-
security_scan=None,
|
|
712
|
-
ai_analysis=None,
|
|
713
|
-
timestamp=datetime.utcnow()
|
|
714
|
-
)
|
|
715
|
-
|
|
716
|
-
# Run all checks in parallel
|
|
717
|
-
results = await asyncio.gather(
|
|
718
|
-
self._run_linters(changed_files),
|
|
719
|
-
self._run_tests(repository),
|
|
720
|
-
self._security_scan(repository),
|
|
721
|
-
self._analyze_complexity(changed_files),
|
|
722
|
-
self._ai_analysis(changed_files, pr),
|
|
723
|
-
return_exceptions=True
|
|
724
|
-
)
|
|
725
|
-
|
|
726
|
-
linter_issues = results[0] if not isinstance(results[0], Exception) else []
|
|
727
|
-
test_results = results[1] if not isinstance(results[1], Exception) else None
|
|
728
|
-
security_scan = results[2] if not isinstance(results[2], Exception) else None
|
|
729
|
-
complexity_issues = results[3] if not isinstance(results[3], Exception) else []
|
|
730
|
-
ai_analysis = results[4] if not isinstance(results[4], Exception) else None
|
|
731
|
-
|
|
732
|
-
# Combine all issues
|
|
733
|
-
all_issues = linter_issues + complexity_issues
|
|
734
|
-
|
|
735
|
-
# Generate summary
|
|
736
|
-
summary = self._generate_summary(changed_files, all_issues)
|
|
737
|
-
|
|
738
|
-
# Determine status
|
|
739
|
-
status = self._determine_status(summary, test_results, security_scan)
|
|
740
|
-
|
|
741
|
-
# Post review comments
|
|
742
|
-
await self._post_review_comments(pr, all_issues, status)
|
|
743
|
-
|
|
744
|
-
# Auto-fix if enabled and appropriate
|
|
745
|
-
if auto_fix and status == "commented":
|
|
746
|
-
await self._apply_auto_fixes(pr, all_issues)
|
|
747
|
-
|
|
748
|
-
# Notify reviewers
|
|
749
|
-
if reviewers:
|
|
750
|
-
await self._notify_reviewers(pr, reviewers)
|
|
751
|
-
|
|
752
|
-
result = ReviewResult(
|
|
753
|
-
review_id=review_id,
|
|
754
|
-
status=status,
|
|
755
|
-
summary=summary,
|
|
756
|
-
issues=all_issues,
|
|
757
|
-
test_results=test_results,
|
|
758
|
-
security_scan=security_scan,
|
|
759
|
-
ai_analysis=ai_analysis,
|
|
760
|
-
timestamp=datetime.utcnow()
|
|
761
|
-
)
|
|
762
|
-
|
|
763
|
-
self.logger.info(f"Review {review_id} completed with status: {status}")
|
|
764
|
-
|
|
765
|
-
# Record metrics
|
|
766
|
-
self.metrics.increment("prs_reviewed_total", {"status": status})
|
|
767
|
-
self.metrics.gauge("issues_found_total", summary.total_issues)
|
|
768
|
-
|
|
769
|
-
return result
|
|
770
|
-
|
|
771
|
-
except Exception as e:
|
|
772
|
-
self.logger.error(f"Review {review_id} failed: {str(e)}")
|
|
773
|
-
self.metrics.increment("prs_reviewed_total", {"status": "error"})
|
|
774
|
-
raise
|
|
775
|
-
|
|
776
|
-
async def _run_linters(self, files: List[str]) -> List[Issue]:
|
|
777
|
-
"""Run linters on changed files."""
|
|
778
|
-
issues = []
|
|
779
|
-
|
|
780
|
-
# Group files by language
|
|
781
|
-
files_by_lang = self._group_files_by_language(files)
|
|
782
|
-
|
|
783
|
-
# Run appropriate linter for each language
|
|
784
|
-
for lang, lang_files in files_by_lang.items():
|
|
785
|
-
if lang == "typescript" or lang == "javascript":
|
|
786
|
-
issues.extend(await self._run_eslint(lang_files))
|
|
787
|
-
elif lang == "python":
|
|
788
|
-
issues.extend(await self._run_pylint(lang_files))
|
|
789
|
-
elif lang == "go":
|
|
790
|
-
issues.extend(await self._run_golint(lang_files))
|
|
791
|
-
# Add more languages as needed
|
|
792
|
-
|
|
793
|
-
return issues
|
|
794
|
-
|
|
795
|
-
async def _run_eslint(self, files: List[str]) -> List[Issue]:
|
|
796
|
-
"""Run ESLint on TypeScript/JavaScript files."""
|
|
797
|
-
issues = []
|
|
798
|
-
|
|
799
|
-
# Execute ESLint
|
|
800
|
-
cmd = f"npx eslint --format json {' '.join(files)}"
|
|
801
|
-
result = await self._execute_command(cmd)
|
|
802
|
-
|
|
803
|
-
if result["returncode"] != 0:
|
|
804
|
-
# Parse ESLint JSON output
|
|
805
|
-
eslint_results = json.loads(result["stdout"])
|
|
806
|
-
|
|
807
|
-
for file_result in eslint_results:
|
|
808
|
-
for message in file_result.get("messages", []):
|
|
809
|
-
issues.append(Issue(
|
|
810
|
-
file=file_result["filePath"],
|
|
811
|
-
line=message["line"],
|
|
812
|
-
severity=self._map_severity(message["severity"]),
|
|
813
|
-
category=Category.STYLE,
|
|
814
|
-
message=f"{message['ruleId']}: {message['message']}",
|
|
815
|
-
suggestion=message.get("fix"),
|
|
816
|
-
auto_fixable=message.get("fix") is not None
|
|
817
|
-
))
|
|
818
|
-
|
|
819
|
-
return issues
|
|
820
|
-
|
|
821
|
-
async def _run_tests(self, repository: str) -> TestResults:
|
|
822
|
-
"""Execute test suite."""
|
|
823
|
-
self.logger.info("Running tests...")
|
|
824
|
-
|
|
825
|
-
# Detect test framework
|
|
826
|
-
test_command = self._detect_test_command(repository)
|
|
827
|
-
|
|
828
|
-
# Run tests with coverage
|
|
829
|
-
result = await self._execute_command(f"{test_command} --coverage")
|
|
830
|
-
|
|
831
|
-
# Parse test results
|
|
832
|
-
# (Implementation depends on test framework)
|
|
833
|
-
|
|
834
|
-
return TestResults(
|
|
835
|
-
passed=result["returncode"] == 0,
|
|
836
|
-
total_tests=100, # Parse from output
|
|
837
|
-
failed_tests=0,
|
|
838
|
-
coverage_percent=85.5
|
|
839
|
-
)
|
|
840
|
-
|
|
841
|
-
async def _security_scan(self, repository: str) -> SecurityScan:
|
|
842
|
-
"""Scan for security vulnerabilities."""
|
|
843
|
-
self.logger.info("Running security scan...")
|
|
844
|
-
|
|
845
|
-
# Run Snyk or Trivy
|
|
846
|
-
cmd = "snyk test --json"
|
|
847
|
-
result = await self._execute_command(cmd)
|
|
848
|
-
|
|
849
|
-
if result["stdout"]:
|
|
850
|
-
scan_results = json.loads(result["stdout"])
|
|
851
|
-
|
|
852
|
-
return SecurityScan(
|
|
853
|
-
vulnerabilities_found=len(scan_results.get("vulnerabilities", [])),
|
|
854
|
-
critical_vulnerabilities=len([
|
|
855
|
-
v for v in scan_results.get("vulnerabilities", [])
|
|
856
|
-
if v["severity"] == "critical"
|
|
857
|
-
]),
|
|
858
|
-
dependencies_scanned=len(scan_results.get("dependencies", []))
|
|
859
|
-
)
|
|
860
|
-
|
|
861
|
-
return SecurityScan(0, 0, 0)
|
|
862
|
-
|
|
863
|
-
async def _analyze_complexity(self, files: List[str]) -> List[Issue]:
|
|
864
|
-
"""Analyze code complexity."""
|
|
865
|
-
issues = []
|
|
866
|
-
|
|
867
|
-
# Run complexity analysis tools
|
|
868
|
-
# (radon for Python, lizard for multi-language)
|
|
869
|
-
|
|
870
|
-
for file in files:
|
|
871
|
-
complexity = await self._calculate_complexity(file)
|
|
872
|
-
|
|
873
|
-
if complexity > 10: # Threshold
|
|
874
|
-
issues.append(Issue(
|
|
875
|
-
file=file,
|
|
876
|
-
line=1,
|
|
877
|
-
severity=Severity.MEDIUM,
|
|
878
|
-
category=Category.BEST_PRACTICE,
|
|
879
|
-
message=f"High cyclomatic complexity: {complexity}",
|
|
880
|
-
suggestion="Consider breaking down this function into smaller units"
|
|
881
|
-
))
|
|
882
|
-
|
|
883
|
-
return issues
|
|
884
|
-
|
|
885
|
-
async def _ai_analysis(self, files: List[str], pr: Any) -> AIAnalysis:
|
|
886
|
-
"""AI-powered code analysis using GPT-4."""
|
|
887
|
-
if not self.openai_client:
|
|
888
|
-
return None
|
|
889
|
-
|
|
890
|
-
# Get PR diff
|
|
891
|
-
diff = await self._get_pr_diff(pr)
|
|
892
|
-
|
|
893
|
-
# Prepare prompt
|
|
894
|
-
prompt = f"""
|
|
895
|
-
Review the following code changes and provide:
|
|
896
|
-
1. Code quality score (0-100)
|
|
897
|
-
2. Maintainability concerns
|
|
898
|
-
3. Potential bugs or issues
|
|
899
|
-
4. Improvement suggestions
|
|
900
|
-
|
|
901
|
-
Diff:
|
|
902
|
-
{diff}
|
|
903
|
-
"""
|
|
904
|
-
|
|
905
|
-
response = await self.openai_client.ChatCompletion.acreate(
|
|
906
|
-
model="gpt-4-turbo-preview",
|
|
907
|
-
messages=[
|
|
908
|
-
{"role": "system", "content": "You are an expert code reviewer."},
|
|
909
|
-
{"role": "user", "content": prompt}
|
|
910
|
-
]
|
|
911
|
-
)
|
|
912
|
-
|
|
913
|
-
analysis_text = response.choices[0].message.content
|
|
914
|
-
|
|
915
|
-
# Parse AI response (simplified)
|
|
916
|
-
return AIAnalysis(
|
|
917
|
-
code_quality_score=85.0,
|
|
918
|
-
maintainability_index=75.0,
|
|
919
|
-
cognitive_complexity=8.0,
|
|
920
|
-
suggestions=self._parse_ai_suggestions(analysis_text)
|
|
921
|
-
)
|
|
922
|
-
|
|
923
|
-
def _generate_summary(self, files: List[str], issues: List[Issue]) -> ReviewSummary:
|
|
924
|
-
"""Generate review summary."""
|
|
925
|
-
return ReviewSummary(
|
|
926
|
-
total_files=len(files),
|
|
927
|
-
total_lines_added=0, # Calculate from diff
|
|
928
|
-
total_lines_deleted=0,
|
|
929
|
-
total_issues=len(issues),
|
|
930
|
-
critical_issues=len([i for i in issues if i.severity == Severity.CRITICAL]),
|
|
931
|
-
high_issues=len([i for i in issues if i.severity == Severity.HIGH]),
|
|
932
|
-
medium_issues=len([i for i in issues if i.severity == Severity.MEDIUM]),
|
|
933
|
-
low_issues=len([i for i in issues if i.severity == Severity.LOW])
|
|
934
|
-
)
|
|
935
|
-
|
|
936
|
-
def _determine_status(
|
|
937
|
-
self,
|
|
938
|
-
summary: ReviewSummary,
|
|
939
|
-
test_results: Optional[TestResults],
|
|
940
|
-
security_scan: Optional[SecurityScan]
|
|
941
|
-
) -> str:
|
|
942
|
-
"""Determine review status."""
|
|
943
|
-
# Block on critical security issues
|
|
944
|
-
if security_scan and security_scan.critical_vulnerabilities > 0:
|
|
945
|
-
return "changes_requested"
|
|
946
|
-
|
|
947
|
-
# Block on failed tests
|
|
948
|
-
if test_results and not test_results.passed:
|
|
949
|
-
return "changes_requested"
|
|
950
|
-
|
|
951
|
-
# Request changes for high severity issues
|
|
952
|
-
if summary.critical_issues > 0 or summary.high_issues > 5:
|
|
953
|
-
return "changes_requested"
|
|
954
|
-
|
|
955
|
-
# Comment on medium/low issues
|
|
956
|
-
if summary.total_issues > 0:
|
|
957
|
-
return "commented"
|
|
958
|
-
|
|
959
|
-
# Approve (if auto-approval enabled)
|
|
960
|
-
return "approved"
|
|
961
|
-
|
|
962
|
-
async def _post_review_comments(self, pr: Any, issues: List[Issue], status: str):
|
|
963
|
-
"""Post review comments to PR."""
|
|
964
|
-
# Group issues by file
|
|
965
|
-
issues_by_file = {}
|
|
966
|
-
for issue in issues:
|
|
967
|
-
if issue.file not in issues_by_file:
|
|
968
|
-
issues_by_file[issue.file] = []
|
|
969
|
-
issues_by_file[issue.file].append(issue)
|
|
970
|
-
|
|
971
|
-
# Post inline comments
|
|
972
|
-
for file, file_issues in issues_by_file.items():
|
|
973
|
-
for issue in file_issues:
|
|
974
|
-
comment = self._format_issue_comment(issue)
|
|
975
|
-
await pr.create_review_comment(
|
|
976
|
-
body=comment,
|
|
977
|
-
path=file,
|
|
978
|
-
line=issue.line
|
|
979
|
-
)
|
|
980
|
-
|
|
981
|
-
def _format_issue_comment(self, issue: Issue) -> str:
|
|
982
|
-
"""Format issue as PR comment."""
|
|
983
|
-
severity_emoji = {
|
|
984
|
-
Severity.CRITICAL: "🔴",
|
|
985
|
-
Severity.HIGH: "🟠",
|
|
986
|
-
Severity.MEDIUM: "🟡",
|
|
987
|
-
Severity.LOW: "🟢",
|
|
988
|
-
Severity.INFO: "ℹ️"
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
comment = f"{severity_emoji[issue.severity]} **{issue.severity.value.upper()}** - {issue.category.value}\n\n"
|
|
992
|
-
comment += f"{issue.message}\n\n"
|
|
993
|
-
|
|
994
|
-
if issue.suggestion:
|
|
995
|
-
comment += f"**Suggestion:** {issue.suggestion}\n\n"
|
|
996
|
-
|
|
997
|
-
if issue.auto_fixable:
|
|
998
|
-
comment += "✨ This issue can be auto-fixed.\n"
|
|
999
|
-
|
|
1000
|
-
return comment
|
|
1001
|
-
|
|
1002
|
-
# Helper methods
|
|
1003
|
-
def _generate_review_id(self) -> str:
|
|
1004
|
-
"""Generate unique review ID."""
|
|
1005
|
-
import uuid
|
|
1006
|
-
return str(uuid.uuid4())
|
|
1007
|
-
|
|
1008
|
-
async def _fetch_pull_request(self, repository: str, pr_number: int) -> Any:
|
|
1009
|
-
"""Fetch PR from GitHub/GitLab."""
|
|
1010
|
-
if self.github_client:
|
|
1011
|
-
repo = self.github_client.get_repo(repository)
|
|
1012
|
-
return repo.get_pull(pr_number)
|
|
1013
|
-
# Add GitLab support
|
|
1014
|
-
return None
|
|
1015
|
-
|
|
1016
|
-
async def _get_changed_files(self, pr: Any) -> List[str]:
|
|
1017
|
-
"""Get list of changed files in PR."""
|
|
1018
|
-
return [f.filename for f in pr.get_files()]
|
|
1019
|
-
|
|
1020
|
-
def _group_files_by_language(self, files: List[str]) -> Dict[str, List[str]]:
|
|
1021
|
-
"""Group files by programming language."""
|
|
1022
|
-
groups = {}
|
|
1023
|
-
for file in files:
|
|
1024
|
-
ext = file.split('.')[-1]
|
|
1025
|
-
lang = self._extension_to_language(ext)
|
|
1026
|
-
if lang not in groups:
|
|
1027
|
-
groups[lang] = []
|
|
1028
|
-
groups[lang].append(file)
|
|
1029
|
-
return groups
|
|
1030
|
-
|
|
1031
|
-
def _extension_to_language(self, ext: str) -> str:
|
|
1032
|
-
"""Map file extension to language."""
|
|
1033
|
-
mapping = {
|
|
1034
|
-
'ts': 'typescript',
|
|
1035
|
-
'tsx': 'typescript',
|
|
1036
|
-
'js': 'javascript',
|
|
1037
|
-
'jsx': 'javascript',
|
|
1038
|
-
'py': 'python',
|
|
1039
|
-
'go': 'go',
|
|
1040
|
-
'rs': 'rust',
|
|
1041
|
-
'java': 'java'
|
|
1042
|
-
}
|
|
1043
|
-
return mapping.get(ext, 'unknown')
|
|
1044
|
-
|
|
1045
|
-
def _map_severity(self, eslint_severity: int) -> Severity:
|
|
1046
|
-
"""Map ESLint severity to OSSA severity."""
|
|
1047
|
-
return Severity.HIGH if eslint_severity == 2 else Severity.MEDIUM
|
|
1048
|
-
|
|
1049
|
-
def _detect_test_command(self, repository: str) -> str:
|
|
1050
|
-
"""Detect appropriate test command."""
|
|
1051
|
-
# Check package.json, pytest.ini, go.mod, etc.
|
|
1052
|
-
return "npm test" # Default
|
|
1053
|
-
|
|
1054
|
-
async def _execute_command(self, cmd: str) -> Dict[str, Any]:
|
|
1055
|
-
"""Execute shell command."""
|
|
1056
|
-
process = await asyncio.create_subprocess_shell(
|
|
1057
|
-
cmd,
|
|
1058
|
-
stdout=asyncio.subprocess.PIPE,
|
|
1059
|
-
stderr=asyncio.subprocess.PIPE
|
|
1060
|
-
)
|
|
1061
|
-
stdout, stderr = await process.communicate()
|
|
1062
|
-
return {
|
|
1063
|
-
"returncode": process.returncode,
|
|
1064
|
-
"stdout": stdout.decode(),
|
|
1065
|
-
"stderr": stderr.decode()
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
async def _calculate_complexity(self, file: str) -> int:
|
|
1069
|
-
"""Calculate cyclomatic complexity."""
|
|
1070
|
-
# Use radon, lizard, or similar tool
|
|
1071
|
-
return 5 # Placeholder
|
|
1072
|
-
|
|
1073
|
-
async def _get_pr_diff(self, pr: Any) -> str:
|
|
1074
|
-
"""Get PR diff."""
|
|
1075
|
-
return pr.diff_url # Simplified
|
|
1076
|
-
|
|
1077
|
-
def _parse_ai_suggestions(self, text: str) -> List[str]:
|
|
1078
|
-
"""Parse suggestions from AI response."""
|
|
1079
|
-
# Parse structured output from AI
|
|
1080
|
-
return ["Suggestion 1", "Suggestion 2"] # Placeholder
|
|
1081
|
-
|
|
1082
|
-
async def _apply_auto_fixes(self, pr: Any, issues: List[Issue]):
|
|
1083
|
-
"""Apply auto-fixes for trivial issues."""
|
|
1084
|
-
fixable_issues = [i for i in issues if i.auto_fixable]
|
|
1085
|
-
if fixable_issues:
|
|
1086
|
-
# Apply fixes and commit
|
|
1087
|
-
pass
|
|
1088
|
-
|
|
1089
|
-
async def _notify_reviewers(self, pr: Any, reviewers: List[str]):
|
|
1090
|
-
"""Notify human reviewers."""
|
|
1091
|
-
for reviewer in reviewers:
|
|
1092
|
-
await pr.create_review_request(reviewers=[reviewer])
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
# Entry point
|
|
1096
|
-
async def main():
|
|
1097
|
-
runtime = OSSARuntime(manifest_path="/etc/ossa/manifest.yaml")
|
|
1098
|
-
agent = CodeReviewerAgent(runtime)
|
|
1099
|
-
await agent.start()
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
if __name__ == "__main__":
|
|
1103
|
-
asyncio.run(main())
|
|
1104
|
-
```
|
|
1105
|
-
|
|
1106
|
-
## Deployment Instructions
|
|
1107
|
-
|
|
1108
|
-
### Step 1: GitHub Actions Integration
|
|
1109
|
-
|
|
1110
|
-
```yaml
|
|
1111
|
-
# .github/workflows/code-review.yml
|
|
1112
|
-
name: OSSA Code Review
|
|
1113
|
-
|
|
1114
|
-
on:
|
|
1115
|
-
pull_request:
|
|
1116
|
-
types: [opened, synchronize, reopened]
|
|
1117
|
-
|
|
1118
|
-
jobs:
|
|
1119
|
-
code-review:
|
|
1120
|
-
runs-on: ubuntu-latest
|
|
1121
|
-
|
|
1122
|
-
steps:
|
|
1123
|
-
- name: Checkout code
|
|
1124
|
-
uses: actions/checkout@v3
|
|
1125
|
-
with:
|
|
1126
|
-
fetch-depth: 0
|
|
1127
|
-
|
|
1128
|
-
- name: Run OSSA Code Reviewer
|
|
1129
|
-
uses: docker://registry.example.com/agents/code-reviewer:3.0.0
|
|
1130
|
-
env:
|
|
1131
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
1132
|
-
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
1133
|
-
with:
|
|
1134
|
-
args: |
|
|
1135
|
-
--repository=${{ github.repository }}
|
|
1136
|
-
--pr-number=${{ github.event.pull_request.number }}
|
|
1137
|
-
--base-branch=${{ github.event.pull_request.base.ref }}
|
|
1138
|
-
--head-branch=${{ github.event.pull_request.head.ref }}
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
### Step 2: GitLab CI Integration
|
|
1142
|
-
|
|
1143
|
-
```yaml
|
|
1144
|
-
# .gitlab-ci.yml
|
|
1145
|
-
code-review:
|
|
1146
|
-
stage: test
|
|
1147
|
-
image: registry.example.com/agents/code-reviewer:3.0.0
|
|
1148
|
-
script:
|
|
1149
|
-
- |
|
|
1150
|
-
code-reviewer \
|
|
1151
|
-
--repository=$CI_PROJECT_PATH \
|
|
1152
|
-
--pr-number=$CI_MERGE_REQUEST_IID \
|
|
1153
|
-
--base-branch=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME \
|
|
1154
|
-
--head-branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
|
1155
|
-
only:
|
|
1156
|
-
- merge_requests
|
|
1157
|
-
```
|
|
1158
|
-
|
|
1159
|
-
### Step 3: Self-Hosted Deployment
|
|
1160
|
-
|
|
1161
|
-
```bash
|
|
1162
|
-
# Deploy as Kubernetes service
|
|
1163
|
-
kubectl apply -f - <<EOF
|
|
1164
|
-
apiVersion: apps/v1
|
|
1165
|
-
kind: Deployment
|
|
1166
|
-
metadata:
|
|
1167
|
-
name: code-reviewer-agent
|
|
1168
|
-
namespace: ci-cd
|
|
1169
|
-
spec:
|
|
1170
|
-
replicas: 3
|
|
1171
|
-
selector:
|
|
1172
|
-
matchLabels:
|
|
1173
|
-
app: code-reviewer
|
|
1174
|
-
template:
|
|
1175
|
-
metadata:
|
|
1176
|
-
labels:
|
|
1177
|
-
app: code-reviewer
|
|
1178
|
-
spec:
|
|
1179
|
-
containers:
|
|
1180
|
-
- name: agent
|
|
1181
|
-
image: registry.example.com/agents/code-reviewer:3.0.0
|
|
1182
|
-
env:
|
|
1183
|
-
- name: GITHUB_TOKEN
|
|
1184
|
-
valueFrom:
|
|
1185
|
-
secretKeyRef:
|
|
1186
|
-
name: git-tokens
|
|
1187
|
-
key: github
|
|
1188
|
-
- name: GITLAB_TOKEN
|
|
1189
|
-
valueFrom:
|
|
1190
|
-
secretKeyRef:
|
|
1191
|
-
name: git-tokens
|
|
1192
|
-
key: gitlab
|
|
1193
|
-
- name: OPENAI_API_KEY
|
|
1194
|
-
valueFrom:
|
|
1195
|
-
secretKeyRef:
|
|
1196
|
-
name: ai-tokens
|
|
1197
|
-
key: openai
|
|
1198
|
-
ports:
|
|
1199
|
-
- containerPort: 8080
|
|
1200
|
-
resources:
|
|
1201
|
-
requests:
|
|
1202
|
-
cpu: 1000m
|
|
1203
|
-
memory: 2Gi
|
|
1204
|
-
limits:
|
|
1205
|
-
cpu: 4000m
|
|
1206
|
-
memory: 8Gi
|
|
1207
|
-
EOF
|
|
1208
|
-
```
|
|
1209
|
-
|
|
1210
|
-
## Cost Management
|
|
1211
|
-
|
|
1212
|
-
- **Monthly budget**: $200 (configurable)
|
|
1213
|
-
- **Per-PR limit**: $2.00
|
|
1214
|
-
- **Optimization strategies**:
|
|
1215
|
-
- Cache dependencies between runs
|
|
1216
|
-
- Skip unchanged files
|
|
1217
|
-
- Parallel analysis
|
|
1218
|
-
- Use cheaper models for simple checks
|
|
1219
|
-
|
|
1220
|
-
## Production Checklist
|
|
1221
|
-
|
|
1222
|
-
- [ ] GitHub/GitLab tokens configured with minimum required permissions
|
|
1223
|
-
- [ ] Webhook secrets configured
|
|
1224
|
-
- [ ] AI API keys stored securely
|
|
1225
|
-
- [ ] Rate limiting configured
|
|
1226
|
-
- [ ] Monitoring and alerting enabled
|
|
1227
|
-
- [ ] Cost tracking dashboard
|
|
1228
|
-
- [ ] Auto-fix tested in safe environment
|
|
1229
|
-
- [ ] Quality gates configured per project
|
|
1230
|
-
- [ ] Rollback plan tested
|
|
1231
|
-
|
|
1232
|
-
## Further Reading
|
|
1233
|
-
|
|
1234
|
-
- [GitHub Actions Documentation](https://docs.github.com/actions)
|
|
1235
|
-
- [GitLab CI Documentation](https://docs.gitlab.com/ee/ci/)
|
|
1236
|
-
- [OSSA Runtime Documentation](https://openstandardagents.org/docs/runtime)
|