Automatically updating themes and plugins to .gjs file format

AI-generated summary

david announces that Discourse’s standard linting config now requires the require-strict-mode rule, necessitating the conversion of .hbs templates to the .gjs file format. To facilitate this, a new discourse-gjs-codemod has been released. The recommended process involves updating dependencies from the plugin or theme skeletons, running ESLint and Prettier for autofixes, and then executing the codemod.

pfaffman initially encountered an error because the repository was private, but david corrected this by making it public. Afterward, pfaffman reported peer dependency warnings and a command failure, though noted that most templates were successfully converted. david suggested ignoring the peer dependency warnings, and pfaffman confirmed the errors were likely spurious, expressing satisfaction with the tool’s effectiveness.

Other users sought clarification on execution environments. gilles asked if updates should be done on the live server or development environment, prompting david to specify that it must be done in a local development setup. jericson advised checking for updated eslint.config.mjs files depending on when the skeleton was created. Finally, das-g asked how to run the codemod within Docker without installing Node tools locally. david recommended using d/shell to access a terminal inside the container, allowing users to navigate to their plugin directory and run the necessary commands directly within the Docker environment.

In the latest version of Discourse’s standard linting config, we’ve enabled the require-strict-mode ember-template-lint rule. This will raise a linting error for any .hbs files.

To resolve the warnings, you should convert all your component, route, and connector templates to .gjs files. To make this easy, we’ve built the discourse-gjs-codemod, which builds on top of Ember’s @embroider/template-tag-codemod.

To use the codemod, first ensure that your linting dependencies are up-to-date by copying the latest package.json from the plugin skeleton or the theme skeleton. Then, run eslint and prettier:

pnpm i
pnpm eslint --fix .
pnpm prettier --write "**/*.{gjs,js,hbs,scss}"

If any issues could not be autofixed, resolve them manually now. Don’t run ember-template-lint yet - that’s expected to fail.

Now run the codemod using this command:

pnpm dlx https://github.com/discourse/discourse-gjs-codemod

If there are any issues which cannot be automatically resolved, information will be printed to the terminal. Once you’ve resolved the problem, run the codemod again.

For more information about the .gjs file format, check out the official guide:

It wants a password?

 *) pfaffman@noreno:~/src/pfaffman/discourse-pfaffmanager$ pnpm dlx https://github.com/discourse/discourse-gjs-codemod
Username for 'https://github.com': pfaffman
Password for 'https://pfaffman@github.com':
/home/pfaffman/.cache/pnpm/dlx/txqdpi2aznswmhsvgh3pgqp3te/1971d72469d-323788:
 ERROR  Command failed with exit code 128: git ls-remote git+ssh://git@github.com/discourse/discourse-gjs-codemod.git HEAD
ERROR: Repository not found.
fatal: Could not read from remote repository.

https://github.com/discourse/discourse-gjs-codemods doesn’t work. Maybe it’s still private?

:facepalm:

You’re right, it was private. It’s unlocked now:

http://github.com/discourse/discourse-gjs-codemod

That made a very big difference! A bunch of stuff happened.

So glad I’m not the only one that happens to. :rofl:

If you want to delete these three messages, no one will know. :slight_smile:

I can move them to a new topic, but not delete them. . .

What about this?

                                                                                                                                                           [107/859]
 WARN  Issues with peer dependencies found
.
├─┬ ember-auto-import 2.10.0
│ ├─┬ babel-loader 8.4.1
│ │ └── ✕ missing peer webpack@>=2
│ ├─┬ css-loader 5.2.7
│ │ └── ✕ missing peer webpack@"^4.27.0 || ^5.0.0"
│ ├─┬ style-loader 2.0.0
│ │ └── ✕ missing peer webpack@"^4.0.0 || ^5.0.0"
│ └─┬ mini-css-extract-plugin 2.9.2
│   └── ✕ missing peer webpack@^5.0.0
└─┬ ember-source 5.12.0
  ├── ✕ missing peer @glimmer/component@^1.1.2
  └─┬ ember-auto-import 2.10.0
    └── ✕ missing peer webpack@^5.0.0
