completed phase 2b
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package ci
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
gitdomain "github.com/forgeo/forgebucket/internal/domain/git"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const workflowDir = ".forgebucket/workflows"
|
||||
|
||||
// ListWorkflows returns the file paths of all workflow YAML files in a repo at a
|
||||
// given ref. Returns nil (no error) when the workflows directory doesn't exist.
|
||||
func ListWorkflows(repoPath, ref string) ([]string, error) {
|
||||
entries, err := gitdomain.TreeLS(repoPath, ref, workflowDir)
|
||||
if err != nil {
|
||||
// Directory does not exist at this ref — no workflows, not an error.
|
||||
return nil, nil
|
||||
}
|
||||
var paths []string
|
||||
for _, e := range entries {
|
||||
if e.Type == "blob" && (strings.HasSuffix(e.Name, ".yml") || strings.HasSuffix(e.Name, ".yaml")) {
|
||||
paths = append(paths, workflowDir+"/"+e.Name)
|
||||
}
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
// ParseWorkflow reads and parses a single workflow YAML file from the repo at ref.
|
||||
func ParseWorkflow(repoPath, ref, filePath string) (*WorkflowFile, error) {
|
||||
data, err := gitdomain.BlobCat(repoPath, ref, filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %s: %w", filePath, err)
|
||||
}
|
||||
var wf WorkflowFile
|
||||
if err := yaml.Unmarshal(data, &wf); err != nil {
|
||||
return nil, fmt.Errorf("parse %s: %w", filePath, err)
|
||||
}
|
||||
return &wf, nil
|
||||
}
|
||||
|
||||
// MatchesPushTrigger reports whether a workflow should run for a push to ref.
|
||||
// ref is the full ref name, e.g. "refs/heads/main".
|
||||
func MatchesPushTrigger(wf *WorkflowFile, ref string) bool {
|
||||
if wf.On.Push == nil {
|
||||
return false
|
||||
}
|
||||
trigger := wf.On.Push
|
||||
// No branch filter means "all branches".
|
||||
if len(trigger.Branches) == 0 && len(trigger.Tags) == 0 {
|
||||
return true
|
||||
}
|
||||
branch := strings.TrimPrefix(ref, "refs/heads/")
|
||||
for _, pattern := range trigger.Branches {
|
||||
if matchGlob(pattern, branch) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
tag := strings.TrimPrefix(ref, "refs/tags/")
|
||||
for _, pattern := range trigger.Tags {
|
||||
if matchGlob(pattern, tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// matchGlob supports simple "*" wildcards (not full glob).
|
||||
func matchGlob(pattern, s string) bool {
|
||||
if pattern == "*" {
|
||||
return true
|
||||
}
|
||||
if !strings.Contains(pattern, "*") {
|
||||
return pattern == s
|
||||
}
|
||||
parts := strings.SplitN(pattern, "*", 2)
|
||||
return strings.HasPrefix(s, parts[0]) && strings.HasSuffix(s, parts[1])
|
||||
}
|
||||
Reference in New Issue
Block a user