基本解析
此示例演示了 GitHub Action Parser 库的基本解析功能。
解析 Action 文件
最基本的操作是解析 GitHub Action 文件:
go
package main
import (
"fmt"
"log"
"github.com/scagogogo/github-action-parser/pkg/parser"
)
func main() {
// 解析 action.yml 文件
action, err := parser.ParseFile("action.yml")
if err != nil {
log.Fatalf("解析 action 失败: %v", err)
}
// 显示基本信息
fmt.Printf("Action 名称: %s\n", action.Name)
fmt.Printf("描述: %s\n", action.Description)
fmt.Printf("作者: %s\n", action.Author)
}
访问输入参数
go
// 访问输入参数
fmt.Println("\n输入:")
for name, input := range action.Inputs {
fmt.Printf(" %s:\n", name)
fmt.Printf(" 描述: %s\n", input.Description)
fmt.Printf(" 必需: %t\n", input.Required)
if input.Default != "" {
fmt.Printf(" 默认值: %s\n", input.Default)
}
if input.Deprecated {
fmt.Printf(" 已弃用: true\n")
}
}
访问输出参数
go
// 访问输出参数
fmt.Println("\n输出:")
for name, output := range action.Outputs {
fmt.Printf(" %s:\n", name)
fmt.Printf(" 描述: %s\n", output.Description)
if output.Value != "" {
fmt.Printf(" 值: %s\n", output.Value)
}
}
检查 Action 类型
go
// 检查这是什么类型的 action
fmt.Printf("\nAction 类型: %s\n", action.Runs.Using)
switch action.Runs.Using {
case "composite":
fmt.Printf("复合 action,包含 %d 个步骤\n", len(action.Runs.Steps))
case "docker":
fmt.Printf("Docker action,使用镜像: %s\n", action.Runs.Image)
case "node16", "node20":
fmt.Printf("JavaScript action,主文件: %s\n", action.Runs.Main)
}
访问品牌信息
go
// 访问品牌信息
if action.Branding.Icon != "" || action.Branding.Color != "" {
fmt.Println("\n品牌:")
if action.Branding.Icon != "" {
fmt.Printf(" 图标: %s\n", action.Branding.Icon)
}
if action.Branding.Color != "" {
fmt.Printf(" 颜色: %s\n", action.Branding.Color)
}
}
完整示例
这是一个演示所有基本解析功能的完整示例:
go
package main
import (
"fmt"
"log"
"os"
"github.com/scagogogo/github-action-parser/pkg/parser"
)
func main() {
if len(os.Args) < 2 {
log.Fatal("用法: go run main.go <action.yml>")
}
actionFile := os.Args[1]
// 解析 action 文件
action, err := parser.ParseFile(actionFile)
if err != nil {
log.Fatalf("解析 %s 失败: %v", actionFile, err)
}
// 显示全面信息
displayActionInfo(action)
}
func displayActionInfo(action *parser.ActionFile) {
fmt.Printf("=== Action 信息 ===\n")
fmt.Printf("名称: %s\n", action.Name)
fmt.Printf("描述: %s\n", action.Description)
if action.Author != "" {
fmt.Printf("作者: %s\n", action.Author)
}
// 显示输入
if len(action.Inputs) > 0 {
fmt.Printf("\n=== 输入 (%d) ===\n", len(action.Inputs))
for name, input := range action.Inputs {
fmt.Printf("• %s", name)
if input.Required {
fmt.Printf(" (必需)")
}
fmt.Printf("\n %s\n", input.Description)
if input.Default != "" {
fmt.Printf(" 默认值: %s\n", input.Default)
}
}
}
// 显示输出
if len(action.Outputs) > 0 {
fmt.Printf("\n=== 输出 (%d) ===\n", len(action.Outputs))
for name, output := range action.Outputs {
fmt.Printf("• %s\n", name)
fmt.Printf(" %s\n", output.Description)
if output.Value != "" {
fmt.Printf(" 值: %s\n", output.Value)
}
}
}
// 显示运行时信息
fmt.Printf("\n=== 运行时 ===\n")
fmt.Printf("使用: %s\n", action.Runs.Using)
switch action.Runs.Using {
case "composite":
fmt.Printf("步骤: %d\n", len(action.Runs.Steps))
for i, step := range action.Runs.Steps {
fmt.Printf(" %d. %s\n", i+1, step.Name)
}
case "docker":
fmt.Printf("镜像: %s\n", action.Runs.Image)
if action.Runs.Entrypoint != "" {
fmt.Printf("入口点: %s\n", action.Runs.Entrypoint)
}
case "node16", "node20":
fmt.Printf("主文件: %s\n", action.Runs.Main)
if action.Runs.Pre != "" {
fmt.Printf("预执行: %s\n", action.Runs.Pre)
}
if action.Runs.Post != "" {
fmt.Printf("后执行: %s\n", action.Runs.Post)
}
}
// 显示品牌
if action.Branding.Icon != "" || action.Branding.Color != "" {
fmt.Printf("\n=== 品牌 ===\n")
if action.Branding.Icon != "" {
fmt.Printf("图标: %s\n", action.Branding.Icon)
}
if action.Branding.Color != "" {
fmt.Printf("颜色: %s\n", action.Branding.Color)
}
}
}
错误处理
解析文件时始终适当处理错误:
go
action, err := parser.ParseFile("action.yml")
if err != nil {
// 检查特定错误类型
if os.IsNotExist(err) {
log.Fatal("Action 文件不存在")
} else if strings.Contains(err.Error(), "yaml") {
log.Fatal("Action 文件中的 YAML 语法无效")
} else {
log.Fatalf("解析 action 失败: %v", err)
}
}