Skip to content

Commit eebfc36

Browse files
authored
feat: Commands should fail the build if their exit code is not zero (#534)
1 parent 52a230b commit eebfc36

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ source_path = [
439439
- If you specify a source path as a string that references a folder and the runtime begins with `python` or `nodejs`, the build process will automatically build python and nodejs dependencies if `requirements.txt` or `package.json` file will be found in the source folder. If you want to customize this behavior, please use the object notation as explained below.
440440
- All arguments except `path` are optional.
441441
- `patterns` - List of Python regex filenames should satisfy. Default value is "include everything" which is equal to `patterns = [".*"]`. This can also be specified as multiline heredoc string (no comments allowed). Some examples of valid patterns:
442+
- If you use the `commands` option and chain multiple commands, only the exit code of last command will be checked for success. If you prefer to fail fast, start the commands with the bash option `set -e` or powershell option `$ErrorActionPreference="Stop"`
442443

443444
```txt
444445
!.*/.*\.txt # Filter all txt files recursively

package.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -914,17 +914,27 @@ def execute(self, build_plan, zip_stream, query):
914914
# XXX: timestamp=0 - what actually do with it?
915915
zs.write_dirs(rd, prefix=prefix, timestamp=0)
916916
elif cmd == "sh":
917-
r, w = os.pipe()
918-
side_ch = os.fdopen(r)
919917
path, script = action[1:]
920-
script = "{}\npwd >&{}".format(script, w)
918+
p = subprocess.Popen(
919+
script,
920+
shell=True,
921+
stdout=subprocess.PIPE,
922+
stderr=subprocess.PIPE,
923+
cwd=path,
924+
)
921925

922-
p = subprocess.Popen(script, shell=True, cwd=path, pass_fds=(w,))
923-
os.close(w)
924-
sh_work_dir = side_ch.read().strip()
925926
p.wait()
926-
log.info("WD: %s", sh_work_dir)
927-
side_ch.close()
927+
call_stdout, call_stderr = p.communicate()
928+
exit_code = p.returncode
929+
log.info("exit_code: %s", exit_code)
930+
if exit_code != 0:
931+
raise RuntimeError(
932+
"Script did not run successfully, exit code {}: {} - {}".format(
933+
exit_code,
934+
call_stdout.decode("utf-8").strip(),
935+
call_stderr.decode("utf-8").strip(),
936+
)
937+
)
928938
elif cmd == "set:filter":
929939
patterns = action[1]
930940
pf = ZipContentFilter(args=self._args)

tests/test_package_toml.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from package import get_build_system_from_pyproject_toml
1+
from package import get_build_system_from_pyproject_toml, BuildPlanManager
2+
from pytest import raises
3+
from unittest.mock import Mock
24

35

46
def test_get_build_system_from_pyproject_toml_inexistent():
@@ -14,6 +16,22 @@ def test_get_build_system_from_pyproject_toml_unknown():
1416
)
1517

1618

19+
def test_build_manager_sucess_command():
20+
bpm = BuildPlanManager(args=Mock())
21+
# Should not have exception raised
22+
bpm.execute(build_plan=[["sh", "/tmp", "pwd"]], zip_stream=None, query=None)
23+
24+
25+
def test_build_manager_failing_command():
26+
bpm = BuildPlanManager(args=Mock())
27+
with raises(Exception):
28+
bpm.execute(
29+
build_plan=[["sh", "/tmp", "NOTACOMMAND"]],
30+
zip_stream=None,
31+
query=None,
32+
)
33+
34+
1735
def test_get_build_system_from_pyproject_toml_poetry():
1836
assert (
1937
get_build_system_from_pyproject_toml(

0 commit comments

Comments
 (0)