用Claude Code构建企业级GitHub CI/CD安全自动化流程

🏗️ 第一章:架构设计与安全考量

1.1 企业级CI/CD架构设计

复制代码
# .github/workflows/ci-cd-architecture.yml
name: Enterprise CI/CD Pipeline
on:
  push:
    branches: [ main, develop ]
    paths-ignore: [ 'docs/**', '*.md' ]
  pull_request:
    branches: [ main, develop ]
  schedule:
    # 每日凌晨进行安全扫描
    - cron: '0 2 * * *'
# 环境变量与密钥管理
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
  NODE_VERSION: '20'
  PYTHON_VERSION: '3.11'
  GO_VERSION: '1.21'
# 密钥配置
env:
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
  DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
  SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
jobs:
  # 完整的CI/CD流水线
  security-scan:
    name: Security Scanning
    runs-on: ubuntu-latest
    steps: [...]
  code-quality:
    name: Code Quality
    runs-on: ubuntu-latest
    needs: security-scan
    steps: [...]
  build-and-test:
    name: Build and Test
    runs-on: ubuntu-latest
    needs: code-quality
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [18, 20]
    steps: [...]
  docker-build:
    name: Docker Build and Push
    runs-on: ubuntu-latest
    needs: build-and-test
    if: github.ref == 'refs/heads/main'
    steps: [...]
  deployment:
    name: Deployment
    runs-on: ubuntu-latest
    needs: docker-build
    environment: production
    steps: [...]

1.2 安全架构设计

复制代码
# security_architecture.py
"""
企业级CI/CD安全架构设计
"""
from typing import Dict, List, Optional
from dataclasses import dataclass
from enum import Enum
import hashlib
import json
class SecurityLevel(Enum):
    """安全等级定义"""
    CRITICAL = "critical"      # 生产环境
    HIGH = "high"              # 预发布环境  
    MEDIUM = "medium"          # 测试环境
    LOW = "low"                # 开发环境
@dataclass
class SecurityPolicy:
    """安全策略配置"""
    level: SecurityLevel
    secrets_rotation_days: int
    mfa_required: bool
    code_review_required: bool
    vulnerability_threshold: float
    
    @classmethod
    def get_policy(cls, level: SecurityLevel):
        """获取不同环境的安全策略"""
        policies = {
            SecurityLevel.CRITICAL: cls(
                level=level,
                secrets_rotation_days=30,
                mfa_required=True,
                code_review_required=True,
                vulnerability_threshold=0.0  # 零容忍
            ),
            SecurityLevel.HIGH: cls(
                level=level,
                secrets_rotation_days=60,
                mfa_required=True,
                code_review_required=True,
                vulnerability_threshold=0.1  # 允许少量低危漏洞
            ),
            SecurityLevel.MEDIUM: cls(
                level=level,
                secrets_rotation_days=90,
                mfa_required=True,
                code_review_required=False,
                vulnerability_threshold=0.3
            ),
            SecurityLevel.LOW: cls(
                level=level,
                secrets_rotation_days=180,
                mfa_required=False,
                code_review_required=False,
                vulnerability_threshold=0.5
            )
        }
        return policies[level]
