diff --git a/CHANGELOG.md b/CHANGELOG.md index 7952088837d..a1ed21a735b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Markup change in `LinkView` component. - Rename `core-sandbox` to `coresandbox` for sake of consistency @sneridagh +- Extend the original intent and rename `RAZZLE_TESTING_ADDONS` to `ADDONS`. @sneridagh See https://docs.voltocms.com/upgrade-guide/ for more information. ### Feature diff --git a/__tests__/addon-registry.test.js b/__tests__/addon-registry.test.js index cd768dd8dc9..d8f60a2ff0d 100644 --- a/__tests__/addon-registry.test.js +++ b/__tests__/addon-registry.test.js @@ -184,3 +184,53 @@ describe('Addon chain loading dependencies', () => { ]); }); }); + +describe('Addon via env var - Released addon', () => { + const originalEnv = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { + ...originalEnv, + ADDONS: 'test-released-via-addons-env-var', + }; + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it('addons can be specified on the fly using ADDONS env var - Released addon', () => { + const base = path.join(__dirname, 'fixtures', 'test-volto-project'); + const reg = new AddonConfigurationRegistry(base); + expect( + Object.keys(reg.packages).includes('test-released-via-addons-env-var'), + ).toBe(true); + }); +}); + +describe('Addon via env var - local packages folder addon', () => { + const originalEnv = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { + ...originalEnv, + ADDONS: 'test-local-packages-via-addons-env-var', + }; + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it('addons can be specified on the fly using ADDONS env var - local packages folder addon', () => { + const base = path.join(__dirname, 'fixtures', 'test-volto-project'); + const reg = new AddonConfigurationRegistry(base); + expect( + Object.keys(reg.packages).includes( + 'test-local-packages-via-addons-env-var', + ), + ).toBe(true); + }); +}); diff --git a/__tests__/fixtures/test-volto-project/node_modules/test-released-via-addons-env-var/index.js b/__tests__/fixtures/test-volto-project/node_modules/test-released-via-addons-env-var/index.js new file mode 100644 index 00000000000..53e61140f21 --- /dev/null +++ b/__tests__/fixtures/test-volto-project/node_modules/test-released-via-addons-env-var/index.js @@ -0,0 +1,2 @@ +export default (config) => config; + diff --git a/__tests__/fixtures/test-volto-project/node_modules/test-released-via-addons-env-var/package.json b/__tests__/fixtures/test-volto-project/node_modules/test-released-via-addons-env-var/package.json new file mode 100644 index 00000000000..c6a44243100 --- /dev/null +++ b/__tests__/fixtures/test-volto-project/node_modules/test-released-via-addons-env-var/package.json @@ -0,0 +1,4 @@ +{ + "name": "test-released-via-addons-env-var", + "main": "index.js" +} diff --git a/__tests__/fixtures/test-volto-project/packages/test-local-packages-via-addons-env-var/package.json b/__tests__/fixtures/test-volto-project/packages/test-local-packages-via-addons-env-var/package.json new file mode 100644 index 00000000000..7e6c4a11fbf --- /dev/null +++ b/__tests__/fixtures/test-volto-project/packages/test-local-packages-via-addons-env-var/package.json @@ -0,0 +1,4 @@ +{ + "name": "test-local-packages-via-addons-env-var", + "main": "src/index.js" +} diff --git a/__tests__/fixtures/test-volto-project/packages/test-local-packages-via-addons-env-var/src/index.js b/__tests__/fixtures/test-volto-project/packages/test-local-packages-via-addons-env-var/src/index.js new file mode 100644 index 00000000000..8cb61d300ac --- /dev/null +++ b/__tests__/fixtures/test-volto-project/packages/test-local-packages-via-addons-env-var/src/index.js @@ -0,0 +1 @@ +export default (config) => config; diff --git a/addon-registry.js b/addon-registry.js index fcf3aea415e..c8f4d6c08cb 100644 --- a/addon-registry.js +++ b/addon-registry.js @@ -124,7 +124,7 @@ class AddonConfigurationRegistry { this.initDevelopmentPackages(); this.initPublishedPackages(); - this.initTestingPackages(); + this.initAddonsFromEnvVar(); this.dependencyGraph = buildDependencyGraph( this.resultantMergedAddons, @@ -203,15 +203,16 @@ class AddonConfigurationRegistry { } } - initTestingPackages() { - if (process.env.RAZZLE_TESTING_ADDONS) { - process.env.RAZZLE_TESTING_ADDONS.split(',').forEach( - this.initTestingPackage.bind(this), + initAddonsFromEnvVar() { + if (process.env.ADDONS) { + process.env.ADDONS.split(',').forEach( + this.initAddonFromEnvVar.bind(this), ); } } - initTestingPackage(name) { + initAddonFromEnvVar(name) { + // First lookup in the packages folder, local to the root (either vanilla Volto or project) const normalizedAddonName = name.split(':')[0]; const testingPackagePath = `${this.projectRootPath}/packages/${normalizedAddonName}/src`; if (fs.existsSync(testingPackagePath)) { @@ -233,6 +234,10 @@ class AddonConfigurationRegistry { this.packages[normalizedAddonName] || {}, pkg, ); + } else { + // Fallback in case the addon is released (not in packages folder nor in development, but in node_modules) + const normalizedAddonName = name.split(':')[0]; + this.initPublishedPackage(normalizedAddonName); } } @@ -385,14 +390,14 @@ class AddonConfigurationRegistry { } /** - * Allow testing packages addons to customize Volto and other addons. + * Allow packages from addons set in env vars to customize Volto and other addons. * - * Same as the above one, but specific for Volto testing addons + * Same as the above one, but specific for Volto addons coming from env vars */ - getTestingAddonCustomizationPaths() { + getAddonsFromEnvVarCustomizationPaths() { let aliases = {}; - if (process.env.RAZZLE_TESTING_ADDONS) { - process.env.RAZZLE_TESTING_ADDONS.split(',').forEach((addon) => { + if (process.env.ADDONS) { + process.env.ADDONS.split(',').forEach((addon) => { const normalizedAddonName = addon.split(':')[0]; const testingPackagePath = `${this.projectRootPath}/packages/${normalizedAddonName}/src`; if (fs.existsSync(testingPackagePath)) { diff --git a/docs/source/configuration/environmentvariables.md b/docs/source/configuration/environmentvariables.md index 790c0dc4758..8a702d0397f 100644 --- a/docs/source/configuration/environmentvariables.md +++ b/docs/source/configuration/environmentvariables.md @@ -89,3 +89,77 @@ It displays the errors of the non-compliant customizations (in server console) i #### Internationalization errors (i18n) It will enable the log of missing i18n messages (in console). + +## Use add-ons via the `ADDONS` environment variable + +You can use the `ADDONS` environment variable to enable and configure add-ons in your project. + +When running your app, the add-ons will be loaded in the following order: + +- the file `package.json` +- programmatically set in the file `volto.config.js` +- the environment variable `ADDONS` + +In the environment variable `ADDONS`, you can specify: + +- released (or published) packages that were installed previously in your environment and are already present in the `node_modules` directory, +- or addons located in the `packages` folder of your project, such as Volto's testing packages. + +`ADDONS` can be used to temporarily add an add-on to your build for testing purposes. + +```bash +yarn add volto-slate +ADDONS=volto-slate:asDefault yarn start +``` + +`ADDONS` can also be used to temporarily enable a feature or a set of customizations. + +```bash +# given a folder './packages/coresandbox', like in vanilla Volto +ADDONS=coresandbox:multilingualFixture yarn start +``` + +You can specify multiple add-ons, seperated by commas: + +```bash +ADDONS=test-addon,test-addon2 yarn start +``` + +You can specify profiles for installation: + +```bash +ADDONS=test-addon:profile1,test-addon2:profile2 yarn start +``` + +The following code snippets demonstrate how to configure add-ons. +First in `package.json`: + +```json +"addons": [ + "@kitconcept/volto-blocks-grid" +] +``` + +...next in `volto.config.js`: + +```js +module.exports = { + addons: ['@eeacms/volto-accordion-block'] +} +``` + +...and finally using `ADDONS`: + +```bash +yarn add volto-slate +ADDONS=volto-slate:asDefault yarn start +``` + +As a result, your app will load the add-ons in the following order: + +- `@kitconcept/volto-blocks-grid` +- `@eeacms/volto-accordion-block` +- `volto-slate` + +!!! important + `ADDONS` does *not* work for development packages, which are *always* enabled if defined in your `jsconfig.json` or via `mrs.developer.json`. diff --git a/docs/source/developer-guidelines/testing.md b/docs/source/developer-guidelines/testing.md index 18f17cad975..4205bdfe18f 100644 --- a/docs/source/developer-guidelines/testing.md +++ b/docs/source/developer-guidelines/testing.md @@ -22,11 +22,16 @@ environment variable. This is specially useful in CI while developing add-ons, so you can pass an specific configuration that deals with the addon config properly. -## Add addons for testing purposes +## Add add-ons via environment variable for testing purposes -Quite often, you need different configurations and enabling components for testing purposes. You can use the `RAZZLE_TESTING_ADDONS` environment variable to define them. These addons do not have the capacity to install dependencies (as opposed to properly defined addons), but all the rest of the addon features work as expected. +Sometimes you need to enable different configurations and enable optional components (for example, testing purposes). +You can use the `ADDONS` environment variable to define them. - RAZZLE_TESTING_ADDONS=test-addon,test-addon2 yarn start +```bash +ADDONS=test-addon,test-addon2 yarn start +``` + +See [Add-ons via environment variables](../configuration/environmentvariables.md) for more information. ## Developing Cypress tests diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 41df4d597ea..7d98fdc8cd7 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -43,6 +43,15 @@ The `LinkView` component `The link address is:` part now it's wrapped in a `

