Creating an Inclusive Django Community with Kenya Phelps
Published July 15, 2026
This video features Paul Gilzow at DjangoCon US 2023 in Durham, North Carolina, USA.
Learn about GitHub Actions, a CI/CD platform for automating build, test, and deployment pipelines. This presentation provides an overview of key terms and concepts, as well as a step-by-step guide to creating reusable components known as "Actions". Perfect for developers new to automation or those looking to transition to GitHub Actions.
This talk was presented at: https://2023.djangocon.us/talks/introduction-to-github-actions-understanding-key-terms-and-building-your-first-github-action/
LINKS:
Follow Paul Gilzow 👇
On Twitter: https://twitter.com/gilzow
Follow DjangCon US 👇
https://fosstodon.org/@djangocon
https://twitter.com/djangocon
Follow DEFNA 👇
https://www.defna.org/
Video production by the presenter and DjangoCon US 2023 volunteers.
GitHub Actions is GitHub’s CI/CD service for automating testing, building, deployment, and other work around a codebase. Paul Gilzow explains how workflows, events, jobs, runners, steps, actions, inputs, outputs, and contexts fit together, then builds a manually triggered workflow and a composite custom action. He also shows how to connect a pull-request workflow to a Platform.sh preview environment and run Backstop.js visual regression tests, while warning about naming ambiguities, runner limitations, required metadata, and script-injection risks when handling context values.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Hey everybody. Unfortunately I came down with COVID, so I'm not able to be with you there at DjangoCon. And so I'm having to share this presentation presentation, excuse me. with you as uh as a recording instead so I'll apologize ahead of time if I have to stop and cough during the presentation. My name is Paul and I'm with a company called platform. sh We are a platform as a service provider, enterprise grade, secure platform as a service provider that handles the complexities of cloud infrastructure and cloud infrastructure automation so that your development teams can spend more time responding to the changing needs. of your organizations. So whether it's one site or a thousand across any kind of runtime, we can help you maintain standard security and compliance across all of them. Now I mention this because this is going to come back up later in the presentation
Specifically though what I want to talk about today is you're building your first GitHub action. Now in my presentations I usually like to give a collection of warnings. So if you're listening in, I have an animation of red light flashing I just kind of give you a heads up. A couple of a couple of warnings before we get started. First is that I am not a GitHub Actions expert However, that said, I have spent the last 18 months managing, maintaining, and building a collection of workflows and GitHub actions. to support various areas inside of our organization. And during that time came across a lot of frustrating aspects of learning GitHub actions. And so my hope is, it's kind of what spawned this presentation, my hope is to help you navigate around those areas of frustration and kind of jumpstart you on your way to building those GitHub actions.
Now, this presentation is more technical than some of my other ones. I do, however, try to temper that with lots of explanations. So even if you don't understand the specifics, you should be able to get kind of the bigger picture And last, with anything technical, especially in programming and development, there are a hundred different ways to get from point A to point B. So what I'm going to show you might not be the best way for your organization. It might not even be the right way But again, giving that big picture and an understanding of how these key concepts and pieces fit together. So specifically what I want to go over today, I want to talk about what GitHub Actions is. And I want to begin to talk about the components of the GitHub Actions that you'll use inside this platform to begin to build out your automation. We'll then dive into one of those components called the workflow.
We can talk about its required pieces. We'll then build our first workflow. Excuse me. I'm going to talk about the components of a custom action Then build our first custom action together and along the way talk about caveats and gotchas and then at the very end kind of how we can put it all together into something more tangible, something you might be able to use right away. So what is GitHub Actions? And GitHub Actions is actually a service. It's a continuous integration, continuous delivery platform that allows you to automate all the pieces. surrounding your code base, whether that be automated testing or building or deploying, but everything kind of surrounding that code base. So, what are the pieces of GitHub Actions that platform that you're going to use? Well, we have things like workflows, events, runners, job
steps, and github actions with a little a So if you're listening in, I've got a I've got an animation of Jim Howper from the office saying, wait, what? Yeah, so it's we've got GitHub Actions with the big A is the is the service, is the CI C D service. GitHub Actions with a little A are individualized modular self-contained pieces of automation that we can use in different ways to build out more complicated automations. So I've got another little warning here, and that is that the way that GitHub Actions, the platform, has named things can be very um frustrating, confusing. They take a word, excuse me, and then depending on where it's used can have different meanings. So get big we got GitHub actions with big A and GitHub actions with little
A. Another one you might come across is status versus checks versus status checks. which are three completely different things, which cause me to have this exasperated sigh, this kind of what? So just be aware that as you're going through the documentation, if you come across something where you've seen it Excuse me, you've read about it and it's not working the way that you just read about it in the documentation. You might have come across one of these scenarios So again, we've got these different components that we're going to use and how do they kind of work together? Well, we configure the GitHub Actions platform in a workflow. That workflow is then going to be triggered by one or more events that occur. That then run one or more jobs on a runner where each of those jobs include a series of steps
where each step can then call a script or a shell command or an action. So let's kind of talk about each of these pieces. So the workflow is kind of your main workhorse, excuse me. It is a YAML file And it must live inside of a workflows directory that sits inside of a. github directory that sits at the root of your repository. Now a repository can have multiple workflow files, each one triggered by a different event or same event. But each of these are going to be kind of the main area that you configure your automation. An event then is simply some activity that occurs to or on or with your repository that is used to trigger that workflow.
In fact, sometimes in the documentation, they are referred to as workflow triggers and not events. But we do have a large collection of them. So I'm going to hop over here. You can see, this is the documentation for events. You can see we have a large collection. events here on the right that we can pick from to give you fine-grained control over exactly when your workflow will fire. A job then is a series of steps that we define inside that workflow that are going to run. Each of them will run on a runner, and they're going to, excuse me. Excuse me that and where we we designate that runner by the runs on property. Now by default your jobs are going to run in parallel.
If we needed though, we do have the ability to chain them or build dependencies, but you have to remember that even though you can have an unlimited number of jobs, they are going to run in parallel. And I do have a little asterisk that's connects to unlimited. Depending on your plan of either your personal account or your organizational account and the way you've configured things, there are some limitations. But it ah god I can't talk. Excuse me. But we'll just skip that part. Uh sorry. Um a runner then is a server instance where your job is going to run. Uh GitHub does provide several public runners that you can utilize. If you choose to utilize those, you can choose from macOS
, Windows, and Ubuntu in various versions. Do note that if you use the public runners, sometimes you do have to wait for them, which is why they give you the option to self-host your runners if you need more dedicated or specifics inside those runner environments. A step in is a collection of things you want to happen inside of a job. These are typically either a shell script or a shell command that you're going to run. or you can access an action that we talked about earlier for that step. They are executed in their order and dependent on each other. So if a step fails, it will step, it'll fail out the rest of those steps. Again, we have the ability to work around that or change that behavior, but that's how it is by default. And it's important to remember that all steps in a job are executed on the same runner.
So they will have access to the same work file, excuse me, the work, same workspace and file system. An action, as I alluded to earlier, is a it's a self-contained modular piece of automation that we can chain together in different ways to build out more complex automation tasks. So now I want to go into one of those components, the workflow, since that is our main workhorse. It's where we're going to be building most of this automation and talk about some of the required pieces there. Excuse me, so a workflow must contain at least one event that designates when this workflow will be triggered. It also has to contain one or more jobs They're going to execute on that runner machine and then it has to have one or more steps defined that are going to run inside of that Java
So what I want to want to do now is build out our first workflow. So I'm going to hop over to my IDE here. So we know we have to have an event. So we're going to use the on keyword. And I will note that I am using a plugin for my IED that helps me build these workflows. So I'm going to use the workflow dispatch event This event allows us to manually run our workflow so I don't have to go in and artificially create like a pull request, open the pull request, and close it back and forth. The next thing we knew We have to define is a job. So we're gonna have the jobs key. We have to define at least one job. So I'm gonna call it say hello. We then have to designate at a minimum where this thing is going to run on. So I'm going to choose a button, oops,
but latest. Ah, I can't type either. Move on to latest, there we go. And then we have to designate at least one step. In this case, I'm going to designate to run on a shell prompt. And I'm going to do echo hello there. And that is our first workflow. So we come back. Let's make sure these match up. So we have to have an event that is that workflow dispatch. We have to have a job, let's say hello. We have to have a runner, which is going to be on Ubuntu latest, then we have to have at least one step, which is going to be echo hello there. And so now if we want to go see this work , You can see these out on my GitHub profile. So if you go to github. com slash Gilzo, it's pinned up here at the top.
And then we should have an actions tab. This first one that we're running is under. github workflows first. When you designate a workflow dispatch, you'll have this nice little run workflow. I'm gonna go ahead and look at a previous run just so we don't have to wait around. For a public runner, here's my say hello job. If I'd had multiple jobs, they'd all be listed out. And inside there I can see it was setting it up and then it ran that hello there. So let's dive deeper into some of these workflow components So you might have noticed that I created a job ID inside of that jobs property. Job IDs have to be a string. They must be unique inside the workflow. So they can be repeated between workflows, but inside the same workflow they have to be unique.
They must start with a letter or an underscore and they can only contain alphanumeric characters, dashes, or underscores. And again, you have to have at least one step Your step then is simply an array of tasks. If you're familiar with the terminal command, which are excuse me, the terminal session, which you probably are, each step is going to run in its own terminal session though it does have access to the workspace and file system. So if a step writes to a file, a further step will be able to still have access to that same file You're never going to have a situation where a second or third step or somewhere down the line is going to run in a different runner. They're all going to be on that same runner Each step then has to include the keywords either uses to designate to the work to the GitHub Actions platform that it's going to use a GitHub Action.
or the run property, which is going to designate that it's going to run a command line, either binary or some shell script. So let's take a look at our second one. In this case, again, I'm still using on workflow dispatch. I've still got uh I might say hello job, I'm still running on Ubuntu latest, and now I've got four steps. So the first one is I'm echoing out again. The second step, this in this case, I'm going to use an action called checkout, then running another one, and then a fourth step. Do note though that I've added some name properties. What this does is allows you to give a more human-friendly version to output inside that actions area on GitHub. So I've given the workflow name I've given the job a name and I've given the third step a name and if we come back out, oops, and
I just went to all my other there we go. Um if we come back out to my actions tab here. I can now see that instead of it being GitHub Workflow Second, it's welcome to the party If I go into a run of this workflow, instead of say underscore hello that ID, I got let's greet the user, and now I can see that that third step now displays the name of the step instead of just what it's doing. All right, now before I go on, uh you might be asking yourself, all right, you've The presentations about GitHub actions and building a custom action. And for at least 15 of the 45 minutes, I've talked about workflows.
So you may be asking yourself, all right, why are you talking about workflows? We're supposed to be building custom actions. Well, the first is that you cannot run a custom action. without a workflow. You have to have a workflow to call the action. The second is that a lot of the Things that we can do in a workflow, particularly with the workflow dispatch event, very closely mimic what we can do in a custom action. such as inputs. So at some point your action is probably going to need to be able to ingest or receive data in order to perform that automation. So every action has the ability to accept inputs. Inside of workflows with the workflow dispatch and the workflow collament, we can also accept inputs.
Each input has to have an ID, just like the jobs, which are also have to be unique alphanumeric dashes or underscores. For actions inside of that input that we define, we have to have a description property. In addition, you can also designate whether an input is required. You can also set up default values in case they do not provide a value. So let's jump out here Take a look at my third workflow. So again, same thing. Workflow dispatch, job say hello. I've still got the name property. And this this time though, I've defined an inputs property. Where I've given a new input, the key or the ID of the name, back to the description property.
It's important to note, I forgot to mention this, that all actions, the type Is always going to be a string for actions. For workflow dispatch events, for a workflow, we have several different types, but for actions, every input is going to be a string. And here I've designated that it's true Now my step is simply to say hello there and then call the value that's been handed in. So if we come back out and we take a look at this action run, which I believe it's hidden, This time I'll show you this. So again, if we had that workflow dispatch, I can run the workflow and notice now because I've defined an input It's going to show me that input. If I try to run the workflow because it's designated as required, it's going to say, hey, you have to do this.
So I'm going to say this is going to be DjangoCon. I'll run that workflow Now it does take a second because again we're using those public runners. I'll know it's running once we get a new line at the top. There it goes. Got a little dot. Now dig into that It is now setting up our let's greet the user job. There it's completed and I can see it has output Django Con. All right. Context, the other piece that we share similarity between workflows with workflow dispatch custom actions. Context is how the GitHub Actions platform shares data with our scripts and our workflows and actions. It provides access, provides information about
The workflow runs, jobs, the runner, steps, inputs, etc. They're exposed to our code as objects that contain properties, and those properties either strings or further objects. We do have 12 types of context that we can utilize. Here you can see these. The GitHub, environment, bears, secrets, jobs, runners, strategies, etc. It is important to note that you might not have access to every context. So for example, there's something called a matrix that you can access. If you're not running inside of a matrix, then it makes sense that you wouldn't have access to that particular context. To access a context for your custom actions, as long as they're not JavaScript custom actions You access it with a dollar
sign, two curly braces, with a context name, dot, and the property you want to access, and then two ending curly braces So in this example I showed you earlier, we have that inputs, dot the input name, or in the case of steps, I might do steps, the step ID, its outputs, and then the output ID. If you happen to be building a JavaScript-based custom action, you can utilize the GitHub Actions package, which then exposes these contexts via a method. Quick warning about these, that not all of the context are not all of the values in the context are prepared for you to utilize inside your
code directly. As an example, if I were to try to create a shell variable where I have a double quote and then I put the context ending double quote such as pull request title Since that comes from the user, the user could do a and then an end double quote and then a semicolon, which means I would end up with double quote a ending double quote semicolon. Um, and then this would then run That's just a regular command. So these inputs are kind of ripe for script injections, whether maliciously or inadvertently. So just be aware that you're going to have to prep these For use in your code. Alright, if we have inputs, then at some point we might need to output information.
This is simply data or information from a step. Whether that's an action or excuse me, whether that's an action being called as a step or step directly in a workflow, we need to be able to provide that information back to further steps that may need to utilize that information. To set an output in anything that isn't a JavaScript-based custom action, we'll do a shell command of echo where we set the output ID equal to the value, and then we send that out to the environmental variable GitHub output. Inside of a JavaScript-based custom action, we have again another method for using that package of dot set output. Then as I showed you earlier, to use that output, we call the particular context in this case
is probably a step. that step ID, its outputs object, and the output ID that we've set. So we'll take a quick look here So in this case I've got an input again same thing as earlier that I showed you down in our steps. This time, as the second step, we're going to grab the current time from the date binary or the date command inside of our shell. We're then going to store that value as an ID of current time. And then the last step, we're going to call the steps context, which comes back up says go get the step called get time. So there's mine with get time. Then go to its outputs object
and then grab the output ID of current time. So if we come back over Whoops, where's my there we go? Here, let's see this. Grab the current time. So again, we're setting That current time to the value of date setting into the GitHub output environmental variable And then that last step, accessing that value via the steps property and the output. Alright, so now we're ready to actually build out our custom actions. Oh wait, wait, wait, wait, wait. Not custom action with big A, but custom action, remember, with a little A.
Alright, so we have three types of custom actions. We have Docker, JavaScript, composite. Docker is nice in that you can either call a Docker image in a public image repository or you include a Docker file and GitHub Actions will build that container for you. These are very good if you have specific requirements for the environment that your action needs to run in. You can also build a JavaScript-based custom action. This is particularly nice because you can kind of compartmentalize your code away from the environment that it's running in. and kind of have it self-contained. Composite's interesting because you can actually utilize other actions inside of your action again to build up these more Complex automation task but expose that overall action is a single action
You can store your actions in one of two locations. You can either store it in a repository all by itself, or you can store it in a directory inside of an existing repository where it's going to be utilized. Now there are some things that actions have to have. The big piece is that all actions must have an action metadata file. It has to be named Action. And it has to be in YAML file. And it has to be stored inside the root of where the action is being stored. So if it's in a repository all by itself, it has to be in the root of the repository. If you're storing it in a directory inside of an existing repository, it has to be in the root of the repository. The metadata file itself must contain at least a name property, a description.
and the runs property with a sub-property of using. And it's that property that tells the GitHub Actions platform what type. of GitHub action we're going to be using. Now in addition, it can also define things like inputs and outputs or names as we've seen earlier. Now, the the asterisk in this case is depending on the type of custom action that you're building, you may have additional required properties. As an example. In this case, I'm building a JavaScript-based custom action. So I've got the name property, description, I've got the run using, node 20. And because it's a JavaScript-based custom action, I'm also required to add in the main property, which simply tells the custom, excuse me,
tells the GitHub custom actions platform that this is the file we need to call when bringing up this custom action. Now a couple of quick warnings. When designating the runs using for Docker and Composite, you actually use the keywords Docker and Composite. Deposit for JavaScript you designate the node version. GitHub Actions currently supports only two versions of Node, version 16 and version 20. In addition, if you're building a JavaScript-based custom action, you must commit your node modules to the repository or use something like Versales NCC package to bundle everything into a single file If you are using a composite custom action, just be aware that those public runners that your action runs in may not have
the versions of the binaries and programs in the OS. that you need and you may have to update those. If you get to the point where you're having to unlike you're having to update almost all the binaries before you can do anything, that might be a good time to look into building a Docker container for your action to run in. So now let's build our first custom action. So if we come in here, right, so first thing I'm gonna do is I'm gonna create the name because it has to have a name. So I'll say this is the welcome to the party action And we're going to give it a description. Again, just welcome someone to our party. I'm going to define an input because I'm going to ingest some information in this case, very similar to that workflow we did earlier. We're just going to get a name of somebody who degreet.
I'm then going to do a composite-based custom action. So I've got runs and then that sub property of using. So composite. I then have to have some steps in here because I'm building a composite action. In this case I'll give it a name and an ID. And then my step will be to run Hello and then go back up to the inputs context and grab that who we greet. Now you'll also notice I might I've added a shell. So you can in addition to an ID and then the run, you have the ability to designate the shell. So you can do bash or sh, PowerShell, or Python. This case again I'm just doing simple bash with an output. Now remember earlier I mentioned we cannot run our action without a workflow.
So I have to have an accompanying workflow in order to run this action. And I also forgot to mention that I've included this action file in a greet user directory. So here's my action metadata file inside a greet user directory. So it's in the root I currently have this inside of an actions directory inside of. github. You don't have to put it there. It can be anywhere inside of your repository. It just makes sense in this case. Oh, so I have to have a workflow. So here's my workflow. So welcome user via in action. Again, I'm gonna I'm doing the workflow dispatch. I've got uh some inputs just like earlier Except this time the first action that I do is a checkout.
So by default in your workflows, the runner does not have access to the repository. Where the workflow lives. So the action checkout checks out the repository into the file system of the rudder Now that I actually have this repository in the runner, I can then say, okay, I want to use an action that's in the repository. So now I'm calling GitHub Actions Create User Then I'm saying it has an input, so I use the with keyword, I then designate the ID and then pass it in the value. So in this case, we're going back up to the inputs to the name, grabbing that value and then sending that into the action we just built. So to see this in action,
come back out Back up to my actions tab. I'll say run the workflow who are we gonna greet. So I'll say JangoCon again. So again, this is going to take this input from the workflow call the action and then send it into the action. There's my job. So there it's checking out the repository. There we go. So then it runs my action. That action then is to note to uh echo out from that input.
All right. All right. So we've talked about the GitHub Actions platform. We've talked about the different pieces of the GitHub Actions platform that we'll work with. We've talked about components of our workflow, that main workhorse. Where we do most of our automation, our building out of our automation. We built our first workflow. We talked about the components of a custom action. different places that we can store those actions as well the different types of actions and the pieces that are required for custom actions. We built our first custom action as well as the accompanying workflow that has to go. with an action. And along the way I talked about caveats and gadgets. The last piece I want to share with you is kind of putting it all together. How do we take all these pieces and parts that we talked about and actually do something uh tangible, something we can actually utilize.
So in this case, what I want to do is with a uh with a repository, when I create a PR, I want to automatically have a uh an instance of my environment brought up with this new code and then run a visual regression test against that PR code versus my production site So I have a, oops, and I forgot to bring that up, so let's hit this real quick. So I have a production website Nothing too fancy here. And again, what I want to do is when I run a PR, I want to have a version of that site brought up. So this is where platform. sh comes back in.
One of the nice things about our service is we have a GitHub integration. When you create a pull request, GitHub contacts us and sends us that pull request code. We then clone your production environment into its own self-contained containers with that new PR code. Once it's all brought up, we send the URL back to GitHub, which then presents it to you inside of your checks. So in this case I can see that I now have a fully cloned version of my production website with this new PR code, and we add the PR number to the beginning of the URL. Alright, so to see this poll, excuse me, to see this workflow
inside of this sites code base Here I've got the event pull request target where I'm going to say, when we are asking to do a pull request into main, I want to run this job. In this case, I'm saying the first step is to use this other action. What that action does is simply asks GitHub, hey. Has uh platform responded back with success? And if so, has it given you the URL? The output for that action is the URL. Then I can turn around and run my other Action that I've built up to run the visual regression testing, passing in a test URL and a reference URL Now, if you've never done visual regression testing before,
what it does is allows you to take screenshots of a baseline site, in this case my production URL. and then take screenshots of a testing version, in this case my PR, and then run diffs. For this custom action I'm using backstop. js, which is a visual regression testing tool. And I kind of show you a quick example. Here's an output of a backstop test instance. And I can see I had 24 passed and one failed. I can then go in and look at my reference site versus my testing site and then look at the difference. In addition, run a scrubber across the two to be able to see Where the difference is, and I can see in this case everything below this image appears to be kind of bumping up just a little bit.
Now the action itself that I'm accessing Is going to be a composite-based action where I'm accepting two inputs because I'm going to be running uh I need a I need a baseline URL and a testing URL. So the first step in this composite action is simply to verify that what we were given for one of these URLs is a URL. So this action that I'm calling simply says, does this string look like a URL? And then does a curl on the URL to make sure the server is responding. So I do it once for the reference URL, once for the test URL. I then install backstop into this file system. In addition, backstop runs its
based on a configuration file called backstop. json, where we designate the viewports of those media breakpoints, and then the URLs and locations that we want to test So in doing so, I need to swap out those example URLs with the URLs we were just given. To do that, I was going to use JQ. But the version of JQ in the runner itself was a little out of date. So the next step then is to update JQ to 1. 7. The next step after that is I simply using JQ swap out those URLs, and then I can then run My backstop reference. So it'll bring up my production URL and take screenshots. Once it's done, I then want to run the same thing but against my testing. But backstop will report a non-uh
zero exit code if the test failed. And as I mentioned earlier, steps are dependent on one another and by default will fail if any command in that step fails, which I don't want to have happen. So in this case I'm saying continue on error troops. So even if this step fails, I want to keep going with my other steps. I'm running in bash, so I'm going to set E to make sure that none of these individual commands will fail the rest. So I'm running backstop test. I then grab the result from backstop test. Then, if the test results were not successful, I'm going to set a variable. And then down below, I'm going to reset that variable as an output.
Now, in this case, I'm setting it as an environmental variable. But we could also use GitHub outputs at this point. We'll skip this next step. This is about debugging, which I did not have time to cover today. The second to last step, then I say if what I set up above during that test failed, then I want to run this step. And in this case, I'm using an action called upload artifact So I want to take the results of that test that it generated, those diffs, and want to save them and attach them back out to the run of this workflow. And the last is I want to return back the results from that test. So if it failed, I want to fail out this action or send a fail from this action back out to the workflow.
So we can see this run. In this case, it did fail. So if I check out the details of this, I can see oh backs. visual regression testing failed. Please see the generated report. I'll go look at the summary Oops, scroll down, scroll down. I can see it did in fact attach that artifact. I've already downloaded that and I can show you the difference here. In this case, it looks like I had an image that failed to load. So between reference and test, I had an image that failed. Excuse me. Cough. Almost made it the whole way without a coffin. I'm very proud. Alright, so unfortunately, because I'm not there, I don't have time for any questions. Hopefully, my uh coworker is possibly there to answer any questions
I would love to talk to you about this, and I'm again very, very sorry. I couldn't be there with you. But again, it was best to because I was positive to just stay away. This is my contact information. You can scan that QR code and reach out to me. You can find me on Linktree. There's my Linktree profile. Really, if you want to just search for my last name, Gilzo, there's only a handful of us in the United States, so you'll probably be able to track me down. Um with that, I thank you very much.
GitHub Actions is a continuous integration and continuous delivery service for automating work around a codebase, including testing, building, and deployment.
Discussed at 2:47A workflow is triggered by one or more events, runs one or more jobs on a runner, and each job contains ordered steps. Steps can execute shell commands or call reusable actions.
Discussed at 4:22A workflow must define at least one triggering event, one or more jobs, and one or more steps that run in those jobs. Workflow files are YAML files stored in the repository’s `.github/workflows` directory.
Discussed at 8:14Define an event such as `workflow_dispatch`, add a job with a runner such as `ubuntu-latest`, and include at least one step, for example a shell step that runs `echo hello there`.
Discussed at 9:04Declare an input with an ID and description in the action or workflow, then pass a workflow input to an action with `with`. Action inputs are strings, and they can be accessed through the inputs context.
Discussed at 14:41The three types are Docker, JavaScript, and composite actions. Docker actions suit specific environment requirements, JavaScript actions keep code separate from the runtime environment, and composite actions combine other actions and steps into one reusable action.
Discussed at 21:40Every action needs an `action.yml` metadata file at the root of its action directory. It must include `name`, `description`, and `runs.using`; JavaScript actions also need a `main` entry identifying the file to execute.
Discussed at 22:29A pull-request workflow can obtain a preview environment URL, pass it and the production URL to a composite action, and use Backstop.js to capture screenshots and compare them. The workflow can upload the diff artifacts and report whether the visual test passed.
Discussed at 29:26Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 14, 2026