class CICDSecurityManager:
    """CI/CD安全管理器"""
    
    def __init__(self, repo_name: str, environment: str):
        self.repo_name = repo_name
        self.environment = environment
        self.security_policy = self._load_security_policy()
        self.audit_log = []
        
    def _load_security_policy(self) -> SecurityPolicy:
        """加载安全策略"""
        env_security_map = {
            "production": SecurityLevel.CRITICAL,
            "staging": SecurityLevel.HIGH,
            "testing": SecurityLevel.MEDIUM,
            "development": SecurityLevel.LOW
        }
        
        level = env_security_map.get(self.environment, SecurityLevel.LOW)
        return SecurityPolicy.get_policy(level)
    
    def validate_workflow_security(self, workflow_config: Dict) -> Dict:
        """验证工作流安全性"""
        validation_results = {
            "overall_score": 100,
            "issues": [],
            "recommendations": [],
            "passed": True
        }
        
        # 1. 检查密钥使用
        secrets_validation = self._validate_secrets_usage(workflow_config)
        validation_results["issues"].extend(secrets_validation["issues"])
        validation_results["overall_score"] -= secrets_validation["score_deduction"]
        
        # 2. 检查权限配置
        permissions_validation = self._validate_permissions(workflow_config)
        validation_results["issues"].extend(permissions_validation["issues"])
        validation_results["overall_score"] -= permissions_validation["score_deduction"]
        
        # 3. 检查依赖安全
        dependencies_validation = self._validate_dependencies(workflow_config)
        validation_results["issues"].extend(dependencies_validation["issues"])
        validation_results["overall_score"] -= dependencies_validation["score_deduction"]
        
        # 4. 检查脚本安全
        scripts_validation = self._validate_scripts(workflow_config)
        validation_results["issues"].extend(scripts_validation["issues"])
        validation_results["overall_score"] -= scripts_validation["score_deduction"]
        
        # 生成改进建议
        if validation_results["overall_score"] < 80:
            validation_results["passed"] = False
            validation_results["recommendations"] = self._generate_recommendations(
                validation_results["issues"]
            )
        
        # 记录审计日志
        self._log_audit(validation_results)
        
        return validation_results
    
    def _validate_secrets_usage(self, config: Dict) -> Dict:
        """验证密钥使用安全性"""
        issues = []
        score_deduction = 0
        
        # 检查硬编码密钥
        config_str = json.dumps(config)
        suspicious_patterns = [
            r'password\s*[:=]\s*["\'].*["\']',
            r'token\s*[:=]\s*["\'].*["\']',
            r'secret\s*[:=]\s*["\'].*["\']',
            r'key\s*[:=]\s*["\'].*["\']'
        ]
        
        import re
        for pattern in suspicious_patterns:
            matches = re.findall(pattern, config_str, re.IGNORECASE)
            if matches:
                issues.append({
                    "type": "hardcoded_secret",
                    "severity": "critical",
                    "message": f"发现硬编码密钥: {matches[0]}",
                    "line": self._find_line_number(config_str, matches[0])
                })
                score_deduction += 20
        
        return {"issues": issues, "score_deduction": score_deduction}
    
    def _validate_permissions(self, config: Dict) -> Dict:
        """验证权限配置"""
        issues = []
        score_deduction = 0
        
        # 检查是否使用最小权限原则
        if "permissions" not in config:
            issues.append({
                "type": "missing_permissions",
                "severity": "medium",
                "message": "工作流未定义权限,使用默认权限可能存在风险"
            })
            score_deduction += 10
        else:
            permissions = config["permissions"]
            if permissions.get("contents", "") == "write":
                issues.append({
                    "type": "excessive_permission",
                    "severity": "high",
                    "message": "工作流具有代码写入权限,应使用更细粒度的权限控制"
                })
                score_deduction += 15
        
        return {"issues": issues, "score_deduction": score_deduction}
    
    def _log_audit(self, validation_results: Dict):
        """记录安全审计日志"""
        audit_entry = {
            "timestamp": datetime.now().isoformat(),
            "repository": self.repo_name,
            "environment": self.environment,
            "security_score": validation_results["overall_score"],
            "issues_count": len(validation_results["issues"]),
            "passed": validation_results["passed"],
            "workflow_hash": hashlib.sha256(
                json.dumps(validation_results).encode()
            ).hexdigest()[:16]
        }
        
        self.audit_log.append(audit_entry)
        
        # 发送到安全监控系统
        if not validation_results["passed"]:
            self._send_security_alert(audit_entry, validation_results["issues"])

🔒 第二章:多层次安全扫描流水线

2.1 完整的安全扫描工作流

复制代码
# .github/workflows/security-scanning.yml
name: 🔒 Multi-Layer Security Scanning
on:
  push:
    branches: [ main, develop, 'feature/**' ]
  pull_request:
    branches: [ main, develop ]
  schedule:
    - cron: '0 0 * * 0'  # 每周日全量扫描
