In this blog, I will walk through my experience setting up a CI workflow for my project dev-mate-cli
, including insights into collaborating on testing and CI with a peer's project. Along the way, I took on the optional challenge of integrating a linter and explored how this addition improves code quality and the CI experience. Here’s how it all came together:
Setting Up the GitHub Actions CI Workflow
To start, I set up a simple CI workflow using GitHub Actions, designed to run tests whenever I pushed new changes. I’ve worked with basic CI setups like this before so I knew what to do. I created a YAML file in the .github/workflows
directory, with the following configuration:
name: CI
jobs:
unit-test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: 'npm'
- name: Install Dependencies and Run Tests
run: npm install-ci-test
This workflow checks out the repository, sets up Node.js, installs dependencies, and runs the tests. As soon as I pushed the changes, GitHub Actions triggered the workflow, running all my Jest test suites, which passed successfully. This was a great way to ensure that each update to my project wouldn’t inadvertently break any functionality. Checkout the action run here.
Collaboration for Testing
As part of the lab in my OSD600 course, I also needed to collaborate with a peer, Anh Chien Vu. We agreed to add tests to each other's projects. Since we had already worked together, we knew each other’s code style and project setups, which made this collaboration easier. Anh Chien’s PR included an additional test suite, which improved my test coverage. His code was well-structured, so after testing his changes locally, I was comfortable merging the PR.
Writing tests for Anh’s project, VShell, involved testing core CLI functions to verify program details and AI response generation. View the PR below:
Add tests for server.js #21
This PR aims to add a new file with unit tests for server.js
Added server.test.js
containing the following unit tests for server.js
-
- should set up CLI information i.e. name, version and description.
- should use default values when no config file exists.
- should exit when no files(for processing) are provided with debug enabled.
- should process files and call promptAI
These tests have 100% code coverage for server.js
file.
- [x] Unit tests added
- [x] Unit tests passed
- [x] Code compiles correctly
- [x] Tests have been written and run
- [x] Code adheres to the style guidelines
- [x] Ready for review
Since both of our projects used Jest, I had a smooth start, but I ran into some challenges mocking modules due to dependencies. I had to use jest.resetModules()
to clear the module cache after each test and directly import the required modules, which was a new but valuable lesson. This hands-on collaboration allowed me to experiment with test structures I can now apply in my own project.
Adding a Linter to the CI Workflow
To further enhance my CI pipeline, I took on the optional challenge of integrating a linter. The project initially used ESLint for linting, but I ran into multiple configuration complexities due to dependencies and plugins for Jest, Prettier, and TypeScript. To simplify things, I migrated to Biome, which combines both formatting and linting, reducing the need for multiple tools.
After updating the project to use Biome, I created a lint
job in the CI configuration to automatically check for linting errors. Here’s what the addition looked like:
lint:
name: Biome Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Run Biome Lint
run: npm run lint
Adding a linter to the CI helped enforce consistent coding practices, catching potential errors before merging.
Conclusion
Overall, I learned that even a basic CI setup can provide a strong foundation to the project. It helps by giving immediate feedback on the code's stability and catching issues before merging. Having CI with both tests and lint checks makes code review easier and encourages better code quality, and I plan to implement it in all future work.
Top comments (0)