feat(gitlab-sim): 🚀 branches support
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
package cicontext
|
||||
|
||||
import "strings"
|
||||
|
||||
// Context holds the simulated CI execution environment used for context-aware
|
||||
// pipeline evaluation (rules:if:, only:, except:, workflow:rules:).
|
||||
// Variables are keyed by their name without the leading $.
|
||||
type Context struct {
|
||||
Vars map[string]string
|
||||
}
|
||||
|
||||
// New builds a Context from high-level shortcut values and optional KEY=VALUE
|
||||
// overrides. Predefined CI variables are derived from the shortcuts so callers
|
||||
// do not need to know their exact names.
|
||||
//
|
||||
// Returns an empty Context (IsEmpty() == true) when all inputs are zero values,
|
||||
// preserving the existing linting behaviour when no context flags are given.
|
||||
//
|
||||
// Override priority (highest wins): extraVars > branch/tag/source shortcuts.
|
||||
func New(branch, tag, source string, extraVars []string) *Context {
|
||||
if branch == "" && tag == "" && source == "" && len(extraVars) == 0 {
|
||||
return &Context{}
|
||||
}
|
||||
|
||||
vars := make(map[string]string)
|
||||
|
||||
if branch != "" {
|
||||
vars["CI_COMMIT_BRANCH"] = branch
|
||||
vars["CI_COMMIT_REF_NAME"] = branch
|
||||
vars["CI_COMMIT_REF_SLUG"] = slugify(branch)
|
||||
if source == "" {
|
||||
source = "push"
|
||||
}
|
||||
}
|
||||
if tag != "" {
|
||||
vars["CI_COMMIT_TAG"] = tag
|
||||
vars["CI_COMMIT_REF_NAME"] = tag
|
||||
vars["CI_COMMIT_REF_SLUG"] = slugify(tag)
|
||||
delete(vars, "CI_COMMIT_BRANCH") // tag pushes have no branch variable
|
||||
if source == "" {
|
||||
source = "push"
|
||||
}
|
||||
}
|
||||
if source != "" {
|
||||
vars["CI_PIPELINE_SOURCE"] = source
|
||||
}
|
||||
if _, ok := vars["CI_DEFAULT_BRANCH"]; !ok {
|
||||
vars["CI_DEFAULT_BRANCH"] = "main"
|
||||
}
|
||||
|
||||
// KEY=VALUE overrides win over shortcuts.
|
||||
for _, kv := range extraVars {
|
||||
k, v, ok := strings.Cut(kv, "=")
|
||||
if ok {
|
||||
vars[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return &Context{Vars: vars}
|
||||
}
|
||||
|
||||
// IsEmpty reports whether no variables have been set (no context flags given).
|
||||
func (c *Context) IsEmpty() bool {
|
||||
return c == nil || len(c.Vars) == 0
|
||||
}
|
||||
|
||||
// Get returns the value of a CI variable (key without the leading $).
|
||||
// Returns an empty string when the variable is not defined.
|
||||
func (c *Context) Get(key string) string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
return c.Vars[key]
|
||||
}
|
||||
|
||||
// Summary returns a short human-readable description of the context for CLI output.
|
||||
func (c *Context) Summary() string {
|
||||
if c.IsEmpty() {
|
||||
return ""
|
||||
}
|
||||
var parts []string
|
||||
if v := c.Get("CI_COMMIT_TAG"); v != "" {
|
||||
parts = append(parts, "tag="+v)
|
||||
} else if v := c.Get("CI_COMMIT_BRANCH"); v != "" {
|
||||
parts = append(parts, "branch="+v)
|
||||
}
|
||||
if v := c.Get("CI_PIPELINE_SOURCE"); v != "" {
|
||||
parts = append(parts, "source="+v)
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// slugify converts a ref name to its GitLab slug form:
|
||||
// lowercased, non-alphanumeric characters replaced with '-', leading/trailing '-' removed.
|
||||
func slugify(s string) string {
|
||||
var b strings.Builder
|
||||
for _, r := range strings.ToLower(s) {
|
||||
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') {
|
||||
b.WriteRune(r)
|
||||
} else {
|
||||
b.WriteByte('-')
|
||||
}
|
||||
}
|
||||
return strings.Trim(b.String(), "-")
|
||||
}
|
||||
Reference in New Issue
Block a user