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
1mkdir src
- Set the dev dependencies for the project by running
1npm i typescript jest @types/jest ts-jest husky gts --save-dev
- Initialise typescript project
npx tsc --init
. This gives:Viewing1 Created a new tsconfig.json with: 2 3 target: es2016 4 module: commonjs 5 strict: true 6 esModuleInterop: true 7 skipLibCheck: true 8 forceConsistentCasingInFileNames: true 9 10 11 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
:1"rootDir": "./src", 2... 3"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
use1npx 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
:1{ 2 "scripts": { 3 "test": "jest", 4 ... 5 } 6 ... 7}
- 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:1module.exports = { 2 roots: ['<rootDir>/src', '<rootDir>/test'], 3 testMatch: ['**/test/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'], 4 transform: { 5 '^.+\\.(ts|tsx)$': 'ts-jest', 6 }, 7};
- Initialise Husky, this will set Husky up with a base configuration. To initialise Husky, run:
1npx 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:1name: Build AOC 2023 project 2 3on: 4 push: 5 branches: [main] 6 pull_request: 7 branches: [main] 8 9jobs: 10 build-project: 11 runs-on: ubuntu-latest 12 steps: 13 - name: Checkout project sources 14 uses: actions/checkout@v4 15 16 - name: Use Node.js 17 uses: actions/setup-node@v3 18 with: 19 node-version: '16.x' 20 21 - name: install dev dependencies 22 run: npm i 23 24 - name: run the test suite 25 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.1function sum(a: string, b: bigint): bigint { 2 return a + b; 3 } 4 5 6 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.1const t_sum = require('../../src/day_00/index.ts'); 2 3test('adds 1 + 2 to equal 3', () => { 4 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.1npm run compile 2 3 4> compile 5> tsc 6 7src/day_00/index.ts:2:5 - error TS2322: Type 'string' is not assignable to type 'bigint'. 8 92 return a + b; 10 ~~~~~~ 11 12 13Found 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:
1npm run lint
Running the1npm 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
1git add --all 2 3git 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.