Using ES6 modules as GitHub custom action

Is it possible to use ES6 style modules when writing custom actions? I am getting all sorts of issues when trying to use them. In the unbundle form (regulard js wiht node_modules committed) I get this error:

SyntaxError: Cannot use import statement outside a module

while in the compiled (bundled) form I get in turn these errors:

(node:6304) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'info' of undefined

This one specifically on imported @actions/core. Plus in the compiled form there are bunch of requires as well and node.js (rightly) complains about mixing import and requires.

So neither way of doing actions supported by GitHub allow ES6 modules it seems. How are the actions called anyway? When I call node main.js locally it works without problems in either form.

Thanks for your feedback.
Do you have a link to the repository or a minimal example repository that shows this behaviour?

What is the version of node you are using in the local environment?
What is the version of node you are using in the action.yml?
May be this problem related to the node version.

It is a private organization in our company’s Enterprise subscription so unfortunately I cannot point you to it.

I am running it on Ubuntu-latest where I believe is node 12. Locally I have node 14. From the link you provided I was missing the --experimental-modules flag it seems. How would I include it in the action?

Thanks for your update.
We cannot investigate further due to lack of information. So could you please create a demo public repo demonstrating this?

Thanks @niconbw but there is no need. The problem is the lack of --experimental-modules flag when running the action since the agents are running Node 12 that still requires it (unlike Node 14 where it is no longer experimental). I just don’t know where to put it. Into the action.yml? E.g.

runs:
  using: 'node12'
  main: 'main.js --experimental-modules'

I’m afraid it doesn’t work.

runs:
using: ‘node12’
main: ‘main.js --experimental-modules’

The previous --experimental-modules allowed import statements of JSON and native modules. This has been removed.

you have to either add a "type": "module" field in your package.json or use the .mjs extension: https://nodejs.org/dist/latest-v12.x/docs/api/esm.html#esm_enabling.
The implementation of ESM in Node.js changed in version 12.0.0.

I have finally figured out how to work around this.

tl;dr

  • remove "type": "module" from the package.json
  • use ncc to compile into .js extension
  • use import * as "something" from "package" syntax beacuse otherwise the ncc will incorrectly process the imports

Unfortunately this is less than ideal but it works. It makes development locally harder ("type": "module" is required for node greater than 12). But when used and interpreted by node12 it will see it in the package.json fro the compiled script and throw a fit. The compiling by ncc also requires that alternative import syntax is used for some reason (import * as x from "whatever"). It is required for using GitHub’s own toolkit like @actions/core or @actions/exec. Otherwise you will get either error that you cannot use require() in modules (when type: module is set in package.json) or that the imported thing is undefined (if using plain syntax, e.g. import actions from "@actions/core" without the modules). I could continue how various combinations of extensions (cjs, mjs, js), settings and ways to do it (committed node_modules, using ncc) don’t work for one reason or another. Even this works only partially.

It is a mess (I undersand it is not GH’s mess but rather node’s mess) and I believe it would be resolved if there was an option to run node14 with actions. It is present on all virtual environments already. Yet when tried (using: node12 in action.yml) you will be told only docker and node12 is available. Hopefully it will be improved sometime soon.