[CI] Support `FORCE_COLOR` env var; enable colors in CPU CI output (#56913)
Signed-off-by: Nick Hill <nickhill123@gmail.com>
Nick Hill committed
Sep 16, 2026 at 19:40 UTC
5efbf0886a7110ae0801b9540e3072e89a23eb36
5 files changed
+30
-3
.buildkite/scripts/hardware_ci/run-cpu-test-arm.sh
+1
-1
@@ -30,7 +30,7 @@ remove_docker_container
30
docker pull "$IMAGE"
31
32
# Run the image
33
-docker run -itd --cpuset-cpus="$CORE_RANGE" --entrypoint /bin/bash -v ~/.cache/huggingface:/root/.cache/huggingface -e HF_TOKEN --env VLLM_CPU_KVCACHE_SPACE=16 --env VLLM_CPU_CI_ENV=1 -e E2E_OMP_THREADS="$OMP_CORE_RANGE" --shm-size=4g --name "$CONTAINER_NAME" "$IMAGE"
33
+docker run -itd --cpuset-cpus="$CORE_RANGE" --entrypoint /bin/bash -v ~/.cache/huggingface:/root/.cache/huggingface -e HF_TOKEN --env VLLM_CPU_KVCACHE_SPACE=16 --env VLLM_CPU_CI_ENV=1 -e E2E_OMP_THREADS="$OMP_CORE_RANGE" -e TERM=xterm-256color -e PY_COLORS=1 -e FORCE_COLOR=1 -e CLICOLOR_FORCE=1 --shm-size=4g --name "$CONTAINER_NAME" "$IMAGE"
34
35
print_packages() {
36
docker exec "$CONTAINER_NAME" bash -c "
.buildkite/scripts/hardware_ci/run-cpu-test.sh
+1
-1
@@ -99,7 +99,7 @@ rm -f "$build_log"
99
OFFLINE_RETRY_PATTERN='huggingface_hub\.errors\.(LocalEntryNotFoundError|OfflineModeIsEnabled)|Invalid repository ID or local directory specified|Cannot find any model weights with'
100
run_test() {
101
local hf_offline=$1
102
- docker run --rm --cpuset-cpus="$CORE_RANGE" --cpuset-mems="$NUMA_NODE" -v ~/.cache/huggingface:/root/.cache/huggingface -v ~/.cache/vllm:/root/.cache/vllm --privileged=true -e HF_TOKEN -e VLLM_CPU_KVCACHE_SPACE=16 -e VLLM_CPU_CI_ENV=1 -e VLLM_CPU_SIM_MULTI_NUMA=1 -e VLLM_CPU_ATTN_SPLIT_KV=0 -e HF_HUB_OFFLINE="$hf_offline" -e HF_DATASETS_OFFLINE="$hf_offline" --shm-size=4g "$IMAGE_NAME" \
102
+ docker run --rm --cpuset-cpus="$CORE_RANGE" --cpuset-mems="$NUMA_NODE" -v ~/.cache/huggingface:/root/.cache/huggingface -v ~/.cache/vllm:/root/.cache/vllm --privileged=true -e HF_TOKEN -e VLLM_CPU_KVCACHE_SPACE=16 -e VLLM_CPU_CI_ENV=1 -e VLLM_CPU_SIM_MULTI_NUMA=1 -e VLLM_CPU_ATTN_SPLIT_KV=0 -e HF_HUB_OFFLINE="$hf_offline" -e HF_DATASETS_OFFLINE="$hf_offline" -e TERM=xterm-256color -e PY_COLORS=1 -e FORCE_COLOR=1 -e CLICOLOR_FORCE=1 --shm-size=4g "$IMAGE_NAME" \
103
timeout "$TIMEOUT_VAL" bash -c "set -euox pipefail; echo \"--- Print packages\"; pip list; echo \"--- Running tests\"; ${TEST_COMMAND}"
104
}
105
tests/test_logger.py
+23
@@ -1,6 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
import enum
4
+import io
5
import json
6
import logging
7
import os
@@ -19,6 +20,7 @@ from vllm.logger import (
20
_DATE_FORMAT,
21
_FORMAT,
22
_configure_vllm_root_logger,
23
+ _use_color,
24
enable_trace_function_call,
25
init_logger,
26
)
@@ -72,6 +74,27 @@ def test_default_vllm_root_logger_configuration(monkeypatch):
74
assert formatter.datefmt == _DATE_FORMAT
75
76
77
+def test_use_color_force_color(monkeypatch):
78
+ """FORCE_COLOR forces colored logs without a TTY, while NO_COLOR and an
79
+ explicit VLLM_LOGGING_COLOR=0 take precedence over it."""
80
+ monkeypatch.setattr(sys, "stdout", io.StringIO())
81
+ monkeypatch.setattr(sys, "stderr", io.StringIO())
82
+ for var in ("NO_COLOR", "FORCE_COLOR", "VLLM_LOGGING_COLOR"):
83
+ monkeypatch.delenv(var, raising=False)
84
+
85
+ assert not _use_color()
86
+
87
+ monkeypatch.setenv("FORCE_COLOR", "1")
88
+ assert _use_color()
89
+
90
+ monkeypatch.setenv("VLLM_LOGGING_COLOR", "0")
91
+ assert not _use_color()
92
+ monkeypatch.delenv("VLLM_LOGGING_COLOR")
93
+
94
+ monkeypatch.setenv("NO_COLOR", "1")
95
+ assert not _use_color()
96
+
97
+
98
def test_descendent_loggers_depend_on_and_propagate_logs_to_root_logger(monkeypatch):
99
"""This test presumes that VLLM_CONFIGURE_LOGGING (default: True) and
100
VLLM_LOGGING_CONFIG_PATH (default: None) are not configured and default
vllm/envs.py
+4
@@ -44,6 +44,7 @@ if TYPE_CHECKING:
44
VLLM_LOGGING_CONFIG_PATH: str | None = None
45
VLLM_LOGGING_COLOR: str = "auto"
46
NO_COLOR: bool = False
47
+ FORCE_COLOR: bool = False
48
VLLM_LOG_STATS_INTERVAL: float = 10.0
49
VLLM_TRACE_FUNCTION: int = 0
50
VLLM_USE_FLASHINFER_SAMPLER: bool = True
@@ -840,6 +841,8 @@ environment_variables: dict[str, Callable[[], Any]] = {
841
"VLLM_LOGGING_COLOR": lambda: os.getenv("VLLM_LOGGING_COLOR", "auto"),
842
# Standard unix flag for disabling ANSI color codes
843
"NO_COLOR": lambda: os.getenv("NO_COLOR", "0") != "0",
844
+ # De-facto standard flag for forcing ANSI color codes (e.g. non-tty case)
845
+ "FORCE_COLOR": lambda: os.getenv("FORCE_COLOR", "0") != "0",
846
# If set, vllm will log stats at this interval in seconds
847
# If not set, vllm will log stats every 10 seconds.
848
"VLLM_LOG_STATS_INTERVAL": lambda: (
@@ -2335,6 +2338,7 @@ def compile_factors() -> dict[str, object]:
2338
"CUDA_VISIBLE_DEVICES",
2339
"NO_COLOR",
2340
"VLLM_SKIP_VERSION_SUFFIX",
2341
+ "FORCE_COLOR",
2342
}
2343
2344
from vllm.config.utils import normalize_value
vllm/logger.py
+1
-1
@@ -29,7 +29,7 @@ _DATE_FORMAT = "%m-%d %H:%M:%S"
29
def _use_color() -> bool:
30
if envs.NO_COLOR or envs.VLLM_LOGGING_COLOR == "0":
31
return False
32
- if envs.VLLM_LOGGING_COLOR == "1":
32
+ if envs.VLLM_LOGGING_COLOR == "1" or envs.FORCE_COLOR:
33
return True
34
if envs.VLLM_LOGGING_STREAM == "ext://sys.stdout": # stdout
35
return hasattr(sys.stdout, "isatty") and sys.stdout.isatty()