magus v0.4.2 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
2 min read

MGS1029: source glob reaches into a pruned directory

A target declares a source pattern whose directory prefix passes through a tree magus prunes, so it matches nothing and keys nothing.

[MGS1029] docs: source glob "proto/gen/*.binpb" can never match: the expansion
walk prunes "gen"

Why

The walk that builds a cache key skips four directory names wholesale, from project.IgnoreDirs:

directory why it is pruned
gen generated code: machine-written, never a discoverable project
vendor Go vendored dependencies
node_modules pnpm/npm dependencies
target Rust build artifacts

Pruning them is what keeps a broad pattern honest. A project declaring **/*.js means its own sources; without the prune it would hash every file in node_modules and key on a dependency tree nobody edits.

The cost is that a pattern aimed at one of those directories can never match. It is not an error at authoring time and not an error at run time - the glob is well-formed, it simply describes files the walk will not visit. The target then replays from cache while the files it named change underneath it.

This is the input-side twin of MGS1014, which catches a declared output that no run produces. Same shape: a declaration and reality quietly disconnected.

What it is not

An exact path is fine, and is not reported:

ctx.readsFiles(workspace.file("proto/gen/descriptor.binpb"));   // works
ctx.readsFiles(workspace.file("proto/gen/*.binpb"));            // MGS1029

A wildcard-free declaration names one file, so magus resolves it by stat rather than by the walk. It reaches the cache key normally even from inside a pruned tree. Only a pattern is unmatchable, because only a pattern could expand to swallow a dependency tree.

Fix

Name the file exactly, if you meant one file:

ctx.readsFiles(workspace.file("proto/gen/descriptor.binpb"));

Or declare the real sources instead of the generated artifact. A generated tree is downstream of something you own, and keying on that something is both narrower and more honest:

// not proto/gen/*.binpb - the schema the descriptor is built from
ctx.readsFiles(workspace.file("proto/magus/**/*.proto"));

If the files genuinely live under a pruned name and are genuinely sources, rename the directory. gen, vendor, node_modules and target carry a meaning across every magus workspace, and a hand-written source tree under one of those names will surprise more than this check.

Confirming the fix

Ask what the cache key actually contains:

magus describe target <target> <project> --cache --inputs

Every hashed file appears as a src: line. If a file you declared is missing from that list, it is not in the key, whatever describe target reports under sources:.

MGS1029magusfilesourcescacheglobs
Last updated (7e005d14)
Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. See workspace.

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. See workspace.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. See targets.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. See targets.

Module

A magus stdlib namespace a magusfile imports for host capabilities: filesystem, exec, vcs, and more. See the module reference.

Buzz

The language magusfiles are written in (the .buzz engine). See engines.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. See cache.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Conventions

This page uses none of the site's convention markers. The full set is on the conventions page.