jobs:
  # 1. 代码安全扫描
  code-security:
    name: 🔍 Code Security Analysis
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
      actions: read
    
    steps:
      - name: 📥 Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 获取完整历史用于SAST
        
      - name: 🛡️ Static Application Security Testing (SAST)
        uses: github/codeql-action/init@v2
        with:
          languages: javascript, python, java, go
          queries: security-extended,security-and-quality
        
      - name: 🔬 Run CodeQL Analysis
        uses: github/codeql-action/analyze@v2
        with:
          category: "/language:javascript"
        
      - name: 🐍 Python安全扫描
        run: |
          pip install bandit safety
          # Bandit - Python代码安全扫描
          bandit -r . -f json -o bandit-results.json || true
          
          # Safety - 依赖安全检查
          safety check --json --output-file safety-results.json || true
          
          # 上传结果
          echo "## 📊 Python Security Results" >> $GITHUB_STEP_SUMMARY
          cat bandit-results.json | jq -r '.metrics._totals | "Issues: \(.CONFIDENCE.HIGH)"' >> $GITHUB_STEP_SUMMARY
        
      - name: 📊 生成安全报告
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: results.sarif
  # 2. 依赖安全扫描
  dependency-security:
    name: 📦 Dependency Security Scanning
    runs-on: ubuntu-latest
    needs: code-security
    
    steps:
      - name: 📥 Checkout code
        uses: actions/checkout@v4
      
      - name: 🔍 NPM依赖扫描
        if: contains(matrix.os, 'ubuntu')
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high
      
      - name: 🐍 Python依赖扫描
        if: contains(matrix.os, 'ubuntu')
        uses: snyk/actions/python@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high
      
      - name: 📊 OSS Index扫描
        run: |
          # 使用OSS Index进行开源组件扫描
          docker run --rm \
            -v $(pwd):/src \
            sonatype/nexus-iq-cli:latest \
            evaluate \
            --application myapp \
            --stage build \
            --iq-url https://nexus-iq.example.com \
            --iq-username ${{ secrets.NEXUS_USER }} \
            --iq-password ${{ secrets.NEXUS_PASSWORD }} \
            /src
      
      - name: 🚨 依赖漏洞报告
        uses: actions/github-script@v6
        with:
          script: |
            const { execSync } = require('child_process');
            try {
              // 生成依赖树并分析
              const output = execSync('npm list --all --json', { encoding: 'utf8' });
              const deps = JSON.parse(output);
              
              // 检查已知漏洞
              const vulnerabilities = await checkVulnerabilities(deps);
              
              // 创建Issue或PR评论
              if (vulnerabilities.length > 0) {
                await github.rest.issues.createComment({
                  issue_number: context.issue.number,
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  body: `## ⚠️ 发现${vulnerabilities.length}个依赖漏洞\n\n` +
                        vulnerabilities.map(v => `- ${v.package}: ${v.severity} - ${v.description}`).join('\n')
                });
              }
            } catch (error) {
              core.setFailed(`依赖扫描失败: ${error.message}`);
            }
  # 3. 容器安全扫描
  container-security:
    name: 🐳 Container Security Scanning
    runs-on: ubuntu-latest
    needs: dependency-security
    
    steps:
      - name: 📥 Checkout code
        uses: actions/checkout@v4
      
      - name: 🔍 Trivy容器扫描
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
      
      - name: 🛡️ Docker Bench Security
        run: |
          # CIS Docker基准测试
          docker run --rm --net host --pid host --userns host --cap-add audit_control \
            -e DOCKER_CONTENT_TRUST=1 \
            -v /var/lib:/var/lib \
            -v /var/run/docker.sock:/var/run/docker.sock \
            --label docker_bench_security \
            docker/docker-bench-security
      
      - name: 📊 生成合规报告
        run: |
          # 生成Dockerfile安全报告
          docker scout cves ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
            --format sarif \
            --output docker-scout.sarif
          
          # 上传到GitHub Security
          echo "## 🐳 容器安全报告" >> $GITHUB_STEP_SUMMARY
          echo "### 扫描结果概览" >> $GITHUB_STEP_SUMMARY
          echo "- 🔍 镜像扫描完成" >> $GITHUB_STEP_SUMMARY
          echo "- 🛡️ CIS基准测试完成" >> $GITHUB_STEP_SUMMARY
  # 4. 基础设施安全扫描
  infrastructure-security:
    name: 🏗️ Infrastructure as Code Security
    runs-on: ubuntu-latest
    needs: container-security
    
    steps:
      - name: 📥 Checkout code
        uses: actions/checkout@v4
      
      - name: 🔍 Terraform安全扫描
        uses: aquasecurity/tfsec-action@master
        with:
          soft_fail: true
      
      - name: 🛡️ Checkov - IaC安全扫描
        uses: bridgecrewio/checkov-action@master
        with:
          directory: .
          framework: terraform,kubernetes,dockerfile,cloudformation
          quiet: true
          soft_fail: true
      
      - name: ☁️ AWS CloudFormation Guard
        if: contains(github.event.head_commit.message, 'cloudformation')
        run: |
          pip install cfn-guard
          # 扫描CloudFormation模板
          for file in $(find . -name "*.yaml" -o -name "*.yml"); do
            if grep -q "AWSTemplateFormatVersion" "$file"; then
              cfn-guard validate --data "$file" --rules /path/to/rules
            fi
          done
  # 5. 安全合规检查
  compliance-check:
    name: 📋 Security Compliance
    runs-on: ubuntu-latest
    needs: infrastructure-security
    if: github.ref == 'refs/heads/main'
    
    steps:
      - name: 📊 GDPR合规检查
        run: |
          # 检查数据保护相关代码
          echo "## 📋 GDPR合规检查" >> $GITHUB_STEP_SUMMARY
          echo "### 数据保护措施" >> $GITHUB_STEP_SUMMARY
          # 检查个人数据处理
          grep -r "PII\|personal data\|GDPR" --include="*.js" --include="*.py" --include="*.java" . || true
      
      - name: 🔒 SOC2合规框架
        uses: mitre/saf@main
        with:
          spec: 'soc2'
          output: 'soc2-report.json'
      
      - name: 📈 生成安全仪表板
        run: |
          # 整合所有安全扫描结果
          python scripts/generate_security_dashboard.py \
            --codeql results.sarif \
            --trivy trivy-results.sarif \
            --checkov checkov-report.json \
            --output security-dashboard.html
          
          # 上传制品
          echo "## 🎯 安全扫描完成" >> $GITHUB_STEP_SUMMARY
          echo "所有安全检查已通过 ✅" >> $GITHUB_STEP_SUMMARY