Peer dependencies that should be installed:
  @glimmer/component@^1.1.2   webpack@">=5.0.0 <6.0.0-0"

…


Done in 1.6s using pnpm v9.15.9
file:///home/pfaffman/.cache/pnpm/dlx/txqdpi2aznswmhsvgh3pgqp3te/1971d8d4970-32e7a4/node_modules/.pnpm/execa@9.6.0/node_modules/execa/lib/return/final-error.js:6
        return new ErrorClass(message, options);
               ^

ExecaError: Command failed with exit code 255: '/home/pfaffman/.cache/pnpm/dlx/txqdpi2aznswmhsvgh3pgqp3te/1971d8d4970-32e7a4/node_modules/.pnpm/@embroider+template-
tag-codemod@1.2.1-unstable.ce3535d_@glimmer+component@2.0.0_handlebars@4._arnanpbg4hbtumvl4wyacggoiu/node_modules/@embroider/template-tag-codemod/dist/src/cli.js' '
--relativeLocalPaths=false' '--nativeRouteTemplates=false' '--nativeLexicalThis=false' '--templateInsertion=end' --addNameToTemplateOnly '--customResolver=/home/pfa
ffman/.cache/pnpm/dlx/txqdpi2aznswmhsvgh3pgqp3te/1971d8d4970-32e7a4/node_modules/.pnpm/discourse-gjs-codemod@https+++codeload.github.com+discourse+discourse-gjs-cod
emod+tar.gz+a4bc_2dxbzd2itovnk6l7sa4geot32y/node_modules/discourse-gjs-codemod/custom-resolver.js' '--renamingRules=/home/pfaffman/.cache/pnpm/dlx/txqdpi2aznswmhsvg
h3pgqp3te/1971d8d4970-32e7a4/node_modules/.pnpm/discourse-gjs-codemod@https+++codeload.github.com+discourse+discourse-gjs-codemod+tar.gz+a4bc_2dxbzd2itovnk6l7sa4geo
t32y/node_modules/discourse-gjs-codemod/rules.js' '--renderTests=test/**/*.js' '--routeTemplates=**/templates/**/*.hbs' '--components=**/components/**/*.hbs'

But it looks like it converted all but a couple of the templates, and though I don’t yet understand why, I’m not surprised, as they have some wacky stuff in them and I was in the process of re-writing them anyway.

I think the peerdependency message is probably just a warning which can be ignored for the purposes of the codemod.

Not sure about the other error. Is there anything more useful further up in the log? Is this a public theme/plugin you could share?

Yeah. I think the errors are all spuriois. Only a couple things didn’t get converted. I’m not sure why, but like I said, I was planning on rewriting those anyway.

I think it was a dozen or more that it did manage to rewrite, so it’s an absolute miracle!

I will try it on some other stuff that is public soon.

Thanks!

A small question regarding the update of .gps formats. Should I do it from discourse development or directly on discourse?

I am using self-hosted discourse docker and I tried the command but it doesn’t work

pnpm i
pnpm eslint --fix .
pnpm prettier --write “\*\*/\*.{gjs,js,hbs,scss}”

It should be done in a local discourse development environment.

Depending on how long ago you created a plugin from the skeleton, you might also need to grab eslint.config.mjs.

Is there a way to do this using the Docker-based development setup from Install Discourse for development using Docker, i.e., without installing pnpm or other node stuff directly on the host?

I guess I’d have to use d/pnpm in place of pnpm, but how would I instruct it to act on my plugin rather than the discourse source code? I have them in sibling directories:

The easiest thing is probably to use d/shell. That will give you a terminal running inside the container, and you can follow the instructions in the OP.

So it would be something like:

d/shell

Then once you’re inside the container:

cd plugins/discourse-weekly-newsletter
pnpm dlx @discourse/update-skeleton@latest
pnpm eslint --fix .
pnpm prettier --write "**/*.{gjs,js,hbs,scss}"
pnpm dlx https://github.com/discourse/discourse-gjs-codemod