Everybody makes mistakes because we are human. However, making a mistake is not necessarily a bad thing. The best kind of mistake is the kind which enables you to learn something. When that happens, usually an A-HA moment occurs. Some of these moments come from small mistakes which cause trouble. I have recently had the chance to make some mistakes, and even though they were small they caused quite a scare. But, I have learnt from them and I'd like to share them, so others might learn from it.
process.env.SURPRISE
One of my recent projects required me to develop a full-stack application using Angular on the front-end and Node on the back-end. I chose NestJS as my back-end framework, and I loved every moment of using it. The application used PostgreSQL as its database and we've decided to use typeOrm
for speeding up the process.
Everything worked fine, the typeOrm
configuration came from environment variables, but to make local development easier, the environment.ts file was populated with the sync
parameter set to false. However, after some time, when there were some changes in the DB schemas, suddenly the deployed application did not start.
We restarted the deploy process a couple of times, and we added more and more debug logs to the application. We realised that our API could not start because typeOrm
tried to do changes in the DB but it failed. So everything pointed to mistakes made in the dev.env
file. The file contained the following:
// ...
TYPEORM_SYNC=false
Boy, I was confused! Then I put a debug log into the application to log the configuration. That is when I saw that the typeOrm
configuration had the sync
property equal 'false'
. Yes, as you can see it was a string, which was truthy. After a huge facepalm and a proper parsing of the environment variables, the deploy worked again.
Lesson learned: Log the non-sensitive configurations in debug mode in a development environment, so you can understand parse errors from the logs and process.env parses values as strings. Since this issue, I always double-check these variables.
It works in Chrome
I don't mean to sound old, but some of you will never know the struggle of hardcore cross-browser compatibility issues. I had the "luck" to work on projects which needed to support IE9, but not for long. It wasn't easy, but we've managed. Several years (and projects) later I am lucky to live in a world of evergreen browsers. Which is good, because caniuse.com is a great source of information, and the ever-changing browsers usually support the cool stuff which makes our jobs easy.
Maybe that is why this mistake I made took a toll on me. I am a huge fan of testing. I do my best to write automated unit tests and test my apps at least on a functional level using Cypress. But I develop mostly on Chrome, and since most of my projects were enterprise applications for back-office users, browser compatibility did not matter that much. I always knew that what I do in Chrome will work in Firefox. I knew this because in the previous years I have checked every edge case that indicated, that something works differently in Firefox. Also, the requirements always state that Chrome is a must.
So here's what happened. I have worked on a public-facing application with my colleagues. We did extensive unit testing and Cypress functional testing. A lot. I'm not kidding, we have even thought about introducing screenshot comparator tests. Then we've released it. And the customer sent us an angry e-mail telling us that it looks extremely ugly...
On Safari. Some parts of our code used flex: 1 1 0
and those parts were broken on Safari. I have a Macbook pro, and I made the mistake of not opening our application even once in one of the evergreen browsers.
You can imagine, our customer was quite angry. It was pure luck that it was an easy fix, but I have decided that never again should this mistake occur. Every time a change has been made on the UI, I manually open it in Safari. I even plan to buy myself an iPhone just to be able to test it natively.
Check the tooling
I have recently been asked to consult on a project with an Angular Front-End. Before the NDA I was told that the app is in Angular 9. So when I was able to check out the project I noticed that something was off. The project itself was not in good shape, and all the tests were missing. Well, not all, there were 15 unit tests generated with components, and they were all failing.
So naturally, my first task was to plug in the linter, so formatting the code would at least give me some perspective of the type of errors I might face in the future. At that point I saw in the package.json that the angular version was indeed 9.0.0, however, all the tooling was still on 8.x.x... So what could go wrong, right? I updated the tooling to leverage it, and I saw that everything works. The project starts up in serve mode, so after carefully double-checking everything I committed and pushed.
Then the build pipeline broke and the console filled with ngcc
errors. So after the initial scare, and thinking about reverting immediately I took a deep breath, carefully read the error description and started googling. The angular documentation helped me out again. At the 'Opting out of Ivy in version 9' section I found the flag that fixed all my problems:
{
"angularCompilerOptions": {
"enableIvy": false
}
}
I am glad Angular comes with fallback for projects that don't have their workflows set up to follow standards. So I have learned an important lesson. Whenever I play around with the package.json (or anything really) in a new project, first I must run everything according to the project's build setup.
Thinking in the fourth dimension, or at least with timezones
"Marty! You're not thinking fourth-dimensionally!"
While I love movies with time travel, I am usually terrified of date/time issues in production. Recently we have developed a food ordering web application for a client. The rule was to display next week's schedule after Friday 14:00. Not a hard thing, it could be done with a few lines of code and since on the back-end, I didn't have to care about bundle size that much, I even used momentjs
to make my job easier.
So the logic got implemented, with lots of unit tests and Cypress tests. Using cy.clock()
was fun, so we could even test scenarios involving the first week of next year, and the same with a leap year, etc. So everything worked, and the tests ran on the CI pipeline as well.
Then came the production release on a Monday. We've eagerly waited until Friday 14:00, and we've checked if the menu would change properly. At Friday 14:00 nothing happened, it did not change. Boy, we got scared, because that meant that people can still order food items that should not be available. It worked on our development environment properly, and the tests were running still. So what went wrong?
At Friday 16:00 the next schedule appeared. We've started checking the logs. It took some time putting 2 and 2 together and noticing that the production logs are 2 hours before the actual time. Well, my local time to be precise. The production server was in GMT timezone, and everything else was in CEST.
My big take-away is that I should always check the server time, and when the server starts up, log it properly, but most importantly:
Keep an environment as close to the production environment as possible. Make it a shadow environment, it could be useful to use a database with similar data to production. You can make a backup and anonymise the data if you work with sensitive information. But keep a prod-like environment, so you can catch errors before you deploy.
I hope you like my stories, and if you face a similar problem, learn from my mistakes. Do you have similar stories? Let me know!
Top comments (0)