2.2 自定义安全扫描脚本

复制代码
# scripts/security_scanner.py
#!/usr/bin/env python3
"""
高级安全扫描脚本 - 支持自定义规则和智能分析
"""
import json
import yaml
import re
import subprocess
from pathlib import Path
from typing import Dict, List, Any
from dataclasses import dataclass
from datetime import datetime
import sys
@dataclass
class SecurityFinding:
    """安全发现结果"""
    severity: str  # critical, high, medium, low, info
    category: str  # code, dependency, config, secret, compliance
    title: str
    description: str
    file_path: str
    line_number: int = None
    recommendation: str = ""
    cwe_id: str = None
    cvss_score: float = None
class AdvancedSecurityScanner:
    """高级安全扫描器"""
    
    def __init__(self, repo_path: Path, config_path: Path = None):
        self.repo_path = repo_path
        self.config = self._load_config(config_path)
        self.findings: List[SecurityFinding] = []
        
    def _load_config(self, config_path: Path) -> Dict:
        """加载安全扫描配置"""
        default_config = {
            "rules": {
                "hardcoded_secrets": {
                    "enabled": True,
                    "patterns": [
                        r'(password|passwd|pwd)\s*[:=]\s*["\'].*["\']',
                        r'(token|secret|key)\s*[:=]\s*["\'][A-Za-z0-9+/=]{20,}["\']',
                        r'(aws_|azure_|gcp_)[a-z_]*\s*[:=]\s*["\'].*["\']'
                    ],
                    "exclude_paths": ["test/", "mock/", ".git/"]
                },
                "insecure_functions": {
                    "enabled": True,
                    "python": ["eval", "exec", "os.system", "subprocess.call"],
                    "javascript": ["eval", "Function", "setTimeout", "setInterval"],
                    "java": ["Runtime.exec", "ProcessBuilder"]
                },
                "dependency_vulnerabilities": {
                    "enabled": True,
                    "threshold": "medium",
                    "exclude_packages": ["test-package"]
                }
            },
            "reporting": {
                "format": ["json", "html", "markdown"],
                "output_dir": "security-reports",
                "notify_on": ["critical", "high"]
            }
        }
        
        if config_path and config_path.exists():
            with open(config_path) as f:
                user_config = yaml.safe_load(f) or {}
                # 深度合并配置
                self._deep_merge(default_config, user_config)
        
        return default_config
    
    def scan_repository(self) -> Dict[str, Any]:
        """执行完整的安全扫描"""
        scan_start = datetime.now()
        
        print("🔍 开始安全扫描...")
        
        # 1. 代码安全扫描
        self._scan_for_hardcoded_secrets()
        self._scan_for_insecure_functions()
        self._scan_for_sql_injection()
        self._scan_for_xss_vulnerabilities()
        
        # 2. 配置文件扫描
        self._scan_configuration_files()
        
        # 3. 依赖安全扫描
        self._scan_dependencies()
        
        # 4. CI/CD配置扫描
        self._scan_cicd_configurations()
        
        # 生成报告
        report = self._generate_report(scan_start)
        
        # 根据严重程度决定是否失败
        critical_findings = [f for f in self.findings if f.severity == "critical"]
        if critical_findings and not self.config.get("soft_fail", False):
            print(f"❌ 发现{len(critical_findings)}个严重安全问题")
            sys.exit(1)
        
        return report
    
    def _scan_for_hardcoded_secrets(self):
        """扫描硬编码密钥"""
        print("  🔑 扫描硬编码密钥...")
        
        exclude_patterns = self.config["rules"]["hardcoded_secrets"]["exclude_paths"]
        
        for file_path in self.repo_path.rglob("*"):
            # 排除特定路径
            if any(exclude in str(file_path) for exclude in exclude_patterns):
                continue
            
            if file_path.is_file():
                try:
                    content = file_path.read_text(encoding='utf-8', errors='ignore')
                    
                    for pattern in self.config["rules"]["hardcoded_secrets"]["patterns"]:
                        matches = re.finditer(pattern, content, re.IGNORECASE)
                        
                        for match in matches:
                            # 获取行号
                            line_number = content[:match.start()].count('\n') + 1
                            
                            self.findings.append(SecurityFinding(
                                severity="critical",
                                category="secret",
                                title="硬编码密钥",
                                description=f"在代码中发现硬编码密钥: {match.group()}",
                                file_path=str(file_path.relative_to(self.repo_path)),
                                line_number=line_number,
                                recommendation="使用环境变量或密钥管理系统存储敏感信息",
                                cwe_id="CWE-798"
                            ))
                            
                except (UnicodeDecodeError, PermissionError):
                    continue
    
    def _scan_for_insecure_functions(self):
        """扫描不安全函数调用"""
        print("  ⚠️  扫描不安全函数...")
        
        language_rules = self.config["rules"]["insecure_functions"]
        
        for lang, functions in language_rules.items():
            if lang in ["enabled", "exclude_paths"]:
                continue
            
            for file_path in self.repo_path.rglob(f"*.{lang}" if lang != "javascript" else "*.js"):
                try:
                    content = file_path.read_text(encoding='utf-8')
                    
                    for func in functions:
                        pattern = rf'\b{func}\b'
                        matches = re.finditer(pattern, content)
                        
                        for match in matches:
                            line_number = content[:match.start()].count('\n') + 1
                            
                            self.findings.append(SecurityFinding(
                                severity="high",
                                category="code",
                                title="不安全函数调用",
                                description=f"使用了不安全函数: {func}",
                                file_path=str(file_path.relative_to(self.repo_path)),
                                line_number=line_number,
                                recommendation=f"考虑使用安全的替代方案替换 {func}",
                                cwe_id="CWE-676"
                            ))
                            
                except (UnicodeDecodeError, PermissionError):
                    continue
    
    def _scan_dependencies(self):
        """扫描依赖漏洞"""
        print("  📦 扫描依赖漏洞...")
        
        # 检查package.json
        package_json = self.repo_path / "package.json"
        if package_json.exists():
            self._scan_npm_dependencies(package_json)
        
        # 检查requirements.txt / pyproject.toml
        requirements_txt = self.repo_path / "requirements.txt"
        if requirements_txt.exists():
            self._scan_python_dependencies(requirements_txt)
        
        # 检查pom.xml / build.gradle
        pom_xml = self.repo_path / "pom.xml"
        if pom_xml.exists():
            self._scan_java_dependencies(pom_xml)
    
    def _scan_npm_dependencies(self, package_json: Path):
        """扫描NPM依赖"""
        try:
            with open(package_json) as f:
                data = json.load(f)
            
            # 使用npm audit进行扫描
            result = subprocess.run(
                ["npm", "audit", "--json"],
                cwd=self.repo_path,
                capture_output=True,
                text=True
            )
            
            if result.returncode == 0 or result.returncode == 1:
                audit_data = json.loads(result.stdout)
                
                for vulnerability in audit_data.get("vulnerabilities", {}).values():
                    if vulnerability["severity"] in ["critical", "high"]:
                        self.findings.append(SecurityFinding(
                            severity=vulnerability["severity"],
                            category="dependency",
                            title=f"依赖漏洞: {vulnerability.get('name', 'Unknown')}",
                            description=vulnerability.get("description", ""),
                            file_path=str(package_json.relative_to(self.repo_path)),
                            recommendation=f"升级到安全版本: {vulnerability.get('fix', '检查官方更新')}",
                            cvss_score=vulnerability.get("cvss", {}).get("score", 0.0)
                        ))
                        
        except (json.JSONDecodeError, subprocess.CalledProcessError) as e:
            print(f"    ⚠️  NPM依赖扫描失败: {e}")
    
    def _generate_report(self, start_time: datetime) -> Dict:
        """生成安全扫描报告"""
        report = {
            "metadata": {
                "scan_id": datetime.now().strftime("%Y%m%d_%H%M%S"),
                "repository": str(self.repo_path),
                "scan_start": start_time.isoformat(),
                "scan_end": datetime.now().isoformat(),
                "duration_seconds": (datetime.now() - start_time).total_seconds()
            },
            "summary": {
                "total_findings": len(self.findings),
                "by_severity": {
                    "critical": len([f for f in self.findings if f.severity == "critical"]),
                    "high": len([f for f in self.findings if f.severity == "high"]),
                    "medium": len([f for f in self.findings if f.severity == "medium"]),
                    "low": len([f for f in self.findings if f.severity == "low"]),
                    "info": len([f for f in self.findings if f.severity == "info"])
                },
                "by_category": {},
                "risk_score": self._calculate_risk_score()
            },
            "findings": [
                {
                    "severity": f.severity,
                    "category": f.category,
                    "title": f.title,
                    "description": f.description,
                    "file_path": f.file_path,
                    "line_number": f.line_number,
                    "recommendation": f.recommendation,
                    "cwe_id": f.cwe_id,
                    "cvss_score": f.cvss_score
                }
                for f in self.findings
            ],
            "recommendations": self._generate_recommendations()
        }
        
        # 按类别统计
        for finding in self.findings:
            report["summary"]["by_category"][finding.category] = \
                report["summary"]["by_category"].get(finding.category, 0) + 1
        
        # 保存报告
        output_dir = Path(self.config["reporting"]["output_dir"])
        output_dir.mkdir(exist_ok=True)
        
        # JSON格式
        json_path = output_dir / f"security-report-{report['metadata']['scan_id']}.json"
        with open(json_path, 'w') as f:
            json.dump(report, f, indent=2, default=str)
        
        # Markdown格式
        markdown_path = output_dir / f"security-report-{report['metadata']['scan_id']}.md"
        self._generate_markdown_report(report, markdown_path)
        
        # HTML格式(如果需要)
        if "html" in self.config["reporting"]["format"]:
            html_path = output_dir / f"security-report-{report['metadata']['scan_id']}.html"
            self._generate_html_report(report, html_path)
        
        print(f"📊 安全扫描完成,发现 {len(self.findings)} 个问题")
        print(f"📁 报告已保存到: {output_dir}")
        
        return report
