mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
6dbc1c377b
* SwarmMemoryManager Refactoring Plan * fix: add missing directories to npm package (v1.9.3) Added templates/, .claude/helpers/, and docs/reference/ to package.json files array. These were missing from the npm distribution, causing `aqe init` to fail with "Template file not found" errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * checkpoint improvements * fix: critical memory/learning system fixes for v1.9.4 ## Critical Fixes - Vector embeddings now stored correctly (was storing NULL) - SQL parameter style fixed for agentdb's SqlJsDatabase wrapper - HNSW index schema mismatch resolved with pattern_id column - Hooks now save to correct database (.agentic-qe/agentdb.db) ## New Features - Added 5 SwarmMemoryManager methods for learning data retrieval: - getBestAction() - Q-learning best action selection - getRecentLearningExperiences() - Recent experience retrieval - getLearningExperiencesByTaskType() - Task-filtered experiences - getHighRewardExperiences() - Successful experience extraction - getLearningStats() - Aggregate learning statistics - Added comprehensive integration test for memory/learning loop - Added RuVector pattern store integration (experimental) ## Technical Details - Vector embeddings: 384 dimensions × 4 bytes = 1,536 bytes per pattern - All 12 integration tests pass - HNSW index: 150x faster vector search enabled 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: move ARM64-only ruvector packages to optionalDependencies Fixes CI failures caused by platform-specific dependencies: - @ruvector/node-linux-arm64-gnu (ARM64 only) - ruvector-core-linux-arm64-gnu (ARM64 only) These packages caused npm ci to fail on x64 CI runners with: "EBADPLATFORM - wanted linux/arm64, current linux/x64" Solution: Move ARM64 packages to optionalDependencies and add x64 variants for cross-platform compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: regenerate package-lock.json with x64 ruvector packages Updates lockfile to include optional x64 platform packages for CI compatibility: - @ruvector/node-linux-x64-gnu@0.1.17 - ruvector-core-linux-x64-gnu@0.1.15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
272 lines
9.6 KiB
YAML
272 lines
9.6 KiB
YAML
name: Quality Gate
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
checks: write
|
|
statuses: write
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main, develop]
|
|
workflow_dispatch:
|
|
inputs:
|
|
min_coverage:
|
|
description: 'Minimum coverage percentage'
|
|
required: false
|
|
default: '80'
|
|
min_pass_rate:
|
|
description: 'Minimum test pass rate (0-1)'
|
|
required: false
|
|
default: '0.95'
|
|
|
|
jobs:
|
|
quality-gate:
|
|
name: Quality Gate Evaluation
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Build project
|
|
run: npm run build
|
|
|
|
- name: Run unit tests with coverage
|
|
id: unit-tests
|
|
run: npm run test:unit
|
|
continue-on-error: true
|
|
env:
|
|
NODE_OPTIONS: '--max-old-space-size=768'
|
|
|
|
- name: Run integration tests
|
|
id: integration-tests
|
|
run: npm run test:integration
|
|
continue-on-error: true
|
|
env:
|
|
NODE_OPTIONS: '--max-old-space-size=1024'
|
|
|
|
- name: Generate coverage report
|
|
if: always()
|
|
run: |
|
|
if [ -d "coverage" ]; then
|
|
echo "Coverage data found"
|
|
ls -la coverage/
|
|
else
|
|
echo "No coverage data generated"
|
|
fi
|
|
|
|
- name: Evaluate quality gates (TypeScript)
|
|
id: quality-gate-ts
|
|
if: always()
|
|
run: |
|
|
npx ts-node scripts/quality-gate.ts \
|
|
--min-coverage ${{ github.event.inputs.min_coverage || '80' }} \
|
|
--min-pass-rate ${{ github.event.inputs.min_pass_rate || '0.95' }} \
|
|
--max-critical-vulns 0 \
|
|
--max-high-vulns 2 \
|
|
--output-dir ./quality-reports \
|
|
--pr-comment
|
|
continue-on-error: true
|
|
env:
|
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
GITHUB_RUN_NUMBER: ${{ github.run_number }}
|
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
GITHUB_REF_NAME: ${{ github.ref_name }}
|
|
GITHUB_SHA: ${{ github.sha }}
|
|
GITHUB_SERVER_URL: ${{ github.server_url }}
|
|
|
|
- name: Evaluate quality gates (Bash)
|
|
id: quality-gate-bash
|
|
if: always() && steps.quality-gate-ts.outcome == 'failure'
|
|
run: |
|
|
bash scripts/quality-gate.sh \
|
|
--min-coverage ${{ github.event.inputs.min_coverage || '80' }} \
|
|
--min-pass-rate ${{ github.event.inputs.min_pass_rate || '0.95' }}
|
|
continue-on-error: true
|
|
env:
|
|
MIN_COVERAGE: ${{ github.event.inputs.min_coverage || '80' }}
|
|
MIN_PASS_RATE: ${{ github.event.inputs.min_pass_rate || '0.95' }}
|
|
QUALITY_REPORT_DIR: ./quality-reports
|
|
|
|
- name: Upload quality reports
|
|
uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: quality-reports
|
|
path: |
|
|
quality-reports/
|
|
coverage/
|
|
retention-days: 30
|
|
|
|
- name: Post quality gate results to PR
|
|
uses: actions/github-script@v7
|
|
if: always() && github.event_name == 'pull_request'
|
|
with:
|
|
script: |
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Read PR comment if available
|
|
const prCommentPath = path.join(process.cwd(), 'quality-reports', 'pr-comment.md');
|
|
let comment = '';
|
|
|
|
if (fs.existsSync(prCommentPath)) {
|
|
comment = fs.readFileSync(prCommentPath, 'utf8');
|
|
} else {
|
|
// Fallback: Read control loop feedback
|
|
const feedbackPath = path.join(process.cwd(), 'quality-reports', 'control-loop-feedback.json');
|
|
|
|
if (fs.existsSync(feedbackPath)) {
|
|
const feedback = JSON.parse(fs.readFileSync(feedbackPath, 'utf8'));
|
|
|
|
const statusIcon = feedback.signals.canDeploy ? '✅' : '❌';
|
|
const statusText = feedback.signals.canDeploy ? 'PASSED' : 'FAILED';
|
|
|
|
comment = `## ${statusIcon} Quality Gate: ${statusText}\n\n`;
|
|
comment += '### 📊 Metrics\n\n';
|
|
comment += `- **Test Pass Rate**: ${(feedback.metrics.testPassRate * 100).toFixed(1)}%\n`;
|
|
comment += `- **Coverage**: ${feedback.metrics.coveragePercentage.toFixed(1)}%\n`;
|
|
comment += `- **Quality Score**: ${feedback.qualityScore}/100\n\n`;
|
|
|
|
if (feedback.violations.length > 0) {
|
|
comment += '### ⚠️ Violations\n\n';
|
|
for (const violation of feedback.violations) {
|
|
comment += `- **${violation.metric}**: ${violation.actualValue} (threshold: ${violation.threshold}) - ${violation.severity}\n`;
|
|
}
|
|
comment += '\n';
|
|
}
|
|
|
|
comment += '### 🚀 Deployment Decision\n\n';
|
|
if (feedback.signals.canDeploy) {
|
|
comment += '✅ **APPROVED** - All quality gates passed.\n';
|
|
} else {
|
|
comment += '❌ **BLOCKED** - Quality gates failed. Fix violations before deployment.\n';
|
|
}
|
|
} else {
|
|
comment = '## ⚠️ Quality Gate: Unable to evaluate\n\nNo quality gate data available.';
|
|
}
|
|
}
|
|
|
|
// Find existing quality gate comment
|
|
const { data: comments } = await github.rest.issues.listComments({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
});
|
|
|
|
const botComment = comments.find(comment =>
|
|
comment.user?.type === 'Bot' &&
|
|
comment.body?.includes('Quality Gate:')
|
|
);
|
|
|
|
const commentBody = `${comment}\n\n---\n*Quality gate evaluated at ${new Date().toISOString()}*`;
|
|
|
|
if (botComment) {
|
|
// Update existing comment
|
|
await github.rest.issues.updateComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: botComment.id,
|
|
body: commentBody
|
|
});
|
|
} else {
|
|
// Create new comment
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
body: commentBody
|
|
});
|
|
}
|
|
|
|
- name: Update commit status
|
|
uses: actions/github-script@v7
|
|
if: always()
|
|
with:
|
|
script: |
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Read feedback
|
|
const feedbackPath = path.join(process.cwd(), 'quality-reports', 'control-loop-feedback.json');
|
|
|
|
let state = 'success';
|
|
let description = 'Quality gates passed';
|
|
|
|
if (fs.existsSync(feedbackPath)) {
|
|
const feedback = JSON.parse(fs.readFileSync(feedbackPath, 'utf8'));
|
|
|
|
if (!feedback.signals.canDeploy) {
|
|
state = 'failure';
|
|
description = `Quality gates failed: ${feedback.violations.length} violation(s)`;
|
|
}
|
|
} else {
|
|
state = 'error';
|
|
description = 'Unable to evaluate quality gates';
|
|
}
|
|
|
|
await github.rest.repos.createCommitStatus({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
sha: context.sha,
|
|
state: state,
|
|
context: 'Quality Gate',
|
|
description: description,
|
|
target_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`
|
|
});
|
|
|
|
- name: Fail workflow if quality gates failed
|
|
if: always()
|
|
run: |
|
|
if [ -f "quality-reports/control-loop-feedback.json" ]; then
|
|
CAN_DEPLOY=$(cat quality-reports/control-loop-feedback.json | jq -r '.signals.canDeploy')
|
|
|
|
if [ "$CAN_DEPLOY" = "true" ]; then
|
|
echo "✅ Quality gates passed - Deployment approved"
|
|
exit 0
|
|
else
|
|
echo "❌ Quality gates failed - Deployment blocked"
|
|
|
|
# Show violations
|
|
VIOLATIONS=$(cat quality-reports/control-loop-feedback.json | jq -r '.violations[] | " - \(.metric): \(.actualValue) (threshold: \(.threshold))"')
|
|
echo ""
|
|
echo "Violations:"
|
|
echo "$VIOLATIONS"
|
|
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "⚠️ No quality gate feedback found - assuming failure"
|
|
exit 1
|
|
fi
|
|
|
|
# Optional: Deploy job that depends on quality gate
|
|
deploy:
|
|
name: Deploy to Environment
|
|
runs-on: ubuntu-latest
|
|
needs: quality-gate
|
|
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
|
|
steps:
|
|
- name: Deployment placeholder
|
|
run: |
|
|
echo "✅ Quality gates passed - Ready for deployment"
|
|
echo "This is where you would deploy to production"
|
|
echo "For example:"
|
|
echo " - Deploy to cloud platform"
|
|
echo " - Update infrastructure"
|
|
echo " - Notify stakeholders"
|