关于 megalinter-check
用于从 CI 日志或本地运行中收集 MegaLinter 错误,并整理简明报告供修复流程使用。它也支持修复后的定向复查。
主要功能
- 01读取受支持 CI 提供方的结果
- 02需要时在本地运行 MegaLinter
- 03按 Linter 键整理错误详情
- 04支持修复后的定向复查
- 05限制本地运行时长并诊断卡顿
适用场景
- 01查看 CI 中的 MegaLinter 结果
- 02推送前检查仓库
- 03仅复查先前修复过的 Linter 和文件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ oxsecurity/ megalinter --skill megalinter-check安装后在 Claude Code 中输入/megalinter-check确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
container-engine.mdperformance.mdproviders/azure.mdbitbucket.mdgithub.mdgitlab.md详细介绍
MegaLinter 检查
收集当前 MegaLinter 错误,并生成一份精简错误列表,供 megalinter-fix 技能使用。
选择模式
- 监视模式 — 当前分支/PR 有 MegaLinter CI 作业(正在运行或已完成):解析其日志。无需 Docker。
- 本地模式 — 没有可用的 CI 作业,或用户想在推送前检查:通过
npx mega-linter-runner使用 Docker 运行 MegaLinter。 - 定向重新检查(本地,修复后):通过并行运行独立镜像,仅重新运行之前失败的代码检查工具。
监视模式
- 根据
git remote get-url origin和现有的 CI 配置文件检测提供商。 - 从此技能的目录中加载匹配的提供商指南——只加载所需的那一份:
- GitHub Actions →
providers/github.md - GitLab CI →
providers/gitlab.md - Azure Pipelines →
providers/azure.md - Bitbucket Pipelines →
providers/bitbucket.md
- GitHub Actions →
- 按照指南操作:找到 MegaLinter 作业,如果正在运行则等待其完成,并获取 MegaLinter 步骤的日志。
- 解析 MegaLinter 摘要(包含
❌/✅的表格)和各代码检查工具的错误部分。 - 检查 MegaLinter 是否将自己的修复推送到了分支(见下文)。
MegaLinter 自动修复提交
使用 APPLY_FIXES 和 APPLY_FIXES_MODE: commit 的仓库,允许 MegaLinter 作业将修复推送回受监视的分支,作为主题为 [MegaLinter] Apply linters fixes 的提交(这是 CI 模板中的 commit_message;如果仓库自定义了该值,请相应调整下方的匹配模式)。这会带来两个影响:
- 本地分支落后了,因此后续工作必须先拉取。
- 不会重新运行检查。 CI 提供商会有意忽略使用 CI 令牌进行的推送,以防止工作流循环,因此分支上仍保留着产生这些修复的那次运行的过期结果——通常会导致 PR 的检查仍处于等待或失败状态,尽管修复已经解决了问题。
使用用户自己的凭据重新推送同一提交会产生真正的推送事件,并重新触发检查。为提交说明加上 🤖 前缀即可实现这一点,同时让重新推送在历史记录中清晰可见。只有在这种情况下,这些技能才可以强制推送,而且只能使用 --force-with-lease。
检测只依赖 git,因此在 GitHub、GitLab、Azure 和 Bitbucket 上的操作完全相同:
BRANCH="$(git branch --show-current)"
git fetch origin "$BRANCH"
TIP_SUBJECT="$(git log -1 --format='%s' "origin/$BRANCH")" # tip commit of the remote branch
LOCAL_AHEAD="$(git rev-list --count "origin/$BRANCH..HEAD")" # local commits not pushed yet
只有以下条件全部满足时才修改提交;否则不要进行任何操作,只需报告观察到的情况:
TIP_SUBJECT是自动修复提交的主题。如果在它之后还有其他提交进入,则不要操作:这些推送已经重新触发了检查。TIP_SUBJECT尚未以 🤖 开头——说明之前的操作已经修改过它,再次修改会造成循环。LOCAL_AHEAD为0。如果有本地提交,直接正常推送即可:这本身就会重新触发检查,无需修改提交。- 工作树干净(
git status --porcelain为空),否则下面的快进操作会失败——请先提交或暂存更改。 - 当前分支不是默认分支。在
main/master上修改提交并强制推送前,必须先询问用户。
git merge --ff-only "origin/$BRANCH" # fast-forward onto the auto-fix commit
git commit --amend -m "🤖 $(git log -1 --format='%B')" # keeps the original author, changes the SHA
git push --force-with-lease origin "$BRANCH" # never --force
推送时明确指定远程和分支:如果分支没有配置上游跟踪,直接运行 git push --force-with-lease 会失败。租约会根据检测步骤中更新的 origin/<branch> 引用进行检查;如果期间有新提交进入,推送就会被拒绝。
然后告知用户提交已修改、检查已重新触发,并继续监视新的运行。如果 --force-with-lease 被拒绝,说明获取更新后远程已发生变化:请从头重新运行检测,不要改用 --force 重试。
本地模式
首次在本地运行前,请务必让用户了解,在本地运行 MegaLinter 会消耗大量资源: 它需要性能足够强的机器(CPU、RAM、可用磁盘空间)和良好的互联网连接——MegaLinter 基于 Docker,首次运行时会下载一个大型镜像(具体大小取决于版本,可能达到数 GB)。 因此,通常建议使用监视模式(由 CI 执行)。 如果两种模式都可行(仓库中存在 MegaLinter CI 作业,或者可以推送分支/PR 来触发该作业),且用户没有明确选择,请询问他们要使用哪种模式(如果你的平台支持结构化提问机制,请使用该机制,并将监视模式放在首位并标为推荐),不要直接开始本地运行。
引擎预检(每次本地运行前)
需要一个能够正常响应的容器引擎(docker 或 podman)——安装了二进制文件并不能证明引擎可用:如果后端已停止(例如 Docker Desktop 的 Windows 服务),docker CLI 可能会无限期挂起,而不是快速报错。每次运行前都应设置超时时间进行探测:
timeout 10 docker info --format '{{.ServerVersion}}' # exit 124 = installed but not answering
timeout 10 podman info --format '{{.Version.Version}}'
- 所选引擎正常响应 → 继续(使用 podman 时传入
--container-engine podman)。 - 所选引擎报错或超时 → 以相同方式探测另一个引擎;如果它正常响应,则改用它。
- 两个引擎都没有响应 → 不要启动运行(否则同样会挂起)。告知用户你的发现(“Docker Desktop 似乎已安装,但没有响应——它正在运行吗?”),并询问是否应安装或启动一个引擎——然后(且仅在此时)从此技能的目录加载
container-engine.md,查看设置说明(优先选择 podman:即使在企业环境中也免费)。
Flavor 和版本会根据 .mega-linter.yml 中的 MEGALINTER_FLAVOR / MEGALINTER_VERSION 自动确定——不要自行传入 --flavor 或 --release。
npx mega-linter-runner # docker
npx mega-linter-runner --container-engine podman # podman
提示:对于重复的本地运行(例如修复 → 重新检查循环),只需使用 npm install -g mega-linter-runner 安装一次运行器,然后直接调用 mega-linter-runner——这样每次调用都无需经历 npx 的包解析开销。
- 如果
.mega-linter.yml将APPLY_FIXES定义为none以外的值,则添加--fix(这表示仓库已启用自动修复)。 - 限制本地机器上的并行度:MegaLinter 默认每个 CPU 核心运行一个并行 linter 进程;当 Docker 与其他程序共享资源时,这可能会让开发机器不堪重负。在本地计算机上运行时(不在 CI 中,即未设置
CI/GITHUB_ACTIONS/GITLAB_CI这类环境变量),为完整运行添加-e PARALLEL_PROCESS_NUMBER=4(如果机器的核心数少于 4,则使用实际核心数)。如果仓库配置已经设置了PARALLEL_PROCESS_NUMBER,则跳过此项;绝不要将其写入.mega-linter.yml,否则也会拖慢 CI。 - 完整运行时始终添加
-e JSON_REPORTER=true:默认不会生成 JSON 报告(JSON_REPORTER默认为false),此环境变量会覆盖仓库配置,确保生成megalinter-reports/mega-linter-report.json。 - 然后读取
megalinter-reports/mega-linter-report.json和megalinter-reports/linters_logs/ERROR-*.log,而不是解析控制台输出;并从持久化日志文件中提取控制台提示(见下文“控制台提示”)——不要为此重新读取整个控制台输出流。 - 缺少报告文件绝不意味着“等待”:运行器是同步的——命令退出后,之后不会再出现报告文件。不要轮询、休眠或为此重新运行。如果预期文件不存在(仓库可能将
REPORT_OUTPUT_FOLDER设为自定义文件夹或none,将TEXT_REPORTER设为false,或设置了不同的TEXT_REPORTER_SUB_FOLDER),则依次回退:检查.mega-linter.yml中的REPORT_OUTPUT_FOLDER,并在该目录下 glob**/mega-linter-report.json/**/linters_logs/,然后解析控制台输出——其中始终会打印❌/✅汇总表和各 linter 的错误部分。
运行时设置时间限制——绝不无限期等待
本地运行可能因环境问题而卡住(引擎后端不可用、Windows 绑定挂载停滞——见下文),因此每次本地调用(预运行、完整运行、定向复查)都要设置明确的时间限制:
- 有可用的运行器自带标志时优先使用:检查
npx mega-linter-runner --help中是否列有--timeout,如果有,则传入--timeout <seconds>——超时后它还会停止并移除容器。不要假设该标志一定存在(较旧的运行器版本/固定的MEGALINTER_VERSION可能不支持)。 - 备用方案:使用 shell coreutils 命令包装——
timeout <seconds> npx mega-linter-runner ...。这只会终止包装命令,不会终止容器:超时后请执行下文的孤立容器清理步骤。 - 在后台启动进程,将输出写入日志文件,并每隔 1–2 分钟检查一次;绝不要在单次调用中无限期等待。
建议的时间限制:完整运行 30 分钟,预运行或定向单个 linter 运行 10 分钟——在中等规模的代码仓库中,完整 flavor 运行通常只需几分钟,而不是几小时。在一台机器上首次运行时,先单独预拉取镜像(docker pull <image>/podman pull <image>),避免下载数 GB 的镜像耗尽时间限制。
卡住了,还是只是运行缓慢?先诊断,不要继续等待
约 5 分钟没有新的日志输出,可能意味着进程卡住,但不能据此确认任务仍在运行。请主动诊断(<engine> = docker 或 podman):
<engine> ps -a——容器还在吗?它已处于 “Up” 状态多久了?<engine> logs --tail 30 <name>——最后一行是什么?未能继续推进的阶段边界(例如 "...collects the files to analyse"、"Processing linters on [N] parallel cores")可以显示卡住的位置。<engine> exec <name> ps aux——内部正在运行什么进程?这些进程显示的累计 CPU TIME 与容器的实际运行时长相比是多少?运行数小时却只有几秒 CPU 时间 = I/O 停滞(文件系统或网络),不是真正的计算:停止等待、终止运行、清理(见下文),并报告诊断结果,不要继续轮询。在 Windows 上,常见原因是 WSL2 绑定挂载开销——见performance.md中的 “Windows bind-mount slowness”。
强制终止后遗留的孤立容器
终止包装命令(shell timeout 超时、按下 Ctrl-C、终止 npx 进程)不能可靠地停止容器——尤其是在 Windows 上,信号转发并不可靠。只有运行器自带的 --timeout 能保证完成清理。每次强制中断后:
<engine> ps -a——查找仍处于 “Up” 状态且使用 megalinter 镜像运行的容器。- 对每个匹配项执行
<engine> stop <name>,然后执行<engine> rm <name>。
首次本地运行:预运行分析
在仓库上首次进行本地完整运行之前(刚完成 megalinter-setup,或不存在之前运行生成的 megalinter-reports/mega-linter-report.json),先进行预运行分析,避免真正运行时因配置不当而浪费时间。之后每当用户要求优化 MegaLinter 性能时,也使用此分析。
预运行需要 MegaLinter v10 或 beta:检查 .mega-linter.yml 中的 MEGALINTER_VERSION,如果固定的版本更早,则跳过此步骤(直接进行完整运行)。
-
以仅分析模式运行 MegaLinter(速度快:不会运行任何 linter,且随后真正运行时会复用拉取的镜像):
npx mega-linter-runner --prerun -
阅读
megalinter-reports/prerun-report.json。suggestions中的每个条目都描述了一项.mega-linter.yml修改:variable、operation(append表示追加到列表 /set表示设置)、values、safe、reason、details。 -
与用户一起审阅建议:
safe: true的建议(仅包含被 git 忽略文件的目录)不会改变 lint 范围——将这些建议分组展示,并建议采纳。safe: false的建议(仍包含可进行 lint 的文件的常见生成目录名称、风格变更)需要用户明确决定——逐项询问,并提供details中的文件数。风格变更还需要更新 CI 工作流文件中的镜像引用。
-
将用户接受的修改应用到
.mega-linter.yml,然后继续正常的完整运行。
如果运行后找不到报告文件(较旧的镜像未达到 v10,忽略了 MEGALINTER_PRERUN 并对所有内容执行了 lint),则将输出视为正常的完整运行结果,而不是重新运行。
定向复查(修复后)
只重新运行之前失败的部分,并行执行(最多 4 个并发容器):
npx mega-linter-runner --linter PYTHON_RUFF -e JSON_REPORTER=true src/a.py src/b.py &
npx mega-linter-runner --linter MARKDOWN_MARKDOWNLINT -e JSON_REPORTER=true README.md &
wait
(出于与完整运行相同的原因,使用 -e JSON_REPORTER=true:默认不会生成 JSON 报告。)
版本规则(适用于所有技能):运行器和 Docker 镜像版本始终遵循 .mega-linter.yml 中的 MEGALINTER_VERSION——值为 beta 时调用 npx mega-linter-runner@beta,否则调用不带标签的 npx mega-linter-runner,并且绝不要自行传入 --release。注意:在 MegaLinter v10 之前,独立的 megalinter-only-* 镜像只有在 beta 标签下才支持多架构。因此,如果 MEGALINTER_VERSION 不是 beta,而独立运行因平台错误而失败,请告知用户,并建议将 MEGALINTER_VERSION 固定为 beta,或改用完整镜像进行复查。
- 对文件级 linter,将修复后的文件作为参数传入;对项目级 linter(例如
REPOSITORY_*、COPYPASTE_JSCPD),省略文件列表。 - 每次运行都会将报告写入
megalinter-reports/<linter_key_lower>/——并行运行之间不会冲突。 - 此处同样适用本地模式的防护措施:先进行引擎预检,为每次运行设置时限(每个独立 linter 约 10 分钟),并在强制终止后检查是否有残留容器。
输出约定
无论使用哪种模式,都按以下格式总结结果(megalinter-fix 会使用此格式):
{
"status": "success|errors|failure",
"linters": [
{
"key": "PYTHON_RUFF",
"errors": 12,
"fixable": true,
"blocking": true,
"files": ["src/a.py"],
"samples": ["src/a.py:10:5 E501 line too long"]
}
]
}
区分阻塞型 linter(❌,会导致作业失败)和非阻塞型 linter(⚠️,DISABLE_ERRORS: true)。failure 状态表示作业或运行本身出错(容器引擎、网络、配置):应添加 "failure_reason" 字段,简要摘录原因,而不是列出 linter 错误。在监视模式下,可以添加 "job_url" 字段以供参考。如果在控制台中发现提示,则添加可选的 "tips" 字段(见下文)。
在监视模式下,如果 MegaLinter 将自身修复推送到了分支,则添加可选的 "auto_fix_commit" 字段,让调用方知道工作副本已落后,以及是否重新触发了检查:
"auto_fix_commit": {
"sha": "94873de",
"subject": "[MegaLinter] Apply linters fixes",
"is_branch_tip": true,
"amended": true
}
控制台提示(即使运行成功也要查看)
MegaLinter 的控制台输出中包含许多可供 Agent 采取行动的建议,但这些建议不会进入 JSON 报告:性能警告(“>300 个被 .gitignore 忽略的文件……请考虑使用 ADDITIONAL_EXCLUDED_DIRECTORIES”,“检测到大型文件夹”)、风味建议、解释为什么某个 linter 未运行的 [Activation] 通知、弃用和移除 linter 的通知、超时终止、转发排除项的跟踪信息。请务必收集这些内容:
- 本地模式:完整的控制台流会保存到报告文件夹中——使用 glob
megalinter-reports/mega*linter.log(文件名来自LOG_FILE,默认为mega-linter.log;LOG_FILE: none会禁用日志文件,此时请使用捕获的控制台输出)。请用 grep 搜索,而不是重新读取控制台:grep -E "⚠|WARNING|\[Activation\]|Heavy folders|To improve|[Ff]lavor|deprecat|Timed out|[Cc]onsider" <log-file>。 - 监视模式:CI 作业日志就是控制台输出——对下载的日志执行相同的 grep。
将匹配项整理为不超过 10 条的单行内容:保留建议进行配置、性能优化或升级的行;删除逐文件的 lint 错误、横幅和进度行;合并重复内容。按以下格式添加到输出中:
"tips": [
"More than 300 .gitignored files detected (612): consider adding directories to ADDITIONAL_EXCLUDED_DIRECTORIES (heaviest: site, coverage)",
"[Activation] MARKDOWN_RUMDL inactive: set MARKDOWN_DEFAULT_STYLE=rumdl to activate"
]
在错误摘要之后将这些提示转告用户,并将与配置相关的提示纳入 megalinter-setup 优化步骤,或在正在进行时纳入预运行建议审查。与性能建议一样,未经用户同意,绝不要应用任何提示。
性能检查(即使运行成功也要查看)
MegaLinter 的摘要表按 linter 列出了 Elapsed time——请务必收集。若有任何 linter 耗时超过 30 秒,或超过总 lint 时间的 25%,请在输出中添加 "slow_linters" 字段:
"slow_linters": [{"key": "REPOSITORY_GRYPE", "elapsed_seconds": 116.6}]
当 slow_linters 非空时,请从此技能的目录加载 performance.md,并向用户报告相应的优化建议——明确说明没有任何检查失败,这些建议纯粹是为了提升速度。未经用户同意,绝不要应用任何性能优化(排除项、缓存、禁用 linter)。
优化:子 Agent(Claude Code 和兼容的 Agent)
如果支持子 Agent,且已安装 Agent 定义(参见 megalinter-setup):
当 MegaLinter 作为 Agent 插件安装时,定义会带有命名空间(megalinter:megalinter-watcher、megalinter:megalinter-runner、megalinter:megalinter-fixer);作为技能安装时,则保留原有名称。请使用平台列出的形式。
- 监视模式 → 使用分支/PR 引用启动
megalinter-watcher;它会轮询、获取并解析内容,然后返回输出约定。 - 本地模式 → 使用要运行的命令启动
megalinter-runner;它会执行命令并汇总报告。 - 定向复查 → 针对每次独立的 linter 运行各启动一个
megalinter-runner,并行执行(最多 4 个)。
这样可以避免数 MB 的 CI 日志和 linter 输出占用上下文。没有子 Agent 时,请直接完成所有操作。