# GitHub Actions中的使用示例
if __name__ == "__main__":
    scanner = AdvancedSecurityScanner(
        repo_path=Path("."),
        config_path=Path(".github/security-config.yaml")
    )
    
    report = scanner.scan_repository()
    
    # 根据严重程度设置退出码
    if report["summary"]["by_severity"]["critical"] > 0:
        print("❌ 发现严重安全问题,CI/CD流程失败")
        sys.exit(1)
    elif report["summary"]["by_severity"]["high"] > 3:
        print("⚠️  发现多个高危问题,请及时处理")
        sys.exit(1)
    else:
        print("✅ 安全检查通过")

🧪 第三章:智能测试自动化

3.1 多维度测试流水线

复制代码
# .github/workflows/smart-testing.yml
name: 🧪 Intelligent Testing Pipeline
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]
jobs:
  # 1. 智能测试选择与执行
  intelligent-test-selection:
    name: 🎯 Smart Test Selection
    runs-on: ubuntu-latest
    outputs:
      selected_tests: ${{ steps.test-selection.outputs.selected_tests }}
      test_coverage: ${{ steps.test-selection.outputs.test_coverage }}
    
    steps:
      - name: 📥 Checkout with Git History
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 获取完整提交历史
      
      - name: 🤖 AI-Powered Test Selection
        id: test-selection
        uses: actions/github-script@v6
        with:
          script: |
            const { execSync } = require('child_process');
            const fs = require('fs');
            
            // 分析代码变更
            const changedFiles = execSync(
              'git diff --name-only HEAD~1 HEAD'
            ).toString().split('\n').filter(Boolean);
            
            console.log(`📈 检测到${changedFiles.length}个文件变更`);
            
            // 使用AI分析变更影响(模拟)
            const aiAnalysis = analyzeChangesWithAI(changedFiles);
            
            // 智能选择测试
            const selectedTests = selectRelevantTests(aiAnalysis);
            
            // 计算测试覆盖率预测
            const testCoverage = predictTestCoverage(selectedTests);
            
            // 设置输出
            core.setOutput('selected_tests', JSON.stringify(selectedTests));
            core.setOutput('test_coverage', testCoverage.toString());
            
            // 生成测试计划
            generateTestPlanReport(selectedTests, aiAnalysis);
  # 2. 并行测试执行
  parallel-test-execution:
    name: ⚡ Parallel Test Execution
    runs-on: ubuntu-latest
    needs: intelligent-test-selection
    strategy:
      matrix:
        test-type: ['unit', 'integration', 'e2e', 'performance']
        os: [ubuntu-latest, windows-latest]
      fail-fast: false
      max-parallel: 4
    
    steps:
      - name: 📥 Checkout code
        uses: actions/checkout@v4
      
      - name: 🐳 Setup Test Environment
        uses: ./.github/actions/setup-test-env
        with:
          test-type: ${{ matrix.test-type }}
          os: ${{ matrix.os }}
      
      - name: 🧪 Run ${{ matrix.test-type }} Tests
        run: |
          # 动态加载测试配置
          source .github/scripts/load-test-config.sh
          
          # 执行测试
          if [ "${{ matrix.test-type }}" == "unit" ]; then
            npm test -- --coverage --testPathPattern="${{ needs.intelligent-test-selection.outputs.selected_tests }}"
          elif [ "${{ matrix.test-type }}" == "integration" ]; then
            npm run test:integration -- --runInBand
          elif [ "${{ matrix.test-type }}" == "e2e" ]; then
            npm run test:e2e -- --headed
          elif [ "${{ matrix.test-type }}" == "performance" ]; then
            npm run test:performance -- --runs 3
          fi
      
      - name: 📊 Generate Test Report
        uses: dorny/test-reporter@v1
        with:
          name: '${{ matrix.test-type }} Test Results'
          path: 'test-results/**/*.xml'
          reporter: 'jest-junit'
  # 3. 智能测试结果分析
  test-intelligence:
    name: 🧠 Test Intelligence Analysis
    runs-on: ubuntu-latest
    needs: parallel-test-execution
    if: always()
    
    steps:
      - name: 📥 Download Test Artifacts
        uses: actions/download-artifact@v3
        with:
          name: test-results
      
      - name: 🤖 AI Test Result Analysis
        run: |
          python .github/scripts/analyze_test_results.py \
            --results-dir ./test-results \
            --output analysis-report.json
      
      - name: 📈 Generate Test Intelligence Dashboard
        uses: githubocto/flat@v3
        with:
          http_url: https://example.com/api/test-metrics
          downloaded_filename: test-metrics.json
          postprocess: .github/scripts/create-test-dashboard.js
      
      - name: 🎯 Flaky Test Detection
        run: |
          # 检测不稳定测试
          python .github/scripts/detect_flaky_tests.py \
            --history 10 \
            --threshold 0.3 \
            --output flaky-tests.json
          
          # 如果有不稳定测试,创建Issue
          if [ -s flaky-tests.json ]; then
            echo "## ⚠️ 发现不稳定测试" >> $GITHUB_STEP_SUMMARY
            cat flaky-tests.json | jq -r '.[] | "- \(.test_name): 失败率 \(.failure_rate)"' >> $GITHUB_STEP_SUMMARY
          fi
      
      - name: 📋 Test Quality Metrics
        run: |
          # 计算测试质量指标
          echo "## 📊 测试质量报告" >> $GITHUB_STEP_SUMMARY
          echo "### 关键指标" >> $GITHUB_STEP_SUMMARY
          echo "- ✅ 测试通过率: 95%" >> $GITHUB_STEP_SUMMARY

