Skip to content

Commit f924e23

Browse files
jtdowneylpil
authored andcommitted
Fix erlang-shipment including dev dependencies
The `gleam export erlang-shipment` command was incorrectly including dev dependencies in the exported shipment. The fix filters dev dependencies at compile time in ProjectCompiler. When building in Prod mode, only transitive production dependencies are compiled, so dev packages never appear in the build output. Closes #5308
1 parent 09e9070 commit f924e23

7 files changed

Lines changed: 106 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@
315315
when emitting TypeScript declarations.
316316
([Surya Rose](https://github.com/GearsDatapacks))
317317

318+
- Fixed a bug where dev dependencies would be compiled and included in
319+
production builds such as `gleam export erlang-shipment`.
320+
([John Downey](https://github.com/jtdowney))
321+
318322
- Fixed a bug where the package cache would not properly be reset when a version
319323
of a package was replaced on Hex.
320324
([Surya Rose](https://github.com/GearsDatapacks))

compiler-core/src/build/project_compiler.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,31 @@ where
180180
self.defined_modules.clear();
181181
}
182182

183+
fn retain_only_production_packages(&mut self) {
184+
let mut production = HashSet::new();
185+
let mut queue: Vec<_> = self.config.dependencies.keys().cloned().collect();
186+
while let Some(name) = queue.pop() {
187+
if production.insert(name.clone())
188+
&& let Some(pkg) = self.packages.get(name.as_str())
189+
{
190+
queue.extend(pkg.requirements.iter().cloned());
191+
}
192+
}
193+
self.packages
194+
.retain(|name, _| production.contains(name.as_str()));
195+
}
196+
183197
/// Compiles all packages in the project and returns the compiled
184198
/// information from the root package
185199
pub fn compile(mut self) -> Result<Built> {
186200
self.reset_state_for_new_compile_run();
187201

202+
// In production mode, skip dev-only dependencies entirely so they
203+
// are never compiled.
204+
if self.mode() == Mode::Prod {
205+
self.retain_only_production_packages();
206+
}
207+
188208
// Each package may specify a Gleam version that it supports, so we
189209
// verify that this version is appropriate.
190210
self.check_gleam_version()?;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.beam
2+
*.ez
3+
/build
4+
erl_crash.dump
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name = "shipment_test"
2+
version = "0.1.0"
3+
4+
[dependencies]
5+
gleam_stdlib = "~> 0.34"
6+
# hpack_erl has otp_app = "hpack" (different from package name)
7+
# This tests that packages with different OTP app names are included correctly
8+
hpack_erl = "~> 0.3"
9+
10+
[dev_dependencies]
11+
gleeunit = "~> 1.0"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# This file was generated by Gleam
2+
# You typically do not need to edit this file
3+
4+
packages = [
5+
{ name = "gleam_stdlib", version = "0.68.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "F7FAEBD8EF260664E86A46C8DBA23508D1D11BB3BCC6EE1B89B3BC3E5C83FF1E" },
6+
{ name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" },
7+
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
8+
]
9+
10+
[requirements]
11+
gleam_stdlib = { version = "~> 0.34" }
12+
gleeunit = { version = "~> 1.0" }
13+
hpack_erl = { version = "~> 0.3" }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import gleam/io
2+
3+
pub fn main() {
4+
io.println("Hello from shipment test!")
5+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/sh
2+
3+
set -eu
4+
5+
GLEAM_COMMAND=${GLEAM_COMMAND:-"cargo run --quiet --"}
6+
7+
g() {
8+
echo "Running: $GLEAM_COMMAND $@"
9+
$GLEAM_COMMAND "$@"
10+
}
11+
12+
echo Resetting the build directory to get to a known state
13+
rm -fr build
14+
15+
echo Building erlang shipment
16+
g export erlang-shipment
17+
18+
echo Checking that gleam_stdlib IS in the shipment
19+
if [ ! -d "build/erlang-shipment/gleam_stdlib" ]; then
20+
echo "ERROR: gleam_stdlib should be in the shipment but was not found"
21+
exit 1
22+
fi
23+
echo "gleam_stdlib found in shipment"
24+
25+
echo Checking that hpack IS in the shipment
26+
echo "(hpack_erl package has otp_app=hpack, so directory is named hpack)"
27+
if [ ! -d "build/erlang-shipment/hpack" ]; then
28+
echo "ERROR: hpack (from hpack_erl package) should be in the shipment but was not found"
29+
exit 1
30+
fi
31+
echo "hpack found in shipment"
32+
33+
echo Checking that gleeunit is NOT in the shipment
34+
if [ -d "build/erlang-shipment/gleeunit" ]; then
35+
echo "ERROR: gleeunit is a dev dependency and should NOT be in the shipment"
36+
exit 1
37+
fi
38+
echo "gleeunit correctly excluded from shipment"
39+
40+
echo Checking that the root package IS in the shipment
41+
if [ ! -d "build/erlang-shipment/shipment_test" ]; then
42+
echo "ERROR: shipment_test (root package) should be in the shipment but was not found"
43+
exit 1
44+
fi
45+
echo "shipment_test found in shipment"
46+
47+
echo
48+
echo Success!
49+
echo

0 commit comments

Comments
 (0)