Files
wehub-resource-sync bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

163 lines
5.3 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package main
import (
"context"
"errors"
"flag"
"fmt"
"os"
"time"
"github.com/larksuite/cli/internal/qualitygate/facts"
"github.com/larksuite/cli/internal/qualitygate/report"
"github.com/larksuite/cli/internal/qualitygate/semantic"
)
func main() {
os.Exit(run(os.Args[1:]))
}
func run(args []string) int {
fs := flag.NewFlagSet("semantic-review", flag.ContinueOnError)
var repo, factsPath, reviewPath, waiversPath, decisionOut, markdownOut string
var block bool
fs.StringVar(&repo, "repo", ".", "repository root")
fs.StringVar(&factsPath, "facts", "", "facts.json path")
fs.StringVar(&reviewPath, "review-json", "", "optional precomputed review JSON")
fs.StringVar(&waiversPath, "waivers-file", "", "optional semantic waiver TSV file")
fs.StringVar(&decisionOut, "decision-out", "", "optional decision JSON output path")
fs.StringVar(&markdownOut, "markdown-out", "", "optional markdown output path")
fs.BoolVar(&block, "block", false, "exit 1 when gatekeeper finds blockers")
if err := fs.Parse(args); err != nil {
return 2
}
if factsPath == "" && fs.NArg() == 1 {
factsPath = fs.Arg(0)
}
if factsPath == "" {
fmt.Fprintln(os.Stderr, "semantic-review: --facts is required")
return 2
}
f, err := facts.ReadFile(factsPath)
if err != nil {
fmt.Fprintf(os.Stderr, "semantic-review: %v\n", err)
return 2
}
policy, waivers, waiverDiags, modelConfig, err := loadSemanticConfig(repo, waiversPath)
if err != nil {
fmt.Fprintf(os.Stderr, "semantic-review: %v\n", err)
decision := semantic.InfrastructureFailureDecision(err)
decision.BlockMode = block
_ = semantic.WriteDecision(decisionOut, decision)
_ = semantic.WriteMarkdown(markdownOut, decision)
return 0
}
if reviewPath == "" && !semantic.BuildInputView(f).HasReviewableFacts() {
decision := finalizeDecision(block, waiverDiags, semantic.Decision{})
if err := writeSemanticOutputs(decisionOut, markdownOut, decision); err != nil {
fmt.Fprintf(os.Stderr, "semantic-review: %v\n", err)
return 2
}
return decisionExitCode(decision)
}
review, err := semantic.LoadOrReviewWithConfig(context.Background(), f, reviewPath, modelConfig)
if err != nil {
fmt.Fprintf(os.Stderr, "semantic-review: %v\n", err)
decision := semantic.DegradedDecision(err)
switch {
case errors.Is(err, semantic.ErrReviewerUnavailable):
decision = semantic.SkippedDecision(err)
case errors.Is(err, semantic.ErrReviewerConfiguration):
decision = semantic.InfrastructureFailureDecision(err)
}
decision.BlockMode = block
_ = semantic.WriteDecision(decisionOut, decision)
_ = semantic.WriteMarkdown(markdownOut, decision)
return 0
}
decision := semantic.DecideWithWaivers(f, review, policy, waivers)
decision = finalizeDecision(block, waiverDiags, decision)
if err := writeSemanticOutputs(decisionOut, markdownOut, decision); err != nil {
fmt.Fprintf(os.Stderr, "semantic-review: %v\n", err)
return 2
}
return decisionExitCode(decision)
}
func finalizeDecision(block bool, waiverDiags []report.Diagnostic, decision semantic.Decision) semantic.Decision {
decision.BlockMode = block
if !block && len(decision.Blockers) > 0 {
for i := range decision.Blockers {
decision.Blockers[i].ReviewAction = semantic.ReviewActionObserve
}
decision.Warnings = append(decision.Warnings, decision.Blockers...)
decision.Blockers = nil
}
decision.SystemWarnings = append(diagnosticSystemWarnings(waiverDiags), decision.SystemWarnings...)
return decision
}
func writeSemanticOutputs(decisionOut, markdownOut string, decision semantic.Decision) error {
if err := semantic.WriteDecision(decisionOut, decision); err != nil {
return fmt.Errorf("write decision: %w", err)
}
if err := semantic.WriteMarkdown(markdownOut, decision); err != nil {
return fmt.Errorf("write markdown: %w", err)
}
return nil
}
func decisionExitCode(decision semantic.Decision) int {
if decision.BlockMode && len(decision.Blockers) > 0 {
return 1
}
return 0
}
func loadSemanticConfig(repo, waiversPath string) (semantic.Policy, semantic.Waivers, []report.Diagnostic, semantic.ModelConfig, error) {
policy, err := semantic.LoadPolicy(repo)
if err != nil {
return semantic.Policy{}, semantic.Waivers{}, nil, semantic.ModelConfig{}, fmt.Errorf("load policy: %w", err)
}
var (
waivers semantic.Waivers
waiverDiags []report.Diagnostic
)
if waiversPath != "" {
waivers, waiverDiags, err = semantic.LoadWaiversFile(waiversPath, now())
} else {
waivers, waiverDiags, err = semantic.LoadWaivers(repo, now())
}
if err != nil {
return semantic.Policy{}, semantic.Waivers{}, nil, semantic.ModelConfig{}, fmt.Errorf("load waivers: %w", err)
}
modelConfig, err := semantic.LoadModelConfig(repo)
if err != nil {
return semantic.Policy{}, semantic.Waivers{}, nil, semantic.ModelConfig{}, fmt.Errorf("load model config: %w", err)
}
return policy, waivers, waiverDiags, modelConfig, nil
}
var now = func() time.Time {
return time.Now()
}
func diagnosticSystemWarnings(diags []report.Diagnostic) []semantic.SystemWarning {
if len(diags) == 0 {
return nil
}
out := make([]semantic.SystemWarning, 0, len(diags))
for _, diag := range diags {
out = append(out, semantic.SystemWarning{
Severity: "minor",
Message: diag.Message,
SuggestedAction: diag.Suggestion,
})
}
return out
}