GitHub Actions, nix-shell and coloured output

GitHub Action logs show pretty coloured output.

When executing a project’s tests in a GHA with nix-shell --run <our test suite>, the output is monochromatic. Doing exactly the same locally, I get pretty colours in the test output.

The monochromatic test output on the GHA makes me really appreciate the colours: I want them back!

How can I persuade nix-shell to pick up whatever it is in the GHA environment that makes the colours appear?

Curious about this as well. I have some CI jobs that run color-using nix-shell demos, and one of the downsides I’ve found about moving to GA from travis-ci is losing that colored output.

Typically I see test suites look at TERM to decide if the can output color. I’d print that out, outside and inside your shell to see what’s going on.

This may not be a perfect proxy for the OP’s case since I just stuck it in a nix-build.

Outside of the execution (i.e., as an entry in the .yml), it is dumb, but inside my test.sh (running inside the nix-build) it is xterm-256color as I’d expect.

Hmm, I seem to get dumb both inside and outside:

- name: Check $TERM outside nix-shell
  run: echo $TERM
- name: Check $TERM inside nix-shell
  run: nix-shell --run "echo $TERM"

gives the outputs

Run echo $TERM
  echo $TERM
  shell: /bin/bash -e {0}
  env:
    NIX_PATH: nixpkgs=channel:nixos-unstable
dumb

and

Run nix-shell --run "echo $TERM"
  nix-shell --run "echo $TERM"
  shell: /bin/bash -e {0}
  env:
    NIX_PATH: nixpkgs=channel:nixos-unstable
[... irrelevant noise ...]
dumb

FWIW, my test runner is pytest. I guess I should try running it outside of the nix-shell and see if it produces any colour.

pytest showed no colours in the GitHub action, both outside and inside the nix-shell.

In the case of pytest I have managed to get around the problem with

nix-shell --run "PYTEST_ADDOPTS=--color=yes <run my tests>"
1 Like

As hinted, I’d try:

...
runs-on: ubuntu-latest
env:
  TERM: xterm-256color
1 Like

That seems to result in monochrome pytest output.

I don’t know if this would be helpful, but I recently reviewed a change to a library that tries to smartly determine whether to print in color or not.

Basically, the fix was to look at the output file descriptor for whether it is a terminal device. If it is, then print in color. If it is not, then don’t print in color.

Here’s the line in question:

Here’s the library function:

https://hackage.haskell.org/package/base-4.14.1.0/docs/System-IO.html#v:hIsTerminalDevice

I’m not actually sure what function is being called under the hood, but my guess is something like isatty():

https://rosettacode.org/wiki/Check_output_device_is_a_terminal#C


It could be that GitHub Actions is redirecting output in some way that isatty() doesn’t return the same thing that you were seeing on TravisCI. Although it seems like you’ve figured out that forcing color output works.

I poked at this a little bit, and it seems like:

It doesn’t look like GA has any short run plan to change this, so it seems like the “solution” is for Nix commands to have a flag or env that explicitly enables passing through escapes. (see also: https://no-color.org)

With the caveat that I don’t know exactly why travis-ci and GA disagree here and realize they may have some compelling reasons, it strikes me as incredibly sad/stupid that every person/team/project who encounters this has to waste time understanding the issue, hunting down which tool in their toolchain is eating the sequences, and fiddling flags/envs (or filing issues…)

2 Likes