Skip to content

Commit 1307f03

Browse files
committed
Bump version to 1.26.0
2 parents ee931df + 5805f3d commit 1307f03

23 files changed

+1137
-826
lines changed

.github/actions/build/action.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ runs:
1717
- name: Setup directory for deb package
1818
run: |
1919
echo ${{ inputs.version }}
20+
sudo apt-get update
2021
sudo apt-get install -y mandoc scdoc ninja-build
2122
mkdir -p litani-${{ inputs.version }}/{DEBIAN,usr/{bin,libexec/litani,share/{doc/litani,man/{man1,man5,man7}}}}
2223
touch litani-${{ inputs.version }}/DEBIAN/control

.github/workflows/run-tests.yaml

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,30 @@ jobs:
99
test-litani:
1010
if: "!contains(github.event.pull_request.labels.*.name, 'no-test')"
1111
name: Run Litani Tests
12-
runs-on: macos-latest
12+
runs-on: ubuntu-latest
1313
steps:
1414
- uses: actions/checkout@v2
1515
- name: Install dependencies
1616
run: |
17-
brew install ninja
17+
sudo apt-get install -y ninja-build
1818
python3 -m pip install jinja2
1919
2020
- name: Run Unit and e2e tests
21-
run: ./test/run
22-
continue-on-error: true
23-
timeout-minutes: 5
21+
run: |
22+
./test/run
23+
exit $?
2424
25-
- name: Get absolute path to report dir
26-
run: echo "REPORT_PATH=$(readlink test/output/latest/html)" >> $GITHUB_ENV
25+
test-build-documentation:
26+
name: Test Build Documentation
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v3
30+
- name: Install dependencies
31+
run: |
32+
sudo apt-get update
33+
sudo apt-get install -y mandoc scdoc ninja-build
2734
28-
- name: Upload report as artifact
29-
uses: actions/upload-artifact@main
30-
if: always()
31-
with:
32-
name: Report
33-
path: ${{ env.REPORT_PATH }}
35+
- name: Test Documentation
36+
run: |
37+
./doc/configure
38+
ninja