` Only applying to Volto core development, for the sake of consistency with the other fixtures, `core-sandbox` fixture it's been renamed to `coresandbox` in all scripts and related file paths and filenames. +### Extend the original intent and rename `RAZZLE_TESTING_ADDONS` to `ADDONS`. + +Originally the `RAZZLE_TESTING_ADDONS` environment variable was an escape hatch to load some components and configurations not present in vanilla Volto. +One could enable them at will. +Initially thought as fixtures for acceptance tests, the original intent has been repurposed and extended to just `ADDONS`. +One could extend the `ADDONS` list configuration via this environment variable. + +It works for published packages, such as those add-ons that live in the `packages` folder locally to your project. +This is similar to the testing add-ons from vanilla Volto. ## Upgrading to Volto 14.x.x diff --git a/package.json b/package.json index c180e967441..db0e49ab818 100644 --- a/package.json +++ b/package.json @@ -70,11 +70,11 @@ "ci:start-api-plone-workingCopy": "make test-acceptance-server-workingcopy", "ci:start-api-guillotina": "make test-acceptance-guillotina", "ci:start-frontend": "RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run", - "ci:start-frontend-coresandbox": "RAZZLE_TESTING_ADDONS=coresandbox RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run:coresandbox", - "ci:start-frontend-multilingual": "RAZZLE_TESTING_ADDONS=coresandbox:multilingualFixture RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run:multilingual", - "ci:start-frontend-workingCopy": "RAZZLE_TESTING_ADDONS=coresandbox:workingCopyFixture RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run:workingCopy", + "ci:start-frontend-coresandbox": "ADDONS=coresandbox RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run:coresandbox", + "ci:start-frontend-multilingual": "ADDONS=coresandbox:multilingualFixture RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run:multilingual", + "ci:start-frontend-workingCopy": "ADDONS=coresandbox:workingCopyFixture RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 cypress:run:workingCopy", "ci:start-project-frontend": "cd my-volto-app && RAZZLE_API_PATH=http://localhost:55001/plone yarn build && start-test start:prod http://localhost:3000 'cd .. && yarn cypress:run'", - "ci:start-frontend-guillotina": "RAZZLE_TESTING_ADDONS=volto-guillotina RAZZLE_API_PATH=http://localhost:8081/db/web RAZZLE_LEGACY_TRAVERSE=true yarn build && start-test start:prod http://localhost:3000 cypress:run:guillotina", + "ci:start-frontend-guillotina": "ADDONS=volto-guillotina RAZZLE_API_PATH=http://localhost:8081/db/web RAZZLE_LEGACY_TRAVERSE=true yarn build && start-test start:prod http://localhost:3000 cypress:run:guillotina", "ci:cypress:run": "start-test ci:start-api-plone http-get://localhost:55001/plone ci:start-frontend", "ci:cypress:project:run": "start-test ci:start-api-plone http-get://localhost:55001/plone ci:start-project-frontend", "ci:cypress:run:coresandbox": "start-test ci:start-api-plone-coresandbox http-get://localhost:55001/plone ci:start-frontend-coresandbox", diff --git a/razzle.config.js b/razzle.config.js index 04948e6a998..70fe2a88806 100644 --- a/razzle.config.js +++ b/razzle.config.js @@ -181,13 +181,13 @@ const defaultModify = ({ // Disabling the ESlint pre loader config.module.rules.splice(0, 1); - let testingAddons = []; - if (process.env.RAZZLE_TESTING_ADDONS) { - testingAddons = process.env.RAZZLE_TESTING_ADDONS.split(','); + let addonsFromEnvVar = []; + if (process.env.ADDONS) { + addonsFromEnvVar = process.env.ADDONS.split(','); } const addonsLoaderPath = createAddonsLoader( - [...registry.getAddonDependencies(), ...testingAddons], + [...registry.getAddonDependencies(), ...addonsFromEnvVar], registry.packages, ); @@ -197,8 +197,8 @@ const defaultModify = ({ ]; config.resolve.alias = { - ...registry.getTestingAddonCustomizationPaths(), ...registry.getAddonCustomizationPaths(), + ...registry.getAddonsFromEnvVarCustomizationPaths(), ...registry.getProjectCustomizationPaths(), ...config.resolve.alias, '../../theme.config$': `${projectRootPath}/theme/theme.config`, @@ -237,8 +237,8 @@ const defaultModify = ({ addonsAsExternals = registry.addonNames.map((addon) => new RegExp(addon)); } - if (process.env.RAZZLE_TESTING_ADDONS) { - testingAddons.forEach((addon) => { + if (process.env.ADDONS) { + addonsFromEnvVar.forEach((addon) => { const normalizedAddonName = addon.split(':')[0]; const p = fs.realpathSync( registry.packages[normalizedAddonName].modulePath,