Build a Fullstack Next.js App, v4

Configure GitHub Actions

Brian Holt
Databricks
Build a Fullstack Next.js App, v4

Lesson Description

The "Configure GitHub Actions" 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 shows how to set up GitHub Actions for CI, running tests and checks, using a temporary Neon database, managing secrets and variables, and configuring triggers for pull requests and pushes.

Preview

Transcript from the "Configure GitHub Actions" Lesson

[00:00:00]
>> Brian Holt: You can do additional stuff with Vercel, but they have additional checks and stuff like that you can do in the CI/CD process. We are going to concern ourselves with GitHub Actions. So let's get back into git checkout main. Back on main. So we have this package.json right here. We have some tests that we can run, and really what we want to run is npm run test CI, so we want this to pass when we run our GitHub Actions, or really specifically what we want to do is we want lint to run and that to pass.

[00:00:56]
Lint runs both format and linting, it runs both of those things together and it doesn't write, it just fails, right, which is what you want. So this will run one thing, we want it to run E2E CI this one, and we want it to run test CI. Yes, or is it just test? I think it's test anyway. So we want all of those checks to pass before we let something go out to production. So linting, formatting, type check, is that in here as well?

[00:01:34]
Yeah, type check up here, we want TypeScript to pass as well. Unit tests and end-to-end tests. So this is where GitHub Actions come into play. I was debating to have you write all of this. It's so long and not interesting and like again, this stuff is like I generally have either like start from a template or I have something like Claude generate the bones for me and then I just go edit it. So I'm not going to have you do that today either.

[00:02:00]
So let's just go through it. So inside of GitHub slash workflows, you can put multiple actions in here. We're just going to have the one which is CI.yml. We call it CI. This is CI is what's actually what's going to be called in the interface. I'll get to the on here in just a second. So what do we want it to do? We have, let's just do this piece by piece. I think that's the easiest thing to do. You want to parallelize this as much as possible.

[00:02:34]
So the more jobs that you can split this into, the better. So I could have had everything run as, you know, lint and test and end-to-end test and TS check is one different or as one continuous job. That takes way longer, and it's much easier if you can see which test pass as opposed to like the block of tests failed, right? So that's why all of these are split into different tasks. Let's look at, actually TS check is the simplest one.

[00:03:04]
You're going to have it run TypeScript check. You can run it on anything, but Ubuntu latest is usually a pretty good one, which is just like a Linux box, right? You can have stuff run on macOS if you're running like iOS, you can have it run on Windows, those are both extremely possible. MacOS is very expensive to run on. Windows, I think it's pretty comparable to Linux. And then here you just basically say like, if you were running this on your computer, what would you do yourself, right?

[00:03:33]
I would have it check out the code, I would have it set up Node, I would have it run npm install, and then I would have it run the task that I wanted to do. So this stuff is going to look more or less the same on most things that you do if it's Node-based, right? Some interesting things here, you can tell what version of Node you want to use. We're on 22 today. We're going to be caching npm. It has a strategy for caching npm.

[00:04:03]
And then this one's kind of interesting. Except you don't want to do that. You want this to just be like this. Package lock, this file will change every single time that you install anything, right? Or anytime that the dependencies has changed at all. So if this file is unchanged from the last time that it ran, it means that its cache is still valid, right? So the nice thing about GitHub Actions is like, as long as your dependencies aren't changing, it'll keep a cache of your npm installs, and it'll run much faster.

[00:04:39]
If you have to run npm install every single time, you're going to double or triple the length that it takes to run your tests. Okay, and so you just point to something that will change every single time based on the dependencies, right? So package lock files are usually what you're looking for. Okay, so that's type check. Let's look at lint and format. I think we have to modify these. Oh, so I guess that's the only one that I had messed up.

[00:05:09]
Does this look very familiar to you? It's like the exact same thing. The only thing that changes this year. If I'm not mistaken it might even reuse the same package, the same cache across the jobs. Maybe, because you would think it would be the same, right? Unit tests. Same sort of thing, but we're getting into something slightly more interesting here, because the unit test will actually will end up interacting with your database, right?

