Skip to content

Instantly share code, notes, and snippets.

@yelhouti
Last active October 30, 2024 04:41
Show Gist options
  • Save yelhouti/bcefa769a421dd60298b34ad653a4d86 to your computer and use it in GitHub Desktop.
Save yelhouti/bcefa769a421dd60298b34ad653a4d86 to your computer and use it in GitHub Desktop.
jhipster generation upgrades

Code Generation

There two main approches of handling upgrades when using a code generator:

  1. The generated code is never touched (only extended...), and regeneration only updates these files
  2. Generated code is stored in a separate branch where generation is done no changes are done manually, the generated branch is merged with master at each upgrade

I find the first approach hard to work with for two reasons:

  1. some files can't be extended like package.json ...
  2. Extending all the files makes for bigger code base and adding simple changes can add a lot of work

the second approch can also be combursume, when you need to merge a big project but I find it to be the best tradeoff

Jhipster

For Jhipster (up to now), all the code is generated in the beggining from a JDL file (jhipster.jh)

In our case we use two blueprints:

npx jhipster import-jdl --blueprints primeng-blueprint jhipster.jh

This automatically creates our initial commit and we create a new branch import-jdl form this same commit.

Update JHipster or Blueprints versions

Next time we want to regenarate the project:

  1. we switch back to the branch import-jdl
git checkout import-jdl
  1. we update the jhipster version and blueprints in its package.json and install them:
npm install
  1. delete all the files except the ones we need to avoid keeping file not generated anymore:
rm -rf !(".git"|".jhipster"|"jhipster.jh"|"node_modules"|".yo-rc.json")
  1. modify .yo-rc to remove deleted entities and remove them from the .jhipster folder and restore liquibase files
  2. regenarte the project:
jhipster import-jdl --blueprints primeng-blueprint,composite-key-server jhipster.jh

When we want to only add a field, or make a small change and there is no risk of forgetting an old file..., we can just regenerate on top of the old files without mentionning the blueprints... by running:

jhipster import-jdl jhipster.jh --force

Once the project is inproducation the command above breaks liquibase, this was known issue as was fixed by creating the diff of the liquibase file manually, now this possible with the new flag: --incremental-changelog

jhipster import-jdl --incremental-changelog  jhipster.jh

There is a bug when using incremental changelogs and generating fake-data (relationship fake-data is not present). To fix this you can add --skip-fake-data carefull, not update application-dev.yml and remove faker profile And change back "skipFakeData": false in .yo-rc.json

Often, you don't want to merge directly into master, (you don't have the permissions, their is a CI you want to go through...) in this case:

  • you create a branch merge-import-jdl from master
  • merge into it
  • fix your tests...
  • amend the extra commit if one was added for merging or add a new one for merging
  • use git log to make sure that you did NOT amend the commit just created in import-jdl in this branch history,with AT MOST ONE for your tests fixes... (the one you ammend)
  • create a pull request WITHOUT the option squash commits, to endup with the commit from import-jdl inside master, so that, hopefully, next merges don't require you to resolve the same conflicts

rerere (remember conflict resolution)

Often, after merging and spending a lot of time resolving conflicts, and adding code after the merge into the new feature-branch feature-x, we find out that there is an issue with the generated code (forget to add/remove pagination, field missing...), or we just needed to apply a hot-fix to main and have to remerge everything again. (we can't just rebase, as the last import-jdl commit hash will change between main and import-jdl).

If rerere was enabled before the first merge (using this command):

git config --global rerere.enabled true

git remembers conflicts resolutions and once we want to remerge, it automatically resolves all conflicts that it rembers from the previous merge. carefull though, rerere doesn't automatically add these files and when using git status it looks like there are still a lot of conflicts to solve manually. Even your IDE doesn't clearly show that the conflicts where resolved.

Before remerging your changes into master first create a bkp of feature-x branch.

git branch -m feature-x-bkp

checkout main and remerge.

git checkout main
git merge import-jdl

To check which files still have conflicts use:

git rerere status

you can also double chec by looking for <<<<<<< HEAD in the project. To add all files except those:

 git ls-files -m | grep -v -f <(git rerere status) | xargs git add

now when you git status you see only the files that still have issues. Use your IDE to resolve conflicts. Make a last check for <<<<<<< HEAD and

git merge --continue
git checkout -b feature-x

do not forget to go back to main and reset it to origin main.

git checkout main
git reset origin/main --hard
git checkout feature-x

For all the work done in commits after the merge, you can just git cherry-pick it.

One could argue that I should not merge merge into main, but create a copy of main then merge into it to avoid this last step, but I prefer when the atiomatically generate commit message says Merge branch 'import-jdl' instead of Merge branch 'import-jdl' into feature-x but to each there own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment