package workflows import ( "context" "errors" "testing" "github.com/stretchr/testify/assert" ) func TestComputeGitPhases(t *testing.T) { t.Parallel() okRefs := func(_ context.Context) ([]string, error) { return []string{"refs/heads/main"}, nil } okFiles := func(_ context.Context, _ []string, _ bool) ([]string, error) { return []string{"docker-compose.yml"}, nil } errRefs := func(_ context.Context) ([]string, error) { return nil, errors.New("connection refused") } errFiles := func(_ context.Context, _ []string, _ bool) ([]string, error) { return nil, errors.New("connection refused") } cases := []struct { name string referenceName string configFilePath []GitEntries listRefs ListRefsFunc listFiles ListFilesFunc expectedSource Status expectedArtifact Status }{ { name: "listRefs errors: source error, artifact unknown", referenceName: "refs/heads/main", configFilePath: []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs: errRefs, listFiles: okFiles, expectedSource: StatusError, expectedArtifact: StatusUnknown, }, { name: "ref not in list: source error, artifact unknown", referenceName: "refs/heads/missing", configFilePath: []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs: func(_ context.Context) ([]string, error) { return []string{"refs/heads/main"}, nil }, listFiles: okFiles, expectedSource: StatusError, expectedArtifact: StatusUnknown, }, { name: "empty configFilePath: artifact error", referenceName: "refs/heads/main", configFilePath: []GitEntries{}, listRefs: okRefs, listFiles: okFiles, expectedSource: StatusHealthy, expectedArtifact: StatusError, }, { name: "listFiles errors: artifact error", referenceName: "refs/heads/main", configFilePath: []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs: okRefs, listFiles: errFiles, expectedSource: StatusHealthy, expectedArtifact: StatusError, }, { name: "file not in list: artifact error", referenceName: "refs/heads/main", configFilePath: []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs: okRefs, listFiles: func(_ context.Context, _ []string, _ bool) ([]string, error) { return []string{"other.yml"}, nil }, expectedSource: StatusHealthy, expectedArtifact: StatusError, }, { name: "both healthy", referenceName: "refs/heads/main", configFilePath: []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs: okRefs, listFiles: okFiles, expectedSource: StatusHealthy, expectedArtifact: StatusHealthy, }, { name: "empty referenceName: source healthy (default HEAD)", referenceName: "", configFilePath: []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs: okRefs, listFiles: okFiles, expectedSource: StatusHealthy, expectedArtifact: StatusHealthy, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { source, artifact := ComputeGitPhases(t.Context(), tc.referenceName, tc.configFilePath, tc.listRefs, tc.listFiles) assert.Equal(t, tc.expectedSource, source.Status) assert.Equal(t, tc.expectedArtifact, artifact.Status) }) } } func TestComputeArtifactPhase_ExtensionFilter(t *testing.T) { t.Parallel() cases := []struct { configPath string wantExts []string }{ {"docker-compose.yml", []string{"yml"}}, {"stack.yaml", []string{"yaml"}}, {"subdir/compose.yml", []string{"yml"}}, {"Makefile", nil}, {"archive.tar.gz", []string{"gz"}}, } for _, tc := range cases { t.Run(tc.configPath, func(t *testing.T) { t.Parallel() var capturedExts []string ComputeGitPhases( t.Context(), "", []GitEntries{{Name: tc.configPath, IsFile: true}}, func(_ context.Context) ([]string, error) { return nil, nil }, func(_ context.Context, exts []string, dirOnly bool) ([]string, error) { capturedExts = exts return []string{tc.configPath}, nil }, ) assert.Equal(t, tc.wantExts, capturedExts) }) } } func TestComputeGitPhases_ArtifactNotCalledOnSourceError(t *testing.T) { t.Parallel() listFilesCalled := false listRefs := func(_ context.Context) ([]string, error) { return nil, errors.New("repo unreachable") } listFiles := func(_ context.Context, _ []string, _ bool) ([]string, error) { listFilesCalled = true return nil, nil } ComputeGitPhases(t.Context(), "refs/heads/main", []GitEntries{{Name: "docker-compose.yml", IsFile: true}}, listRefs, listFiles) assert.False(t, listFilesCalled, "listFiles must not be called when source fails") }