📈 依赖仪表盘
10 分钟,把 Outdated / Licenses / Abandoned / Funding 四类信号聚合成一份依赖健康报告。需要本机有 PHP + Composer。
为什么需要仪表盘
单独看每个 composer 命令的输出,很难回答"我的依赖整体健康吗"。把它们合并成一张结构化表,就能一眼看到:哪些过期、哪些被废弃、许可证有没有风险、哪些包该赞助。
四类数据源
| 信号 | 方法 | 返回 |
|---|---|---|
| 过期包 | comp.GetOutdatedInfo() | *OutdatedResult(Installed []OutdatedPackage) |
| 许可证 | comp.GetLicensesInfo() | *LicensesResult(Licenses []LicenseInfo) |
| 被废弃 | comp.GetAbandonedPackagesFromLock() | []string |
| 资金 | comp.GetFundingURLs() | map[包名][]string |
完整可运行示例
go
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"github.com/scagogogo/composer-skills/pkg/composer"
)
type Dashboard struct {
Outdated []composer.OutdatedPackage `json:"outdated"`
Licenses []composer.LicenseInfo `json:"licenses"`
Abandoned []string `json:"abandoned"`
Funding map[string][]string `json:"funding"`
}
func main() {
comp, err := composer.New(composer.DefaultOptions())
if err != nil {
log.Fatal(err)
}
comp.SetWorkingDir(".")
dash := Dashboard{}
// 1️⃣ 过期包
if info, err := comp.GetOutdatedInfo(); err == nil {
dash.Outdated = info.Installed
fmt.Printf("⏳ 过期包: %d\n", len(dash.Outdated))
for _, p := range dash.Outdated {
fmt.Printf(" - %s: %s → %s (%s)\n", p.Name, p.Installed, p.Latest, p.LatestStatus)
}
}
// 2️⃣ 许可证
if lic, err := comp.GetLicensesInfo(); err == nil {
dash.Licenses = lic.Licenses
fmt.Printf("\n📜 许可证种类: %d 个包\n", len(dash.Licenses))
for _, l := range dash.Licenses {
fmt.Printf(" - %s: %v\n", l.Package, l.Licenses)
}
}
// 3️⃣ 被废弃的包
if ab, err := comp.GetAbandonedPackagesFromLock(); err == nil {
dash.Abandoned = ab
fmt.Printf("\n🚫 被废弃: %d\n", len(dash.Abandoned))
for _, name := range dash.Abandoned {
fmt.Printf(" - %s\n", name)
}
}
// 4️⃣ 资金链接
if fund, err := comp.GetFundingURLs(); err == nil {
dash.Funding = fund
fmt.Printf("\n💰 有资金入口的包: %d\n", len(dash.Funding))
for pkg, urls := range dash.Funding {
fmt.Printf(" - %s: %v\n", pkg, urls)
}
}
// 5️⃣ 落盘
b, _ := json.MarshalIndent(dash, "", " ")
os.WriteFile("dependency-dashboard.json", b, 0644)
fmt.Println("\n✅ 仪表盘已写入 dependency-dashboard.json")
}预期输出
⏳ 过期包: 3
- monolog/monolog: 3.5.0 → 3.7.1 (semver-safe-update)
- guzzlehttp/guzzle: 7.7.0 → 7.8.1 (semver-safe-update)
- psr/log: 3.0.0 → 3.0.2 (semver-safe-update)
📜 许可证种类: 12 个包
- monolog/monolog: [MIT]
- guzzlehttp/guzzle: [MIT]
🚫 被废弃: 1
- old/deprecated-pkg
💰 有资金入口的包: 4
- monolog/monolog: [https://github.com/Seldaek]
✅ 仪表盘已写入 dependency-dashboard.json进阶:便捷方法速查
仪表盘里常会用到的组合便捷方法:
go
fmt.Println("已安装包数:", len(comp.GetDirectDependencyNames()))
fmt.Println("有 lock 文件:", comp.HasComposerLock())
fmt.Println("有 vendor:", comp.HasVendorDir())
summary := comp.GetProjectSummary() // 一次性拿到项目元信息渲染成网页
dependency-dashboard.json 是纯结构化数据,前端用任意图表库(ECharts / Chart.js)即可渲染。把这份 JSON 由 CI 定时生成并发布到内部站点,就是活的依赖看板。
GetAbandonedPackagesFromLock 依赖 lock
该方法读 composer.lock,若项目刚 require 还没 update,可能拿不到最新结果。先跑一次 comp.Install(false, true) 再统计。
下一步
- 给看板加安全维度:🔒 构建安全审计流水线。
- 让 CI 自动生成这份看板:🤖 CI/CD 中自动检测与安装。