Ctrl K
ComunidadGuías…

ci_workflow_test.go

Rama dev · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package main

import (
	"os"
	"os/exec"
	"strings"
	"testing"
)

// Execute the workflow's actual gate after resolving its two GitHub contexts.
// Both inline expressions and step env are resolved, so putting a ref back into
// shell source would exercise the same expansion as a pull-request run.
func TestCIMainSourceGateTreatsBranchNamesAsData(t *testing.T) {
	contents, err := os.ReadFile(".github/workflows/ci.yml")
	if err != nil {
		t.Fatal(err)
	}
	var script strings.Builder
	stepEnv := make(map[string]string)
	inStep, inRun, inEnv := false, false, false
	for _, line := range strings.Split(string(contents), "\n") {
		if line == "      - name: Require staging source for main" {
			inStep = true
			continue
		}
		if !inStep {
			continue
		}
		if strings.TrimSpace(line) != "" && !strings.HasPrefix(line, "        ") {
			break
		}
		if line == "        run: |" {
			inRun, inEnv = true, false
			continue
		}
		if inRun {
			if strings.TrimSpace(line) != "" && !strings.HasPrefix(line, "          ") {
				break
			}
			script.WriteString(strings.TrimPrefix(line, "          ") + "\n")
			continue
		}
		if line == "        env:" {
			inEnv = true
			continue
		}
		if inEnv && strings.HasPrefix(line, "          ") {
			name, value, ok := strings.Cut(strings.TrimSpace(line), ":")
			if !ok {
				t.Fatalf("invalid gate environment entry: %q", line)
			}
			stepEnv[name] = strings.TrimSpace(value)
		} else {
			inEnv = false
		}
	}
	if script.Len() == 0 {
		t.Fatal("main source gate script was not found")
	}

	for _, tc := range []struct {
		name, base, head string
		allowed          bool
	}{
		{"promotion", "main", "staging", true},
		{"wrong source", "main", "dev", false},
		{"development", "dev", "feature/change", true},
		{"staging", "staging", "dev", true},
		{"substitution", "main", "topic$(>gate-marker)", false},
		{"backticks", "main", "topic`>gate-marker`", false},
		{"development substitution", "dev", "topic$(>gate-marker)", true},
	} {
		t.Run(tc.name, func(t *testing.T) {
			if output, err := exec.Command("git", "check-ref-format", "--branch", tc.head).CombinedOutput(); err != nil {
				t.Fatalf("test branch is not a valid Git ref: %v: %s", err, output)
			}
			expand := strings.NewReplacer("${{ github.base_ref }}", tc.base, "${{ github.head_ref }}", tc.head)
			cmd := exec.Command("bash", "-c", expand.Replace(script.String()))
			cmd.Dir = t.TempDir()
			cmd.Env = os.Environ()
			for name, value := range stepEnv {
				cmd.Env = append(cmd.Env, name+"="+expand.Replace(value))
			}
			output, err := cmd.CombinedOutput()
			if _, markerErr := os.Stat(cmd.Dir + "/gate-marker"); !os.IsNotExist(markerErr) {
				t.Fatal("branch name executed shell syntax")
			}
			if (err == nil) != tc.allowed {
				t.Fatalf("gate allowed=%v, want %v: %v: %s", err == nil, tc.allowed, err, output)
			}
		})
	}
}