Files

160 lines
4.4 KiB
Go

package core
import (
"fmt"
"net"
"net/url"
"os"
"regexp"
"strings"
)
// Dependencies defines workflow requirements
type Dependencies struct {
Commands []string `yaml:"commands"`
Files []string `yaml:"files"`
Variables []VariableDep `yaml:"variables"`
TargetTypes []TargetType `yaml:"target_types"`
FunctionsConditions []string `yaml:"functions_conditions"`
}
// VariableDep defines variable requirements
type VariableDep struct {
Name string `yaml:"name"`
Type VariableType `yaml:"type"`
Required bool `yaml:"required"`
}
// HasCommandDeps returns true if there are command dependencies
func (d *Dependencies) HasCommandDeps() bool {
return d != nil && len(d.Commands) > 0
}
// HasFileDeps returns true if there are file dependencies
func (d *Dependencies) HasFileDeps() bool {
return d != nil && len(d.Files) > 0
}
// HasVariableDeps returns true if there are variable dependencies
func (d *Dependencies) HasVariableDeps() bool {
return d != nil && len(d.Variables) > 0
}
// HasFunctionConditions returns true if there are function-based condition dependencies
func (d *Dependencies) HasFunctionConditions() bool {
return d != nil && len(d.FunctionsConditions) > 0
}
// GetRequiredVariables returns all required variable dependencies
func (d *Dependencies) GetRequiredVariables() []VariableDep {
if d == nil {
return nil
}
var required []VariableDep
for _, v := range d.Variables {
if v.Required {
required = append(required, v)
}
}
return required
}
var domainRegex = regexp.MustCompile(`^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`)
var numericRegex = regexp.MustCompile(`^-?\d+(\.\d+)?$`)
var simpleRepoRegex = regexp.MustCompile(`^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$`)
var hostedRepoRegex = regexp.MustCompile(`^(?:(?:https?://)?(?:www\.)?(github\.com|gitlab\.com)/)([A-Za-z0-9_.-]+)/([A-Za-z0-9_.-]+?)(?:\.git)?/?$`)
var sshRepoRegex = regexp.MustCompile(`^git@[^:]+:([A-Za-z0-9_.-]+)/([A-Za-z0-9_.-]+?)(\.git)?$`)
func MatchesVariableType(value string, varType VariableType) (bool, error) {
switch varType {
case VarTypeDomain:
return domainRegex.MatchString(value), nil
case VarTypeSubdomain:
if !domainRegex.MatchString(value) {
return false, nil
}
return strings.Count(value, ".") >= 2, nil
case VarTypeURL:
u, err := url.Parse(value)
if err != nil {
return false, nil
}
if u.Scheme == "http" || u.Scheme == "https" {
return u.Host != "", nil
}
return false, nil
case VarTypeCIDR:
_, _, err := net.ParseCIDR(value)
return err == nil, nil
case VarTypeRepo:
return isRepo(value), nil
case VarTypePath, VarTypeFile, VarTypeFolder:
return value != "", nil
case VarTypeNumber:
return numericRegex.MatchString(value), nil
case VarTypeString:
return true, nil
default:
return false, fmt.Errorf("unknown variable type: %s", varType)
}
}
func MatchesTargetType(target string, targetType TargetType) (bool, error) {
switch targetType {
case TargetTypeDomain:
return MatchesVariableType(target, VarTypeDomain)
case TargetTypeSubdomain:
return MatchesVariableType(target, VarTypeSubdomain)
case TargetTypeURL:
return MatchesVariableType(target, VarTypeURL)
case TargetTypeCIDR:
return MatchesVariableType(target, VarTypeCIDR)
case TargetTypeRepo:
return MatchesVariableType(target, VarTypeRepo)
case TargetTypePath:
return MatchesVariableType(target, VarTypePath)
case TargetTypeNumber:
return MatchesVariableType(target, VarTypeNumber)
case TargetTypeString:
return true, nil
case TargetTypeFile:
info, err := os.Stat(target)
if err != nil {
return false, nil
}
return !info.IsDir(), nil
case TargetTypeFolder:
info, err := os.Stat(target)
if err != nil {
return false, nil
}
return info.IsDir(), nil
default:
return false, fmt.Errorf("unknown target type: %s", targetType)
}
}
func isRepo(value string) bool {
if simpleRepoRegex.MatchString(value) {
return true
}
if hostedRepoRegex.MatchString(value) {
return true
}
if sshRepoRegex.MatchString(value) {
return true
}
u, err := url.Parse(value)
if err == nil && (u.Scheme == "http" || u.Scheme == "https" || u.Scheme == "ssh" || u.Scheme == "git") {
parts := strings.Split(strings.Trim(u.Path, "/"), "/")
if len(parts) >= 2 {
owner := parts[0]
repo := strings.TrimSuffix(parts[1], ".git")
if owner != "" && repo != "" {
return true
}
}
}
return false
}