Skip to content

fix(product): capture products on traced builds (workdir-anchored, absolute glob)#21

Open
colek42 wants to merge 5 commits into
mainfrom
nk/product-workdir-anchor
Open

fix(product): capture products on traced builds (workdir-anchored, absolute glob)#21
colek42 wants to merge 5 commits into
mainfrom
nk/product-workdir-anchor

Conversation

@colek42
Copy link
Copy Markdown
Contributor

@colek42 colek42 commented May 26, 2026

Summary

Trace-mode builds through cilock-action silently recorded zero products
(treeSize=0) while trace evidence captured thousands of files. This PR fixes
that and gives the product attestation a coherent, workdir-anchored model.

Root cause: trace mode emits absolute product paths (the kernel
read-tap / path-hash resolves fds via /proc/<pid>/fd). The product
include-glob was anchored to cfg.WorkingDir via filepath.Join, but
WorkingDir is typically relative (the common workingdir: yq-src input),
so the glob stayed relative (yq-src/**) and a relative glob never matches an
absolute path → nothing captured.

What changed

  • products input + workdir default + no-products warning — newline list of
    paths/globs; default is workingDir/** so the build's outputs count as
    products without matching every compiler intermediate.
  • Anchor relative product paths to workingDir.
  • Absolutize WorkingDir before anchoring the glob and for
    attestation.WithWorkingDir, so the glob and the resolved trace paths live in
    one absolute namespace. Adds TDD coverage (default / legacy / products-list /
    absolute-passthrough).
  • Empty default for the legacy product-include-glob on both GitHub and
    GitLab (the constant was stale at "*", which broke TestParseGitHub_Defaults
    and left the platforms inconsistent; "*" also can't match trace-mode
    absolute paths).

Evidence

Validated end-to-end on a real ubuntu-24.04 eBPF runner building mikefarah/yq:

  • Before (relative glob yq-src/**): tree:products = empty-tree root
    e3b0c442…, treeSize: 0.
  • After / proof (absolute glob, exercising the same matching path the fix
    makes automatic): tree:products root 7ee52167…, treeSize: 1 — the
    yq binary captured — alongside 9.7k traced files / 1.3k processes.

Notes

Test plan

  • go test ./... (GOWORK=off) green
  • New TestResolveProductIncludeGlob_* unit tests
  • End-to-end yq build on ubuntu-24.04 records tree:products (treeSize=1)
  • Re-validate the relative-workingdir path through a released binary

🤖 Generated with Claude Code

cole-rgb and others added 5 commits May 26, 2026 17:02
…ild)

rookery split the eBPF code into its own Go submodule at
plugins/attestors/commandrun/ebpf. cilock-action's go.mod had no require/
replace for it, so any Linux build (tracing_ebpf_linux.go is build-tagged
linux) failed with "missing go.sum entry for .../commandrun/ebpf" — this is
why main's Build (linux/amd64, linux/arm64) checks are currently red.

Add the require + local replace (matching every other rookery sibling) and
run go mod tidy so go.sum gains the submodule's transitive deps
(github.com/cilium/ebpf and friends). Linux build now resolves.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three changes that fix the conceptual model surfaced by the gh CLI
smoke (which classified 9281 compiler intermediates as "products"):

1. New \`products\` input — newline-separated list of paths/globs
   the build is expected to produce. Joined as a {a,b,c} brace
   pattern for the rookery product attestor.

2. Default = workingDir/** when \`products\` is empty. Idiomatic
   builds that write under the workspace just work. Builds that
   write to /tmp or ~/.local/bin/ must explicitly list those paths.

3. \`::warning::no products detected\` when the resolved glob
   matched nothing. Surfaces the active glob and tells the user
   exactly where + how to override it in their workflow YAML.

Legacy \`product-include-glob\` input still honoured (no default,
opt-in). \`product-exclude-glob\` unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
resolveProductIncludeGlob compiled relative entries (e.g.,
\`products: bin/gh\`) as-is, but rookery's trace mode emits absolute
paths in TraceOutputs (e.g., /home/runner/work/cli/cli/bin/gh).
The relative glob matched zero paths → empty products map even when
the summary classifier saw 2.

Now: relative entries get filepath.Join'd against cfg.WorkingDir
(falling back to os.Getwd if WorkingDir is empty) before compiling
into the {a,b,c} brace glob.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Trace mode emits ABSOLUTE product paths (the kernel read-tap/path-hash
resolves fds via /proc/<pid>/fd). resolveProductIncludeGlob anchored the
include-glob to cfg.WorkingDir via filepath.Join, but WorkingDir is
typically RELATIVE (the common `workingdir: yq-src` input). A relative
glob (e.g. "yq-src/**") never matches an absolute product path, so every
traced build with a relative workingdir silently recorded zero products
(treeSize=0) while trace evidence captured thousands of files.

Resolve WorkingDir to an absolute path before anchoring, and pass the
same absolute path to attestation.WithWorkingDir so relative trace paths
resolve into the same namespace the glob lives in. Adds TDD coverage for
default/legacy/products-list globs + absolute-workingdir passthrough.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…atforms)

e210ec8 deprecated `product-include-glob` in favor of `products` and made
the GitHub parser return the raw (empty) input, but left the
DefaultProductIncludeGlob constant at "*". That broke TestParseGitHub_Defaults
and, worse, left GitLab still applying a "*" default via glEnvDefault — so the
two platforms disagreed on the default product surface. A non-empty "*" default
also defeats trace mode: it never matches the absolute product paths trace mode
emits. Set the constant to "" so an unset glob falls through to the
workingDir/** default in resolveProductIncludeGlob, consistently on GitHub and
GitLab.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@colek42 colek42 force-pushed the nk/product-workdir-anchor branch from 151c281 to f8177dd Compare May 26, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants