用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/microwind/ai-skills --skill cicd命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | CI/CD验证器 |
| description | 当验证CI/CD流水线时,检查配置正确性,验证安全策略,分析性能瓶颈。审查工作流配置,检查部署流程,和最佳实践。 |
| license | MIT |
CI/CD验证器用于检查流水线配置的正确性和最佳实践。不当的CI/CD配置会导致安全漏洞、性能问题和部署失败。在部署到生产环境前需要全面验证流水线配置。
核心原则: 好的CI/CD验证应该全面、自动化、持续、安全。坏的CI/CD验证会遗漏关键问题,导致生产环境故障。
始终:
触发短语:
问题:
测试串行执行而非并行,构建时间30分钟
后果:
- 开发者反馈缓慢
- 部署频率低
- 形成瓶颈
解决方案:
1. 并行执行测试
2. 缓存依赖项
3. 优化构建步骤
4. 使用矩阵策略
问题:
测试覆盖率降低时流水线不会失败
后果:
- 代码质量随时间下降
- 缺陷无法捕获
- 技术债务累积
解决方案:
1. 添加覆盖率阈值检查
2. 低于阈值时失败
3. 设置覆盖率趋势监控
4. 集成质量门禁
问题:
任何提交都会自动部署到生产环境
后果:
- 损坏功能部署
- 可能数据丢失
- 停机风险
解决方案:
1. 生产部署前添加审批门禁
2. 设置多级审批流程
3. 配置环境保护规则
4. 实施部署策略
问题:
敏感信息泄露,权限配置不当
后果:
- 安全漏洞
- 数据泄露风险
- 合规问题
解决方案:
1. 使用密钥管理服务
2. 配置最小权限原则
3. 添加安全扫描
4. 实施访问控制
import yaml
import json
import re
import os
from pathlib import Path
from typing import List, Dict, Any, Optional, Set
from dataclasses import dataclass
from enum import Enum
class Severity(Enum):
"""问题严重程度"""
CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
class ValidationType(Enum):
"""验证类型"""
SECURITY = "security"
PERFORMANCE = "performance"
RELIABILITY = "reliability"
COMPLIANCE = "compliance"
@dataclass
class ValidationIssue:
"""验证问题"""
severity: Severity
type: ValidationType
file: str
resource: str
field: str
message: str
suggestion: str
line: Optional[int] = None
@dataclass
class ValidationResult:
"""验证结果"""
is_valid:
issues: [ValidationIssue]
score:
summary: [, ]
:
():
.repo_path = Path(repo_path)
.issues: [ValidationIssue] = []
.validation_rules = ._load_validation_rules()
() -> ValidationResult:
:
._scan_ci_files()
._validate_github_actions()
._validate_gitlab_ci()
._validate_jenkins()
._validate_security()
._validate_performance()
._generate_result()
Exception e:
.issues.append(ValidationIssue(
severity=Severity.CRITICAL,
=ValidationType.RELIABILITY,
file=,
resource=,
field=,
message=,
suggestion=
))
._generate_result()
() -> [, ]:
{
: {
: Severity.CRITICAL,
: Severity.HIGH,
: Severity.MEDIUM,
: Severity.CRITICAL
},
: {
: Severity.MEDIUM,
: Severity.LOW,
: Severity.MEDIUM,
: Severity.LOW
},
: {
: Severity.HIGH,
: Severity.MEDIUM,
: Severity.HIGH,
: Severity.MEDIUM
},
: {
: Severity.MEDIUM,
: Severity.LOW,
: Severity.HIGH,
: Severity.MEDIUM
}
}
() -> :
ci_files = []
github_workflows = .repo_path / /
github_workflows.exists():
ci_files.extend(github_workflows.glob())
ci_files.extend(github_workflows.glob())
gitlab_ci = .repo_path /
gitlab_ci.exists():
ci_files.append(gitlab_ci)
jenkinsfile = .repo_path /
jenkinsfile.exists():
ci_files.append(jenkinsfile)
azure_pipelines = .repo_path /
azure_pipelines.exists():
ci_files.append(azure_pipelines)
ci_files:
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.COMPLIANCE,
file=,
resource=,
field=,
message=,
suggestion=
))
() -> :
github_workflows = .repo_path / /
github_workflows.exists():
workflow_file github_workflows.glob():
:
(workflow_file, , encoding=) f:
content = f.read()
._validate_github_workflow(content, (workflow_file))
Exception e:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.RELIABILITY,
file=(workflow_file),
resource=,
field=,
message=,
suggestion=
))
() -> :
:
yaml_data = yaml.safe_load(content)
._check_triggers(yaml_data, file_path)
yaml_data:
._validate_jobs(yaml_data[], file_path)
._check_env_vars(yaml_data, file_path)
._check_workflow_security(yaml_data, file_path)
._check_workflow_performance(yaml_data, file_path)
yaml.YAMLError e:
.issues.append(ValidationIssue(
severity=Severity.CRITICAL,
=ValidationType.RELIABILITY,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> :
yaml_data yaml_data:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.COMPLIANCE,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
yaml_data:
triggers = yaml_data[]
(triggers, ) triggers:
schedule = triggers[]
(schedule, ) (schedule) > :
.issues.append(ValidationIssue(
severity=Severity.LOW,
=ValidationType.PERFORMANCE,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> :
job_name, job_config jobs.items():
job_config:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.RELIABILITY,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
job_config:
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.RELIABILITY,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
:
._validate_job_steps(job_config[], job_name, file_path)
job_config job_name.lower():
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.PERFORMANCE,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
() -> :
has_checkout =
has_test =
has_security_scan =
step steps:
step:
step[]:
has_checkout =
step[].lower() step[].lower():
has_security_scan =
step[].lower():
has_test =
step:
command = step[]
command.lower() command.lower():
has_checkout =
command.lower():
has_test =
command.lower() command.lower():
has_security_scan =
has_checkout:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.RELIABILITY,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
has_test job_name.lower():
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.RELIABILITY,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
has_security_scan job_name.lower():
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.SECURITY,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
() -> :
content = (yaml_data)
sensitive_patterns = [
,
,
,
,
]
pattern sensitive_patterns:
re.search(pattern, content, re.IGNORECASE):
.issues.append(ValidationIssue(
severity=Severity.CRITICAL,
=ValidationType.SECURITY,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
content content:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.SECURITY,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> :
yaml_data:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.SECURITY,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
content = (yaml_data)
content:
uses_pattern =
matches = re.findall(uses_pattern, content)
action, version matches:
version [, , ]:
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.SECURITY,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> :
content = (yaml_data)
content:
.issues.append(ValidationIssue(
severity=Severity.LOW,
=ValidationType.PERFORMANCE,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
content:
.issues.append(ValidationIssue(
severity=Severity.LOW,
=ValidationType.PERFORMANCE,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> :
gitlab_ci = .repo_path /
gitlab_ci.exists():
:
(gitlab_ci, , encoding=) f:
content = f.read()
yaml_data = yaml.safe_load(content)
yaml_data:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.COMPLIANCE,
file=(gitlab_ci),
resource=,
field=,
message=,
suggestion=
))
jobs = {k: v k, v yaml_data.items() k != k.startswith()}
job_name, job_config jobs.items():
._validate_gitlab_job(job_config, job_name, (gitlab_ci))
Exception e:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.RELIABILITY,
file=(gitlab_ci),
resource=,
field=,
message=,
suggestion=
))
() -> :
job_config:
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.RELIABILITY,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
job_config:
artifacts = job_config[]
(artifacts, ) artifacts:
.issues.append(ValidationIssue(
severity=Severity.LOW,
=ValidationType.PERFORMANCE,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
job_config job_config job_config:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.COMPLIANCE,
file=file_path,
resource=job_name,
field=,
message=,
suggestion=
))
() -> :
jenkinsfile = .repo_path /
jenkinsfile.exists():
:
(jenkinsfile, , encoding=) f:
content = f.read()
content:
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.COMPLIANCE,
file=(jenkinsfile),
resource=,
field=,
message=,
suggestion=
))
content:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.RELIABILITY,
file=(jenkinsfile),
resource=,
field=,
message=,
suggestion=
))
stages = re.findall(, content)
(stages) == :
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.COMPLIANCE,
file=(jenkinsfile),
resource=,
field=,
message=,
suggestion=
))
Exception e:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.RELIABILITY,
file=(jenkinsfile),
resource=,
field=,
message=,
suggestion=
))
() -> :
security_files = [
,
,
,
]
security_config_found =
security_file security_files:
(.repo_path / security_file).exists():
security_config_found =
security_config_found:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.SECURITY,
file=,
resource=,
field=,
message=,
suggestion=
))
() -> :
build_files = [
,
,
,
,
]
build_file build_files:
file_path = .repo_path / build_file
file_path.exists():
._validate_build_file(file_path)
() -> :
:
(build_file, , encoding=) f:
content = f.read()
build_file.name == :
._validate_package_json(content, (build_file))
build_file.name == :
._validate_pom_xml(content, (build_file))
Exception e:
.issues.append(ValidationIssue(
severity=Severity.LOW,
=ValidationType.RELIABILITY,
file=(build_file),
resource=,
field=,
message=,
suggestion=
))
() -> :
:
package_data = json.loads(content)
package_data:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.COMPLIANCE,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
json.JSONDecodeError e:
.issues.append(ValidationIssue(
severity=Severity.HIGH,
=ValidationType.RELIABILITY,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> :
content:
.issues.append(ValidationIssue(
severity=Severity.MEDIUM,
=ValidationType.COMPLIANCE,
file=file_path,
resource=,
field=,
message=,
suggestion=
))
() -> ValidationResult:
score = ._calculate_score()
summary = ._generate_summary()
is_valid = score >= (
issue.severity == Severity.CRITICAL issue .issues
)
ValidationResult(
is_valid=is_valid,
issues=.issues,
score=score,
summary=summary
)
() -> :
score =
issue .issues:
issue.severity == Severity.CRITICAL:
score -=
issue.severity == Severity.HIGH:
score -=
issue.severity == Severity.MEDIUM:
score -=
issue.severity == Severity.LOW:
score -=
(, score)
() -> [, ]:
issue_counts = {
: (.issues),
: ([i i .issues i.severity == Severity.CRITICAL]),
: ([i i .issues i.severity == Severity.HIGH]),
: ([i i .issues i.severity == Severity.MEDIUM]),
: ([i i .issues i.severity == Severity.LOW])
}
type_counts = {}
issue .issues:
type_name = issue..value
type_counts[type_name] = type_counts.get(type_name, ) +
{
: issue_counts,
: type_counts,
: ._generate_recommendations()
}
() -> []:
recommendations = []
type_counts = {}
issue .issues:
type_name = issue..value
type_counts[type_name] = type_counts.get(type_name, ) +
type_counts.get(, ) > :
recommendations.append()
type_counts.get(, ) > :
recommendations.append()
type_counts.get(, ) > :
recommendations.append()
type_counts.get(, ) > :
recommendations.append()
recommendations
():
validator = CICDValidator()
result = validator.validate_pipeline()
()
()
()
()
summary = result.summary
issue_counts = summary[]
()
()
()
()
()
()
rec summary[]:
()
()
issue result.issues:
()
()
__name__ == :
main()