Skip to content

Commit 81ad9d1

Browse files
Log multiple lines, log tests, and logging bug fixes (#527)
## Overview Changes: - Log multiple lines Allow the `log` command (defined in `scripts/logging.include.sh`) to log messages that span multiple lines. This also adds unit tests for the `scripts/logging.include.sh` file. Fixes: - Logging bug fixes: - Setting `NO_COLOR` or setting `BIRDHOUSE_COLOR` to a non-integer value raised an error since `BIRDHOUSE_COLOR` was tested with the numeric comparison `-eq`. This has now been fixed. - Providing an invalid log message level (e.g. `log BADLEVEL message`) would log a critical error message but not exit unless the `set -o pipefail` option was set. This has been updated so that the script will exit as intended even if the `pipefail` option is not set. ## Changes **Non-breaking changes** - logging behaviour changes for multiline logs - bug fixes **Breaking changes** - None ## Related Issue / Discussion ## Additional Information Links to other issues or sources. ## CI Operations <!-- The test suite can be run using a different DACCS config with ``birdhouse_daccs_configs_branch: branch_name`` in the PR description. To globally skip the test suite regardless of the commit message use ``birdhouse_skip_ci`` set to ``true`` in the PR description. Using ``[<cmd>]`` (with the brackets) where ``<cmd> = skip ci`` in the commit message will override ``birdhouse_skip_ci`` from the PR description. Such commit command can be used to override the PR description behavior for a specific commit update. However, a commit message cannot 'force run' a PR which the description turns off the CI. To run the CI, the PR should instead be updated with a ``true`` value, and a running message can be posted in following PR comments to trigger tests once again. --> birdhouse_daccs_configs_branch: master birdhouse_skip_ci: false
2 parents f0b2698 + 71e6dbf commit 81ad9d1

File tree

10 files changed

+333
-52
lines changed

10 files changed

+333
-52
lines changed

.bumpversion.cfg

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 2.13.1
2+
current_version = 2.13.2
33
commit = True
44
tag = False
55
tag_name = {new_version}
@@ -30,11 +30,11 @@ search = {current_version}
3030
replace = {new_version}
3131

3232
[bumpversion:file:RELEASE.txt]
33-
search = {current_version} 2025-04-28T19:56:45Z
33+
search = {current_version} 2025-05-02T12:53:59Z
3434
replace = {new_version} {utcnow:%Y-%m-%dT%H:%M:%SZ}
3535

3636
[bumpversion:part:releaseTime]
37-
values = 2025-04-28T19:56:45Z
37+
values = 2025-05-02T12:53:59Z
3838

3939
[bumpversion:file(version):birdhouse/components/canarie-api/docker_configuration.py.template]
4040
search = 'version': '{current_version}'

CHANGES.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@
1717

1818
[//]: # (list changes here, using '-' for each new entry, remove this when items are added)
1919

20+
[2.13.2](https://github.com/bird-house/birdhouse-deploy/tree/2.13.2) (2025-05-02)
21+
------------------------------------------------------------------------------------------------------------------
22+
23+
## Changes
24+
25+
- Log multiple lines
26+
27+
Allow the `log` command (defined in `scripts/logging.include.sh`) to log messages that span multiple lines.
28+
This also adds unit tests for the `scripts/logging.include.sh` file.
29+
30+
## Fixes
31+
32+
- Logging bug fixes:
33+
34+
- Setting `NO_COLOR` or setting `BIRDHOUSE_COLOR` to a non-integer value raised an error since `BIRDHOUSE_COLOR`
35+
was tested with the numeric comparison `-eq`. This has now been fixed.
36+
37+
- Providing an invalid log message level (e.g. `log BADLEVEL message`) would log a critical error message but not
38+
exit unless the `set -o pipefail` option was set. This has been updated so that the script will exit as intended
39+
even if the `pipefail` option is not set.
40+
2041
[2.13.1](https://github.com/bird-house/birdhouse-deploy/tree/2.13.1) (2025-04-28)
2142
------------------------------------------------------------------------------------------------------------------
2243

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Generic variables
22
override SHELL := bash
33
override APP_NAME := birdhouse-deploy
4-
override APP_VERSION := 2.13.1
4+
override APP_VERSION := 2.13.2
55

66
# utility to remove comments after value of an option variable
77
override clean_opt = $(shell echo "$(1)" | $(_SED) -r -e "s/[ '$'\t'']+$$//g")

README.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ for a full-fledged production platform.
1818
* - citation
1919
- | |citation|
2020

21-
.. |commits-since| image:: https://img.shields.io/github/commits-since/bird-house/birdhouse-deploy/2.13.1.svg
21+
.. |commits-since| image:: https://img.shields.io/github/commits-since/bird-house/birdhouse-deploy/2.13.2.svg
2222
:alt: Commits since latest release
23-
:target: https://github.com/bird-house/birdhouse-deploy/compare/2.13.1...master
23+
:target: https://github.com/bird-house/birdhouse-deploy/compare/2.13.2...master
2424

25-
.. |latest-version| image:: https://img.shields.io/badge/tag-2.13.1-blue.svg?style=flat
25+
.. |latest-version| image:: https://img.shields.io/badge/tag-2.13.2-blue.svg?style=flat
2626
:alt: Latest Tag
27-
:target: https://github.com/bird-house/birdhouse-deploy/tree/2.13.1
27+
:target: https://github.com/bird-house/birdhouse-deploy/tree/2.13.2
2828

2929
.. |readthedocs| image:: https://readthedocs.org/projects/birdhouse-deploy/badge/?version=latest
3030
:alt: ReadTheDocs Build Status (latest version)

RELEASE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.13.1 2025-04-28T19:56:45Z
1+
2.13.2 2025-05-02T12:53:59Z

birdhouse/components/canarie-api/docker_configuration.py.template

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ SERVICES = {
108108
# NOTE:
109109
# Below version and release time auto-managed by 'make VERSION=x.y.z bump'.
110110
# Do NOT modify it manually. See 'Tagging policy' in 'birdhouse/README.rst'.
111-
'version': '2.13.1',
112-
'releaseTime': '2025-04-28T19:56:45Z',
111+
'version': '2.13.2',
112+
'releaseTime': '2025-05-02T12:53:59Z',
113113
'institution': '${BIRDHOUSE_INSTITUTION}',
114114
'researchSubject': '${BIRDHOUSE_SUBJECT}',
115115
'supportEmail': '${BIRDHOUSE_SUPPORT_EMAIL}',
@@ -141,8 +141,8 @@ PLATFORMS = {
141141
# NOTE:
142142
# Below version and release time auto-managed by 'make VERSION=x.y.z bump'.
143143
# Do NOT modify it manually. See 'Tagging policy' in 'birdhouse/README.rst'.
144-
'version': '2.13.1',
145-
'releaseTime': '2025-04-28T19:56:45Z',
144+
'version': '2.13.2',
145+
'releaseTime': '2025-05-02T12:53:59Z',
146146
'institution': '${BIRDHOUSE_INSTITUTION}',
147147
'researchSubject': '${BIRDHOUSE_SUBJECT}',
148148
'supportEmail': '${BIRDHOUSE_SUPPORT_EMAIL}',

birdhouse/scripts/logging.include.sh

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if [ -z "${BIRDHOUSE_COLOR}" ] && [ -z "${NO_COLOR}" ]; then
55
BIRDHOUSE_COLOR=1
66
fi
77

8-
if [ "${BIRDHOUSE_COLOR}" -eq "1" ]; then
8+
if [ "${BIRDHOUSE_COLOR}" = "1" ]; then
99
BLUE=$(tput setaf 12)
1010
GRAY=$(tput setaf 8)
1111
CYAN=$(tput setaf 6)
@@ -25,6 +25,7 @@ if [ "${BIRDHOUSE_BACKWARD_COMPATIBLE_ALLOWED}" = 'True' ] || [ "${__BIRDHOUSE_S
2525
# (this supports backwards compatible scripts that don't use the interface)
2626
BIRDHOUSE_LOG_DEST_OVERRIDE=${BIRDHOUSE_LOG_DEST_OVERRIDE:-"DEBUG:fd:1:INFO:fd:1:WARN:fd:2:ERROR:fd:2:CRITICAL:fd:2"}
2727
fi
28+
# These logging prefixes are right-padded with space characters to ensure that each prefix is a fixed width of 10 characters.
2829
export LOG_DEBUG="${GRAY}DEBUG${NORMAL}: "
2930
export LOG_INFO="${BLUE}INFO${NORMAL}: "
3031
export LOG_WARN="${YELLOW}WARNING${NORMAL}: "
@@ -58,7 +59,15 @@ export LOG_CRITICAL="${REG_BG_BOLD}CRITICAL${NORMAL}: " # to report misuse of f
5859
log_dest() {
5960
level=$1
6061
option=$2
61-
read log_line || true
62+
log_line=
63+
while IFS= read -r line; do
64+
if [ -z "${log_line}" ]; then
65+
log_line="$line"
66+
else
67+
# pad the next line by 10 space characters so that it aligns with the first line in the message.
68+
log_line="${log_line}\n ${line}"
69+
fi
70+
done
6271
if [ -n "${log_line}" ]; then
6372
log_quiet="${BIRDHOUSE_LOG_QUIET}"
6473
log_fd="${BIRDHOUSE_LOG_FD}"
@@ -84,12 +93,12 @@ log_dest() {
8493
done
8594
fi
8695
if [ "${log_quiet}" = "True" ]; then
87-
echo "$log_line" >> "${log_file:-/dev/null}"
96+
printf "${log_line}\n" >> "${log_file:-/dev/null}"
8897
else
8998
if [ -n "${log_file}" ]; then
90-
echo "$log_line" | tee -a "${log_file}" 1>&"${log_fd}"
99+
printf "${log_line}\n" | tee -a "${log_file}" 1>&"${log_fd}"
91100
else
92-
echo "$log_line" 1>&"${log_fd}"
101+
printf "${log_line}\n" 1>&"${log_fd}"
93102
fi
94103
fi
95104
fi
@@ -128,28 +137,26 @@ log() {
128137
echo "${LOG_CRITICAL}Invalid: log message is missing." | log_dest CRITICAL
129138
exit 2
130139
fi
131-
{
132-
case "${BIRDHOUSE_LOG_LEVEL}-${level}" in
133-
DEBUG-DEBUG)
134-
echo "${LOG_DEBUG}$*"
135-
;;
136-
DEBUG-INFO|INFO-INFO)
137-
echo "${LOG_INFO}$*"
138-
;;
139-
DEBUG-WARN|INFO-WARN|WARN-WARN)
140-
echo "${LOG_WARN}$*"
141-
;;
142-
*-ERROR)
143-
echo "${LOG_ERROR}$*"
144-
;;
145-
*-DEBUG|*-INFO|*-WARN)
146-
;;
147-
*)
148-
echo "${LOG_CRITICAL}Invalid log level: [${level}]" | log_dest CRITICAL
149-
exit 2
150-
;;
151-
esac
152-
} | log_dest ${level}
140+
case "${BIRDHOUSE_LOG_LEVEL}-${level}" in
141+
DEBUG-DEBUG)
142+
echo "${LOG_DEBUG}$*" | log_dest DEBUG
143+
;;
144+
DEBUG-INFO|INFO-INFO)
145+
echo "${LOG_INFO}$*" | log_dest INFO
146+
;;
147+
DEBUG-WARN|INFO-WARN|WARN-WARN)
148+
echo "${LOG_WARN}$*" | log_dest WARN
149+
;;
150+
*-ERROR)
151+
echo "${LOG_ERROR}$*" | log_dest ERROR
152+
;;
153+
*-DEBUG|*-INFO|*-WARN)
154+
;;
155+
*)
156+
echo "${LOG_CRITICAL}Invalid log level: [${level}]" | log_dest CRITICAL
157+
exit 2
158+
;;
159+
esac
153160
;;
154161
*)
155162
echo "${LOG_CRITICAL}Invalid log level setting: [BIRDHOUSE_LOG_LEVEL=${BIRDHOUSE_LOG_LEVEL}]." | log_dest CRITICAL

docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@
6969
# built documents.
7070
#
7171
# The short X.Y version.
72-
version = '2.13.1'
72+
version = '2.13.2'
7373
# The full version, including alpha/beta/rc tags.
74-
release = '2.13.1'
74+
release = '2.13.2'
7575

7676
# The language for content autogenerated by Sphinx. Refer to documentation
7777
# for a list of supported languages.

tests/unit/test_cli.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,70 +180,70 @@ def test_configs_set_env_file(cli_path, run, local_env_file, tmp_path, flag):
180180

181181
@pytest.mark.parametrize("flag", ["-s", "--log-stdout"])
182182
def test_log_stdout(cli_path, run, logging_script, flag):
183-
proc = run(f"{cli_path} {flag} compose", compose=logging_script)
183+
proc = run(f"{cli_path} {flag} compose", compose=logging_script, expect_error=True)
184184
check_log_output(DEFAULT_LOG_CHECK_LEVELS, proc.stdout)
185185

186186

187187
@pytest.mark.parametrize("flag", ["--log-file ", "-l ", "--log-file=", "-l="])
188188
def test_log_file(cli_path, run, flag, tmp_path, logging_script):
189189
log_path = tmp_path / "test.log"
190-
proc = run(f"{cli_path} {flag}{log_path} compose", compose=logging_script)
190+
proc = run(f"{cli_path} {flag}{log_path} compose", compose=logging_script, expect_error=True)
191191
with open(log_path) as f:
192192
check_log_output(DEFAULT_LOG_CHECK_LEVELS, f.read())
193193
check_log_output(DEFAULT_LOG_CHECK_LEVELS, proc.stderr)
194194
assert not proc.stdout
195195

