action/command/check.go
Rama main · réplica de lectura del repositorio original.
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
}
}