feat(04-01): generate jobs and admin controllers, reject model imports
Scaffold pact.Job and pact.AdminController stubs with Winter YAML assets, and fail summer build when models imports a sibling package. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
81
internal/build/leaf.go
Normal file
81
internal/build/leaf.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var modelsSiblingLeaves = []string{
|
||||
"classes",
|
||||
"controllers",
|
||||
"console",
|
||||
"jobs",
|
||||
"middleware",
|
||||
"updates",
|
||||
}
|
||||
|
||||
func checkModelsLeaf(appDir string, m Manifest) error {
|
||||
for _, p := range m.Plugins {
|
||||
pluginDir := localModuleDir(appDir, p.Module)
|
||||
if pluginDir == "" {
|
||||
pluginDir = filepath.Join(appDir, "plugins", pluginName(p.ID))
|
||||
}
|
||||
if !underRoot(appDir, pluginDir) {
|
||||
continue
|
||||
}
|
||||
modelsDir := filepath.Join(pluginDir, "models")
|
||||
st, err := os.Stat(modelsDir)
|
||||
if err != nil || !st.IsDir() {
|
||||
continue
|
||||
}
|
||||
module, err := readModulePath(filepath.Join(pluginDir, "go.mod"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := inspectModelsImports(p.ID, pluginDir, module, modelsDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func inspectModelsImports(pluginID, pluginDir, module, modelsDir string) error {
|
||||
entries, err := os.ReadDir(modelsDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build: read %s: %w", modelsDir, err)
|
||||
}
|
||||
fset := token.NewFileSet()
|
||||
for _, entry := range entries {
|
||||
name := entry.Name()
|
||||
if entry.IsDir() || !strings.HasSuffix(name, ".go") {
|
||||
continue
|
||||
}
|
||||
path := filepath.Join(modelsDir, name)
|
||||
file, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build: parse %s: %w", path, err)
|
||||
}
|
||||
rel, err := filepath.Rel(pluginDir, path)
|
||||
if err != nil {
|
||||
rel = filepath.Join("models", name)
|
||||
}
|
||||
for _, spec := range file.Imports {
|
||||
imp, err := strconv.Unquote(spec.Path.Value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, sib := range modelsSiblingLeaves {
|
||||
prefix := module + "/" + sib
|
||||
if imp == prefix || strings.HasPrefix(imp, prefix+"/") {
|
||||
return fmt.Errorf("build: plugin %s: %s imports %s", pluginID, filepath.ToSlash(rel), imp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user