telemachus.me

Git Can Break Automated Tests

2022-03-21

Did you know that git will sometimes silently change the line endings on files? I learned this yesterday, and now you can learn from my confusion.

Background

I recently contributed to a go tool that will format long lines. I was happy with my contribution (more on that in another post maybe), but unfortunately I broke the build on Windows. Someone else quickly contributed a fix for my mistake, and I asked the maintainer whether they would welcome a pull request to do cross-platform testing using GitHub Actions. That’s where the real story begins for us.

A Mystery

When I set up the GitHub action, I discovered that the current tests failed on Windows. To be clear, I don’t mean an edge-case failure. The test failures suggested that the tool shouldn’t work at all on Windows. This confused me since the tool clearly works on Windows. (People are using it there—you can tell from the immediate bug report that I just mentioned. Yet nobody had reported this complete failure.)

When I dug into the log of the failed tests, I quickly saw that the failures were about line endings. The tool uses LF for line endings, and the tests expected CRLF—but only on Windows. At first, however, I couldn’t figure out why the tests on Windows expected those line endings.

A bit more background: the failing tests compared the output of the tool to golden files. I had the golden files in my repository (on macOS), and I could confirm that they had LF rather than CRLF line endings. Nevertheless, the tests were failing, and the output of the failed tests made clear that the line endings were to blame. Why were the line endings in the testing environment different from my line endings but only on Windows?

Blame Git

As my title suggests, git was the culprit. git has a configuration setting core.autocrlf that controls how line endings are handled in a repository. (Actually, git has several configuration settings that affect line endings. There’s also core.eol and core.safecrlf. But core.autocrlf was to blame here.) On Windows, the default installation option for core.autocrlf is true, but for macOS and Linux, the default is false. When you test on Windows using GitHub Actions, the test environment has core.autocrlf set to true. As a result, when files are checked out by git, git will automatically change LF line endings into CRLF line endings. If some of those files are golden files, tests may fail.

For the record, GitHub is aware of this situation, but they feel that they are doing the right thing. See this discussion and this discussion. (To be clear, they may be absolutely right. The result was a pain for me, but that doesn’t mean GitHub is wrong.)

A Solution

Happily, you can fix this problem pretty easily. All you need to do is create a .gitattributes file and tell git not to tamper with the line endings of the test files. (You can also globally change how git handles line endings, but that may not be very kind to people who work on your project on Windows. That should probably be a group decision.)

In my case, the fix was as simple as this .gitattributes file. The tests pass, and all is well.

_fixtures/* text eol=lf

One More Warning

If you add a .gitattributes file, people who work with the repository on Windows may have one other problem. git may claim that there have been changes to files that the developers have not changed. That is simply git telling them that the line endings have changed on some files. There’s a fix for that too. Check out this link for details.

References