Lesson Description

The "Deployment" Lesson is part of the full, Build a Fullstack Next.js App, v4 course featured in this preview video. Here's what you'd learn in this lesson:

Brian covers setting up deployments, CI/CD, preview environments, observability, and analytics with Vercel and GitHub Actions. He demonstrates running unit and end-to-end tests to gate deployments, updating the project to v4, configuring testing directories, and using `.env` files to separate environments. Brian also explains creating isolated test branches in Neon to safely manipulate data without affecting production.

Preview

Transcript from the "Deployment" Lesson

[00:00:00]
>> Brian Holt: I know you were just craving some DevOps in your life, some more Next.js, some more Brian Holt. No, I'm just kidding, that part was probably definitely not true. Let's go talk about how to essentially get your app from I have built this thing to getting out to production. You can call this DevOps, you can call this, you know, whatever you want, but we are going to use Vercel to do this, we're going to use GitHub Actions, it'll be pretty cool.

[00:00:32]
I'm going to do a pretty basic pipeline here, and I'll give you some ways that you could go and figure out how to do some more kind of extended ways to do this, but I mean, my goal here is to kind of try and keep this cheap for you while you're learning it, because otherwise you have to start paying new services quite a bit of money to get all their kind of more enterprisey deploying kind of features.

[00:00:54]
Yeah, we're going to set up deployments, we're going to set up CI/CD, we're going to set up some preview environments and we'll also do some of our observability and some analytics. And luckily, the only additional service we're going to need here is GitHub, because Vercel handles a lot of this stuff for you, for specifically Next.js apps. OK, so one, you do have to get on the 09 with tests checkpoint.

[00:01:25]
So please leave your 08 AI1 behind and change this 09 with tests. Reason being, as you can see in here, I added a bunch of tests. I didn't want to write tests in the course of this class, because I already really covered Next.js tests here in this course, my React course. That guy, this guy. In this course, there is all sorts of stuff about testing. So we're not doing that today. But we are going to use the tests, and I want to show you like how would you run unit tests, how would you run end-to-end tests, and like how would you kind of gate deployments on those passings, and stuff like that.

[00:02:15]
So we're going to do CI/CD. I'm going to move from V3 final final to V4, final, final, final. Maybe put an extra final on there just to be sure that this one's really final. That'll take a second because I have, there's like a lot of dependencies that I've already installed in that particular folder. I did have you earlier set up a Vercel account against the GitHub repo. So I'm just going to reuse that one.

[00:02:56]
So if I go into WikiMasters before. OK, and we're going to go into, I'm going to open this with Coda. So let me get you a little bit acquainted with what I've added here. We now have a testing directory which has end-to-end tests and unit tests, so it has both the Vitest and Playwright tests in it. I've done some modern, some like slight modifications to like summarize here. Like for example, if you're inside of Playwright or Vitest, it's just not going to do your summarize, right, so that we don't waste a bunch of tokens, or if you haven't signed up, and you didn't want to give Vercel your credit card, then it won't matter.

[00:03:46]
So you can see here, if it's a test environment, it's just going to say this is a test summary. What else have we added in here? I've put, we're going to actually need a second .env file for your test stuff. Trying to think if there's anything else, there's a Vitest config file, there's a Playwright config file, and that's mostly it. Let's go ahead and I'm going to show you how to run the test, which is also all here in the package.json.

[00:04:25]
If you do npm run test, it'll run your unit tests. So test files, I only have one, but there's 9 tests that passed in that. And then we can also run test e2e and that will run our Playwright test, so it's going to build it into production mode, it's going to run it, and then it'll run a bunch of Playwright tests against that. And you can see here it's going to run 21 tests. This takes usually about 2 minutes for it to run all the way through.

[00:05:05]
Hopefully everything passed because I wrote these somewhat recently. But it's hitting everything, right? It's hitting against the cache, it's hitting against a bunch of stuff like that. And let's see, the one thing I do need to do, I need to copy over from my WikiMasters V3. I need the .env file in here. So these should be my previous .envs, which should be the. Yeah, cosmic mutt. I don't know why I remember this, but the Cosmic mutt stuck out with me that I know that that's the one that we've been working with today.

[00:06:00]
OK. So we now have this, our finished project, it's the exact same, I haven't added any more features or anything like that. But now we want to make it work for production deployments. So I'm going to say git. Uh, a init. How do I want to do this? Because we had this GitHub, I might even just make a new repo. Is that probably the easiest thing to do. Because otherwise we're going to try and like overwrite everything in here, which could be fun.

