Marketing Codemods
This is the home for codemods intended for use on web projects managed by the digital marketing team.
Iterations on shared packages such as components and design tokens sometimes result in breaking changes. Accounting for those changes can be a time-consuming chore. Many changes have straightforward upgrade paths, but occur many times throughout a project. Codemods can reduce the time and effort needed to account for such changes.
So far, we've explored two flavours of codemods:
- Javascript, with
jscodeshift
- CSS, with
postcss
plugins and postcss-cli
Running Codemods on Your Project
To run a codemod, you can use the CLI interface as such:
$ npx @hashicorp/mktg-codemods
The CLI will guide you through the process of selecting a codemod to run and running it for your project. It will not allow codemods to run unless you have a clean git working tree. This ensures that if the changes didn't work the way you want, you can roll them back without any of your other work being affected.
The CLI can be run without arguments and will allow you to select your desired arguments without issue. It also accepts direct arguments. For example, if you know you want to run a specific codemod, let's say it's called 2019-09-10-foo
, you could invoke the CLI as such:
$ npx @hashicorp/mktg-codemods 2019-09-10-foo
Codemod names are the name of the folder within /codemods
in this project.
Writing a Codemod
To get started writing a new codemod, run npm run generate
- this will get you started with a good base template in the codemods
folder. Your codemod can contain javascript and/or css modification scripts, which are contained in js
and/or css
folders. Let's talk about how each type of codemod is structured.
Javascript Codemods
JS codemods are typically written with jscodeshift. Their docs are excellent, and there are several good examples of jscodeshift codemods in this repo and in other places. Your entry point is <your-codemod>/js/index.js
, which exports a function that is expected to return a string representing the modified source code. In between, you are encouraged to use jscodeshift to write a transform, but it's not mandatory, and if you can truly achieve your goal easily with a regular expression, its not off limits.
CSS Codemods
CSS codemods are typically written with postcss, as plugins. Since postcss parses css and allows plugins to modify the AST, it is a perfect tool for precisely modifying css. Your entrypoint is <your-codemod>/css/index.js
, which exports a function that expects to recieve a promise returned from postcss processing.
Codemod Utilities
There are a number of shared utilities in the utils
folder. Make sure to take a look and see if there's a tool that fits your codemod's needs already before you start writing code! If you are writing a codemod that you feel follows a common pattern that would be needed in future codemods, also by all means consider wrapping your behavior in a utility and adding to the utils
folder.
Testing Codemods
You can test codemods using jest
, which is configured and installed for this project. For an example of how one might test a codemod, check out this codemod and its tests.
Tests are recommended simply for the benefits of using TDD to write your code more quickly. Since codemods are ot meant to change and evolve over time, you are not writing tests to ensure that a feature works in the face of changes over time, as tests are often used otherwise, but rather to make the process of working/iterating on your codemod and verifying that it behaves the way you expect as fast and easy as possible.
The recommended approach is to set up a test as soon as you begin working on your codemod, and to run jest --watch
, which will re-run your tests as you make changes to your code and test fixtures. This way, you can make code changes and immediately see the effects on your sample code structure. Typically the best way to run tests like this is to use test fixtures and console.log
the results of your codemods running on sample code. Once you are at a place where the codemod does what you intend it to, you can "lock" your tests by using jest's snapshot feature to verify that your results are the expected results of a codemod run.