Skip to content

Commit 5805f3d

Browse files
committed
Fix incorrect RC with --fail-on-pipeline-failure
This fixes an important bug in --fail-on-pipeline-failure. Prior to this commit, litani run-build would only terminate abnormally with this flag set when ninja terminated abnormally. This commit fixes this behavior so that litani run-build instead checks whether any pipeline failed, and terminates abnormally if so. When using --fail-on-pipeline-failure, `litani run-build` will now terminate with an exit code of 0 if all pipelines passed, and 10 if at least one of them failed.
2 parents 9506e7a + ff8e57c commit 5805f3d

File tree

4 files changed

+120
-7
lines changed

4 files changed

+120
-7
lines changed

lib/run_build.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# permissions and limitations under the License
1313

1414
import datetime
15+
import itertools
1516
import json
1617
import logging
1718
import os
@@ -219,6 +220,9 @@ async def run_build(args):
219220
f"file://{run_info['latest_symlink']}/html/index.html")
220221

221222
if args.fail_on_pipeline_failure:
222-
sys.exit(0 if runner.was_successful() else 1)
223+
for _ in itertools.filterfalse(
224+
lambda pipe: pipe["status"] != "fail", run["pipelines"]):
225+
sys.exit(10)
226+
sys.exit(0)
223227

224228
sys.exit(0)

test/e2e/run

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,18 @@ DESCRIPTION = "Execute a single Litani run and test the resulting run.json"
2929
EPILOG = "See test/e2e/README for the organization of this test suite"
3030

3131

32-
def run_cmd(cmd):
32+
def run_cmd(cmd, check):
3333
cmd_list = [str(c) for c in cmd]
3434
print(" ".join(cmd_list))
3535
try:
36-
subprocess.run(cmd_list, check=True)
36+
proc = subprocess.run(cmd_list, check=check)
3737
except subprocess.CalledProcessError:
3838
logging.error("Invocation failed")
3939
sys.exit(1)
4040
except FileNotFoundError:
4141
logging.error("Executable not found")
4242
sys.exit(1)
43+
return proc
4344

4445

4546
def configure_args(*args, **kwargs):
@@ -57,10 +58,10 @@ def configure_args(*args, **kwargs):
5758
return cmd
5859

5960

60-
def run_litani(litani, subcommand, *args, **kwargs):
61+
def run_litani(litani, subcommand, *args, check=True, **kwargs):
6162
cmd = [litani, subcommand]
6263
cmd.extend(configure_args(*args, **kwargs))
63-
run_cmd(cmd)
64+
return run_cmd(cmd, check)
6465

6566

6667
def get_test_module(module_file):
@@ -130,8 +131,24 @@ def set_jobs(litani, run_dir, mod):
130131
def run_build(litani, run_dir, mod):
131132
os.chdir(run_dir)
132133
args = mod.get_run_build_args()
133-
run_litani(
134-
litani, "run-build", *args.get("args", []), **args.get("kwargs", {}))
134+
proc = run_litani(
135+
litani, "run-build",
136+
*args.get("args", []), check=False, **args.get("kwargs", {}))
137+
138+
try:
139+
expected_rc = mod.get_run_build_return_code()
140+
if expected_rc != proc.returncode:
141+
logging.error(
142+
"Expected return code %d did not match actual "
143+
"return code %d", expected_rc, proc.returncode)
144+
sys.exit(1)
145+
except AttributeError:
146+
# test does not have a get_run_build_return_code method, so assume that
147+
# run-build is expected to succeed
148+
if proc.returncode:
149+
logging.error("Invocation failed")
150+
sys.exit(1)
151+
135152

136153

137154
def init(litani, run_dir, mod):

test/e2e/tests/exit_rc.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License").
4+
# You may not use this file except in compliance with the License.
5+
# A copy of the License is located at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
12+
# permissions and limitations under the License.
13+
14+
SLOW = False
15+
16+
def get_init_args():
17+
return {
18+
"kwargs": {
19+
"project": "foo",
20+
}
21+
}
22+
23+
24+
def get_jobs():
25+
return [{
26+
"kwargs": {
27+
"command": "false",
28+
"ci-stage": "build",
29+
"pipeline": "foo",
30+
"ignore_returns": "1",
31+
}
32+
}]
33+
34+
35+
def get_run_build_args():
36+
return {}
37+
38+
39+
def get_run_build_return_code():
40+
return 0
41+
42+
43+
def check_run(run):
44+
return True
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License").
4+
# You may not use this file except in compliance with the License.
5+
# A copy of the License is located at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# or in the "license" file accompanying this file. This file is distributed
10+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
12+
# permissions and limitations under the License.
13+
14+
SLOW = False
15+
16+
def get_init_args():
17+
return {
18+
"kwargs": {
19+
"project": "foo",
20+
}
21+
}
22+
23+
24+
def get_jobs():
25+
return [{
26+
"kwargs": {
27+
"command": "false",
28+
"ci-stage": "build",
29+
"pipeline": "foo",
30+
"ignore_returns": "1",
31+
}
32+
}]
33+
34+
35+
def get_run_build_args():
36+
return {
37+
"args": [
38+
"fail-on-pipeline-failure",
39+
]
40+
}
41+
42+
43+
def get_run_build_return_code():
44+
return 10
45+
46+
47+
def check_run(run):
48+
return True

0 commit comments

Comments
 (0)