2023 Advent of Code
It’s that time of year again with Advent of Code on the horizon, this year I will be mostly using TypeScript
As with last year), I’m going to attempt Advent of Code to see how far I get. This year has been a lot busier though so I’m not anticipating getting very far unless the problems are really easy and quick to solve. That being said, it can still be a learning opportunity so this year I will be using the challenge to get used to TypeScript.
TypeScript is a superset of JavaScript, this means it builds on JavaScript by providing static typing. TypeScript can be transpiled to JavaScript and JavaScript is syntactically valid TypeScript although would probably fail compilation unless it also includes typing.
The plan
My plan is to create a new folder for each days challenge and include a solution file and 1..n test files. My experience of 2021 and 2022 is that the problem is given with 1..n small example solution(s), finally a bigger problem input. This fits well with my plan of having one or more test files.
Getting set up
For this exercise, I will use:
- TypeScript
- GTS, this is a prettifier and linter that uses prettier and eslint under the hood
- Jest, standard unit test framework
- Husky, used for pre commit hooks
- GitHub Actions, for the build pipeline
Environment setup
- Create a new GitHub project using the web UI. I selected a public repo and didn’t ask for any files other than a
README.md
- Clone the repository locally and enter the newly cloned repository
- Create a source directory to hold source files
mkdir src
- Set the dev dependencies for the project by running
npm i typescript jest @types/jest ts-jest husky gts --save-dev
- Initialise typescript project
npx tsc --init
. This gives:ViewingCreated a new tsconfig.json with: target: es2016 module: commonjs strict: true esModuleInterop: true skipLibCheck: true forceConsistentCasingInFileNames: true You can learn more at https://aka.ms/tsconfig
tsconfig.json
gives the details of what all of the above settings are. - Update
tsconfig.json
so that the output of builds go tobuild
, this means we cangitignore
anything in thebuild
folder. Also change the root directory of source to besrc
:"rootDir": "./src", ... "outDir": "./build",
- Then initialise
gts
within the project, the initialisation process will prompt to update settings, accept the updates and wait for the process to finish. To initialisegts
usenpx gts init
- Update the
package.json
file to include a test script for running jest tests, this is as simple as adding a mapping fromtest
tojest
:{ "scripts": { "test": "jest", ... } ... }
- Create a
jest.config.js
file in the root of the project to ensure jest is set up for running tests. The content of the file should look like:module.exports = { roots: ['<rootDir>/src', '<rootDir>/test'], testMatch: ['**/test/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'], transform: { '^.+\\.(ts|tsx)$': 'ts-jest', }, };
- Initialise Husky, this will set Husky up with a base configuration. To initialise Husky, run:
npx husky-init
- Edit
.husky/pre-commit
so thatlint
is run on commit rather thantest
, this will speed up the commit process and enable us to push the testing to the CI server. - Create a
.github/workflows
folder structure and create abuild_and_test.yml
file to details the build steps needed. The contents of my build file is:name: Build AOC 2023 project on: push: branches: [main] pull_request: branches: [main] jobs: build-project: runs-on: ubuntu-latest steps: - name: Checkout project sources uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v3 with: node-version: '16.x' - name: install dev dependencies run: npm i - name: run the test suite run: npm run test
We’re now at a point where we can:
- Compile using TypeScript
- Run unit tests locally
- Lint source code
- Format source code
- Run a lint check on commit.
- Build and test commits in a GitHub workflow
The next step will be to add a test to ensure it all hangs together
Testing the config
- Create an
index.ts
source file in./src/day_00
with the following content:Note that the content of this is intentionally wrong, this is to test that all elements of the pipeline work.function sum(a: string, b: bigint): bigint { return a + b; } module.exports = sum
- Create a
index.test.ts
file in./test/day_00
with the following content:Again, the content of this doesn’t match our linting rules and this is intentional.const t_sum = require('../../src/day_00/index.ts'); test('adds 1 + 2 to equal 3', () => { expect(t_sum(1, 2)).toBe(3);})
- Now we will test the build, this should identify the type issue in the
src
folder`Correct the issue and run again, this time the build should be successful so we know our typescript compiler is working ok and picking up our source files.npm run compile > compile > tsc src/day_00/index.ts:2:5 - error TS2322: Type 'string' is not assignable to type 'bigint'. 2 return a + b; ~~~~~~ Found 1 error in src/day_00/index.ts:2
- Now we’ll test our prettifier and linter, this will ensure our code is formatted correctly and that common issues are removed. Firstly check that the linter picks up some errors (remember the funky formatting above):There should be some errors reported, these can be fixed using the following command:
npm run lint
Running thenpm run fix
lint
command again should report no errors - Our final local test is to check the pre-commit hooks, remember that on commit the linter should run:As we’ve already fixed the linting issues there should be none reported, if there were some though the commit would fail. I could update the hook so that the code is automatically fixed but I have chosen not to so that I can learn what I’m doing wrong rather than
git add --all git commit -a
gts
silently fixing things for me - Commit the code and push to GitHub. This should trigger the build_and_test workflow which will run the tests for the project. The test was very basic and the pipeline should go green.
We have proven that the whole build pipeline will work under problem solving conditions. I’m not anticipating being a challenger for any of the top spots on the AoC leader board but it is good to know that I shouldn’t get distracted by a silly build issue.