NUS Hackers Wiki
NUS Hackers Wiki
  • NUS Hackers Wiki
  • Hackerschool
    • Virtual Machines and Linux
    • Beginners' Guide to the Terminal
      • Introduction to the Terminal
      • Modern Shell Tools
      • Shell Scripting
      • Real World Scripting
      • Resources
    • Self-Hosting: Three Easy Pieces
      • 1. Setting up your server
      • 2. Running Services
      • 3. Monitoring your server
    • Vim
    • Introduction to Zig
      • Language Basics
      • Error Handling
      • Memory Management
      • Working with C
      • Exploring comptime
    • CI/CD with Github Actions
      • Background
      • Basics of Github Actions
        • Target workflow
        • Running unit tests
        • Linting code
        • Deploying to Github Pages
      • Advanced use cases
        • Pollers
        • Github script
        • Executing third-party scripts
        • Reusable workflows
      • Cookbook
    • Lightning Git
      • Git Concepts
      • Getting Started with Git
      • Making your first commit
      • Branching
      • Merge Conflicts
      • Integrating remote repositories
      • Collaborative Workflows
      • Commit Manipulation and Reflog
      • Interactive rebasing
      • filter-repo
  • Orbital
    • JavaScript
      • Browser Developer Tools
      • Getting Started
      • Datatypes
      • Operators and Operations
      • Loops and Conditions
      • Functions
      • Strings
      • Arrays
      • HTML
        • Getting Started
        • Tag Attributes
        • HTML Forms
        • Browser Inspector
      • CSS
        • Selectors
        • Colors in CSS
        • Measurements in CSS
        • The Box Model
        • Adding Styles - Part 1
        • Adding Styles - Part 2
      • Working with the DOM
        • Querying the DOM - Selectors
        • Querying the DOM - Element Attributes
        • Querying the DOM - Element Styles
        • Events with JS and HTML
        • Exercise: Click Counter
        • Editing the DOM
        • Fetch Requests
        • Exercise: The NUSMods API
    • React
      • Setup
      • State
    • React Native
      • Setup
      • Intro to JSX
      • Basic Syntax
      • Handling UI
      • Props
      • State Management
    • Git
      • Setup
      • Command Glossary
      • Fundamental Concepts
        • Getting Started
        • Integrating Remote Repositories
        • Branching
        • Merge Conflicts
      • Collaborative Workflows
        • Fork and PR Workflow
        • Branch and PR Workflow
      • Advanced Concepts
        • Ignoring Files
        • Commit Message Conventions
        • Github Collaborators
        • CI/CD with Github Actions
        • Advanced Git Commands
      • FAQ
    • Telegram Bot
      • Creating a TeleBot
      • API Calls
      • Telebot Basics
      • Integrating API's
    • Relational Database
      • Database Overview
      • Database Design
      • Entity Relationship Diagram
      • SQL Basics & PostgreSQL
    • TypeScript
      • Types and Interfaces
      • Utility Types
      • Typing Component Props, Events, and Hooks
      • Why You Should Avoid Using any (and What to Do Instead)
      • TypeScript Tricks You’ll Use All the Time in React
Powered by GitBook
On this page
  • Constructing the workflow
  • Designing the workflow
  • Breaking it down
  • Linting code
  • Visualizing the workflow
  • Verifying the workflow
Edit on GitHub
Export as PDF
  1. Hackerschool
  2. CI/CD with Github Actions
  3. Basics of Github Actions

Linting code

With your new workflow ci.yml, you are able to run unit tests. But another key operation in most CI/CD workflows is linting the project, ensuring that the code follows a certain standard and set of conventions.

Using Github Actions, we want a pull request to fail if the branch contains poorly linted code.

Given that we have already demonstrated how pull_request events trigger the workflow and have verified that our workflow works correctly with unit testing, we will be demonstrating the aforementioned using the workflow_dispatch event instead for the sake of simplicity.

Constructing the workflow

As described in the previous section, we think of answering two key questions when constructing the workflow:

  1. "When will it run?" — established to be during pull_request (and additionally workflow_dispatch for testing)

  2. "What will it do?" — execute the yarn lint script given in the package.json

However, there is an additional question we will want to answer, given that we already have an existing workflow:

  1. "Is this going to be a separate workflow? A separate job in the same workflow? Or just another step in the existing job?"

There is no right or wrong answer for the above. But it is worth considering the following factors:

  • Is this a part of the CI workflow? — yes, so we might not want to separate it out

  • Is the task a part of unit testing? — no, so we might want to split it out to avoid cluttering a single job

So in this case, we choose to create a separate job within the same workflow ci.yml. By default, jobs will run in parallel, but can be designed to run sequentially. So, we get the added benefit of having both linting and unit tests running in parallel, saving time (arguable since we need to reinstall the project dependencies in each job, but as jobs get more complex, running them in parallel will allow simpler ones to complete first), and preventing the results of one job from affecting the other (one can fail while the others pass).

Before we dive into the code required, maybe take some time to think about and attempt to implement the above job! It is not very different from the previous implementation!

Designing the workflow

# .github/workflows/ci.yml
name: CI/CD Pipeline
on: [pull_request, workflow_dispatch]
jobs:
  linting:
    runs-on: ubuntu-latest
    steps:
      - name: Fetch repository
        uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'yarn'
      - name: Install dependencies
        run: |
          yarn
      - name: Lint code
        run: |
          yarn lint

  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - name: Fetch repository
        uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'yarn'
      - name: Install dependencies
        run: |
          yarn
      - name: Run unit tests
        run: |
          NODE_ENV=production yarn test

Breaking it down

You will notice that every step except the last is the same as the unit-tests job. That is because the initial setup of the virtual machine runner does not change! We still need to

  1. Fetch the repository

  2. Setup Node.js

  3. Install project dependencies

And this is all because all jobs run in separate virtual machine runners! So linting does not share these steps with unit-tests .

Linting code

      - name: Lint code
        run: |
          yarn lint

The only step that differs between linting and unit-tests is the linting step, which we rely on the provided lint script in package.json, which calls eslint ..

Visualizing the workflow

Now, the single workflow has evolved to include two parallel jobs!

Verifying the workflow

As mentioned at the start of this section, we will be verifying that the linting works by using the workflow_dispatch event. So, once again, push the latest changes to ci.yml to your fork and manually run the workflow:

git add .github/workflows/ci.yml
git commit -m "Add linting step"
git push -u origin main

This time, you will see that there are now two separate jobs running within the same workflow:

Both of them will also complete at around the same time since both linting and unit tests are relatively small at this time:

Try playing around with this new job. Create a branch and purposely commit and PR poorly linted code and see what happens! The linting job should fail while the unit-tests job will continue to work.

Poorly linted code

Add the following to the top of the App.tsx file:

  if (true) {
    useEffect(() => console.log("hi"), [])
  }

Amazing! We have not only setup a CI/CD workflow that runs unit tests, but also linting, and both run in parallel and don't affect each other's outcomes!

Let's tackle the the final piece of the puzzle: deploying the application to Github Pages!

PreviousRunning unit testsNextDeploying to Github Pages

Last updated 2 months ago