diff --git a/config/schema.error.yaml b/config/schema.error.yaml
index 2e57576a2..23e65fdce 100644
--- a/config/schema.error.yaml
+++ b/config/schema.error.yaml
@@ -440,6 +440,16 @@
suggestion: 'Check the `cloud.log` for more information.'
stage: general
type: critical
+!php/const Magento\MagentoCloud\App\Error::GLOBAL_WEBHOOKS_MODULE_GENERATE_FAILED:
+ title: 'Unable to generate a module for commerce webhooks'
+ suggestion: 'Check the `cloud.log` for more information.'
+ stage: general
+ type: critical
+!php/const Magento\MagentoCloud\App\Error::GLOBAL_WEBHOOKS_MODULE_ENABLEMENT_FAILED:
+ title: 'Unable to enable a module for commerce webhooks'
+ suggestion: 'Check the `cloud.log` for more information.'
+ stage: general
+ type: critical
# Warning errors
!php/const Magento\MagentoCloud\App\Error::WARN_CONFIG_PHP_NOT_EXISTS:
title: 'File app/etc/config.php does not exist'
diff --git a/config/schema.yaml b/config/schema.yaml
index 5317b4d4f..ab0342534 100644
--- a/config/schema.yaml
+++ b/config/schema.yaml
@@ -717,6 +717,17 @@ variables:
- stage:
global:
ENABLE_EVENTING: true
+ ENABLE_WEBHOOKS:
+ description: Enables commerce webhooks.
+ type: boolean
+ stages:
+ - global
+ default:
+ global: false
+ examples:
+ - stage:
+ global:
+ ENABLE_WEBHOOKS: true
# Environment variables
ENV_RELATIONSHIPS:
diff --git a/dist/error-codes.md b/dist/error-codes.md
index 17355c388..2a533fb30 100644
--- a/dist/error-codes.md
+++ b/dist/error-codes.md
@@ -102,6 +102,8 @@ Critical errors indicate a problem with the Commerce on cloud infrastructure pro
| 246 | | Unable to read the `.schema.yaml` file | |
| 247 | | Unable to generate a module for eventing | Check the `cloud.log` for more information. |
| 248 | | Unable to enable a module for eventing | Check the `cloud.log` for more information. |
+| 249 | | Unable to generate a module for commerce webhooks | Check the `cloud.log` for more information. |
+| 250 | | Unable to enable a module for commerce webhooks | Check the `cloud.log` for more information. |
## Warning Errors
diff --git a/scenario/build/generate.xml b/scenario/build/generate.xml
index 008161aa0..4e3ccbff1 100644
--- a/scenario/build/generate.xml
+++ b/scenario/build/generate.xml
@@ -30,6 +30,7 @@
+
diff --git a/src/App/Error.php b/src/App/Error.php
index 11d6cd830..7835f3679 100644
--- a/src/App/Error.php
+++ b/src/App/Error.php
@@ -96,6 +96,8 @@ class Error
public const GLOBAL_CONFIG_UNABLE_TO_READ_SCHEMA_YAML = 246;
public const GLOBAL_EVENTING_MODULE_GENERATE_FAILED = 247;
public const GLOBAL_EVENTING_MODULE_ENABLEMENT_FAILED = 248;
+ public const GLOBAL_WEBHOOKS_MODULE_GENERATE_FAILED = 249;
+ public const GLOBAL_WEBHOOKS_MODULE_ENABLEMENT_FAILED = 250;
/**
* Build
diff --git a/src/Config/StageConfigInterface.php b/src/Config/StageConfigInterface.php
index 36d1ca4e8..5df54d544 100644
--- a/src/Config/StageConfigInterface.php
+++ b/src/Config/StageConfigInterface.php
@@ -43,6 +43,7 @@ interface StageConfigInterface
public const VAR_SCD_NO_PARENT = 'SCD_NO_PARENT';
public const VAR_X_FRAME_CONFIGURATION = 'X_FRAME_CONFIGURATION';
public const VAR_ENABLE_EVENTING = 'ENABLE_EVENTING';
+ public const VAR_ENABLE_WEBHOOKS = 'ENABLE_WEBHOOKS';
/**
* Settings for deployment from git.
diff --git a/src/Step/Build/EnableWebhooks.php b/src/Step/Build/EnableWebhooks.php
new file mode 100644
index 000000000..4f1c5ee67
--- /dev/null
+++ b/src/Step/Build/EnableWebhooks.php
@@ -0,0 +1,94 @@
+logger = $logger;
+ $this->magentoShell = $shellFactory->createMagento();
+ $this->globalConfig = $globalConfig;
+ }
+
+ /**
+ * Generates and enables a module for commerce webhooks
+ * if @see StageConfigInterface::VAR_ENABLE_WEBHOOKS set to true
+ *
+ * {@inheritDoc}
+ */
+ public function execute()
+ {
+ try {
+ if (!$this->globalConfig->get(StageConfigInterface::VAR_ENABLE_WEBHOOKS)) {
+ return;
+ }
+ } catch (ConfigException $e) {
+ throw new StepException($e->getMessage(), $e->getCode(), $e);
+ }
+
+ try {
+ $this->logger->notice('Generating module for commerce webhooks');
+ $this->magentoShell->execute('webhooks:generate:module');
+ } catch (ShellException $e) {
+ $this->logger->error(
+ 'Failed to generate the AdobeCommerceWebhookPlugins module. ' .
+ 'Refer to the commerce webhooks documentation to determine if all ' .
+ 'required modules are have been installed. ' .
+ 'Error: ' . $e->getMessage()
+ );
+ throw new StepException($e->getMessage(), Error::GLOBAL_WEBHOOKS_MODULE_GENERATE_FAILED, $e);
+ }
+
+ try {
+ $this->logger->notice('Enabling module for commerce webhooks');
+ $this->magentoShell->execute('module:enable Magento_AdobeCommerceWebhookPlugins');
+ } catch (ShellException $e) {
+ $this->logger->error('Failed to enable module for commerce webhooks: ' . $e->getMessage());
+ throw new StepException($e->getMessage(), Error::GLOBAL_WEBHOOKS_MODULE_ENABLEMENT_FAILED, $e);
+ }
+ }
+}
diff --git a/src/Test/Unit/Config/SchemaTest.php b/src/Test/Unit/Config/SchemaTest.php
index e8ff40030..90e0643c2 100644
--- a/src/Test/Unit/Config/SchemaTest.php
+++ b/src/Test/Unit/Config/SchemaTest.php
@@ -175,6 +175,7 @@ public function testGetDefaultsForGlobalSection(): void
StageConfigInterface::VAR_MIN_LOGGING_LEVEL => '',
StageConfigInterface::VAR_X_FRAME_CONFIGURATION => 'SAMEORIGIN',
StageConfigInterface::VAR_ENABLE_EVENTING => false,
+ StageConfigInterface::VAR_ENABLE_WEBHOOKS => false,
],
$this->schema->getDefaults(StageConfigInterface::STAGE_GLOBAL)
);
diff --git a/src/Test/Unit/Step/Build/EnableWebhooksTest.php b/src/Test/Unit/Step/Build/EnableWebhooksTest.php
new file mode 100644
index 000000000..eb2bcbd46
--- /dev/null
+++ b/src/Test/Unit/Step/Build/EnableWebhooksTest.php
@@ -0,0 +1,165 @@
+loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
+ $this->magentoShellMock = $this->createMock(MagentoShell::class);
+ /** @var ShellFactory|MockObject $shellFactoryMock */
+ $shellFactoryMock = $this->createMock(ShellFactory::class);
+ $shellFactoryMock->expects($this->once())
+ ->method('createMagento')
+ ->willReturn($this->magentoShellMock);
+ $this->globalConfigMock = $this->createMock(GlobalSection::class);
+
+ $this->step = new EnableWebhooks(
+ $this->loggerMock,
+ $shellFactoryMock,
+ $this->globalConfigMock
+ );
+ }
+
+ /**
+ * @return void
+ * @throws StepException
+ */
+ public function testExecuteWebhooksNotEnabled()
+ {
+ $this->globalConfigMock->expects(self::once())
+ ->method('get')
+ ->with(StageConfigInterface::VAR_ENABLE_WEBHOOKS)
+ ->willReturn(false);
+
+ $this->magentoShellMock->expects(self::never())
+ ->method('execute');
+ $this->loggerMock->expects(self::never())
+ ->method('notice');
+
+ $this->step->execute();
+ }
+
+ /**
+ * @return void
+ * @throws StepException
+ */
+ public function testExecuteGenerateCommandFailed()
+ {
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage('error during module generation');
+ $this->expectExceptionCode(Error::GLOBAL_WEBHOOKS_MODULE_GENERATE_FAILED);
+
+ $this->globalConfigMock->expects(self::once())
+ ->method('get')
+ ->with(StageConfigInterface::VAR_ENABLE_WEBHOOKS)
+ ->willReturn(true);
+ $this->magentoShellMock->expects(self::once())
+ ->method('execute')
+ ->with('webhooks:generate:module')
+ ->willThrowException(new ShellException('error during module generation'));
+ $this->loggerMock->expects(self::once())
+ ->method('notice');
+ $this->loggerMock->expects(self::once())
+ ->method('error');
+
+ $this->step->execute();
+ }
+
+ /**
+ * @return void
+ * @throws StepException
+ */
+ public function testExecuteEnableModuleCommandFailed()
+ {
+ $this->expectException(StepException::class);
+ $this->expectExceptionMessage('error during module enablement');
+ $this->expectExceptionCode(Error::GLOBAL_WEBHOOKS_MODULE_ENABLEMENT_FAILED);
+
+ $this->globalConfigMock->expects(self::once())
+ ->method('get')
+ ->with(StageConfigInterface::VAR_ENABLE_WEBHOOKS)
+ ->willReturn(true);
+ $this->magentoShellMock->expects(self::at(0))
+ ->method('execute')
+ ->with('webhooks:generate:module');
+ $this->magentoShellMock->expects(self::at(1))
+ ->method('execute')
+ ->with('module:enable Magento_AdobeCommerceWebhookPlugins')
+ ->willThrowException(new ShellException('error during module enablement'));
+ $this->loggerMock->expects(self::exactly(2))
+ ->method('notice');
+ $this->loggerMock->expects(self::once())
+ ->method('error');
+
+ $this->step->execute();
+ }
+
+ /**
+ * @return void
+ * @throws StepException
+ */
+ public function testExecuteSuccess()
+ {
+ $this->globalConfigMock->expects(self::once())
+ ->method('get')
+ ->with(StageConfigInterface::VAR_ENABLE_WEBHOOKS)
+ ->willReturn(true);
+ $this->magentoShellMock->expects(self::at(0))
+ ->method('execute')
+ ->with('webhooks:generate:module');
+ $this->magentoShellMock->expects(self::at(1))
+ ->method('execute')
+ ->with('module:enable Magento_AdobeCommerceWebhookPlugins');
+ $this->loggerMock->expects(self::exactly(2))
+ ->method('notice');
+ $this->loggerMock->expects(self::never())
+ ->method('error');
+
+ $this->step->execute();
+ }
+}