CHANGELOG

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
11
CHANGELOG
22
`````````
33

4+
Version 1.26.0 -- 2022-05-18
5+
----------------------------
6+
7+
This release fixes an important bug and contains several other fixes
8+
and improvements.
9+
10+
- Fix incorrect RC with --fail-on-pipeline-failure
11+
12+
This fixes an important bug in --fail-on-pipeline-failure. Prior to
13+
this commit, litani run-build would only terminate abnormally with
14+
this flag set when ninja terminated abnormally. This commit fixes
15+
this behavior so that litani run-build instead checks whether any
16+
pipeline failed, and terminates abnormally if so.
17+
18+
When using --fail-on-pipeline-failure, `litani run-build` will now
19+
terminate with an exit code of 0 if all pipelines passed, and 10 if
20+
at least one of them failed.
21+
22+
- Fix litani(7) HTML documentation and improve font size and choice
23+
24+
25+
26+
427
Version 1.25.0 -- 2022-05-18
528
----------------------------
629
- Fix litani run.json and litani outcome-table.json man pages

doc/bin/build-html-doc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ def get_manual(man, man_html_dir):
5757
"body": [],
5858
"chapter": get_chapter(man_html_dir / man.name),
5959
}
60+
if record["title"] == "litani.7":
61+
record["title"] = "litani"
6062
with open(man) as handle:
6163
for line in handle:
6264
record["body"].append(line.rstrip())

doc/src/man/litani-run-build.scdoc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ parallel.
6666

6767
# RETURN CODE
6868

69-
Unless there was a crash, this program should return _0_ upon exit
70-
unless the *--fail-on-pipeline-failure* flag was supplied. In that case,
71-
this program will return _0_ if all pipelines were successful and _1_
72-
otherwise.
69+
This program will return _1_ if it terminates abnormally. On normal
70+
termination:
71+
72+
- If the *--fail-on-pipeline-failure* flag was passed, this program will
73+
return _0_ if all pipelines were successful and _10_ otherwise.
74+
- Otherwise, this program will always return _0_ upon normal
75+
termination, regardless of the pipelines' success or failure.

doc/templates/index.jinja.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@
5656
padding-left: 1em;
5757
}
5858
body {
59-
line-height: 24pt;
6059
margin: 0;
6160
font-family: Helvetica, sans-serif;
62-
font-size: 16pt;
61+
font-size: 12pt;
62+
line-height: 14pt;
6363
color: #3d4d53;
6464
background-color: #fdf6e3;
6565
letter-spacing: 1px;
@@ -92,7 +92,7 @@
9292
color: #fdf6e3; background-color: #859900;
9393
}
9494
code {
95-
font-size: 13pt;
95+
font-size: 10pt;
9696
}
9797
pre br {
9898
display: block;
@@ -137,6 +137,7 @@
137137
min-height: 2em;
138138
}
139139
#corner-email {
140+
z-index: 2;
140141
font-family: Helvetica;
141142
font-weight: bold;
142143
letter-spacing: 2px;
@@ -353,8 +354,8 @@
353354
padding-top: 0.0em;
354355
}
355356
h1 {
356-
font-size: 48pt;
357-
line-height: 48pt;
357+
font-size: 33pt;
358+
line-height: 54pt;
358359
text-align: center;
359360
}
360361
}

lib/capabilities.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@
3636
}
3737

3838

39+
def add_subparser(subparsers):
40+
caps_pars = subparsers.add_parser("print-capabilities",
41+
help="Print out Litani's capabilities in a list")
42+
caps_pars.set_defaults(func=dump)
43+
for arg in [{
44+
"flags": ["-r", "--human-readable"],
45+
"help": "also print out capabilities with their descriptions",
46+
"action": "store_true"
47+
}]:
48+
flags = arg.pop("flags")
49+
caps_pars.add_argument(*flags, **arg)
50+
51+
3952
def _human_readable_dump():
4053
longest_capability = 0
4154
for capability in _CAPABILITIES:

lib/exec.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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+
import __main__
15+
16+
import json
17+
import logging
18+
import os
19+
import pathlib
20+
import shutil
21+
import shlex
22+
import sys
23+
24+
from lib import litani
25+
import lib.jobs
26+
import lib.output_artifact
27+
import lib.util
28+
29+
30+
def get_exec_job_args():
31+
exec_job_args = list(lib.jobs.get_add_job_args())
32+
exec_job_args.append((
33+
"`litani exec`-specific flags", [{
34+
"flags": ["--status-file"],
35+
"metavar": "F",
36+
"required": True,
37+
"help": "JSON file to write command status to",
38+
}, {
39+
"flags": ["--job-id"],
40+
"metavar": "ID",
41+
"required": True,
42+
"help": "the globally unique job ID",
43+
}]))
44+
return exec_job_args
45+
46+
47+
def add_subparser(subparsers):
48+
exec_job_pars = subparsers.add_parser("exec")
49+
exec_job_pars.set_defaults(func=exec_job)
50+
for group_name, args in get_exec_job_args():
51+
group = exec_job_pars.add_argument_group(title=group_name)
52+
for arg in args:
53+
flags = arg.pop("flags")
54+
group.add_argument(*flags, **arg)
55+
56+
57+
def make_litani_exec_command(add_args):
58+
cmd = [os.path.realpath(__main__.__file__), "exec"]
59+
# strings
60+
for arg in [
61+
"command", "pipeline_name", "ci_stage", "cwd", "job_id",
62+
"stdout_file", "stderr_file", "description", "timeout",
63+
"status_file", "outcome_table", "pool",
64+
"profile_memory_interval",
65+
]:
66+
if arg in add_args and add_args[arg]:
67+
cmd.append("--%s" % arg.replace("_", "-"))
68+
cmd.append(shlex.quote(str(add_args[arg]).strip()))
69+
70+
# lists
71+
for arg in [
72+
"inputs", "outputs", "ignore_returns", "ok_returns",
73+
"tags", "phony_outputs",
74+
]:
75+
if arg not in add_args or add_args[arg] is None:
76+
continue
77+
cmd.append("--%s" % arg.replace("_", "-"))
78+
for item in add_args[arg]:
79+
cmd.append(shlex.quote(str(item).strip()))
80+
81+
# switches
82+
for arg in [
83+
"timeout_ignore", "timeout_ok", "interleave_stdout_stderr",
84+
"profile_memory",
85+
]:
86+
if arg in add_args and add_args[arg]:
87+
cmd.append("--%s" % arg.replace("_", "-"))
88+
89+
return " ".join(cmd)
90+
91+
92+
async def exec_job(args):
93+
args_dict = vars(args)
94+
args_dict.pop("func")
95+
out_data = {
96+
"wrapper_arguments": args_dict,
97+
"complete": False,
98+
}
99+
lib.util.timestamp("start_time", out_data)
100+
with litani.atomic_write(args.status_file) as handle:
101+
print(json.dumps(out_data, indent=2), file=handle)
102+
103+
run = lib.process.Runner(
104+
args.command, args.interleave_stdout_stderr, args.cwd,
105+
args.timeout, args.profile_memory, args.profile_memory_interval,
106+
args_dict["job_id"])
107+
await run()
108+
lib.job_outcome.fill_in_result(run, out_data, args)
109+
110+
for out_field, proc_pipe, arg_file in [
111+
("stdout", run.get_stdout(), args.stdout_file),
112+
("stderr", run.get_stderr(), args.stderr_file)
113+
]:
114+
if proc_pipe:
115+
out_data[out_field] = proc_pipe.splitlines()
116+
else:
117+
out_data[out_field] = []
118+
119+
if arg_file:
120+
out_str = proc_pipe if proc_pipe else ""
121+
with litani.atomic_write(arg_file) as handle:
122+
print(out_str, file=handle)
123+
124+
if out_data["stderr"]:
125+
print(
126+
"\n".join([l.rstrip() for l in out_data["stderr"]]),
127+
file=sys.stderr)
128+
129+
lib.util.timestamp("end_time", out_data)
130+
out_str = json.dumps(out_data, indent=2)
131+
logging.debug("run status: %s", out_str)
132+
with litani.atomic_write(args.status_file) as handle:
133+
print(out_str, file=handle)
134+
135+
artifacts_dir = (litani.get_artifacts_dir() /
136+
out_data["wrapper_arguments"]["pipeline_name"] /
137+
out_data["wrapper_arguments"]["ci_stage"])
138+
artifacts_dir.mkdir(parents=True, exist_ok=True)
139+
140+
copier = lib.output_artifact.Copier(
141+
artifacts_dir, out_data["wrapper_arguments"])
142+
for fyle in out_data["wrapper_arguments"]["outputs"] or []:
143+
try:
144+
copier.copy_output_artifact(fyle)
145+
except lib.output_artifact.MissingOutput:
146+
logging.warning(
147+
"Output file '%s' of pipeline '%s' did not exist upon job "
148+
"completion. Not copying to artifacts directory. "
149+
"If this job is not supposed to emit the file, pass "
150+
"`--phony-outputs %s` to suppress this warning", fyle,
151+
out_data["wrapper_arguments"]["pipeline_name"], fyle)
152+
except IsADirectoryError:
153+
artifact_src = pathlib.Path(fyle)
154+
try:
155+
shutil.copytree(
156+
fyle, str(artifacts_dir / artifact_src.name))
157+
except FileExistsError:
158+
logging.warning(
159+
"Multiple files with same name in artifacts directory")
160+
161+
sys.exit(out_data["wrapper_return_code"])

lib/graph.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@
2222
import lib.litani_report
2323

2424

25+
def add_subparser(subparsers):
26+
graph_pars = subparsers.add_parser("graph")
27+
graph_pars.set_defaults(func=print_graph)
28+
for arg in [{
29+
"flags": ["-p", "--pipelines"],
30+
"help": "only display the graph for these pipelines (default: all)",
31+
"nargs": "+",
32+
"metavar": "P",
33+
}]:
34+
flags = arg.pop("flags")
35+
graph_pars.add_argument(*flags, **arg)
36+
2537

2638
class Node:
2739
@staticmethod

0 commit comments

Comments
 (0)