September 26, 2022

Codemods

Codemods

I'm excited to announce we've added the ability to do automated large-scale codebase refactors to Githasx!

We've named this feature Codemod after the open-source tool Facebook created - which is now archived.

Facebook created Codemod to make refactoring their code bases easier by automating the refactoring with scripts. In practice, a developer would create a codemod script and then use a CLI tool to execute the codemod on a repository. This is extremely helpful if you need to upgrade a library which has breaking API changes - you can write a codemod to automate the updates. Vue has created a codemod repository to help developers upgrade their versions of Vue.

Codemods are great, but there is still one point of friction, what happens if you need to apply this same codemod to hundreds of repositories? Well, before today, a developer would need to clone each repo, run the CLI, create a pull request, and wait for it to be merged in. This is the definition of TOIL and I assure you no developer enjoys this type of work.

With the addition of Codemods to Githaxs we have made the first three steps of the process much easier. Using Githaxs the current way to apply codemods to many repos looks like this:

  • Create a codemod file (more on this to come)
  • Create a single pull request adding the codemod to your codmod repo
  • Githaxs creates a preview Pull Request for you to review and ensure the codemod works as expected
  • Merge the codemod Pull Request
  • Githaxs applies the codemod and creates Pull Requests in all of the repos you specified

Think of this tool like Dependabot or Renovate Bot, but on steroids. You can now bulk update anything: CircleCI Configs, README templates, .gitignore files, major library upgrades, etc and not just dependencies.

How does it work?

If you haven't already, install the Githaxs GitHub application.

Next, you'll need a repository to store all of your codemods. Think of this repository as a directory that would store your Database migrations but instead stores a history of all codemod scripts you've run. I recommend the following configuration for the repo:


.
├── codemods
│   ├── 001-test-mods.yaml
│   ├── 002-test-pull-request.yaml
│   └── 003-standardize-gitignore.yaml
├── scripts
└── templates

Once this repository is created, login to your Githaxs Dashboard and edit the settings for the Codemod task to run on the repo you created above and save the settings.

Now it's time to see this in action. In your codemod repo add a new yaml file with the following format:


name: Standard .gitignore files # <-- name of the codemod, used in pull requests
repos: # <-- list of repos to run the codemod on - the first repo will be used for the preview pull request
  - autopep8
  - bandit
  - checkov
  - code-freeze
  - hadolint
  - horusec
  - max-wip
  - pr-too-big
  - pylint
  - pytest
  - semgrep
  - shellcheck
  - trivy
  - title-lint
description: | # <-- description of codemod will be included in description of pull requests
  This codemod is to add standard .gitignore files in all of the task repos.
commands: | # <-- codemod commands to run
  cp $CODE_MOD_REPO/templates/.gitignore .

Create a pull request and within a few seconds and you should see a new pull request created on the test repo (i.e. the first repo in the list).

Review this Pull Request to ensure the codemod is doing exactly what you expect. In the Pull Request you will be able to see the codemod commands that were executed as well as any output, if there was any.

Any time you make changes to the pull request with the codemod it will automatically run again the codemod again on the test repo and update the pull request.

The last step is to merge in your codemod. Once this is done Githaxs will run the codemod on the remaining repositories in your list and create a Pull Request for each one. Githaxs will also link all of the created pull requests to the codemod pull request.

Additional Details

Your codemod scripts are able to use standard linux commands, python3.9, and the Jinja CLI to render templates.

Your codemod scripts will also have a variable named CODE_MOD_REPO so you can reference various files in your codemod repo in your codemod scripts. As an example, you can include a jinja template for CircleCI configs named templates/.config.j2 and reference it in your codemod script as $CODE_MOD_REPO/templates/.config.j2.

Related posts

Browse all posts
We haven't published any posts