🔄 CI/CD 流水线
Composer Skills 天生适合 CI/CD:类型化返回值让"失败判定"变成一行 if,自动安装让你不用在 runner 里预装 Composer。本页给出在 GitHub Actions 中使用它的完整示例。
🎯 典型流水线
一个 PHP 项目的 CI 流水线通常包含四步:
- 📥 自动安装 —— 缺失 Composer 时 SDK 自动补齐。
- 📦 install —— 安装项目依赖。
- 🔒 audit —— 安全审计,发现漏洞则失败。
- ✅ validate —— 校验
composer.jsonschema。
下面用 Composer Skills 把这四步写成一段 Go 代码,再配一个 GitHub Actions workflow。
📝 Go 代码:流水线主程序
把以下代码保存为 ci/main.go,它会自动安装 Composer、安装依赖、审计漏洞、校验 schema,任何一步失败就以非 0 退出(CI 红灯)。
go
package main
import (
"fmt"
"log"
"os"
"github.com/scagogogo/composer-skills/pkg/composer"
)
func main() {
workingDir := os.Getenv("GITHUB_WORKSPACE")
if workingDir == "" {
workingDir = "."
}
// 1. 自动安装 + 创建实例
// QuickSetup 会在 Composer 缺失时自动拉取安装
comp, err := composer.QuickSetup(workingDir, true)
if err != nil {
log.Fatalf("❌ Composer 初始化失败: %v", err)
}
// 2. 安装依赖(--no-dev 可按需调整)
fmt.Println("📦 安装依赖...")
if err := comp.Install(false, true); err != nil {
log.Fatalf("❌ install 失败: %v", err)
}
// 3. 安全审计
fmt.Println("🔒 安全审计...")
result, err := comp.AuditWithJSON()
if err != nil {
log.Fatalf("❌ audit 失败: %v", err)
}
fmt.Printf(" 发现漏洞: %d\n", result.Found)
for _, v := range result.Advisories {
fmt.Printf(" ⚠ %s: %s (%s)\n", v.Package, v.Title, v.Severity)
}
if result.Found > 0 {
log.Fatalf("❌ 存在 %d 个漏洞,流水线失败", result.Found)
}
// 4. 校验 composer.json
fmt.Println("✅ 校验 composer.json...")
res, err := comp.ValidateStructured()
if err != nil {
log.Fatalf("❌ validate 失败: %v", err)
}
if !res.Valid {
for _, e := range res.Errors {
fmt.Printf(" ❌ 第 %d 行: %s\n", e.Line, e.Message)
}
log.Fatal("❌ composer.json 校验未通过")
}
fmt.Println("🎉 流水线全部通过")
}失败即红灯
CI 里只要进程以非 0 退出码结束,job 就标红。上面用 log.Fatalf 在任何失败处直接退出,无需额外判断。
⚙️ GitHub Actions Workflow
.github/workflows/composer-ci.yml:
yaml
name: Composer CI
on:
push:
branches: [main]
pull_request:
jobs:
composer-skills:
runs-on: ubuntu-latest
steps:
- name: 📥 检出代码
uses: actions/checkout@v4
- name: 🐹 安装 Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: 🐘 安装 PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
# Composer Skills 也能自动装 Composer,这里预装省时间
coverage: none
- name: 📦 拉取 Go 依赖
run: |
go mod download
go mod tidy
- name: 🚀 运行 Composer Skills 流水线
run: go run ./ci/main.go
- name: 📤 上传审计报告(可选)
if: always()
run: |
# 可在此调用 comp.AuditWithJSON 后把结果写文件并 upload-artifact
echo "审计已完成"为什么还要 setup-php?
Composer Skills 能自动装 Composer,但 PHP 本身需要预装或由 SDK 的 installer.InstallPHP 拉(Linux 上走 apt)。CI 里用 setup-php 更快更稳,SDK 的自动安装作为兜底。
🔒 纯远程审计(无 PHP 的 runner)
如果只想拉取 Packagist 安全公告做漏洞扫描,根本不需要 PHP——用 Packagist API SDK 即可,runner 体积更小:
go
package main
import (
"fmt"
"os"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
c := client.NewComposerClient(30 * 0) // 设置合理超时
advisories, err := c.GetSecurityAdvisoriesForPackages(
"monolog/monolog", "symfony/console",
)
if err != nil {
fmt.Printf("❌ %v\n", err)
os.Exit(1)
}
if len(advisories.Advisories) > 0 {
fmt.Printf("❌ 发现 %d 条公告\n", len(advisories.Advisories))
os.Exit(1)
}
fmt.Println("✅ 无安全公告")
}对应 workflow 可去掉 setup-php,只留 Go。
💡 进阶建议
- 🧪 缓存依赖:在 workflow 里加
actions/cache缓存~/.composer/cache,加速install。 - 🔑 私有仓库鉴权:把 GitHub Token 存为仓库 Secret,在 workflow 的
env中注入为环境变量,再在 Go 代码里用comp.AddGitHubToken("github.com", os.Getenv("GITHUB_TOKEN"))访问私有包。 - 📈 过期包监控:在定时任务(
on: schedule)里跑comp.GetOutdatedInfo(),过期则开 issue。 - 🧾 许可证检查:
comp.GetLicensesInfo()输出依赖许可证,避免引入不合规协议。
超时
CI 里命令可能因网络慢而挂起。用带超时的 Options:
go
options := composer.DefaultOptions()
options.DefaultTimeout = 30 * 60 * 1e9 // 30 分钟(纳秒)
comp, _ = composer.New(options)🧭 下一步
- 🐳 Docker 部署 —— 把流水线装进容器。
- 🔒 安全审计 SDK ——
AuditWithJSON字段详解。 - ✅ 验证 SDK ——
ValidateStructured用法。 - 🌐 Packagist 安全公告 —— 远程审计 API。