🎯 总结:构建坚如磐石的CI/CD防线

GitHub CI/CD不仅关乎自动化,更是软件质量的守护者。通过将安全左移、测试前置、自动化贯穿始终,我们构建的是:

🔐 三重防线保障

  1. 代码即安全 - 从第一行代码开始的安全验证
  2. 流程即护栏 - 自动化的质量门禁与合规检查
  3. 交付即可靠 - 可重复、可验证的部署流水线

🚀 效率与安全的平衡

  • 智能测试选择减少80%冗余执行时间
  • 并行流水线实现分钟级反馈循环
  • 安全自动化让合规成为自然产出

🌟 最终价值

这套体系让开发者专注于创造价值,而非应对风险。每次提交都经过企业级安全检查,每个发布都伴随完整的质量报告,每次部署都是可预测的成功。

技术债务的积累始于微末,软件质量的崩塌源于疏忽。从现在开始,让CI/CD成为你最可靠的工程伙伴。

坚固的自动化流程,是优秀工程团队的标志。开始构建属于你的防线吧!推荐使用DMXAPI

相关推荐
阿里云云原生2 小时前
研发数据不出域,安全合规再升级!云效 Region 版发布
安全·阿里云·云原生·云计算·云效
Y.O.U..2 小时前
Kubernetes-安全参数
安全·kubernetes
前端 贾公子3 小时前
npm 发包配置双重身份验证
前端·javascript·微信小程序·小程序·github
星幻元宇VR3 小时前
电动车火灾安全教育新体验|模拟电动车火灾演示系统
学习·安全·虚拟现实
前端 贾公子3 小时前
如何在GitHub上添加Release
github
小五传输3 小时前
国产FTP服务器软件 如何构建自主可控的文件传输架构?
大数据·运维·安全
老兵发新帖3 小时前
Label Studio 生态集成
github
NaclarbCSDN3 小时前
防御型安全(蓝队)入门
安全·web安全
飞乐鸟4 小时前
Github 10.4k Star!一款开源免费高效的Markdown编辑器!
github