Skip to content

🔄 CI/CD 流水线

Composer Skills 天生适合 CI/CD:类型化返回值让"失败判定"变成一行 if,自动安装让你不用在 runner 里预装 Composer。本页给出在 GitHub Actions 中使用它的完整示例。

🎯 典型流水线

一个 PHP 项目的 CI 流水线通常包含四步:

  1. 📥 自动安装 —— 缺失 Composer 时 SDK 自动补齐。
  2. 📦 install —— 安装项目依赖。
  3. 🔒 audit —— 安全审计,发现漏洞则失败。
  4. validate —— 校验 composer.json schema。

下面用 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)

🧭 下一步

基于 MIT 许可证发布