Inspect committed workspace files
This commit is contained in:
@@ -17,6 +17,8 @@ const (
|
||||
PackageCompile Check = "package-compile"
|
||||
// GoFormat identifies committed Go source formatting.
|
||||
GoFormat Check = "go-format"
|
||||
// WorkspaceFiles identifies committed workspace files in module source.
|
||||
WorkspaceFiles Check = "workspace-files"
|
||||
)
|
||||
|
||||
// Finding describes a validation observation at an optional source location.
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"go/format"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/gotool"
|
||||
@@ -15,10 +16,16 @@ import (
|
||||
|
||||
// Settings selects shared validation behavior.
|
||||
type Settings struct {
|
||||
Race bool
|
||||
FullVet bool
|
||||
CompileTargets []Target
|
||||
GoFormat bool
|
||||
Race bool
|
||||
FullVet bool
|
||||
CompileTargets []Target
|
||||
GoFormat bool
|
||||
ModuleDistribution ModuleDistributionSettings
|
||||
}
|
||||
|
||||
// ModuleDistributionSettings selects candidate distribution checks.
|
||||
type ModuleDistributionSettings struct {
|
||||
WorkspaceFiles bool
|
||||
}
|
||||
|
||||
// Target selects one package-compilation target.
|
||||
@@ -91,14 +98,45 @@ func Run(ctx context.Context, request Request) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if request.Settings.GoFormat {
|
||||
if request.Settings.GoFormat || request.Settings.ModuleDistribution.WorkspaceFiles {
|
||||
tree, err := request.ReadCandidateTree(ctx)
|
||||
if err != nil {
|
||||
return &Failure{Check: GoFormat, Cause: err}
|
||||
check := WorkspaceFiles
|
||||
if request.Settings.GoFormat {
|
||||
check = GoFormat
|
||||
}
|
||||
return &Failure{Check: check, Cause: err}
|
||||
}
|
||||
if err := checkGoFormat(ctx, tree); err != nil {
|
||||
return err
|
||||
if request.Settings.GoFormat {
|
||||
if err := checkGoFormat(ctx, tree); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if request.Settings.ModuleDistribution.WorkspaceFiles {
|
||||
if err := checkWorkspaceFiles(tree); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkWorkspaceFiles(tree *CandidateTree) error {
|
||||
var findings []Finding
|
||||
for _, entry := range tree.Entries() {
|
||||
if entry.Type != "blob" {
|
||||
continue
|
||||
}
|
||||
switch path.Base(entry.Path) {
|
||||
case "go.work", "go.work.sum":
|
||||
findings = append(findings, Finding{
|
||||
Path: entry.Path,
|
||||
Message: "workspace file is committed in the candidate",
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(findings) != 0 {
|
||||
return &Failure{Check: WorkspaceFiles, Findings: findings}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
100
internal/validation/workspace_test.go
Normal file
100
internal/validation/workspace_test.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/git"
|
||||
)
|
||||
|
||||
func TestCheckWorkspaceFilesReportsCommittedBlobNames(t *testing.T) {
|
||||
tree := &CandidateTree{entries: []git.TreeEntry{
|
||||
{Path: "go.work", Type: "blob", Mode: "100644"},
|
||||
{Path: "nested/go.work.sum", Type: "blob", Mode: "100644"},
|
||||
{Path: "vendor/nested/link/go.work", Type: "blob", Mode: "120000"},
|
||||
{Path: "nested/not-go.work.backup", Type: "blob", Mode: "100644"},
|
||||
{Path: "submodule/go.work", Type: "commit", Mode: "160000"},
|
||||
}}
|
||||
err := checkWorkspaceFiles(tree)
|
||||
failure, ok := err.(*Failure)
|
||||
if !ok || failure.Check != WorkspaceFiles {
|
||||
t.Fatalf("checkWorkspaceFiles error = %v, want workspace-files failure", err)
|
||||
}
|
||||
want := map[string]bool{
|
||||
"go.work": false,
|
||||
"nested/go.work.sum": false,
|
||||
"vendor/nested/link/go.work": false,
|
||||
}
|
||||
if len(failure.Findings) != len(want) {
|
||||
t.Fatalf("workspace findings = %#v, want %d paths", failure.Findings, len(want))
|
||||
}
|
||||
for _, finding := range failure.Findings {
|
||||
if _, ok := want[finding.Path]; !ok {
|
||||
t.Errorf("unexpected workspace path %q", finding.Path)
|
||||
}
|
||||
want[finding.Path] = true
|
||||
}
|
||||
for path, found := range want {
|
||||
if !found {
|
||||
t.Errorf("workspace path %q was not reported", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckWorkspaceFilesAllowsOtherNames(t *testing.T) {
|
||||
tree := &CandidateTree{entries: []git.TreeEntry{
|
||||
{Path: "go.mod", Type: "blob", Mode: "100644"},
|
||||
{Path: "examples/go.work.example", Type: "blob", Mode: "100644"},
|
||||
}}
|
||||
if err := checkWorkspaceFiles(tree); err != nil {
|
||||
t.Fatalf("checkWorkspaceFiles error = %v, want no findings", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunWorkspaceFilesUsesCommittedTreeWithGoWorkspaceDisabled(t *testing.T) {
|
||||
t.Setenv("GOWORK", "off")
|
||||
repository := newTreeRepository(t)
|
||||
writeTreeFile(t, repository, "go.work", []byte("go 1.25.0\n"))
|
||||
writeTreeFile(t, repository, "nested/go.work.sum", []byte("committed workspace metadata\n"))
|
||||
gitTree(t, repository, "add", ".")
|
||||
gitTree(t, repository, "commit", "-m", "capture workspace files")
|
||||
commit := strings.TrimSpace(gitTree(t, repository, "rev-parse", "HEAD"))
|
||||
writeTreeFile(t, repository, "untracked/go.work.sum", []byte("uncommitted workspace metadata\n"))
|
||||
|
||||
logPath := installGoShim(t, "", false)
|
||||
if err := Run(context.Background(), Request{RepositoryDir: repository, Commit: commit}); err != nil {
|
||||
t.Fatalf("default validation = %v, want workspace check disabled", err)
|
||||
}
|
||||
|
||||
logPath = installGoShim(t, "", false)
|
||||
err := Run(context.Background(), Request{
|
||||
RepositoryDir: repository,
|
||||
Commit: commit,
|
||||
Settings: Settings{ModuleDistribution: ModuleDistributionSettings{
|
||||
WorkspaceFiles: true,
|
||||
}},
|
||||
})
|
||||
failure, ok := err.(*Failure)
|
||||
if !ok || failure.Check != WorkspaceFiles {
|
||||
t.Fatalf("selected workspace error = %v, want workspace-files failure", err)
|
||||
}
|
||||
want := map[string]bool{"go.work": false, "nested/go.work.sum": false}
|
||||
if len(failure.Findings) != len(want) {
|
||||
t.Fatalf("workspace findings = %#v, want committed paths only", failure.Findings)
|
||||
}
|
||||
for _, finding := range failure.Findings {
|
||||
if _, ok := want[finding.Path]; !ok {
|
||||
t.Errorf("unexpected workspace path %q", finding.Path)
|
||||
}
|
||||
want[finding.Path] = true
|
||||
}
|
||||
for path, found := range want {
|
||||
if !found {
|
||||
t.Errorf("committed workspace path %q was not reported", path)
|
||||
}
|
||||
}
|
||||
if got := strings.Join(readGoShimLog(t, logPath), "\n"); !strings.Contains(got, "test -mod=readonly -count=1 ./...") {
|
||||
t.Fatalf("Go commands = %q, want ordinary test suite with GOWORK=off", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user