Ctrl K
ComunidadGuías…

action/command/check.go

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

Archivo original ↗Preguntar a KiBot
package command

import (
	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	"github.com/bytebase/bytebase/action/args"
	"github.com/bytebase/bytebase/action/azure"
	"github.com/bytebase/bytebase/action/bitbucket"
	"github.com/bytebase/bytebase/action/command/output"
	"github.com/bytebase/bytebase/action/github"
	"github.com/bytebase/bytebase/action/gitlab"
	"github.com/bytebase/bytebase/action/world"
	v1pb "github.com/bytebase/bytebase/backend/generated-go/v1"
)

func NewCheckCommand(w *world.World) *cobra.Command {
	// bytebase-action check flags
	cmdCheck := &cobra.Command{
		Use:               "check",
		Short:             "Check the release files",
		Args:              cobra.NoArgs,
		PersistentPreRunE: validateCheckFlags(w),
		RunE:              runCheck(w),
	}
	cmdCheck.Flags().StringVar(&w.CheckRelease, "check-release", "SKIP", "Whether to fail on warning/error. Valid values: SKIP, FAIL_ON_WARNING, FAIL_ON_ERROR")
	cmdCheck.Flags().StringVar(&w.CustomRules, "custom-rules", "", "Custom linting rules in natural language for AI-powered validation")
	return cmdCheck
}

func validateCheckFlags(w *world.World) func(*cobra.Command, []string) error {
	return func(cmd *cobra.Command, args []string) error {
		if p := cmd.Parent(); p != nil {
			if p.PersistentPreRunE != nil {
				if err := p.PersistentPreRunE(cmd, args); err != nil {
					return err
				}
			}
		}
		switch w.CheckRelease {
		case "SKIP", "FAIL_ON_WARNING", "FAIL_ON_ERROR":
		default:
			return errors.Errorf("invalid check-release value: %s. Valid values: SKIP, FAIL_ON_WARNING, FAIL_ON_ERROR", w.CheckRelease)
		}
		return nil
	}
}

func runCheck(w *world.World) func(*cobra.Command, []string) error {
	return func(cmd *cobra.Command, _ []string) error {
		defer func() {
			output.WriteOutput(w)
		}()
		platform := w.Platform
		w.Logger.Info("running on platform", "platform", platform.String())
		client, err := newClientFromWorld(w)
		if err != nil {
			return err
		}
		defer client.close()

		// Check version compatibility
		if err := checkVersionCompatibility(w, client, args.Version); err != nil {
			return err
		}

		releaseFiles, err := getReleaseFiles(w)
		if err != nil {
			return err
		}
		releaseType := v1pb.Release_VERSIONED
		if w.Declarative {
			releaseType = v1pb.Release_DECLARATIVE
		}
		checkReleaseResponse, err := client.checkRelease(cmd.Context(), &v1pb.CheckReleaseRequest{
			Parent: w.Project,
			Release: &v1pb.Release{
				Files: releaseFiles,
				Type:  releaseType,
			},
			Targets:     w.Targets,
			CustomRules: w.CustomRules,
			VcsUser:     getVCSUser(platform),
		})
		if err != nil {
			return err
		}

		// Store check results in OutputMap for file output
		w.OutputMap.CheckResults = checkReleaseResponse

		w.Logger.Info("check release response", "resultCount", len(checkReleaseResponse.Results))

		// Generate platform-specific outputs
		switch platform {
		case world.GitHub:
			if err := github.CreateCommentAndAnnotation(checkReleaseResponse); err != nil {
				return err
			}
		case world.GitLab:
			if err := gitlab.WriteReleaseCheckToCodeQualityJSON(checkReleaseResponse); err != nil {
				return err
			}
		case world.AzureDevOps:
			if err := azure.LoggingReleaseChecks(checkReleaseResponse); err != nil {
				return err
			}
		case world.Bitbucket:
			if err := bitbucket.CreateBitbucketReport(checkReleaseResponse); err != nil {
				return err
			}
		default:
			// Unknown platform, no specific output handling
		}

		// Evaluate check results and return errors based on CheckRelease flag
		if w.CheckRelease == "SKIP" {
			return nil
		}

		var errorCount, warningCount int
		for _, result := range checkReleaseResponse.Results {
			for _, advice := range result.Advices {
				switch advice.Status {
				case v1pb.Advice_ERROR:
					errorCount++
				case v1pb.Advice_WARNING:
					warningCount++
				default:
					// Other advice statuses don't affect counts
				}
			}
		}

		if errorCount > 0 {
			return errors.Errorf("found %d error(s) in release check. view on Bytebase", errorCount)
		}
		if warningCount > 0 && w.CheckRelease == "FAIL_ON_WARNING" {
			return errors.Errorf("found %d warning(s) in release check. view on Bytebase", warningCount)
		}

		return nil
	}
}