mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-02-21 21:52:15 +00:00
feat: ignore vendored directories (#135)
* feat: ignore vendored directories * chore: cr tweaks * fix: sonarcloud detected issues * fix: sonarcloud detected issues
This commit is contained in:
@@ -87,8 +87,6 @@ const (
|
|||||||
const (
|
const (
|
||||||
// ContextKeyError is used as a key for error information in context maps.
|
// ContextKeyError is used as a key for error information in context maps.
|
||||||
ContextKeyError = "error"
|
ContextKeyError = "error"
|
||||||
// ContextKeyTheme is used as a key for theme information.
|
|
||||||
ContextKeyTheme = "theme"
|
|
||||||
// ContextKeyConfig is used as a key for configuration information.
|
// ContextKeyConfig is used as a key for configuration information.
|
||||||
ContextKeyConfig = "config"
|
ContextKeyConfig = "config"
|
||||||
)
|
)
|
||||||
@@ -182,6 +180,8 @@ const (
|
|||||||
ConfigKeyVerbose = "verbose"
|
ConfigKeyVerbose = "verbose"
|
||||||
// ConfigKeyQuiet is the configuration key for quiet mode.
|
// ConfigKeyQuiet is the configuration key for quiet mode.
|
||||||
ConfigKeyQuiet = "quiet"
|
ConfigKeyQuiet = "quiet"
|
||||||
|
// ConfigKeyIgnoredDirectories is the configuration key for ignored directories during discovery.
|
||||||
|
ConfigKeyIgnoredDirectories = "ignored_directories"
|
||||||
|
|
||||||
// GitHub Integration
|
// GitHub Integration
|
||||||
// ConfigKeyGitHubToken is the configuration key for GitHub token.
|
// ConfigKeyGitHubToken is the configuration key for GitHub token.
|
||||||
@@ -261,6 +261,26 @@ func GetConfigSearchPaths() []string {
|
|||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defaultIgnoredDirectories lists directories to ignore during file discovery.
|
||||||
|
var defaultIgnoredDirectories = []string{
|
||||||
|
DirGit, DirGitHub, DirGitLab, DirSVN, // VCS
|
||||||
|
DirNodeModules, DirBowerComponents, // JavaScript
|
||||||
|
DirVendor, // Go/PHP
|
||||||
|
DirVenvDot, DirVenv, DirEnv, DirTox, DirPycache, // Python
|
||||||
|
DirDist, DirBuild, DirTarget, DirOut, // Build outputs
|
||||||
|
DirIdea, DirVscode, // IDEs
|
||||||
|
DirCache, DirTmpDot, DirTmp, // Cache/temp
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDefaultIgnoredDirectories returns a copy of the default ignored directory names.
|
||||||
|
// Returns a new slice to prevent external modification of the internal list.
|
||||||
|
func GetDefaultIgnoredDirectories() []string {
|
||||||
|
dirs := make([]string, len(defaultIgnoredDirectories))
|
||||||
|
copy(dirs, defaultIgnoredDirectories)
|
||||||
|
|
||||||
|
return dirs
|
||||||
|
}
|
||||||
|
|
||||||
// Output format constants.
|
// Output format constants.
|
||||||
const (
|
const (
|
||||||
// OutputFormatMarkdown is the Markdown output format.
|
// OutputFormatMarkdown is the Markdown output format.
|
||||||
@@ -317,6 +337,46 @@ const (
|
|||||||
EnvPrefix = "GH_ACTION_README"
|
EnvPrefix = "GH_ACTION_README"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Directory names commonly ignored during file discovery.
|
||||||
|
// These constants are used to exclude build artifacts, dependencies,
|
||||||
|
// version control, and temporary files from action file discovery.
|
||||||
|
const (
|
||||||
|
// Version Control System directories
|
||||||
|
// DirGit = ".git" (already defined above in "Directory and path constants").
|
||||||
|
DirGitHub = ".github"
|
||||||
|
DirGitLab = ".gitlab"
|
||||||
|
DirSVN = ".svn"
|
||||||
|
|
||||||
|
// JavaScript/Node.js dependencies.
|
||||||
|
DirNodeModules = "node_modules"
|
||||||
|
DirBowerComponents = "bower_components"
|
||||||
|
|
||||||
|
// Package manager vendor directories.
|
||||||
|
DirVendor = "vendor"
|
||||||
|
|
||||||
|
// Python virtual environments and cache.
|
||||||
|
DirVenv = "venv"
|
||||||
|
DirVenvDot = ".venv"
|
||||||
|
DirEnv = "env"
|
||||||
|
DirTox = ".tox"
|
||||||
|
DirPycache = "__pycache__"
|
||||||
|
|
||||||
|
// Build output directories.
|
||||||
|
DirDist = "dist"
|
||||||
|
DirBuild = "build"
|
||||||
|
DirTarget = "target"
|
||||||
|
DirOut = "out"
|
||||||
|
|
||||||
|
// IDE configuration directories.
|
||||||
|
DirIdea = ".idea"
|
||||||
|
DirVscode = ".vscode"
|
||||||
|
|
||||||
|
// Cache and temporary directories.
|
||||||
|
DirCache = ".cache"
|
||||||
|
DirTmp = "tmp"
|
||||||
|
DirTmpDot = ".tmp"
|
||||||
|
)
|
||||||
|
|
||||||
// Git constants.
|
// Git constants.
|
||||||
const (
|
const (
|
||||||
// GitCommand is the git command name.
|
// GitCommand is the git command name.
|
||||||
@@ -485,6 +545,8 @@ const (
|
|||||||
FlagOutput = "output"
|
FlagOutput = "output"
|
||||||
// FlagRecursive is the recursive flag name.
|
// FlagRecursive is the recursive flag name.
|
||||||
FlagRecursive = "recursive"
|
FlagRecursive = "recursive"
|
||||||
|
// FlagIgnoreDirs is the ignore-dirs flag name.
|
||||||
|
FlagIgnoreDirs = "ignore-dirs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Field names for validation.
|
// Field names for validation.
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ const (
|
|||||||
|
|
||||||
// Test file path constants.
|
// Test file path constants.
|
||||||
const (
|
const (
|
||||||
TestPathActionYML = "action.yml"
|
|
||||||
TestPathActionYAML = "action.yaml"
|
|
||||||
TestPathConfigYML = "config.yml"
|
TestPathConfigYML = "config.yml"
|
||||||
TestPathCustomConfigYML = "custom-config.yml"
|
TestPathCustomConfigYML = "custom-config.yml"
|
||||||
TestPathNonexistentYML = "nonexistent.yml"
|
TestPathNonexistentYML = "nonexistent.yml"
|
||||||
@@ -67,6 +65,18 @@ const (
|
|||||||
// Config directories.
|
// Config directories.
|
||||||
TestDirConfigGhActionReadme = ".config/gh-action-readme"
|
TestDirConfigGhActionReadme = ".config/gh-action-readme"
|
||||||
TestDirDotConfig = ".config"
|
TestDirDotConfig = ".config"
|
||||||
TestDirDotGitHub = ".github"
|
|
||||||
TestDirCacheGhActionReadme = ".cache/gh-action-readme"
|
TestDirCacheGhActionReadme = ".cache/gh-action-readme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// (Test file permission constants removed - use production constants from appconstants/constants.go)
|
||||||
|
|
||||||
|
// Test YAML content for parser tests.
|
||||||
|
const (
|
||||||
|
TestYAMLRoot = "name: root"
|
||||||
|
TestYAMLNodeModules = "name: node_modules"
|
||||||
|
TestYAMLVendor = "name: vendor"
|
||||||
|
TestYAMLGit = "name: git"
|
||||||
|
TestYAMLSrc = "name: src"
|
||||||
|
TestYAMLNested = "name: nested"
|
||||||
|
TestYAMLSub = "name: sub"
|
||||||
|
)
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ func buildTestBinary(t *testing.T) string {
|
|||||||
// setupCompleteWorkflow creates a realistic project structure for testing.
|
// setupCompleteWorkflow creates a realistic project structure for testing.
|
||||||
func setupCompleteWorkflow(t *testing.T, tmpDir string) {
|
func setupCompleteWorkflow(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, "README.md"), "# Old README")
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, "README.md"), "# Old README")
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, ".gitignore"), testutil.GitIgnoreContent)
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, ".gitignore"), testutil.GitIgnoreContent)
|
||||||
@@ -146,7 +146,7 @@ func setupCompleteWorkflow(t *testing.T, tmpDir string) {
|
|||||||
// setupMultiActionWorkflow creates a project with multiple actions.
|
// setupMultiActionWorkflow creates a project with multiple actions.
|
||||||
func setupMultiActionWorkflow(t *testing.T, tmpDir string) {
|
func setupMultiActionWorkflow(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
testutil.CreateActionSubdir(t, tmpDir, "actions/deploy", appconstants.TestFixtureDockerBasic)
|
testutil.CreateActionSubdir(t, tmpDir, "actions/deploy", appconstants.TestFixtureDockerBasic)
|
||||||
@@ -156,14 +156,14 @@ func setupMultiActionWorkflow(t *testing.T, tmpDir string) {
|
|||||||
// setupConfigWorkflow creates a simple action for config testing.
|
// setupConfigWorkflow creates a simple action for config testing.
|
||||||
func setupConfigWorkflow(t *testing.T, tmpDir string) {
|
func setupConfigWorkflow(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
}
|
}
|
||||||
|
|
||||||
// setupErrorWorkflow creates an invalid action file for error testing.
|
// setupErrorWorkflow creates an invalid action file for error testing.
|
||||||
func setupErrorWorkflow(t *testing.T, tmpDir string) {
|
func setupErrorWorkflow(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureInvalidMissingDescription))
|
testutil.MustReadFixture(appconstants.TestFixtureInvalidMissingDescription))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ func setupErrorWorkflow(t *testing.T, tmpDir string) {
|
|||||||
func setupConfigurationHierarchy(t *testing.T, tmpDir string) {
|
func setupConfigurationHierarchy(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Create action file
|
// Create action file
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
|
|
||||||
// Create global config
|
// Create global config
|
||||||
@@ -193,7 +193,7 @@ func setupConfigurationHierarchy(t *testing.T, tmpDir string) {
|
|||||||
func setupMultiActionWithTemplates(t *testing.T, tmpDir string) {
|
func setupMultiActionWithTemplates(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Root action
|
// Root action
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
// Nested actions with different types
|
// Nested actions with different types
|
||||||
@@ -239,7 +239,7 @@ func setupDependencyAnalysisWorkflow(t *testing.T, tmpDir string) {
|
|||||||
"actions/upload-artifact@v3",
|
"actions/upload-artifact@v3",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML), compositeAction)
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML), compositeAction)
|
||||||
|
|
||||||
// Add package.json with npm dependencies
|
// Add package.json with npm dependencies
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, "package.json"), testutil.PackageJSONContent)
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, "package.json"), testutil.PackageJSONContent)
|
||||||
@@ -256,14 +256,14 @@ func setupDependencyAnalysisWorkflow(t *testing.T, tmpDir string) {
|
|||||||
"aws-actions/configure-aws-credentials@v2",
|
"aws-actions/configure-aws-credentials@v2",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
testutil.WriteTestFile(t, filepath.Join(nestedDir, appconstants.TestPathActionYML), nestedAction)
|
testutil.WriteTestFile(t, filepath.Join(nestedDir, appconstants.ActionFileNameYML), nestedAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setupConfigurationHierarchyWorkflow creates a comprehensive configuration hierarchy.
|
// setupConfigurationHierarchyWorkflow creates a comprehensive configuration hierarchy.
|
||||||
func setupConfigurationHierarchyWorkflow(t *testing.T, tmpDir string) {
|
func setupConfigurationHierarchyWorkflow(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Create action file
|
// Create action file
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
|
|
||||||
// Set up XDG config home
|
// Set up XDG config home
|
||||||
@@ -305,7 +305,7 @@ output_dir: docs`
|
|||||||
func setupTemplateErrorScenario(t *testing.T, tmpDir string) {
|
func setupTemplateErrorScenario(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Create valid action file
|
// Create valid action file
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
// Create a broken template directory structure
|
// Create a broken template directory structure
|
||||||
@@ -323,7 +323,7 @@ func setupTemplateErrorScenario(t *testing.T, tmpDir string) {
|
|||||||
func setupConfigurationErrorScenario(t *testing.T, tmpDir string) {
|
func setupConfigurationErrorScenario(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Create valid action file
|
// Create valid action file
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
// Create invalid configuration files
|
// Create invalid configuration files
|
||||||
@@ -362,7 +362,7 @@ func setupFileDiscoveryErrorScenario(t *testing.T, tmpDir string) {
|
|||||||
func setupServiceIntegrationErrorScenario(t *testing.T, tmpDir string) {
|
func setupServiceIntegrationErrorScenario(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Valid action at root
|
// Valid action at root
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
// Invalid action in subdirectory
|
// Invalid action in subdirectory
|
||||||
@@ -753,7 +753,7 @@ type errorScenario struct {
|
|||||||
func testProjectSetup(t *testing.T, binaryPath, tmpDir string) {
|
func testProjectSetup(t *testing.T, binaryPath, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Create a new GitHub Action project
|
// Create a new GitHub Action project
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureMyNewAction))
|
testutil.MustReadFixture(appconstants.TestFixtureMyNewAction))
|
||||||
|
|
||||||
// Validate the action
|
// Validate the action
|
||||||
@@ -791,7 +791,7 @@ func testDocumentationGeneration(t *testing.T, binaryPath, tmpDir string) {
|
|||||||
func testDependencyManagement(t *testing.T, binaryPath, tmpDir string) {
|
func testDependencyManagement(t *testing.T, binaryPath, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Update action to be composite with dependencies
|
// Update action to be composite with dependencies
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
|
|
||||||
// List dependencies
|
// List dependencies
|
||||||
@@ -1164,7 +1164,7 @@ func TestStressTestWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
actionContent := strings.ReplaceAll(testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple),
|
actionContent := strings.ReplaceAll(testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple),
|
||||||
"Simple Action", "Action "+string(rune('A'+i)))
|
"Simple Action", "Action "+string(rune('A'+i)))
|
||||||
testutil.WriteTestFile(t, filepath.Join(actionDir, appconstants.TestPathActionYML), actionContent)
|
testutil.WriteTestFile(t, filepath.Join(actionDir, appconstants.ActionFileNameYML), actionContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test recursive processing
|
// Test recursive processing
|
||||||
@@ -1295,7 +1295,7 @@ func TestErrorRecoveryWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
// Create a project with mixed valid and invalid files
|
// Create a project with mixed valid and invalid files
|
||||||
// Note: validation looks for files named exactly "action.yml" or "action.yaml"
|
// Note: validation looks for files named exactly "action.yml" or "action.yaml"
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
testutil.CreateActionSubdir(t, tmpDir, appconstants.TestDirSubdir,
|
testutil.CreateActionSubdir(t, tmpDir, appconstants.TestDirSubdir,
|
||||||
@@ -1345,7 +1345,7 @@ func TestConfigurationWorkflow(t *testing.T) {
|
|||||||
configHome := filepath.Join(tmpDir, "config")
|
configHome := filepath.Join(tmpDir, "config")
|
||||||
t.Setenv("XDG_CONFIG_HOME", configHome)
|
t.Setenv("XDG_CONFIG_HOME", configHome)
|
||||||
|
|
||||||
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
testutil.WriteTestFile(t, filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@@ -1418,7 +1418,7 @@ func verifyProgressIndicators(t *testing.T, tmpDir string) {
|
|||||||
// The actual progress output is captured during the workflow step execution
|
// The actual progress output is captured during the workflow step execution
|
||||||
// Here we verify the infrastructure was set up correctly
|
// Here we verify the infrastructure was set up correctly
|
||||||
|
|
||||||
actionFile := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionFile := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
if _, err := os.Stat(actionFile); err != nil {
|
if _, err := os.Stat(actionFile); err != nil {
|
||||||
t.Error("action file missing, progress tracking test setup failed")
|
t.Error("action file missing, progress tracking test setup failed")
|
||||||
|
|
||||||
@@ -1440,10 +1440,10 @@ func verifyProgressIndicators(t *testing.T, tmpDir string) {
|
|||||||
func verifyFileDiscovery(t *testing.T, tmpDir string) {
|
func verifyFileDiscovery(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
expectedActions := []string{
|
expectedActions := []string{
|
||||||
filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
filepath.Join(tmpDir, "actions", "composite", appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, "actions", "composite", appconstants.ActionFileNameYML),
|
||||||
filepath.Join(tmpDir, "actions", "docker", appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, "actions", "docker", appconstants.ActionFileNameYML),
|
||||||
filepath.Join(tmpDir, "actions", "minimal", appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, "actions", "minimal", appconstants.ActionFileNameYML),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify action files were set up correctly and exist
|
// Verify action files were set up correctly and exist
|
||||||
@@ -1482,13 +1482,13 @@ func verifyTemplateRendering(t *testing.T, tmpDir string) {
|
|||||||
actionFiles, _ := filepath.Glob(filepath.Join(tmpDir, "**/action.yml"))
|
actionFiles, _ := filepath.Glob(filepath.Join(tmpDir, "**/action.yml"))
|
||||||
if len(actionFiles) == 0 {
|
if len(actionFiles) == 0 {
|
||||||
// Try different pattern
|
// Try different pattern
|
||||||
actionFiles, _ = filepath.Glob(filepath.Join(tmpDir, appconstants.TestPathActionYML))
|
actionFiles, _ = filepath.Glob(filepath.Join(tmpDir, appconstants.ActionFileNameYML))
|
||||||
if len(actionFiles) == 0 {
|
if len(actionFiles) == 0 {
|
||||||
t.Error("no action files found for template rendering verification")
|
t.Error("no action files found for template rendering verification")
|
||||||
t.Logf(
|
t.Logf(
|
||||||
"Checked patterns: %s and %s",
|
"Checked patterns: %s and %s",
|
||||||
filepath.Join(tmpDir, "**/action.yml"),
|
filepath.Join(tmpDir, "**/action.yml"),
|
||||||
filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -1530,7 +1530,7 @@ func verifyCompleteServiceChain(t *testing.T, tmpDir string) {
|
|||||||
|
|
||||||
// Verify the complete test environment was set up correctly
|
// Verify the complete test environment was set up correctly
|
||||||
requiredComponents := []string{
|
requiredComponents := []string{
|
||||||
filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
filepath.Join(tmpDir, "package.json"),
|
filepath.Join(tmpDir, "package.json"),
|
||||||
filepath.Join(tmpDir, ".gitignore"),
|
filepath.Join(tmpDir, ".gitignore"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,9 @@ type AppConfig struct {
|
|||||||
RepoOverrides map[string]AppConfig `mapstructure:"repo_overrides" yaml:"repo_overrides,omitempty"`
|
RepoOverrides map[string]AppConfig `mapstructure:"repo_overrides" yaml:"repo_overrides,omitempty"`
|
||||||
|
|
||||||
// Behavior
|
// Behavior
|
||||||
Verbose bool `mapstructure:"verbose" yaml:"verbose"`
|
Verbose bool `mapstructure:"verbose" yaml:"verbose"`
|
||||||
Quiet bool `mapstructure:"quiet" yaml:"quiet"`
|
Quiet bool `mapstructure:"quiet" yaml:"quiet"`
|
||||||
|
IgnoredDirectories []string `mapstructure:"ignored_directories" yaml:"ignored_directories,omitempty"`
|
||||||
|
|
||||||
// Default values for action.yml files (legacy)
|
// Default values for action.yml files (legacy)
|
||||||
Defaults DefaultValues `mapstructure:"defaults" yaml:"defaults,omitempty"`
|
Defaults DefaultValues `mapstructure:"defaults" yaml:"defaults,omitempty"`
|
||||||
@@ -243,8 +244,9 @@ func DefaultAppConfig() *AppConfig {
|
|||||||
RepoOverrides: map[string]AppConfig{},
|
RepoOverrides: map[string]AppConfig{},
|
||||||
|
|
||||||
// Behavior
|
// Behavior
|
||||||
Verbose: false,
|
Verbose: false,
|
||||||
Quiet: false,
|
Quiet: false,
|
||||||
|
IgnoredDirectories: appconstants.GetDefaultIgnoredDirectories(),
|
||||||
|
|
||||||
// Default values for action.yml files (legacy)
|
// Default values for action.yml files (legacy)
|
||||||
Defaults: DefaultValues{
|
Defaults: DefaultValues{
|
||||||
@@ -318,6 +320,10 @@ func mergeSliceFields(dst *AppConfig, src *AppConfig) {
|
|||||||
dst.RunsOn = make([]string, len(src.RunsOn))
|
dst.RunsOn = make([]string, len(src.RunsOn))
|
||||||
copy(dst.RunsOn, src.RunsOn)
|
copy(dst.RunsOn, src.RunsOn)
|
||||||
}
|
}
|
||||||
|
if len(src.IgnoredDirectories) > 0 {
|
||||||
|
dst.IgnoredDirectories = make([]string, len(src.IgnoredDirectories))
|
||||||
|
copy(dst.IgnoredDirectories, src.IgnoredDirectories)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mergeBooleanFields merges boolean fields from src to dst if true.
|
// mergeBooleanFields merges boolean fields from src to dst if true.
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func TestAnalyzer_AnalyzeActionFile(t *testing.T) {
|
|||||||
tmpDir, cleanup := testutil.TempDir(t)
|
tmpDir, cleanup := testutil.TempDir(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, tt.actionYML)
|
testutil.WriteTestFile(t, actionPath, tt.actionYML)
|
||||||
|
|
||||||
// Create analyzer with mock GitHub client
|
// Create analyzer with mock GitHub client
|
||||||
@@ -432,7 +432,7 @@ func TestAnalyzer_GeneratePinnedUpdate(t *testing.T) {
|
|||||||
// Create a test action file with composite steps
|
// Create a test action file with composite steps
|
||||||
actionContent := testutil.MustReadFixture(appconstants.TestFixtureTestCompositeAction)
|
actionContent := testutil.MustReadFixture(appconstants.TestFixtureTestCompositeAction)
|
||||||
|
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, actionContent)
|
testutil.WriteTestFile(t, actionPath, actionContent)
|
||||||
|
|
||||||
// Create analyzer
|
// Create analyzer
|
||||||
@@ -551,7 +551,7 @@ func TestAnalyzer_WithoutGitHubClient(t *testing.T) {
|
|||||||
tmpDir, cleanup := testutil.TempDir(t)
|
tmpDir, cleanup := testutil.TempDir(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
|
|
||||||
deps, err := analyzer.AnalyzeActionFile(actionPath)
|
deps, err := analyzer.AnalyzeActionFile(actionPath)
|
||||||
|
|||||||
@@ -139,8 +139,8 @@ func (g *Generator) GenerateFromFile(actionPath string) error {
|
|||||||
|
|
||||||
// DiscoverActionFiles finds action.yml and action.yaml files in the given directory
|
// DiscoverActionFiles finds action.yml and action.yaml files in the given directory
|
||||||
// using the centralized parser function and adds verbose logging.
|
// using the centralized parser function and adds verbose logging.
|
||||||
func (g *Generator) DiscoverActionFiles(dir string, recursive bool) ([]string, error) {
|
func (g *Generator) DiscoverActionFiles(dir string, recursive bool, ignoredDirs []string) ([]string, error) {
|
||||||
actionFiles, err := DiscoverActionFiles(dir, recursive)
|
actionFiles, err := DiscoverActionFiles(dir, recursive, ignoredDirs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -161,9 +161,14 @@ func (g *Generator) DiscoverActionFiles(dir string, recursive bool) ([]string, e
|
|||||||
|
|
||||||
// DiscoverActionFilesWithValidation discovers action files with centralized error handling and validation.
|
// DiscoverActionFilesWithValidation discovers action files with centralized error handling and validation.
|
||||||
// This function consolidates the duplicated file discovery logic across the codebase.
|
// This function consolidates the duplicated file discovery logic across the codebase.
|
||||||
func (g *Generator) DiscoverActionFilesWithValidation(dir string, recursive bool, context string) ([]string, error) {
|
func (g *Generator) DiscoverActionFilesWithValidation(
|
||||||
|
dir string,
|
||||||
|
recursive bool,
|
||||||
|
ignoredDirs []string,
|
||||||
|
context string,
|
||||||
|
) ([]string, error) {
|
||||||
// Discover action files
|
// Discover action files
|
||||||
actionFiles, err := g.DiscoverActionFiles(dir, recursive)
|
actionFiles, err := g.DiscoverActionFiles(dir, recursive, ignoredDirs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.Output.ErrorWithContext(
|
g.Output.ErrorWithContext(
|
||||||
appconstants.ErrCodeFileNotFound,
|
appconstants.ErrCodeFileNotFound,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func TestGenerator_DiscoverActionFiles(t *testing.T) {
|
|||||||
testutil.WriteActionFixtureAs(
|
testutil.WriteActionFixtureAs(
|
||||||
t,
|
t,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
appconstants.TestPathActionYAML,
|
appconstants.ActionFileNameYAML,
|
||||||
appconstants.TestFixtureJavaScriptSimple,
|
appconstants.TestFixtureJavaScriptSimple,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -75,7 +75,7 @@ func TestGenerator_DiscoverActionFiles(t *testing.T) {
|
|||||||
testutil.WriteActionFixtureAs(
|
testutil.WriteActionFixtureAs(
|
||||||
t,
|
t,
|
||||||
tmpDir,
|
tmpDir,
|
||||||
appconstants.TestPathActionYAML,
|
appconstants.ActionFileNameYAML,
|
||||||
appconstants.TestFixtureMinimalAction,
|
appconstants.TestFixtureMinimalAction,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -145,7 +145,7 @@ func TestGenerator_DiscoverActionFiles(t *testing.T) {
|
|||||||
testDir = filepath.Join(tmpDir, "nonexistent")
|
testDir = filepath.Join(tmpDir, "nonexistent")
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := generator.DiscoverActionFiles(testDir, tt.recursive)
|
files, err := generator.DiscoverActionFiles(testDir, tt.recursive, []string{})
|
||||||
|
|
||||||
if tt.expectError {
|
if tt.expectError {
|
||||||
testutil.AssertError(t, err)
|
testutil.AssertError(t, err)
|
||||||
@@ -160,8 +160,8 @@ func TestGenerator_DiscoverActionFiles(t *testing.T) {
|
|||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
testutil.AssertFileExists(t, file)
|
testutil.AssertFileExists(t, file)
|
||||||
|
|
||||||
if !strings.HasSuffix(file, appconstants.TestPathActionYML) &&
|
if !strings.HasSuffix(file, appconstants.ActionFileNameYML) &&
|
||||||
!strings.HasSuffix(file, appconstants.TestPathActionYAML) {
|
!strings.HasSuffix(file, appconstants.ActionFileNameYAML) {
|
||||||
t.Errorf("discovered file is not an action file: %s", file)
|
t.Errorf("discovered file is not an action file: %s", file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ func TestGenerator_GenerateFromFile(t *testing.T) {
|
|||||||
testutil.SetupTestTemplates(t, tmpDir)
|
testutil.SetupTestTemplates(t, tmpDir)
|
||||||
|
|
||||||
// Write action file
|
// Write action file
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, tt.actionYML)
|
testutil.WriteTestFile(t, actionPath, tt.actionYML)
|
||||||
|
|
||||||
// Create generator with explicit template path
|
// Create generator with explicit template path
|
||||||
@@ -341,8 +341,8 @@ func TestGenerator_ProcessBatch(t *testing.T) {
|
|||||||
dirs := createTestDirs(t, tmpDir, "action1", "action2")
|
dirs := createTestDirs(t, tmpDir, "action1", "action2")
|
||||||
|
|
||||||
files := []string{
|
files := []string{
|
||||||
filepath.Join(dirs[0], appconstants.TestPathActionYML),
|
filepath.Join(dirs[0], appconstants.ActionFileNameYML),
|
||||||
filepath.Join(dirs[1], appconstants.TestPathActionYML),
|
filepath.Join(dirs[1], appconstants.ActionFileNameYML),
|
||||||
}
|
}
|
||||||
testutil.WriteTestFile(t, files[0], testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.WriteTestFile(t, files[0], testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
testutil.WriteTestFile(t, files[1], testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.WriteTestFile(t, files[1], testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
@@ -360,8 +360,8 @@ func TestGenerator_ProcessBatch(t *testing.T) {
|
|||||||
dirs := createTestDirs(t, tmpDir, "valid-action", "invalid-action")
|
dirs := createTestDirs(t, tmpDir, "valid-action", "invalid-action")
|
||||||
|
|
||||||
files := []string{
|
files := []string{
|
||||||
filepath.Join(dirs[0], appconstants.TestPathActionYML),
|
filepath.Join(dirs[0], appconstants.ActionFileNameYML),
|
||||||
filepath.Join(dirs[1], appconstants.TestPathActionYML),
|
filepath.Join(dirs[1], appconstants.ActionFileNameYML),
|
||||||
}
|
}
|
||||||
testutil.WriteTestFile(t, files[0], testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.WriteTestFile(t, files[0], testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
testutil.WriteTestFile(
|
testutil.WriteTestFile(
|
||||||
@@ -567,7 +567,7 @@ func TestGenerator_WithDifferentThemes(t *testing.T) {
|
|||||||
// Set up test templates for this theme test
|
// Set up test templates for this theme test
|
||||||
testutil.SetupTestTemplates(t, tmpDir)
|
testutil.SetupTestTemplates(t, tmpDir)
|
||||||
|
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(appconstants.TestFixtureJavaScriptSimple))
|
||||||
|
|
||||||
config := &AppConfig{
|
config := &AppConfig{
|
||||||
@@ -611,7 +611,7 @@ func TestGenerator_ErrorHandling(t *testing.T) {
|
|||||||
Quiet: true,
|
Quiet: true,
|
||||||
}
|
}
|
||||||
generator := NewGenerator(config)
|
generator := NewGenerator(config)
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(
|
testutil.WriteTestFile(
|
||||||
t,
|
t,
|
||||||
actionPath,
|
actionPath,
|
||||||
@@ -640,7 +640,7 @@ func TestGenerator_ErrorHandling(t *testing.T) {
|
|||||||
Template: filepath.Join(tmpDir, "templates", "readme.tmpl"),
|
Template: filepath.Join(tmpDir, "templates", "readme.tmpl"),
|
||||||
}
|
}
|
||||||
generator := NewGenerator(config)
|
generator := NewGenerator(config)
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(
|
testutil.WriteTestFile(
|
||||||
t,
|
t,
|
||||||
actionPath,
|
actionPath,
|
||||||
|
|||||||
@@ -58,46 +58,84 @@ func ParseActionYML(path string) (*ActionYML, error) {
|
|||||||
return &a, nil
|
return &a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldIgnoreDirectory checks if a directory name matches the ignore list.
|
||||||
|
func shouldIgnoreDirectory(dirName string, ignoredDirs []string) bool {
|
||||||
|
for _, ignored := range ignoredDirs {
|
||||||
|
if strings.HasPrefix(ignored, ".") {
|
||||||
|
// Pattern match: ".git" matches ".git", ".github", etc.
|
||||||
|
if strings.HasPrefix(dirName, ignored) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Exact match for non-hidden dirs
|
||||||
|
if dirName == ignored {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// actionFileWalker encapsulates the logic for walking directories and finding action files.
|
||||||
|
type actionFileWalker struct {
|
||||||
|
ignoredDirs []string
|
||||||
|
actionFiles []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// walkFunc is the callback function for filepath.Walk.
|
||||||
|
func (w *actionFileWalker) walkFunc(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
if shouldIgnoreDirectory(info.Name(), w.ignoredDirs) {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for action.yml or action.yaml files
|
||||||
|
filename := strings.ToLower(info.Name())
|
||||||
|
if filename == appconstants.ActionFileNameYML || filename == appconstants.ActionFileNameYAML {
|
||||||
|
w.actionFiles = append(w.actionFiles, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DiscoverActionFiles finds action.yml and action.yaml files in the given directory.
|
// 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.
|
// This consolidates the file discovery logic from both generator.go and dependencies/parser.go.
|
||||||
func DiscoverActionFiles(dir string, recursive bool) ([]string, error) {
|
func DiscoverActionFiles(dir string, recursive bool, ignoredDirs []string) ([]string, error) {
|
||||||
var actionFiles []string
|
|
||||||
|
|
||||||
// Check if dir exists
|
// Check if dir exists
|
||||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
return nil, fmt.Errorf("directory does not exist: %s", dir)
|
return nil, fmt.Errorf("directory does not exist: %s", dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
if recursive {
|
if recursive {
|
||||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
walker := &actionFileWalker{ignoredDirs: ignoredDirs}
|
||||||
if err != nil {
|
if err := filepath.Walk(dir, walker.walkFunc); 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)
|
return nil, fmt.Errorf("failed to walk directory %s: %w", dir, err)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Check only the specified directory
|
return walker.actionFiles, nil
|
||||||
for _, filename := range []string{appconstants.ActionFileNameYML, appconstants.ActionFileNameYAML} {
|
}
|
||||||
path := filepath.Join(dir, filename)
|
|
||||||
if _, err := os.Stat(path); err == nil {
|
// Check only the specified directory (non-recursive)
|
||||||
actionFiles = append(actionFiles, path)
|
return discoverActionFilesNonRecursive(dir), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// discoverActionFilesNonRecursive finds action files in a single directory.
|
||||||
|
func discoverActionFilesNonRecursive(dir string) []string {
|
||||||
|
var actionFiles []string
|
||||||
|
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
|
return actionFiles
|
||||||
}
|
}
|
||||||
|
|||||||
285
internal/parser_test.go
Normal file
285
internal/parser_test.go
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ivuorinen/gh-action-readme/appconstants"
|
||||||
|
"github.com/ivuorinen/gh-action-readme/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// createTestDirWithAction creates a directory with an action.yml file and returns both paths.
|
||||||
|
func createTestDirWithAction(t *testing.T, baseDir, dirName, yamlContent string) (string, string) {
|
||||||
|
t.Helper()
|
||||||
|
dirPath := filepath.Join(baseDir, dirName)
|
||||||
|
if err := os.Mkdir(dirPath, appconstants.FilePermDir); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateDir(dirName), err)
|
||||||
|
}
|
||||||
|
actionPath := filepath.Join(dirPath, appconstants.ActionFileNameYML)
|
||||||
|
if err := os.WriteFile(
|
||||||
|
actionPath, []byte(yamlContent), appconstants.FilePermDefault,
|
||||||
|
); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateFile(dirName+"/action.yml"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirPath, actionPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// createTestFile creates a file with the given content and returns its path.
|
||||||
|
func createTestFile(t *testing.T, baseDir, fileName, content string) string {
|
||||||
|
t.Helper()
|
||||||
|
filePath := filepath.Join(baseDir, fileName)
|
||||||
|
if err := os.WriteFile(
|
||||||
|
filePath, []byte(content), appconstants.FilePermDefault,
|
||||||
|
); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateFile(fileName), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateDiscoveredFiles checks if discovered files match expected count and paths.
|
||||||
|
func validateDiscoveredFiles(t *testing.T, files []string, wantCount int, wantPaths []string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if len(files) != wantCount {
|
||||||
|
t.Errorf("DiscoverActionFiles() returned %d files, want %d", len(files), wantCount)
|
||||||
|
t.Logf("Got files: %v", files)
|
||||||
|
t.Logf("Want files: %v", wantPaths)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all expected files are present
|
||||||
|
fileMap := make(map[string]bool)
|
||||||
|
for _, f := range files {
|
||||||
|
fileMap[f] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, wantPath := range wantPaths {
|
||||||
|
if !fileMap[wantPath] {
|
||||||
|
t.Errorf("Expected file %s not found in results", wantPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestShouldIgnoreDirectory tests the directory filtering logic.
|
||||||
|
func TestShouldIgnoreDirectory(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
dirName string
|
||||||
|
ignoredDirs []string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "exact match - node_modules",
|
||||||
|
dirName: appconstants.DirNodeModules,
|
||||||
|
ignoredDirs: []string{appconstants.DirNodeModules, appconstants.DirVendor},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exact match - vendor",
|
||||||
|
dirName: appconstants.DirVendor,
|
||||||
|
ignoredDirs: []string{appconstants.DirNodeModules, appconstants.DirVendor},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no match",
|
||||||
|
dirName: "src",
|
||||||
|
ignoredDirs: []string{appconstants.DirNodeModules, appconstants.DirVendor},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty ignore list",
|
||||||
|
dirName: appconstants.DirNodeModules,
|
||||||
|
ignoredDirs: []string{},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dot prefix match - .git",
|
||||||
|
dirName: appconstants.DirGit,
|
||||||
|
ignoredDirs: []string{appconstants.DirGit},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dot prefix pattern match - .github",
|
||||||
|
dirName: appconstants.DirGitHub,
|
||||||
|
ignoredDirs: []string{appconstants.DirGit},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dot prefix pattern match - .gitlab",
|
||||||
|
dirName: appconstants.DirGitLab,
|
||||||
|
ignoredDirs: []string{appconstants.DirGit},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dot prefix no match",
|
||||||
|
dirName: ".config",
|
||||||
|
ignoredDirs: []string{appconstants.DirGit},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "case sensitive - NODE_MODULES vs node_modules",
|
||||||
|
dirName: "NODE_MODULES",
|
||||||
|
ignoredDirs: []string{appconstants.DirNodeModules},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "partial name not matched",
|
||||||
|
dirName: "my_vendor",
|
||||||
|
ignoredDirs: []string{appconstants.DirVendor},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := shouldIgnoreDirectory(tt.dirName, tt.ignoredDirs)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("shouldIgnoreDirectory(%q, %v) = %v, want %v",
|
||||||
|
tt.dirName, tt.ignoredDirs, got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDiscoverActionFilesWithIgnoredDirectories tests file discovery with directory filtering.
|
||||||
|
func TestDiscoverActionFilesWithIgnoredDirectories(t *testing.T) {
|
||||||
|
// Create temporary directory structure
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
// Create directory structure:
|
||||||
|
// tmpDir/
|
||||||
|
// action.yml (should be found)
|
||||||
|
// node_modules/
|
||||||
|
// action.yml (should be ignored)
|
||||||
|
// vendor/
|
||||||
|
// action.yml (should be ignored)
|
||||||
|
// .git/
|
||||||
|
// action.yml (should be ignored)
|
||||||
|
// src/
|
||||||
|
// action.yml (should be found)
|
||||||
|
|
||||||
|
// Create root action.yml
|
||||||
|
rootAction := createTestFile(t, tmpDir, appconstants.ActionFileNameYML, appconstants.TestYAMLRoot)
|
||||||
|
|
||||||
|
// Create directories with action.yml files
|
||||||
|
_, nodeModulesAction := createTestDirWithAction(
|
||||||
|
t,
|
||||||
|
tmpDir,
|
||||||
|
appconstants.DirNodeModules,
|
||||||
|
appconstants.TestYAMLNodeModules,
|
||||||
|
)
|
||||||
|
_, vendorAction := createTestDirWithAction(t, tmpDir, appconstants.DirVendor, appconstants.TestYAMLVendor)
|
||||||
|
_, gitAction := createTestDirWithAction(t, tmpDir, appconstants.DirGit, appconstants.TestYAMLGit)
|
||||||
|
_, srcAction := createTestDirWithAction(t, tmpDir, "src", appconstants.TestYAMLSrc)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ignoredDirs []string
|
||||||
|
wantCount int
|
||||||
|
wantPaths []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "with default ignore list",
|
||||||
|
ignoredDirs: []string{appconstants.DirGit, appconstants.DirNodeModules, appconstants.DirVendor},
|
||||||
|
wantCount: 2,
|
||||||
|
wantPaths: []string{rootAction, srcAction},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with empty ignore list",
|
||||||
|
ignoredDirs: []string{},
|
||||||
|
wantCount: 5,
|
||||||
|
wantPaths: []string{rootAction, gitAction, nodeModulesAction, srcAction, vendorAction},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ignore only node_modules",
|
||||||
|
ignoredDirs: []string{appconstants.DirNodeModules},
|
||||||
|
wantCount: 4,
|
||||||
|
wantPaths: []string{rootAction, gitAction, srcAction, vendorAction},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
files, err := DiscoverActionFiles(tmpDir, true, tt.ignoredDirs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(testutil.ErrDiscoverActionFiles(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
validateDiscoveredFiles(t, files, tt.wantCount, tt.wantPaths)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDiscoverActionFilesNestedIgnoredDirs tests that subdirectories of ignored dirs are skipped.
|
||||||
|
func TestDiscoverActionFilesNestedIgnoredDirs(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
// Create directory structure:
|
||||||
|
// tmpDir/
|
||||||
|
// node_modules/
|
||||||
|
// deep/
|
||||||
|
// nested/
|
||||||
|
// action.yml (should be ignored)
|
||||||
|
|
||||||
|
nodeModulesDir := filepath.Join(tmpDir, appconstants.DirNodeModules, "deep", "nested")
|
||||||
|
if err := os.MkdirAll(nodeModulesDir, appconstants.FilePermDir); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateDir("nested"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nestedAction := filepath.Join(nodeModulesDir, appconstants.ActionFileNameYML)
|
||||||
|
if err := os.WriteFile(
|
||||||
|
nestedAction, []byte(appconstants.TestYAMLNested), appconstants.FilePermDefault,
|
||||||
|
); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateFile("nested action.yml"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := DiscoverActionFiles(tmpDir, true, []string{appconstants.DirNodeModules})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(testutil.ErrDiscoverActionFiles(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) != 0 {
|
||||||
|
t.Errorf("DiscoverActionFiles() returned %d files, want 0 (nested dirs should be skipped)", len(files))
|
||||||
|
t.Logf("Got files: %v", files)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDiscoverActionFilesNonRecursive tests that non-recursive mode ignores the filter.
|
||||||
|
func TestDiscoverActionFilesNonRecursive(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
// Create action.yml in root
|
||||||
|
rootAction := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
|
if err := os.WriteFile(
|
||||||
|
rootAction, []byte(appconstants.TestYAMLRoot), appconstants.FilePermDefault,
|
||||||
|
); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateFile("action.yml"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create subdirectory (should not be searched in non-recursive mode)
|
||||||
|
subDir := filepath.Join(tmpDir, "sub")
|
||||||
|
if err := os.Mkdir(subDir, appconstants.FilePermDir); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateDir("sub"), err)
|
||||||
|
}
|
||||||
|
subAction := filepath.Join(subDir, appconstants.ActionFileNameYML)
|
||||||
|
if err := os.WriteFile(
|
||||||
|
subAction, []byte(appconstants.TestYAMLSub), appconstants.FilePermDefault,
|
||||||
|
); err != nil { // nolint:gosec
|
||||||
|
t.Fatalf(testutil.ErrCreateFile("sub/action.yml"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := DiscoverActionFiles(tmpDir, false, []string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf(testutil.ErrDiscoverActionFiles(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) != 1 {
|
||||||
|
t.Errorf("DiscoverActionFiles() non-recursive returned %d files, want 1", len(files))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) > 0 && files[0] != rootAction {
|
||||||
|
t.Errorf("DiscoverActionFiles() = %v, want %v", files[0], rootAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,6 +64,7 @@ func setConfigDefaults(v *viper.Viper, defaults *AppConfig) {
|
|||||||
v.SetDefault(appconstants.ConfigKeyShowSecurityInfo, defaults.ShowSecurityInfo)
|
v.SetDefault(appconstants.ConfigKeyShowSecurityInfo, defaults.ShowSecurityInfo)
|
||||||
v.SetDefault(appconstants.ConfigKeyVerbose, defaults.Verbose)
|
v.SetDefault(appconstants.ConfigKeyVerbose, defaults.Verbose)
|
||||||
v.SetDefault(appconstants.ConfigKeyQuiet, defaults.Quiet)
|
v.SetDefault(appconstants.ConfigKeyQuiet, defaults.Quiet)
|
||||||
|
v.SetDefault(appconstants.ConfigKeyIgnoredDirectories, defaults.IgnoredDirectories)
|
||||||
v.SetDefault(appconstants.ConfigKeyDefaultsName, defaults.Defaults.Name)
|
v.SetDefault(appconstants.ConfigKeyDefaultsName, defaults.Defaults.Name)
|
||||||
v.SetDefault(appconstants.ConfigKeyDefaultsDescription, defaults.Defaults.Description)
|
v.SetDefault(appconstants.ConfigKeyDefaultsDescription, defaults.Defaults.Description)
|
||||||
v.SetDefault(appconstants.ConfigKeyDefaultsBrandingIcon, defaults.Defaults.Branding.Icon)
|
v.SetDefault(appconstants.ConfigKeyDefaultsBrandingIcon, defaults.Defaults.Branding.Icon)
|
||||||
|
|||||||
37
main.go
37
main.go
@@ -183,6 +183,11 @@ Examples:
|
|||||||
cmd.Flags().StringP(appconstants.FlagOutput, "", "", "custom output filename (overrides default naming)")
|
cmd.Flags().StringP(appconstants.FlagOutput, "", "", "custom output filename (overrides default naming)")
|
||||||
cmd.Flags().StringP(appconstants.ConfigKeyTheme, "t", "", "template theme: github, gitlab, minimal, professional")
|
cmd.Flags().StringP(appconstants.ConfigKeyTheme, "t", "", "template theme: github, gitlab, minimal, professional")
|
||||||
cmd.Flags().BoolP(appconstants.FlagRecursive, "r", false, "search for action.yml files recursively")
|
cmd.Flags().BoolP(appconstants.FlagRecursive, "r", false, "search for action.yml files recursively")
|
||||||
|
cmd.Flags().StringSlice(
|
||||||
|
appconstants.FlagIgnoreDirs,
|
||||||
|
[]string{},
|
||||||
|
"directories to ignore during recursive discovery (comma-separated)",
|
||||||
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
@@ -241,9 +246,17 @@ func genHandler(cmd *cobra.Command, args []string) {
|
|||||||
workingDir = absTargetPath
|
workingDir = absTargetPath
|
||||||
generator := internal.NewGenerator(globalConfig) // Temporary generator for discovery
|
generator := internal.NewGenerator(globalConfig) // Temporary generator for discovery
|
||||||
recursive, _ := cmd.Flags().GetBool(appconstants.FlagRecursive)
|
recursive, _ := cmd.Flags().GetBool(appconstants.FlagRecursive)
|
||||||
|
|
||||||
|
// Get ignored directories from CLI flag or use config defaults
|
||||||
|
ignoredDirs, _ := cmd.Flags().GetStringSlice(appconstants.FlagIgnoreDirs)
|
||||||
|
if len(ignoredDirs) == 0 {
|
||||||
|
ignoredDirs = globalConfig.IgnoredDirectories
|
||||||
|
}
|
||||||
|
|
||||||
actionFiles, err = generator.DiscoverActionFilesWithValidation(
|
actionFiles, err = generator.DiscoverActionFilesWithValidation(
|
||||||
workingDir,
|
workingDir,
|
||||||
recursive,
|
recursive,
|
||||||
|
ignoredDirs,
|
||||||
"documentation generation",
|
"documentation generation",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -350,6 +363,7 @@ func validateHandler(_ *cobra.Command, _ []string) {
|
|||||||
actionFiles, err := generator.DiscoverActionFilesWithValidation(
|
actionFiles, err := generator.DiscoverActionFilesWithValidation(
|
||||||
currentDir,
|
currentDir,
|
||||||
true,
|
true,
|
||||||
|
globalConfig.IgnoredDirectories,
|
||||||
"validation",
|
"validation",
|
||||||
) // Recursive for validation
|
) // Recursive for validation
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -589,7 +603,12 @@ func depsListHandler(_ *cobra.Command, _ []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generator := internal.NewGenerator(globalConfig)
|
generator := internal.NewGenerator(globalConfig)
|
||||||
actionFiles, err := generator.DiscoverActionFilesWithValidation(currentDir, true, "dependency listing")
|
actionFiles, err := generator.DiscoverActionFilesWithValidation(
|
||||||
|
currentDir,
|
||||||
|
true,
|
||||||
|
globalConfig.IgnoredDirectories,
|
||||||
|
"dependency listing",
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// For deps list, we can continue if no files found (show warning instead of error)
|
// For deps list, we can continue if no files found (show warning instead of error)
|
||||||
output.Warning(appconstants.ErrNoActionFilesFound)
|
output.Warning(appconstants.ErrNoActionFilesFound)
|
||||||
@@ -668,7 +687,12 @@ func depsSecurityHandler(_ *cobra.Command, _ []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generator := internal.NewGenerator(globalConfig)
|
generator := internal.NewGenerator(globalConfig)
|
||||||
actionFiles, err := generator.DiscoverActionFilesWithValidation(currentDir, true, "security analysis")
|
actionFiles, err := generator.DiscoverActionFilesWithValidation(
|
||||||
|
currentDir,
|
||||||
|
true,
|
||||||
|
globalConfig.IgnoredDirectories,
|
||||||
|
"security analysis",
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -766,7 +790,12 @@ func depsOutdatedHandler(_ *cobra.Command, _ []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generator := internal.NewGenerator(globalConfig)
|
generator := internal.NewGenerator(globalConfig)
|
||||||
actionFiles, err := generator.DiscoverActionFilesWithValidation(currentDir, true, "outdated dependency analysis")
|
actionFiles, err := generator.DiscoverActionFilesWithValidation(
|
||||||
|
currentDir,
|
||||||
|
true,
|
||||||
|
globalConfig.IgnoredDirectories,
|
||||||
|
"outdated dependency analysis",
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// For deps outdated, we can continue if no files found (show warning instead of error)
|
// For deps outdated, we can continue if no files found (show warning instead of error)
|
||||||
output.Warning(appconstants.ErrNoActionFilesFound)
|
output.Warning(appconstants.ErrNoActionFilesFound)
|
||||||
@@ -897,7 +926,7 @@ func depsUpgradeHandler(cmd *cobra.Command, _ []string) {
|
|||||||
// setupDepsUpgrade handles initial setup and validation for dependency upgrades.
|
// setupDepsUpgrade handles initial setup and validation for dependency upgrades.
|
||||||
func setupDepsUpgrade(output *internal.ColoredOutput, currentDir string) (*dependencies.Analyzer, []string) {
|
func setupDepsUpgrade(output *internal.ColoredOutput, currentDir string) (*dependencies.Analyzer, []string) {
|
||||||
generator := internal.NewGenerator(globalConfig)
|
generator := internal.NewGenerator(globalConfig)
|
||||||
actionFiles, err := generator.DiscoverActionFiles(currentDir, true)
|
actionFiles, err := generator.DiscoverActionFiles(currentDir, true, globalConfig.IgnoredDirectories)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
output.Error("Error discovering action files: %v", err)
|
output.Error("Error discovering action files: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func TestCLICommands(t *testing.T) {
|
|||||||
args: []string{"deps", "list"},
|
args: []string{"deps", "list"},
|
||||||
setupFunc: func(t *testing.T, tmpDir string) {
|
setupFunc: func(t *testing.T, tmpDir string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(appconstants.TestFixtureCompositeBasic))
|
||||||
},
|
},
|
||||||
wantExit: 0,
|
wantExit: 0,
|
||||||
@@ -305,7 +305,7 @@ func TestCLIErrorHandling(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
testutil.WriteTestFile(
|
testutil.WriteTestFile(
|
||||||
t,
|
t,
|
||||||
filepath.Join(tmpDir, appconstants.TestPathActionYML),
|
filepath.Join(tmpDir, appconstants.ActionFileNameYML),
|
||||||
"invalid: yaml: content: [",
|
"invalid: yaml: content: [",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -588,7 +588,7 @@ func runTestCommand(binaryPath string, args []string, dir string) cmdResult {
|
|||||||
// It writes the specified fixture to action.yml in the given temporary directory.
|
// It writes the specified fixture to action.yml in the given temporary directory.
|
||||||
func createTestActionFile(t *testing.T, tmpDir, fixture string) {
|
func createTestActionFile(t *testing.T, tmpDir, fixture string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
actionPath := filepath.Join(tmpDir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(tmpDir, appconstants.ActionFileNameYML)
|
||||||
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(fixture))
|
testutil.WriteTestFile(t, actionPath, testutil.MustReadFixture(fixture))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ func WriteTestFile(t *testing.T, path, content string) {
|
|||||||
// WriteActionFixture writes an action fixture to a standard action.yml file.
|
// WriteActionFixture writes an action fixture to a standard action.yml file.
|
||||||
func WriteActionFixture(t *testing.T, dir, fixturePath string) string {
|
func WriteActionFixture(t *testing.T, dir, fixturePath string) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
actionPath := filepath.Join(dir, appconstants.TestPathActionYML)
|
actionPath := filepath.Join(dir, appconstants.ActionFileNameYML)
|
||||||
fixture := MustLoadActionFixture(t, fixturePath)
|
fixture := MustLoadActionFixture(t, fixturePath)
|
||||||
WriteTestFile(t, actionPath, fixture.Content)
|
WriteTestFile(t, actionPath, fixture.Content)
|
||||||
|
|
||||||
@@ -585,3 +585,18 @@ func GetGitHubTokenHierarchyTests() []GitHubTokenTestCase {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrCreateFile returns a formatted error message for file creation failures.
|
||||||
|
func ErrCreateFile(name string) string {
|
||||||
|
return fmt.Sprintf("Failed to create %s: %s", name, "%v")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrCreateDir returns a formatted error message for directory creation failures.
|
||||||
|
func ErrCreateDir(name string) string {
|
||||||
|
return fmt.Sprintf("Failed to create %s dir: %s", name, "%v")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrDiscoverActionFiles returns the error format string for DiscoverActionFiles failures.
|
||||||
|
func ErrDiscoverActionFiles() string {
|
||||||
|
return "DiscoverActionFiles() error = %v"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user