Monorepo management for opam overlays
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

monopam: failing test for missing dep via private executable

A subtree with a private (executable ... (libraries re)) stanza in a
[gen/] subdir but no [re] entry in opam depends should be flagged as
missing — that's exactly what tripped up ocaml-publicsuffix in
tangled.org/.../ocaml-publicsuffix/pulls/1. The current lint silently
passes because stanza_owner returns None for private stanzas (no
public_name, no (package ...)) so the executable's libs never make it
into dune_packages_by_owner.

Test currently fails (red), matching the bug.

+61
+61
test/test_lint.ml
··· 55 55 (* Verify the run function type signature is accessible *) 56 56 ignore (Monopam.Lint.run : fs:_ -> monorepo:_ -> unit -> Monopam.Lint.result) 57 57 58 + (* Build a throw-away monorepo on disk, run [Lint.run] on it, return result. *) 59 + let with_temp_monorepo build_subtrees f = 60 + Eio_main.run @@ fun env -> 61 + let parent = Filename.get_temp_dir_name () in 62 + let root = Filename.temp_file ~temp_dir:parent "monopam-lint-" "" in 63 + Sys.remove root; 64 + Unix.mkdir root 0o700; 65 + let cleanup () = 66 + ignore (Sys.command (Fmt.str "rm -rf %s" (Filename.quote root))) 67 + in 68 + Fun.protect ~finally:cleanup (fun () -> 69 + let mkpath p = Filename.concat root p in 70 + let mkdir p = 71 + let p = mkpath p in 72 + if not (Sys.file_exists p) then Unix.mkdir p 0o755 73 + in 74 + let write p s = 75 + let oc = open_out (mkpath p) in 76 + output_string oc s; 77 + close_out oc 78 + in 79 + build_subtrees ~mkdir ~write; 80 + let result = 81 + Monopam.Lint.run 82 + ~fs:(Eio.Stdenv.fs env) 83 + ~monorepo:(Fpath.v root) () 84 + in 85 + f result) 86 + 87 + (** A subtree whose only opam package is [test-pkg]. The library proper has no 88 + extra deps, but a sibling private [(executable)] in [gen/] uses [re]. 89 + Since [re] is not in [test-pkg.opam], a [dune build -p test-pkg @install] 90 + would fail to compile [gen.exe] — and the lint should flag it. *) 91 + let test_missing_dep_via_private_executable () = 92 + with_temp_monorepo 93 + (fun ~mkdir ~write -> 94 + mkdir "test-pkg"; 95 + mkdir "test-pkg/lib"; 96 + mkdir "test-pkg/gen"; 97 + write "test-pkg/test-pkg.opam" 98 + "opam-version: \"2.0\"\ndepends: [ \"dune\" {>= \"3.21\"} ]\n"; 99 + write "test-pkg/lib/dune" 100 + "(library\n (name test_pkg)\n (public_name test-pkg))\n"; 101 + write "test-pkg/gen/dune" 102 + "(executable\n (name gen)\n (libraries re))\n") 103 + (fun (result : Monopam.Lint.result) -> 104 + let re_missing = 105 + List.exists 106 + (fun (i : Monopam.Lint.issue) -> 107 + i.subtree = "test-pkg" 108 + && i.kind = Monopam.Lint.Missing 109 + && i.package = "re") 110 + result.issues 111 + in 112 + Alcotest.(check bool) 113 + "private executable's library deps are attributed to the subtree's \ 114 + single opam package" 115 + true re_missing) 116 + 58 117 let suite = 59 118 ( "lint", 60 119 [ ··· 63 122 Alcotest.test_case "result construction" `Quick test_result_construction; 64 123 Alcotest.test_case "result with issues" `Quick test_result_with_issues; 65 124 Alcotest.test_case "run type" `Quick test_run_type; 125 + Alcotest.test_case "missing dep via private executable" `Quick 126 + test_missing_dep_via_private_executable; 66 127 ] )