196196

197197
def test_default_log_fd(cli_path, run, logging_script):
198-
proc = run(f"{cli_path} compose", compose=logging_script)
198+
proc = run(f"{cli_path} compose", compose=logging_script, expect_error=True)
199199
check_log_output(DEFAULT_LOG_CHECK_LEVELS, proc.stderr)
200200
assert not proc.stdout
201201

202202

203203
@pytest.mark.parametrize("flag", ["-q", "--quiet"])
204204
def test_log_quiet(cli_path, run, logging_script, flag):
205-
proc = run(f"{cli_path} {flag} compose", compose=logging_script)
205+
proc = run(f"{cli_path} {flag} compose", compose=logging_script, expect_error=True)
206206
assert not proc.stdout
207207

208208

209209
def test_log_file_stdout(cli_path, run, tmp_path, logging_script):
210210
log_path = tmp_path / "test.log"
211-
proc = run(f"{cli_path} -l {log_path} -s compose", compose=logging_script)
211+
proc = run(f"{cli_path} -l {log_path} -s compose", compose=logging_script, expect_error=True)
212212
with open(log_path) as f:
213213
check_log_output(DEFAULT_LOG_CHECK_LEVELS, f.read())
214214
check_log_output(DEFAULT_LOG_CHECK_LEVELS, proc.stdout)
215215

