Skip to content

Commit 6f385c5

Browse files
committed
fix(hub): apply module exclude rules when loading from a directory source
Why: live changeset expansion loaded every entry from a module's directory (e.g. a lock replacement pointed at the module's source), including the module's own excluded fixtures (test/_index.yaml entries). Those leaked into the host registry and collided with the host app's real entries during linking. Published .wapp packs were already filtered at publish time, so only directory/replacement sources were affected. What: loadEntriesForModule now applies the module's wippy.yaml exclude / exclude_meta rules for directory sources via the same DisableWithOptions stage the CLI entries loader uses, skipping .wapp packs. Mirrors cmd/internal/entries/loader.go shouldApplyModuleConfigFilters.
1 parent 33884e8 commit 6f385c5

2 files changed

Lines changed: 88 additions & 1 deletion

File tree

boot/deps/hub/dependency_handler.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/wippyai/runtime/boot/build"
2525
"github.com/wippyai/runtime/boot/build/stages"
2626
"github.com/wippyai/runtime/boot/deps/auth"
27+
depconfig "github.com/wippyai/runtime/boot/deps/config"
2728
"github.com/wippyai/runtime/boot/deps/graph"
2829
"github.com/wippyai/runtime/boot/deps/lock"
2930
"github.com/wippyai/runtime/boot/deps/wappextract"
@@ -584,7 +585,40 @@ func (h *DependencyHandler) loadEntriesForModule(ctx context.Context, transcoder
584585
return nil, err
585586
}
586587
registerResolvedModuleSourceRoot(ctx, mod.Org+"/"+mod.Name, modulePath)
587-
return loadRawEntriesFromPaths(ctx, []string{modulePath}, h.logger, transcoder)
588+
entries, err := loadRawEntriesFromPaths(ctx, []string{modulePath}, h.logger, transcoder)
589+
if err != nil {
590+
return nil, err
591+
}
592+
return h.applyModuleConfigFilters(ctx, modulePath, entries)
593+
}
594+
595+
// applyModuleConfigFilters drops entries the module's wippy.yaml excludes
596+
// (exclude / exclude_meta) when the module is loaded from a directory tree —
597+
// e.g. a lock replacement pointed at the module's source. Without it a host app
598+
// picks up the module's own fixtures (test/_index.yaml under namespace "app"),
599+
// which then collide with the host's real entries during linking. .wapp packs
600+
// are skipped: they were already filtered at publish time.
601+
func (h *DependencyHandler) applyModuleConfigFilters(ctx context.Context, modulePath string, entries []regapi.Entry) ([]regapi.Entry, error) {
602+
if filepath.Ext(modulePath) == ".wapp" {
603+
return entries, nil
604+
}
605+
cfg, err := depconfig.Load(modulePath)
606+
if err != nil {
607+
return entries, nil
608+
}
609+
entryExcludes := cfg.EntryExcludes()
610+
if len(entryExcludes) == 0 && len(cfg.ExcludeMeta) == 0 {
611+
return entries, nil
612+
}
613+
filtered := append([]regapi.Entry(nil), entries...)
614+
stage := stages.DisableWithOptions(stages.DisableOptions{
615+
Entries: entryExcludes,
616+
MetaFilters: cfg.ExcludeMeta,
617+
})
618+
if err := stage.Execute(ctx, &filtered); err != nil {
619+
return nil, NewDependencyLoadError(modulePath, err)
620+
}
621+
return filtered, nil
588622
}
589623

590624
func registerResolvedModuleSourceRoot(ctx context.Context, moduleName, modulePath string) {

boot/deps/hub/dependency_handler_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,59 @@ replacements:
12361236
assert.Equal(t, "0.3.0", modules[0].Version)
12371237
}
12381238

1239+
func TestDependencyHandler_LoadEntriesForModule_AppliesExcludeMetaForDirectorySource(t *testing.T) {
1240+
ctx := newTestContext()
1241+
tmpDir := t.TempDir()
1242+
lockPath := filepath.Join(tmpDir, "wippy.lock")
1243+
localMod := filepath.Join(tmpDir, "local-mod")
1244+
require.NoError(t, os.MkdirAll(localMod, 0755))
1245+
require.NoError(t, os.WriteFile(filepath.Join(localMod, "wippy.yaml"),
1246+
[]byte("organization: local\nmodule: mod\nversion: 0.1.0\nexclude_meta:\n type:\n - test\n"), 0600))
1247+
require.NoError(t, os.WriteFile(filepath.Join(localMod, "_index.json"), []byte(`{
1248+
"namespace": "local.mod",
1249+
"entries": [
1250+
{ "name": "keep", "kind": "fs.directory", "path": "./keep" },
1251+
{ "name": "drop", "kind": "fs.directory", "meta": { "type": "test" }, "path": "./drop" }
1252+
]
1253+
}`), 0600))
1254+
require.NoError(t, os.WriteFile(lockPath, []byte(`directories:
1255+
modules: .wippy
1256+
src: ./src
1257+
modules:
1258+
- name: local/mod
1259+
version: 0.1.0
1260+
replacements:
1261+
- from: local/mod
1262+
to: ./local-mod
1263+
`), 0600))
1264+
1265+
handler, err := NewDependencyHandler(DependencyHandlerOptions{
1266+
Hub: &fakeHub{},
1267+
Logger: zap.NewNop(),
1268+
LockPath: lockPath,
1269+
VendorDir: t.TempDir(),
1270+
})
1271+
require.NoError(t, err)
1272+
1273+
transcoder := payload.GetTranscoder(ctx)
1274+
require.NotNil(t, transcoder)
1275+
1276+
entries, err := handler.loadEntriesForModule(ctx, transcoder, ResolvedModule{Org: "local", Name: "mod", Version: "0.1.0"})
1277+
require.NoError(t, err)
1278+
1279+
var hasKeep, hasDrop bool
1280+
for _, e := range entries {
1281+
if e.ID == regapi.NewID("local.mod", "keep") {
1282+
hasKeep = true
1283+
}
1284+
if e.ID == regapi.NewID("local.mod", "drop") {
1285+
hasDrop = true
1286+
}
1287+
}
1288+
assert.True(t, hasKeep, "non-test entry must load")
1289+
assert.False(t, hasDrop, "test entry must be excluded per the module's exclude_meta")
1290+
}
1291+
12391292
func TestDependencyHandler_CollectDesiredDependencies_DoesNotPinUpdatedDependency(t *testing.T) {
12401293
ctx := newTestContext()
12411294
transcoder := payload.GetTranscoder(ctx)

0 commit comments

Comments
 (0)