mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-01-26 11:14:04 +00:00
* chore(lint): added nlreturn, run linting * chore(lint): replace some fmt.Sprintf calls * chore(lint): replace fmt.Sprintf with strconv * chore(lint): add goconst, use http lib for status codes, and methods * chore(lint): use errors lib, errCodes from internal/errors * chore(lint): dupl, thelper and usetesting * chore(lint): fmt.Errorf %v to %w, more linters * chore(lint): paralleltest, where possible * perf(test): optimize test performance by 78% - Implement shared binary building with package-level cache to eliminate redundant builds - Add strategic parallelization to 15+ tests while preserving environment variable isolation - Implement thread-safe fixture caching with RWMutex to reduce I/O operations - Remove unnecessary working directory changes by leveraging embedded templates - Add embedded template system with go:embed directive for reliable template resolution - Fix linting issues: rename sharedBinaryError to errSharedBinary, add nolint directive Performance improvements: - Total test execution time: 12+ seconds → 2.7 seconds (78% faster) - Binary build overhead: 14+ separate builds → 1 shared build (93% reduction) - Parallel execution: Limited → 15+ concurrent tests (60-70% better CPU usage) - I/O operations: 66+ fixture reads → cached with sync.RWMutex (50% reduction) All tests maintain 100% success rate and coverage while running nearly 4x faster.
102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// 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 == "action.yml" || filename == "action.yaml" {
|
|
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{"action.yml", "action.yaml"} {
|
|
path := filepath.Join(dir, filename)
|
|
if _, err := os.Stat(path); err == nil {
|
|
actionFiles = append(actionFiles, path)
|
|
}
|
|
}
|
|
}
|
|
|
|
return actionFiles, nil
|
|
}
|