216216

217217
def test_log_file_quiet(cli_path, run, tmp_path, logging_script):
218218
log_path = tmp_path / "test.log"
219-
proc = run(f"{cli_path} -l {log_path} -q compose", compose=logging_script)
219+
proc = run(f"{cli_path} -l {log_path} -q compose", compose=logging_script, expect_error=True)
220220
with open(log_path) as f:
221221
check_log_output(DEFAULT_LOG_CHECK_LEVELS, f.read())
222222
assert not proc.stdout
223223

224224

225225
@pytest.mark.parametrize("flag", ["-L ", "--log-level ", "-L=", "--log-level="])
226226
def test_log_level_flags(cli_path, run, logging_script, flag):
227-
proc = run(f"{cli_path} {flag}DEBUG compose", compose=logging_script)
227+
proc = run(f"{cli_path} {flag}DEBUG compose", compose=logging_script, expect_error=True)
228228
check_log_output(LOG_CHECK_LEVELS, proc.stderr)
229229

230230

231231
@pytest.mark.parametrize("level", LOG_LEVELS)
232232
def test_log_level(cli_path, run, logging_script, level):
233-
proc = run(f"{cli_path} -L {level} compose", compose=logging_script)
233+
proc = run(f"{cli_path} -L {level} compose", compose=logging_script, expect_error=True)
234234
check_log_output(LOG_CHECK_LEVELS[LOG_CHECK_LEVELS.index(level) :], proc.stderr)
235235

236236

237237
@pytest.mark.parametrize("level", LOG_LEVELS)
238238
def test_log_override_stdout(cli_path, run, logging_script, level):
239-
proc = run(f"{cli_path} -L DEBUG -s {level} compose", compose=logging_script)
239+
proc = run(f"{cli_path} -L DEBUG -s {level} compose", compose=logging_script, expect_error=True)
240240
check_log_output([level_ for level_ in LOG_CHECK_LEVELS if level_ != level], proc.stderr)
241241
check_log_output([level], proc.stdout)
242242

243243

244244
@pytest.mark.parametrize("level", LOG_LEVELS)
245245
def test_log_override_quiet(cli_path, run, logging_script, level):
246-
proc = run(f"{cli_path} -L DEBUG -q {level} compose", compose=logging_script)
246+
proc = run(f"{cli_path} -L DEBUG -q {level} compose", compose=logging_script, expect_error=True)
247247
check_log_output([level_ for level_ in LOG_CHECK_LEVELS if level_ != level], proc.stderr)
248248
check_log_output([], proc.stdout)
249249

@@ -254,6 +254,7 @@ def test_log_override_file(cli_path, run, logging_script, tmp_path, level):
254254
proc = run(
255255
f"{cli_path} -L DEBUG -l {level} {log_file} compose",
256256
compose=logging_script,
257+
expect_error=True,
257258
)
258259
with open(log_file) as f:
259260
check_log_output([level], f.read())
@@ -265,6 +266,7 @@ def test_configs_log_override_multiple(cli_path, run, logging_script, tmp_path):
265266
proc = run(
266267
f"{cli_path} -L DEBUG -l DEBUG {log_file} -s INFO " f"-q WARN -l ERROR {log_file} -q ERROR compose",
267268
compose=logging_script,
269+
expect_error=True,
268270
)
269271
check_log_output(["DEBUG"], proc.stderr)
270272
check_log_output(["INFO"], proc.stdout)
@@ -278,6 +280,7 @@ def test_configs_log_override_file_default(cli_path, run, logging_script, tmp_pa
278280
proc = run(
279281
f"{cli_path} -L DEBUG -l {log_file} -l ERROR {error_log_file} compose",
280282
compose=logging_script,
283+
expect_error=True,
281284
)
282285
check_log_output(LOG_LEVELS, proc.stderr)
283286
with open(log_file) as f:

0 commit comments

Comments
 (0)