package main import ( "fmt" "strings" ) // serviceVersion runs git describe in the service directory and returns // the version string. If strict is true, it rejects versions that are // dirty or not exactly on a tag. func serviceVersion(svcPath string, strict bool) (string, error) { version, err := runOutput(svcPath, "git", "describe", "--tags", "--always", "--dirty") if err != nil { return "", fmt.Errorf("git describe in %s: %w", svcPath, err) } if strict { if strings.HasSuffix(version, "-dirty") { return "", fmt.Errorf("--strict: working tree is dirty (%s); commit or stash changes before building", version) } // git describe produces "v1.0.0-3-gabcdef" when HEAD is 3 commits past a tag. // A clean tag has no hyphen after the version (except pre-release like v1.0.0-rc1, // which we allow). Detect the "-N-gHASH" suffix. if parts := strings.Split(version, "-"); len(parts) >= 3 { // Check if second-to-last part is a number (commit count). secondToLast := parts[len(parts)-2] if len(secondToLast) > 0 && secondToLast[0] >= '0' && secondToLast[0] <= '9' { last := parts[len(parts)-1] if strings.HasPrefix(last, "g") { return "", fmt.Errorf("--strict: HEAD is not on a tag (%s); create a tag before building", version) } } } } return version, nil }