[00:05:45]
And you don't want to like write to your production database, you don't want to be doing that in your CI/CD environment, and you just need some sort of temporary environment that gets thrown away at the end. That's where like Neon kind of shines here is we have branches, which we were just talking about earlier, where you can just like branch your database. So this will actually use a Neon, it'll branch a database here using the Neon CI/CD action here.

[00:06:15]
And it creates a new project, a new branch, then it just like reads and writes a bunch of stuff to it. If the job fails, like it'll still delete the branch after 4 hours, that's what this is doing, that 2 weeks. This has working after 2 weeks. So no matter what, you're not going to end up with too many branches, that's happened to a lot of people, that's why I put this in here. And then that's it, right?

[00:06:41]
You'd run all your tests against this Neon branch, it spins up, you run your test, it spins down at the end. And that's it. This is kind of fun, you have to tell it specifically each and every single variable that you want. So I need the database URL. I'm setting the node env, that's usually set already, but I just did anyway. You're going to have to get a test email and a test user password. So just like go create one, I think I created one.

[00:07:13]
Do I have it in here? Yeah, I put mine as like tester@example.com and 123 tester as the username and password. And let's see, what else is interesting in here. And then at the end, I have this delete Neon branch job at the end. And I say if always, that means like even if the entire job fails, I still want you to delete the branch because I don't want it to outlive this run. So E2E test looks very much the same as the unit tests.

[00:07:46]
The only difference is that you're running E2E with the same kind of credentials and then you delete the branch at the end, same thing. Again, the nice thing about VS Code and GitHub being created by the same company is like there's really good documentation around like you just mouse over this, it'll tell you everything that you need to know about, here's what's available, here's what you can use, here's what's expected here.

[00:08:17]
It's very well typed for these kind of things. Questions about our CI file here? Let's talk about on here in just a second as well. When do we want to run CI/CD? That's what you can define here, right? On pull request. So that is, we just saw it here. This, all of these are running because this is on pull request. If you didn't have it on this, then these wouldn't run on the pull requests. So you can run something on some pull requests, you cannot run them on others, you can say, hey, if I'm making a pull request to main, run these tests, if I'm running it to against development, you can do that, right?

[00:09:08]
You can get pretty sophisticated about what runs when. And then on push, that is the one, like if we go in here to issues, you can see like, or not issues to code. This X here is because of push, right? So it runs it against every single commit that gets committed into main as well. Why is TypeScript failing? Some specified paths were not resolved, unable to cache dependencies. Oh, that's because I had the, I had this incorrectly said.

[00:09:52]
This one. So if you fix this, then the TypeScript should pass, and I'll fix that in the final course as well. Okay, so now like the unfun part about this, setting this all up, we have to go into settings. We have to run into actions, general. So you should say allow all actions, that's fine. Require approval, like I don't want, so if someone wants to troll me right now and run my CI/CD 1 trillion times, I don't want them to go open a bunch of pull requests just to run the CI/CD a bunch and waste all of my minutes.

[00:10:37]
So that's why I require approval for first-time contributors, so that you don't mess me over. That's the idea here. That's all what that is. If you have, you can have GitHub Actions actually be able to create pull requests and stuff like that, where I'm not doing anything like that today. But we do need to set up some environments. I think that's what we want to do. Is it in preview? I'm trying to remember.

[00:11:15]
Nope. Production. Where, oh no, here it's in secrets and variables. I always forget what these are. Secrets and variables for actions. And then this is where you have secrets and you have variables. So I was not judicious when I did this. I just made everything a secret. But you can have some actions have access to variables which are not secret, but they are like configurable. Like a good example this should like is node env.

[00:11:42]
It's not a secret that your node env is test here or production here or development there, it's just a variable, but it is an environmental variable. Whereas like your Resend API key, that is genuinely secret, you do need to keep that secret. Why does this matter? Doesn't really a whole lot. The only part where it makes a bigger difference is if we look at the logs, it'll be careful about hiding secrets from people.

[00:12:20]
So I wonder if I can show you that. And to end here, it might see if we might be able to find one in here. API host branch expires at run actions here, token. These three stars right there, that is somewhere where it hid the API key from you, because I saw that. I think, but even if it's not in that particular case, that's what it looks like, where it just puts stars instead of your API key. Whereas if it's a variable, it will show, it'll show you that this is test or dev or something like that.

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