Files
gh-action-readme/internal/parser.go
Ismo Vuorinen 7f80105ff5 feat: go 1.25.5, dependency updates, renamed internal/errors (#129)
* feat: rename internal/errors to internal/apperrors

* fix(tests): clear env values before using in tests

* feat: rename internal/errors to internal/apperrors

* chore(deps): update go and all dependencies

* chore: remove renovate from pre-commit, formatting

* chore: sonarcloud fixes

* feat: consolidate constants to appconstants/constants.go

* chore: sonarcloud fixes

* feat: simplification, deduplication, test utils

* chore: sonarcloud fixes

* chore: sonarcloud fixes

* chore: sonarcloud fixes

* chore: sonarcloud fixes

* chore: clean up

* fix: config discovery, const deduplication

* chore: fixes
2026-01-01 23:17:29 +02:00

104 lines
2.8 KiB
Go

package internal
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/goccy/go-yaml"
"github.com/ivuorinen/gh-action-readme/appconstants"
)
// ActionYML models the action.yml metadata (fields are updateable as schema evolves).
type ActionYML struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Inputs map[string]ActionInput `yaml:"inputs"`
Outputs map[string]ActionOutput `yaml:"outputs"`
Runs map[string]any `yaml:"runs"`
Branding *Branding `yaml:"branding,omitempty"`
// Add more fields as the schema evolves
}
// ActionInput represents an input parameter for a GitHub Action.
type ActionInput struct {
Description string `yaml:"description"`
Required bool `yaml:"required"`
Default any `yaml:"default"`
}
// ActionOutput represents an output parameter for a GitHub Action.
type ActionOutput struct {
Description string `yaml:"description"`
}
// Branding represents the branding configuration for a GitHub Action.
type Branding struct {
Icon string `yaml:"icon"`
Color string `yaml:"color"`
}
// ParseActionYML reads and parses action.yml from given path.
func ParseActionYML(path string) (*ActionYML, error) {
f, err := os.Open(path) // #nosec G304 -- path from function parameter
if err != nil {
return nil, err
}
defer func() {
_ = f.Close() // Ignore close error in defer
}()
var a ActionYML
dec := yaml.NewDecoder(f)
if err := dec.Decode(&a); err != nil {
return nil, err
}
return &a, nil
}
// DiscoverActionFiles finds action.yml and action.yaml files in the given directory.
// This consolidates the file discovery logic from both generator.go and dependencies/parser.go.
func DiscoverActionFiles(dir string, recursive bool) ([]string, error) {
var actionFiles []string
// Check if dir exists
if _, err := os.Stat(dir); os.IsNotExist(err) {
return nil, fmt.Errorf("directory does not exist: %s", dir)
}
if recursive {
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
// Check for action.yml or action.yaml files
filename := strings.ToLower(info.Name())
if filename == appconstants.ActionFileNameYML || filename == appconstants.ActionFileNameYAML {
actionFiles = append(actionFiles, path)
}
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to walk directory %s: %w", dir, err)
}
} else {
// Check only the specified directory
for _, filename := range []string{appconstants.ActionFileNameYML, appconstants.ActionFileNameYAML} {
path := filepath.Join(dir, filename)
if _, err := os.Stat(path); err == nil {
actionFiles = append(actionFiles, path)
}
}
}
return actionFiles, nil
}