How To Create a GitHub Actions Workflow

This is a featured image for the article about how to create a workflow in GitHub actions and consist of a GitHub logo and an interesting office in the blurred background.

In this tutorial, I would like to show you how to set up a new GitHub Actions workflow and a few interesting things that will help you configure it in no time.

At the end of this tutorial, you will know precisely how to:

  • navigate in GitHub actions and create new workflows,
  • trigger workflows manually,
  • create a job that runs only when another job succeeds,
  • use GitHub context and access its data.

Video Tutorial

If you prefer video content, then check out my video:

If you find this content useful, please leave a subscription  ๐Ÿ˜‰

What Is GitHub Actions?

GitHub Actions is nothing else than a CI/CD (continuous integration/continuous delivery) platform.

To put it simply, it is a platform, that allows us to automate builds, testing, deployments, and many other things related to the process in your company, or the project.

In practice, we define so-called workflows, which are triggered whenever some event happens in our repository. An event can be a merge to the main, a push to the remote branch, a deployment update, and plenty more.

Each workflow consists of jobs running inside their own machine runner and each job can have multiple steps responsible for performing an actual action, like code check, running a test, or creating a deployment.

Lastly, each workflow is nothing else than a YAML file placed within the .github/workflows directory.

Create First Workflow

With all of that said, let’s navigate to our GitHub repository and select the actions tab. Alternatively, you can do that with the following link: https://github.com/codersee-blog/{YOUR_REPO_NAME}/actions/new.

Nextly, let’s click the configure button:

Image presents how to create a first GitHub Actions workflow.

As a result, we should see the editor with the following code:

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the "main" branch
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3

      # Runs a single command using the runners shell
      - name: Run a one-line script
        run: echo Hello, world!

      # Runs a set of commands using the runners shell
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.

So, let’s clean it up a bit to avoid distraction:

name: CI

on:
  push:
    branches: [ "main" ]
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.

To sum up, we’ve defined a new GitHub Actions workflow, named CI, which will be triggered whenever we push a new commit to the main branch.

Our workflow consists of one job, build, which will be run on the Ubuntu runner. This job will invoke has two steps, which will be run one after another:

  • firstly, it will print out a one-line script,
  • lastly, it will invoke the multiline script.

Quite easy, isn’t it?

So with all of that done, let’s change the name of the file to ci.yml and let’s commit our changes to the main branch:

Image presents a popup for merging to the main branch

How To View Workflow Run?

With all of that done, let’s see how we can see the result of our triggered workflow.

To do so, let’s navigate to the following URL: https://github.com/codersee-blog/{your-repo-name}/actions/workflows/ci.yml.

On this page, we should see that our workflow run has completed successfully:

As the next step, let’s click on the build job and let’s see the output:

Image presents the output ot the workflow

Excellent!

Both our scripts run successfully and we can see the expected output.

How To Trigger Flow Manually?

At this point, you might be wondering if (and if yes, then how) we can manually trigger the flow.

Well, unfortunately, to do so, we must edit our YAML file a little:

name: CI

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:  
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.

As we can see, the only thing we need to add is the workflow_dispatch.

This event, allows us to trigger our workflow using the GitHub API, GitHub CLI, or GitHub browser interface:

Image shows how to manually trigger the GitHub Actions workflow thanks to the workflow_dispatch event trigger

How To Disable The Workflow?

But can we disable the workflow without deleting the file?

Yes, we can.

We can do that simply by using the Disable workflow button from the workflow runs page:

Image shows how to disable GitHub Actions workflow

Contexts And Debugging

Wonderful. At this point, we already know the basics of workflows and navigation in GitHub Actions.

As the next step, let’s learn a bit more about contexts.

Contexts allow us to access information about the workflow runs, variables, runner environments, jobs, and steps. If you are looking for commit sha, PR author, branch name, or maybe GitHub access token, then that’s the place you should check out.

For the full list of contexts with descriptions please take a look at the official documentation.

But from my end, I wanted to show you a useful tip if you would like to debug anything:

name: CI

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:  
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
  
      - name: Who initialized the flow? 
        run: echo "${{ github.actor }} initialized the flow."

      - name: Debug GitHub context
        run: |
            echo " ${{ toJSON(github) }}"

As we can see, the third step – Who initialized the flow?- prints out the “actor” (or simply the account) that initialized the flow.

The fourth step- Debug GitHub context- prints out github context to the output.

The toJson function returns a pretty-print JSON representation of our value.

As a result, we should see the following:

Image shows the result of the Debug GitHub context job.

Whatsoever, when debugging we don’t need to worry about exposing our secrets.

GitHub hides them by default.

Run Job After Another Job Finishes Successfully

Excellent! At this point, we learned quite a lot about the GitHub Actions workflows.

We know how to declare them, how to debug contexts, and how to navigate inside the GitHub world.

As the last thing for our first meeting, let’s learn how we can make one job dependent on the other.

To do so, let’s edit our YAML file once again:

name: CI

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:  
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
  
  second_job:        
    needs: build
    runs-on: ubuntu-latest
    
    steps:
      - name: I run only when build succeeds
        run: echo Hi!

As we can see, the only thing we need here is needs: build.

To be more specific, the needs instruction allows us to specify jobs that must be completed successfully before our job starts.

Of course, we can define multiple jobs using the array syntax: needs: [job1, job2].

Summary

And that’s all for this quick tutorial on how to create GitHub Actions workflows.

If you are interested in learning more about this topic, then I highly encourage you to check out their documentation. I’m pretty sure you will find there anything you need.

But if that’s not the case, then let me know in the comments section or by using the contact form ๐Ÿ™‚

Share this:

Picture of Hi there! ๐Ÿ‘‹

Hi there! ๐Ÿ‘‹

My name is Piotr and I've created Codersee to share my knowledge about Kotlin, Spring Framework, and other related topics through practical, step-by-step guides. Always eager to chat and exchange knowledge.

Related content

Newsletter

Image presents 3 ebooks with Java, Spring and Kotlin interview questions.

Never miss any important updates from the Kotlin world and get 3 ebooks!

You may opt out any time. Terms of Use and Privacy Policy

Free tutorials and courses on Kotlin & backend

To make Codersee work, we log user data. By using our site, you agree to our Privacy Policy and Terms of Use.