# 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.&#x20;

{% hint style="info" %}
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.
{% endhint %}

## 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).&#x20;

{% hint style="success" %}
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!
{% endhint %}

## Designing the workflow

```yaml
# .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&#x20;

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

```yaml
      - 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

<figure><img src="/files/F9uxNDdt64c5izY2ozUE" alt=""><figcaption></figcaption></figure>

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:

<figure><img src="/files/LT9uUnVf84CKEho1OyxC" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/9V3TAHavrxy73dXhg28G" alt=""><figcaption></figcaption></figure>

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.

<details>

<summary>Poorly linted code</summary>

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

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

</details>

<figure><img src="/files/t3PglO4FNAoc88hIwRq7" alt=""><figcaption></figcaption></figure>

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!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.nushackers.org/hackerschool/ci-cd-with-github-actions/basics-of-github-actions/linting-code.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
