mirror of
https://github.com/openimsdk/open-im-server.git
synced 2025-11-05 20:43:38 +08:00
Merge remote-tracking branch 'origin/3.6.1-code-conventions' into 3.6.1-code-conventions
# Conflicts: # tools/component/component.go # tools/formitychecker/checker/checker.go
This commit is contained in:
commit
34df324789
@ -579,6 +579,7 @@ linters-settings:
|
|||||||
rowserrcheck:
|
rowserrcheck:
|
||||||
packages:
|
packages:
|
||||||
- github.com/jmoiron/sqlx
|
- github.com/jmoiron/sqlx
|
||||||
|
|
||||||
revive:
|
revive:
|
||||||
# see https://github.com/mgechev/revive#available-rules for details.
|
# see https://github.com/mgechev/revive#available-rules for details.
|
||||||
ignore-generated-header: true
|
ignore-generated-header: true
|
||||||
@ -586,15 +587,16 @@ linters-settings:
|
|||||||
rules:
|
rules:
|
||||||
- name: indent-error-flow
|
- name: indent-error-flow
|
||||||
severity: warning
|
severity: warning
|
||||||
|
|
||||||
staticcheck:
|
staticcheck:
|
||||||
# Select the Go version to target. The default is '1.13'.
|
# Select the Go version to target. The default is '1.13'.
|
||||||
go: "1.16"
|
go: "1.20"
|
||||||
# https://staticcheck.io/docs/options#checks
|
# https://staticcheck.io/docs/options#checks
|
||||||
checks: [ "all" ]
|
checks: [ "all" ]
|
||||||
|
|
||||||
stylecheck:
|
stylecheck:
|
||||||
# Select the Go version to target. The default is '1.13'.
|
# Select the Go version to target. The default is '1.13'.
|
||||||
go: "1.16"
|
go: "1.20"
|
||||||
|
|
||||||
# https://staticcheck.io/docs/options#checks
|
# https://staticcheck.io/docs/options#checks
|
||||||
checks: [ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022" ]
|
checks: [ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022" ]
|
||||||
|
|||||||
@ -89,10 +89,7 @@ func FriendsDB2Pb(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func FriendRequestDB2Pb(ctx context.Context,
|
func FriendRequestDB2Pb(ctx context.Context, friendRequests []*relation.FriendRequestModel, getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) ([]*sdkws.FriendRequest, error) {
|
||||||
friendRequests []*relation.FriendRequestModel,
|
|
||||||
getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
|
|
||||||
) ([]*sdkws.FriendRequest, error) {
|
|
||||||
if len(friendRequests) == 0 {
|
if len(friendRequests) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,12 +56,7 @@ func Pb2DbGroupRequest(req *pbgroup.GroupApplicationResponseReq, handleUserID st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Db2PbCMSGroup(
|
func Db2PbCMSGroup(m *relation.GroupModel, ownerUserID string, ownerUserName string, memberCount uint32) *pbgroup.CMSGroup {
|
||||||
m *relation.GroupModel,
|
|
||||||
ownerUserID string,
|
|
||||||
ownerUserName string,
|
|
||||||
memberCount uint32,
|
|
||||||
) *pbgroup.CMSGroup {
|
|
||||||
return &pbgroup.CMSGroup{
|
return &pbgroup.CMSGroup{
|
||||||
GroupInfo: Db2PbGroupInfo(m, ownerUserID, memberCount),
|
GroupInfo: Db2PbGroupInfo(m, ownerUserID, memberCount),
|
||||||
GroupOwnerUserID: ownerUserID,
|
GroupOwnerUserID: ownerUserID,
|
||||||
@ -86,11 +81,7 @@ func Db2PbGroupMember(m *relation.GroupMemberModel) *sdkws.GroupMemberFullInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Db2PbGroupRequest(
|
func Db2PbGroupRequest(m *relation.GroupRequestModel, user *sdkws.PublicUserInfo, group *sdkws.GroupInfo) *sdkws.GroupRequest {
|
||||||
m *relation.GroupRequestModel,
|
|
||||||
user *sdkws.PublicUserInfo,
|
|
||||||
group *sdkws.GroupInfo,
|
|
||||||
) *sdkws.GroupRequest {
|
|
||||||
return &sdkws.GroupRequest{
|
return &sdkws.GroupRequest{
|
||||||
UserInfo: user,
|
UserInfo: user,
|
||||||
GroupInfo: group,
|
GroupInfo: group,
|
||||||
|
|||||||
@ -19,8 +19,5 @@
|
|||||||
# Usage: `scripts/list-feature-tests.sh`.
|
# Usage: `scripts/list-feature-tests.sh`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||||
grep "\[Feature:\w+\]" "${OPENIM_ROOT}"/test/e2e/**/*.go -Eoh | LC_ALL=C sort -u
|
grep "\[Feature:\w+\]" "${OPENIM_ROOT}"/test/e2e/**/*.go -Eoh | LC_ALL=C sort -u
|
||||||
@ -243,7 +243,7 @@ func checkKafka(config *config.GlobalConfig) error {
|
|||||||
|
|
||||||
for _, requiredTopic := range requiredTopics {
|
for _, requiredTopic := range requiredTopics {
|
||||||
if !isTopicPresent(requiredTopic, topics) {
|
if !isTopicPresent(requiredTopic, topics) {
|
||||||
return errs.WrapMsg(err, fmt.Sprintf("Kafka doesn't contain topic: %v", requiredTopic))
|
return errs.WrapMsg(nil, "Kafka missing required topic", "topic", requiredTopic, "availableTopics", strings.Join(topics, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,99 +15,136 @@
|
|||||||
package checker
|
package checker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/OpenIMSDK/tools/errs"
|
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/tools/formitychecker/config"
|
"github.com/openimsdk/open-im-server/tools/formitychecker/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
type Issue struct {
|
||||||
underscoreRegex = regexp.MustCompile(`^[a-zA-Z0-9_]+\.[a-zA-Z0-9]+$`)
|
Type string
|
||||||
hyphenRegex = regexp.MustCompile(`^[a-zA-Z0-9\-]+\.[a-zA-Z0-9]+$`)
|
Path string
|
||||||
)
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
// CheckDirectory initiates the checking process for the specified directories using configuration from config.Config.
|
type Checker struct {
|
||||||
func CheckDirectory(cfg *config.Config) error {
|
Config *config.Config
|
||||||
ignoreMap := make(map[string]struct{})
|
Summary struct {
|
||||||
for _, dir := range cfg.IgnoreDirs {
|
CheckedDirectories int
|
||||||
ignoreMap[dir] = struct{}{}
|
CheckedFiles int
|
||||||
|
Issues []Issue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Checker) Check() error {
|
||||||
|
return filepath.Walk(c.Config.BaseConfig.SearchDirectory, c.checkPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Checker) checkPath(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, targetDir := range cfg.TargetDirs {
|
relativePath, err := filepath.Rel(c.Config.BaseConfig.SearchDirectory, path)
|
||||||
err := filepath.Walk(targetDir, func(path string, info os.FileInfo, err error) error {
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return errs.WrapMsg(err, fmt.Sprintf("error walking directory '%s'", targetDir))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if the directory is in the ignore list
|
if relativePath == "." {
|
||||||
dirName := filepath.Base(filepath.Dir(path))
|
return nil
|
||||||
if _, ok := ignoreMap[dirName]; ok && info.IsDir() {
|
}
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the naming convention
|
|
||||||
if err := checkNamingConvention(path, info); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
c.Summary.CheckedDirectories++
|
||||||
|
if c.isIgnoredDirectory(relativePath) {
|
||||||
|
c.Summary.Issues = append(c.Summary.Issues, Issue{
|
||||||
|
Type: "ignoredDirectory",
|
||||||
|
Path: path,
|
||||||
|
Message: "This directory has been ignored",
|
||||||
|
})
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
if !c.checkDirectoryName(relativePath) {
|
||||||
|
c.Summary.Issues = append(c.Summary.Issues, Issue{
|
||||||
|
Type: "directoryNaming",
|
||||||
|
Path: path,
|
||||||
|
Message: "The directory name is invalid",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if c.isIgnoredFile(path) {
|
||||||
return nil
|
return nil
|
||||||
})
|
}
|
||||||
|
c.Summary.CheckedFiles++
|
||||||
if err != nil {
|
if !c.checkFileName(relativePath) {
|
||||||
return fmt.Errorf("error checking directory '%s': %w", targetDir, err)
|
c.Summary.Issues = append(c.Summary.Issues, Issue{
|
||||||
|
Type: "fileNaming",
|
||||||
|
Path: path,
|
||||||
|
Message: "The file name does not comply with the specification",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkNamingConvention checks if the file or directory name conforms to the standard naming conventions.
|
func (c *Checker) isIgnoredDirectory(path string) bool {
|
||||||
func checkNamingConvention(path string, info os.FileInfo) error {
|
for _, ignoredDir := range c.Config.IgnoreDirectories {
|
||||||
fileName := info.Name()
|
if strings.Contains(path, ignoredDir) {
|
||||||
|
return true
|
||||||
// Handle special cases for directories like .git
|
|
||||||
if info.IsDir() && strings.HasPrefix(fileName, ".") {
|
|
||||||
return nil // Skip special directories
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the main part of the name (without extension for files)
|
|
||||||
mainName := fileName
|
|
||||||
if !info.IsDir() {
|
|
||||||
mainName = strings.TrimSuffix(fileName, filepath.Ext(fileName))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the type of file and apply corresponding naming rule
|
|
||||||
switch {
|
|
||||||
case info.IsDir():
|
|
||||||
if !isValidName(mainName, "_") { // Directory names must only contain underscores
|
|
||||||
return fmt.Errorf("!!! invalid directory name: %s", path)
|
|
||||||
}
|
|
||||||
case strings.HasSuffix(fileName, ".go"):
|
|
||||||
if !isValidName(mainName, "_") { // Go files must only contain underscores
|
|
||||||
return fmt.Errorf("!!! invalid Go file name: %s", path)
|
|
||||||
}
|
|
||||||
case strings.HasSuffix(fileName, ".yml"), strings.HasSuffix(fileName, ".yaml"), strings.HasSuffix(fileName, ".md"):
|
|
||||||
if !isValidName(mainName, "-") { // YML, YAML, and Markdown files must only contain hyphens
|
|
||||||
return fmt.Errorf("!!! invalid file name: %s", path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isValidName checks if the file name conforms to the specified rule (underscore or hyphen).
|
func (c *Checker) isIgnoredFile(path string) bool {
|
||||||
func isValidName(name, charType string) bool {
|
ext := filepath.Ext(path)
|
||||||
switch charType {
|
for _, format := range c.Config.IgnoreFormats {
|
||||||
case "_":
|
if ext == format {
|
||||||
return underscoreRegex.MatchString(name)
|
return true
|
||||||
case "-":
|
}
|
||||||
return hyphenRegex.MatchString(name)
|
}
|
||||||
default:
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Checker) checkDirectoryName(path string) bool {
|
||||||
|
dirName := filepath.Base(path)
|
||||||
|
if c.Config.DirectoryNaming.MustBeLowercase && (dirName != strings.ToLower(dirName)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !c.Config.DirectoryNaming.AllowHyphens && strings.Contains(dirName, "-") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !c.Config.DirectoryNaming.AllowUnderscores && strings.Contains(dirName, "_") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Checker) checkFileName(path string) bool {
|
||||||
|
fileName := filepath.Base(path)
|
||||||
|
ext := filepath.Ext(fileName)
|
||||||
|
|
||||||
|
allowHyphens := c.Config.FileNaming.AllowHyphens
|
||||||
|
allowUnderscores := c.Config.FileNaming.AllowUnderscores
|
||||||
|
mustBeLowercase := c.Config.FileNaming.MustBeLowercase
|
||||||
|
|
||||||
|
if specificNaming, ok := c.Config.FileTypeSpecificNaming[ext]; ok {
|
||||||
|
allowHyphens = specificNaming.AllowHyphens
|
||||||
|
allowUnderscores = specificNaming.AllowUnderscores
|
||||||
|
mustBeLowercase = specificNaming.MustBeLowercase
|
||||||
|
}
|
||||||
|
|
||||||
|
if mustBeLowercase && (fileName != strings.ToLower(fileName)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !allowHyphens && strings.Contains(fileName, "-") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !allowUnderscores && strings.Contains(fileName, "_") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
47
tools/formitychecker/config.yaml
Normal file
47
tools/formitychecker/config.yaml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# config.yaml 示例配置
|
||||||
|
|
||||||
|
# 基础配置
|
||||||
|
baseConfig:
|
||||||
|
searchDirectory: "./" # 检索的根目录,"./" 代表当前目录
|
||||||
|
ignoreCase: false # 是否忽略大小写,true 为忽略,false 为区分大小写
|
||||||
|
|
||||||
|
# 目录命名风格配置
|
||||||
|
directoryNaming:
|
||||||
|
allowHyphens: true # 是否允许目录名中含有中划线
|
||||||
|
allowUnderscores: false # 是否允许目录名中含有下划线
|
||||||
|
mustBeLowercase: true # 目录名是否必须为小写
|
||||||
|
|
||||||
|
# 文件命名风格配置
|
||||||
|
fileNaming:
|
||||||
|
allowHyphens: true # 是否允许文件名中含有中划线
|
||||||
|
allowUnderscores: true # 是否允许文件名中含有下划线
|
||||||
|
mustBeLowercase: true # 文件名是否必须为小写
|
||||||
|
|
||||||
|
# 忽略的文件格式列表
|
||||||
|
ignoreFormats:
|
||||||
|
- ".log"
|
||||||
|
- ".env"
|
||||||
|
- "_test.go"
|
||||||
|
|
||||||
|
# 忽略的目录列表
|
||||||
|
ignoreDirectories:
|
||||||
|
- "vendor"
|
||||||
|
- ".git"
|
||||||
|
- "node_modules"
|
||||||
|
- "logs"
|
||||||
|
- "components"
|
||||||
|
- "_output"
|
||||||
|
- "README.md"
|
||||||
|
- "tools/openim-web"
|
||||||
|
- "CHANGELOG"
|
||||||
|
- "docs/readme"
|
||||||
|
|
||||||
|
fileTypeSpecificNaming:
|
||||||
|
".yaml":
|
||||||
|
allowHyphens: true
|
||||||
|
allowUnderscores: false
|
||||||
|
mustBeLowercase: true
|
||||||
|
".go":
|
||||||
|
allowHyphens: false
|
||||||
|
allowUnderscores: true
|
||||||
|
mustBeLowercase: true
|
||||||
@ -15,27 +15,66 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"os"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/tools/codescan/config"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config holds all the configuration parameters for the checker.
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
TargetDirs []string // Directories to check
|
BaseConfig struct {
|
||||||
IgnoreDirs []string // Directories to ignore
|
SearchDirectory string `yaml:"searchDirectory"`
|
||||||
|
IgnoreCase bool `yaml:"ignoreCase"`
|
||||||
|
} `yaml:"baseConfig"`
|
||||||
|
DirectoryNaming struct {
|
||||||
|
AllowHyphens bool `yaml:"allowHyphens"`
|
||||||
|
AllowUnderscores bool `yaml:"allowUnderscores"`
|
||||||
|
MustBeLowercase bool `yaml:"mustBeLowercase"`
|
||||||
|
} `yaml:"directoryNaming"`
|
||||||
|
FileNaming struct {
|
||||||
|
AllowHyphens bool `yaml:"allowHyphens"`
|
||||||
|
AllowUnderscores bool `yaml:"allowUnderscores"`
|
||||||
|
MustBeLowercase bool `yaml:"mustBeLowercase"`
|
||||||
|
} `yaml:"fileNaming"`
|
||||||
|
IgnoreFormats []string `yaml:"ignoreFormats"`
|
||||||
|
IgnoreDirectories []string `yaml:"ignoreDirectories"`
|
||||||
|
FileTypeSpecificNaming map[string]FileTypeSpecificNaming `yaml:"fileTypeSpecificNaming"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig creates and returns a new Config instance.
|
type FileTypeSpecificNaming struct {
|
||||||
func NewConfig(targetDirs, ignoreDirs string) *Config {
|
AllowHyphens bool `yaml:"allowHyphens"`
|
||||||
return &Config{
|
AllowUnderscores bool `yaml:"allowUnderscores"`
|
||||||
TargetDirs: parseDirs(targetDirs),
|
MustBeLowercase bool `yaml:"mustBeLowercase"`
|
||||||
IgnoreDirs: parseDirs(ignoreDirs),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseDirs splits a comma-separated string into a slice of directory names.
|
type Issue struct {
|
||||||
func parseDirs(dirs string) []string {
|
Type string
|
||||||
if dirs == "" {
|
Path string
|
||||||
return nil
|
Message string
|
||||||
}
|
}
|
||||||
return strings.Split(dirs, ",")
|
|
||||||
|
type Checker struct {
|
||||||
|
Config *config.Config
|
||||||
|
Summary struct {
|
||||||
|
CheckedDirectories int
|
||||||
|
CheckedFiles int
|
||||||
|
Issues []Issue
|
||||||
|
}
|
||||||
|
Errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConfig(configPath string) (*Config, error) {
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
file, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,27 +15,57 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/tools/formitychecker/checker"
|
"github.com/openimsdk/open-im-server/tools/formitychecker/checker"
|
||||||
"github.com/openimsdk/open-im-server/tools/formitychecker/config"
|
"github.com/openimsdk/open-im-server/tools/formitychecker/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defaultTargetDirs := "."
|
var configPath string
|
||||||
defaultIgnoreDirs := "components,.git"
|
flag.StringVar(&configPath, "config", "", "Path to the configuration file")
|
||||||
|
|
||||||
var targetDirs string
|
|
||||||
var ignoreDirs string
|
|
||||||
flag.StringVar(&targetDirs, "target", defaultTargetDirs, "Directories to check (default: current directory)")
|
|
||||||
flag.StringVar(&ignoreDirs, "ignore", defaultIgnoreDirs, "Directories to ignore (default: A/, B/)")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
conf := config.NewConfig(targetDirs, ignoreDirs)
|
if configPath == "" {
|
||||||
|
configPath = os.Getenv("CONFIG_PATH")
|
||||||
err := checker.CheckDirectory(conf)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error:", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if configPath == "" {
|
||||||
|
configPath = "config.yaml"
|
||||||
|
if _, err := os.Stat(".github/formitychecker.yaml"); err == nil {
|
||||||
|
configPath = ".github/formitychecker.yaml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := config.LoadConfig(configPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error loading config:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &checker.Checker{Config: cfg}
|
||||||
|
err = c.Check()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error during check:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if len(c.Errors) > 0 {
|
||||||
|
// fmt.Println("Found errors:")
|
||||||
|
// for _, errMsg := range c.Errors {
|
||||||
|
// fmt.Println("-", errMsg)
|
||||||
|
// }
|
||||||
|
// os.Exit(1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
summaryJSON, err := json.MarshalIndent(c.Summary, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error marshalling summary:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(summaryJSON))
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user