[00:06:45]
Oh yeah, the deployment failed, that does make sense. I don't know, let's try it. Let's see what happens. We're going to copy this. We're just going to force, I'm going to let you force push, which is my advice is you should always force push on all of your git pushes. I'm wondering if anyone takes me seriously. All right, so I'm going to say git remote add origin, uh, add my. In there, I want to say git add, git commit.

[00:07:27]
Not force push. And then I'm going to say git push origin main. Man, I just gotta make sure I git remote. I'm just, what wasn't the git remote I added? Now I'm terrified. Yep, no, that's the one I, all right, git push origin main --force. YOLO. So let's see if this actually did work. Not force push. There we go, OK. So this is going to, this actually, no, I don't think it's going to work.

[00:08:04]
Oh, it actually it might. So I actually do have the workflows already set up here for you. We'll go into those, in fact, we'll probably try and write part of them together just so you can see it. But writing the YAML files is one like not fun. And probably not the most useful thing that for you to do today. So we'll just, we'll get there though. All right. So we're here on Vercel, we're going to go to our projects and we're going to go to FAM WikiMasters, which is what I call mine.

[00:08:44]
FAM WikiMasters, there's an error in the deployment very expected right now because we haven't set up all the keys and a bunch of stuff like that. So the nice thing with these .env files, like um .env like the actual library is pretty smart about which .env file it will pull from. So .env with nothing else will get pulled in every environment, .env.test, it will, this corresponds to like your Node environment, right?

[00:09:21]
So if your Node environment is equal to test, then it will pull .env and then it'll pull .env.test. If you have one here called like .env.local, that's one that I see quite a bit, as well as .env.development. And obviously .env.production could be there as well. So this will correspond to whatever environment you're in, we're going to make one for tests here, that we're going to give like a test instance of Upstash, a test instance of Neon, a test instance of blob storage and all those different things, so that we're not running our tests against production, right, because our end-to-end test like creates an article, updates an article, deletes an article, you don't want that going against your production database, you want that going in some test instance that you can delete, recreate, all that kind of stuff.

[00:10:09]
So that's why I have a .env.test here, so that I can do all my development against one set of services, and then later I can come back and do it against the test services, and they're separate. Now, for what we're doing here, where we're kind of just like hobbyists developing by ourselves, I would probably just only have one set of services, my production is my test and is my development.

[00:10:32]
But for a more mature, like I'm building an enterprise app at work, you want to have a staging environment, a canary environment, those kind of things. With Neon, do you automatically like replicate the latest data on production on your testing environment so that you can have like say real data to test against it? Yeah, let me show you. So if you go to neon.tech, we go to log in. This is our environment here, I have tables.

[00:11:09]
Right, so you can see here, let's look at public. So I have this table here. I can come to branches and I can just say new branch. And say something like the test. Deployment. And here you can say, do I just want a copy of all the data that exists? Do I want to try and pull data from the past, because Neon keeps everything that you've ever written to us, so you can, we call it point-in-time restore, you can restore like, give me the branch as it was 7 hours ago.

[00:11:34]
You can do schema only, which is just like, I want the schema, like the table to exist, but I want no data in it. And anonymized data, I don't think this is actually ready yet. But this is a feature that I've been working on as well, where you can, it runs it through an anonymization feature, so like you don't get like real emails, you don't get real private information in there, you can just get like, you know, John Does and john@example.com, those kind of things.

[00:12:13]
So for our case, we don't have any PII that we're like worried about leaking, so we're just going to say create a branch here. And would that take about a second. So you can see here now I have a new connection string in here. This is the exact same copy of data. But I can come in here to the tables. And they're not tables, but let's, well, yeah, we look at tables first. Made a SQL editor.

[00:12:58]
What is going on here? Oh, there we go. OK, it's working. So again, I'm on the test deployment branch right here. I'm going to say drop table articles. Ran it, so if I go look at my tables here, obviously you wouldn't want to do that against your production database, but because I am in a, so you can see here I have no data in here because it's a branch, all I got to do is just delete the branch and, yeah, branches.

[00:13:22]
So if we go back to our production branch here and we look at the tables again, it's all still there, right? That's like my favorite feature of Neon is that you can just branch, the branches are instant because it's all copy on write, which means that like, you're not actually getting a real copy of your database. It's just like, they share a common root and then the roots diverge, right?

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now