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

  1. 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
  2. Clone the repository locally and enter the newly cloned repository
  3. Create a source directory to hold source files
    mkdir src
    
  4. Set the dev dependencies for the project by running
    npm i typescript jest @types/jest ts-jest husky gts --save-dev
    
  5. Initialise typescript project npx tsc --init. This gives:
     Created 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
    
    Viewing tsconfig.json gives the details of what all of the above settings are.
  6. Update tsconfig.json so that the output of builds go to build, this means we can gitignore anything in the build folder. Also change the root directory of source to be src:
    "rootDir": "./src",
    ...
    "outDir": "./build",
    
  7. 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 initialise gts use
    npx gts init
    
  8. Update the package.json file to include a test script for running jest tests, this is as simple as adding a mapping from test to jest:
    {
      "scripts": {
        "test": "jest",
        ...
      }
      ...
    }
    
  9. 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',
      },
    };
    
  10. Initialise Husky, this will set Husky up with a base configuration. To initialise Husky, run:
    npx husky-init
    
  11. Edit .husky/pre-commit so that lint is run on commit rather than test, this will speed up the commit process and enable us to push the testing to the CI server.
  12. Create a .github/workflows folder structure and create a build_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

  1. Create an index.ts source file in ./src/day_00 with the following content:
    function sum(a: string, b: bigint): bigint {
       return a + b;
     }
    
    
     module.exports = sum
    
    Note that the content of this is intentionally wrong, this is to test that all elements of the pipeline work.
  2. Create a index.test.ts file in ./test/day_00 with the following content:
    const t_sum = require('../../src/day_00/index.ts');
    
    test('adds 1 + 2 to equal 3', () => {
          expect(t_sum(1, 2)).toBe(3);})
    
    Again, the content of this doesn’t match our linting rules and this is intentional.
  3. Now we will test the build, this should identify the type issue in the src folder`
    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
    
    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.
  4. 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):
    npm run lint
    
    There should be some errors reported, these can be fixed using the following command:
    npm run fix
    
    Running the lint command again should report no errors
  5. Our final local test is to check the pre-commit hooks, remember that on commit the linter should run:
    git add --all
    
    git commit -a
    
    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 gts silently fixing things for me
  6. 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.