diff --git a/COPYING.txt b/COPYING.txt
index 2ba7d78d58a25298063b9f46ae944f882af86448..040bdd5f3ce72cf75a1edc05a712b4e83fb521f6 100644
--- a/COPYING.txt
+++ b/COPYING.txt
@@ -1,4 +1,4 @@
-Copyright © 2013-2018 Magento, Inc.
+Copyright © 2013-present Magento, Inc.
 
 Each Magento source file included in this distribution is licensed under OSL 3.0 or the Magento Enterprise Edition (MEE) license
 
diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/CommentRepository.php b/app/code/Magento/Sales/Model/Order/Creditmemo/CommentRepository.php
index 14d4ccae2244655ed86030ae53fee0f43e7f6a71..a3dde4e5172e72d0b20e966b17bbe27c792ab8d0 100644
--- a/app/code/Magento/Sales/Model/Order/Creditmemo/CommentRepository.php
+++ b/app/code/Magento/Sales/Model/Order/Creditmemo/CommentRepository.php
@@ -7,6 +7,7 @@ namespace Magento\Sales\Model\Order\Creditmemo;
 
 use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
 use Magento\Framework\Api\SearchCriteriaInterface;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Exception\CouldNotDeleteException;
 use Magento\Framework\Exception\CouldNotSaveException;
 use Magento\Sales\Api\CreditmemoCommentRepositoryInterface;
@@ -14,7 +15,15 @@ use Magento\Sales\Api\Data\CreditmemoCommentInterface;
 use Magento\Sales\Api\Data\CreditmemoCommentInterfaceFactory;
 use Magento\Sales\Api\Data\CreditmemoCommentSearchResultInterfaceFactory;
 use Magento\Sales\Model\Spi\CreditmemoCommentResourceInterface;
+use Magento\Sales\Model\Order\Email\Sender\CreditmemoCommentSender;
+use Magento\Sales\Api\CreditmemoRepositoryInterface;
+use Psr\Log\LoggerInterface;
 
+/**
+ * Class CommentRepository
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class CommentRepository implements CreditmemoCommentRepositoryInterface
 {
     /**
@@ -37,22 +46,48 @@ class CommentRepository implements CreditmemoCommentRepositoryInterface
      */
     private $collectionProcessor;
 
+    /**
+     * @var CreditmemoCommentSender
+     */
+    private $creditmemoCommentSender;
+
+    /**
+     * @var CreditmemoRepositoryInterface
+     */
+    private $creditmemoRepository;
+
+    /**
+     * @var LoggerInterface
+     */
+    private $logger;
+
     /**
      * @param CreditmemoCommentResourceInterface $commentResource
      * @param CreditmemoCommentInterfaceFactory $commentFactory
      * @param CreditmemoCommentSearchResultInterfaceFactory $searchResultFactory
      * @param CollectionProcessorInterface $collectionProcessor
+     * @param CreditmemoCommentSender|null $creditmemoCommentSender
+     * @param CreditmemoRepositoryInterface|null $creditmemoRepository
+     * @param LoggerInterface|null $logger
      */
     public function __construct(
         CreditmemoCommentResourceInterface $commentResource,
         CreditmemoCommentInterfaceFactory $commentFactory,
         CreditmemoCommentSearchResultInterfaceFactory $searchResultFactory,
-        CollectionProcessorInterface $collectionProcessor
+        CollectionProcessorInterface $collectionProcessor,
+        CreditmemoCommentSender $creditmemoCommentSender = null,
+        CreditmemoRepositoryInterface $creditmemoRepository = null,
+        LoggerInterface $logger = null
     ) {
         $this->commentResource = $commentResource;
         $this->commentFactory = $commentFactory;
         $this->searchResultFactory = $searchResultFactory;
         $this->collectionProcessor = $collectionProcessor;
+        $this->creditmemoCommentSender = $creditmemoCommentSender
+            ?: ObjectManager::getInstance()->get(CreditmemoCommentSender::class);
+        $this->creditmemoRepository = $creditmemoRepository
+            ?: ObjectManager::getInstance()->get(CreditmemoRepositoryInterface::class);
+        $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
     }
 
     /**
@@ -97,7 +132,14 @@ class CommentRepository implements CreditmemoCommentRepositoryInterface
         try {
             $this->commentResource->save($entity);
         } catch (\Exception $e) {
-            throw new CouldNotSaveException(__('Could not save the comment.'), $e);
+            throw new CouldNotSaveException(__('Could not save the creditmemo comment.'), $e);
+        }
+
+        try {
+            $creditmemo = $this->creditmemoRepository->get($entity->getParentId());
+            $this->creditmemoCommentSender->send($creditmemo, $entity->getIsCustomerNotified(), $entity->getComment());
+        } catch (\Exception $exception) {
+            $this->logger->warning('Something went wrong while sending email.');
         }
         return $entity;
     }
diff --git a/app/code/Magento/Sales/Model/Order/Invoice/CommentRepository.php b/app/code/Magento/Sales/Model/Order/Invoice/CommentRepository.php
index 858490132e0c7e117021bea37904c6e37b221d80..00b1bb62556f7cecbdc30f0c87e70d78e6662fff 100644
--- a/app/code/Magento/Sales/Model/Order/Invoice/CommentRepository.php
+++ b/app/code/Magento/Sales/Model/Order/Invoice/CommentRepository.php
@@ -7,6 +7,7 @@ namespace Magento\Sales\Model\Order\Invoice;
 
 use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
 use Magento\Framework\Api\SearchCriteriaInterface;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Exception\CouldNotDeleteException;
 use Magento\Framework\Exception\CouldNotSaveException;
 use Magento\Sales\Api\Data\InvoiceCommentInterface;
@@ -14,7 +15,15 @@ use Magento\Sales\Api\Data\InvoiceCommentInterfaceFactory;
 use Magento\Sales\Api\Data\InvoiceCommentSearchResultInterfaceFactory;
 use Magento\Sales\Api\InvoiceCommentRepositoryInterface;
 use Magento\Sales\Model\Spi\InvoiceCommentResourceInterface;
+use Magento\Sales\Model\Order\Email\Sender\InvoiceCommentSender;
+use Magento\Sales\Api\InvoiceRepositoryInterface;
+use Psr\Log\LoggerInterface;
 
+/**
+ * Class CommentRepository
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class CommentRepository implements InvoiceCommentRepositoryInterface
 {
     /**
@@ -37,22 +46,48 @@ class CommentRepository implements InvoiceCommentRepositoryInterface
      */
     private $collectionProcessor;
 
+    /**
+     * @var InvoiceCommentSender
+     */
+    private $invoiceCommentSender;
+
+    /**
+     * @var InvoiceRepositoryInterface
+     */
+    private $invoiceRepository;
+
+    /**
+     * @var LoggerInterface
+     */
+    private $logger;
+
     /**
      * @param InvoiceCommentResourceInterface $commentResource
      * @param InvoiceCommentInterfaceFactory $commentFactory
      * @param InvoiceCommentSearchResultInterfaceFactory $searchResultFactory
      * @param CollectionProcessorInterface $collectionProcessor
+     * @param InvoiceCommentSender|null $invoiceCommentSender
+     * @param InvoiceRepositoryInterface|null $invoiceRepository
+     * @param LoggerInterface|null $logger
      */
     public function __construct(
         InvoiceCommentResourceInterface $commentResource,
         InvoiceCommentInterfaceFactory $commentFactory,
         InvoiceCommentSearchResultInterfaceFactory $searchResultFactory,
-        CollectionProcessorInterface $collectionProcessor
+        CollectionProcessorInterface $collectionProcessor,
+        InvoiceCommentSender $invoiceCommentSender = null,
+        InvoiceRepositoryInterface $invoiceRepository = null,
+        LoggerInterface $logger = null
     ) {
         $this->commentResource = $commentResource;
         $this->commentFactory = $commentFactory;
         $this->searchResultFactory = $searchResultFactory;
         $this->collectionProcessor = $collectionProcessor;
+        $this->invoiceCommentSender = $invoiceCommentSender
+            ?:ObjectManager::getInstance()->get(InvoiceCommentSender::class);
+        $this->invoiceRepository = $invoiceRepository
+            ?:ObjectManager::getInstance()->get(InvoiceRepositoryInterface::class);
+        $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
     }
 
     /**
@@ -99,6 +134,13 @@ class CommentRepository implements InvoiceCommentRepositoryInterface
         } catch (\Exception $e) {
             throw new CouldNotSaveException(__('Could not save the invoice comment.'), $e);
         }
+
+        try {
+            $invoice = $this->invoiceRepository->get($entity->getParentId());
+            $this->invoiceCommentSender->send($invoice, $entity->getIsCustomerNotified(), $entity->getComment());
+        } catch (\Exception $exception) {
+            $this->logger->warning('Something went wrong while sending email.');
+        }
         return $entity;
     }
 }
diff --git a/app/code/Magento/Sales/Model/Order/Shipment/CommentRepository.php b/app/code/Magento/Sales/Model/Order/Shipment/CommentRepository.php
index b0d3b03aec4ed6e284233cbd48141f016840959d..4f6e6ee9c2241c93a31b7a9339f0902c79f76959 100644
--- a/app/code/Magento/Sales/Model/Order/Shipment/CommentRepository.php
+++ b/app/code/Magento/Sales/Model/Order/Shipment/CommentRepository.php
@@ -7,6 +7,7 @@ namespace Magento\Sales\Model\Order\Shipment;
 
 use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
 use Magento\Framework\Api\SearchCriteriaInterface;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\Exception\CouldNotDeleteException;
 use Magento\Framework\Exception\CouldNotSaveException;
 use Magento\Sales\Api\Data\ShipmentCommentInterface;
@@ -14,7 +15,15 @@ use Magento\Sales\Api\Data\ShipmentCommentInterfaceFactory;
 use Magento\Sales\Api\Data\ShipmentCommentSearchResultInterfaceFactory;
 use Magento\Sales\Api\ShipmentCommentRepositoryInterface;
 use Magento\Sales\Model\Spi\ShipmentCommentResourceInterface;
+use Magento\Sales\Model\Order\Email\Sender\ShipmentCommentSender;
+use Magento\Sales\Api\ShipmentRepositoryInterface;
+use Psr\Log\LoggerInterface;
 
+/**
+ * Class CommentRepository
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class CommentRepository implements ShipmentCommentRepositoryInterface
 {
     /**
@@ -37,22 +46,48 @@ class CommentRepository implements ShipmentCommentRepositoryInterface
      */
     private $collectionProcessor;
 
+    /**
+     * @var ShipmentCommentSender
+     */
+    private $shipmentCommentSender;
+
+    /**
+     * @var ShipmentRepositoryInterface
+     */
+    private $shipmentRepository;
+
+    /**
+     * @var LoggerInterface
+     */
+    private $logger;
+
     /**
      * @param ShipmentCommentResourceInterface $commentResource
      * @param ShipmentCommentInterfaceFactory $commentFactory
      * @param ShipmentCommentSearchResultInterfaceFactory $searchResultFactory
      * @param CollectionProcessorInterface $collectionProcessor
+     * @param ShipmentCommentSender|null $shipmentCommentSender
+     * @param ShipmentRepositoryInterface|null $shipmentRepository
+     * @param LoggerInterface|null $logger
      */
     public function __construct(
         ShipmentCommentResourceInterface $commentResource,
         ShipmentCommentInterfaceFactory $commentFactory,
         ShipmentCommentSearchResultInterfaceFactory $searchResultFactory,
-        CollectionProcessorInterface $collectionProcessor
+        CollectionProcessorInterface $collectionProcessor,
+        ShipmentCommentSender $shipmentCommentSender = null,
+        ShipmentRepositoryInterface $shipmentRepository = null,
+        LoggerInterface $logger = null
     ) {
         $this->commentResource = $commentResource;
         $this->commentFactory = $commentFactory;
         $this->searchResultFactory = $searchResultFactory;
         $this->collectionProcessor = $collectionProcessor;
+        $this->shipmentCommentSender = $shipmentCommentSender
+            ?: ObjectManager::getInstance()->get(ShipmentCommentSender::class);
+        $this->shipmentRepository = $shipmentRepository
+            ?: ObjectManager::getInstance()->get(ShipmentRepositoryInterface::class);
+        $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
     }
 
     /**
@@ -99,6 +134,13 @@ class CommentRepository implements ShipmentCommentRepositoryInterface
         } catch (\Exception $e) {
             throw new CouldNotSaveException(__('Could not save the shipment comment.'), $e);
         }
+
+        try {
+            $shipment = $this->shipmentRepository->get($entity->getParentId());
+            $this->shipmentCommentSender->send($shipment, $entity->getIsCustomerNotified(), $entity->getComment());
+        } catch (\Exception $exception) {
+            $this->logger->warning('Something went wrong while sending email.');
+        }
         return $entity;
     }
 }
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/CommentRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/CommentRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..115cb4bc7c91c8e23f7f0b0a468c9921ef457108
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/CommentRepositoryTest.php
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\Unit\Model\Order\Creditmemo;
+
+use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
+use Magento\Sales\Api\CreditmemoRepositoryInterface;
+use Magento\Sales\Api\Data\CreditmemoCommentInterfaceFactory;
+use Magento\Sales\Api\Data\CreditmemoCommentSearchResultInterfaceFactory;
+use Magento\Sales\Model\Order\Creditmemo;
+use Magento\Sales\Model\Order\Creditmemo\Comment;
+use Magento\Sales\Model\Order\Creditmemo\CommentRepository;
+use Magento\Sales\Model\Order\Email\Sender\CreditmemoCommentSender;
+use Magento\Sales\Model\Spi\CreditmemoCommentResourceInterface;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Class CommentRepositoryTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class CommentRepositoryTest extends \PHPUnit\Framework\TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CreditmemoCommentResourceInterface
+     */
+    private $commentResource;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CreditmemoCommentInterfaceFactory
+     */
+    private $commentFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CreditmemoCommentSearchResultInterfaceFactory
+     */
+    private $searchResultFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CollectionProcessorInterface
+     */
+    private $collectionProcessor;
+
+    /**
+     * @var CommentRepository
+     */
+    private $commentRepository;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CreditmemoCommentSender
+     */
+    private $creditmemoCommentSender;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CreditmemoRepositoryInterface
+     */
+    private $creditmemoRepositoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Creditmemo
+     */
+    private $creditmemoMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Comment
+     */
+    private $commentMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|LoggerInterface
+     */
+    private $loggerMock;
+
+    protected function setUp()
+    {
+        $this->commentResource = $this->getMockBuilder(CreditmemoCommentResourceInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->commentFactory = $this->getMockBuilder(CreditmemoCommentInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->searchResultFactory = $this->getMockBuilder(CreditmemoCommentSearchResultInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->collectionProcessor = $this->getMockBuilder(CollectionProcessorInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->creditmemoRepositoryMock = $this->getMockBuilder(CreditmemoRepositoryInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->creditmemoCommentSender = $this->getMockBuilder(CreditmemoCommentSender::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->loggerMock = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
+
+        $this->creditmemoMock = $this->getMockBuilder(Creditmemo::class)->disableOriginalConstructor()->getMock();
+        $this->commentMock = $this->getMockBuilder(Comment::class)->disableOriginalConstructor()->getMock();
+
+        $this->commentRepository = new CommentRepository(
+            $this->commentResource,
+            $this->commentFactory,
+            $this->searchResultFactory,
+            $this->collectionProcessor,
+            $this->creditmemoCommentSender,
+            $this->creditmemoRepositoryMock,
+            $this->loggerMock
+        );
+    }
+
+    public function testSave()
+    {
+        $comment = "Comment text";
+        $creditmemoId = 123;
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willReturnSelf();
+        $this->commentMock->expects($this->once())
+            ->method('getIsCustomerNotified')
+            ->willReturn(1);
+        $this->commentMock->expects($this->once())
+            ->method('getParentId')
+            ->willReturn($creditmemoId);
+        $this->commentMock->expects($this->once())
+            ->method('getComment')
+            ->willReturn($comment);
+
+        $this->creditmemoRepositoryMock->expects($this->once())
+            ->method('get')
+            ->with($creditmemoId)
+            ->willReturn($this->creditmemoMock);
+        $this->creditmemoCommentSender->expects($this->once())
+            ->method('send')
+            ->with($this->creditmemoMock, true, $comment)
+            ->willReturn(true);
+        $this->commentRepository->save($this->commentMock);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     * @expectedExceptionMessage Could not save the creditmemo comment.
+     */
+    public function testSaveWithException()
+    {
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willThrowException(
+                new \Magento\Framework\Exception\CouldNotSaveException(__('Could not save the creditmemo comment.'))
+            );
+
+         $this->commentRepository->save($this->commentMock);
+    }
+
+    public function testSaveSendCatchException()
+    {
+        $comment = "Comment text";
+        $creditmemoId = 123;
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willReturnSelf();
+        $this->commentMock->expects($this->once())
+            ->method('getIsCustomerNotified')
+            ->willReturn(1);
+        $this->commentMock->expects($this->once())
+            ->method('getParentId')
+            ->willReturn($creditmemoId);
+        $this->commentMock->expects($this->once())
+            ->method('getComment')
+            ->willReturn($comment);
+
+        $this->creditmemoRepositoryMock->expects($this->once())
+            ->method('get')
+            ->with($creditmemoId)
+            ->willReturn($this->creditmemoMock);
+        $this->creditmemoCommentSender->expects($this->once())
+            ->method('send')
+            ->willThrowException(new \Exception());
+        $this->loggerMock->expects($this->once())
+            ->method('warning');
+
+        $this->commentRepository->save($this->commentMock);
+    }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/CommentRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/CommentRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4790490c1ecf3f902a973c6125ddb7e9dc15d333
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/CommentRepositoryTest.php
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\Unit\Model\Order\Invoice;
+
+use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
+use Magento\Sales\Api\InvoiceRepositoryInterface;
+use Magento\Sales\Api\Data\InvoiceCommentInterfaceFactory;
+use Magento\Sales\Api\Data\InvoiceCommentSearchResultInterfaceFactory;
+use Magento\Sales\Model\Order\Invoice;
+use Magento\Sales\Model\Order\Invoice\Comment;
+use Magento\Sales\Model\Order\Invoice\CommentRepository;
+use Magento\Sales\Model\Order\Email\Sender\InvoiceCommentSender;
+use Magento\Sales\Model\Spi\InvoiceCommentResourceInterface;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Class CommentRepositoryTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class CommentRepositoryTest extends \PHPUnit\Framework\TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|InvoiceCommentResourceInterface
+     */
+    private $commentResource;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|InvoiceCommentInterfaceFactory
+     */
+    private $commentFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|InvoiceCommentSearchResultInterfaceFactory
+     */
+    private $searchResultFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CollectionProcessorInterface
+     */
+    private $collectionProcessor;
+
+    /**
+     * @var CommentRepository
+     */
+    private $commentRepository;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|InvoiceCommentSender
+     */
+    private $invoiceCommentSender;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|InvoiceRepositoryInterface
+     */
+    private $invoiceRepositoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Invoice
+     */
+    private $invoiceMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Comment
+     */
+    private $commentMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|LoggerInterface
+     */
+    private $loggerMock;
+
+    protected function setUp()
+    {
+        $this->commentResource = $this->getMockBuilder(InvoiceCommentResourceInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->commentFactory = $this->getMockBuilder(InvoiceCommentInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->searchResultFactory = $this->getMockBuilder(InvoiceCommentSearchResultInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->collectionProcessor = $this->getMockBuilder(CollectionProcessorInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->invoiceRepositoryMock = $this->getMockBuilder(InvoiceRepositoryInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->invoiceCommentSender = $this->getMockBuilder(InvoiceCommentSender::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->loggerMock = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
+
+        $this->invoiceMock = $this->getMockBuilder(Invoice::class)->disableOriginalConstructor()->getMock();
+        $this->commentMock = $this->getMockBuilder(Comment::class)->disableOriginalConstructor()->getMock();
+
+        $this->commentRepository = new CommentRepository(
+            $this->commentResource,
+            $this->commentFactory,
+            $this->searchResultFactory,
+            $this->collectionProcessor,
+            $this->invoiceCommentSender,
+            $this->invoiceRepositoryMock,
+            $this->loggerMock
+        );
+    }
+
+    public function testSave()
+    {
+        $comment = "Comment text";
+        $invoiceId = 123;
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willReturnSelf();
+        $this->commentMock->expects($this->once())
+            ->method('getIsCustomerNotified')
+            ->willReturn(1);
+        $this->commentMock->expects($this->once())
+            ->method('getParentId')
+            ->willReturn($invoiceId);
+        $this->commentMock->expects($this->once())
+            ->method('getComment')
+            ->willReturn($comment);
+
+        $this->invoiceRepositoryMock->expects($this->once())
+            ->method('get')
+            ->with($invoiceId)
+            ->willReturn($this->invoiceMock);
+        $this->invoiceCommentSender->expects($this->once())
+            ->method('send')
+            ->with($this->invoiceMock, true, $comment)
+            ->willReturn(true);
+        $this->commentRepository->save($this->commentMock);
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     * @expectedExceptionMessage Could not save the invoice comment.
+     */
+    public function testSaveWithException()
+    {
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willThrowException(
+                new \Magento\Framework\Exception\CouldNotSaveException(__('Could not save the invoice comment.'))
+            );
+
+        $this->commentRepository->save($this->commentMock);
+    }
+
+    public function testSaveSendCatchException()
+    {
+        $comment = "Comment text";
+        $creditmemoId = 123;
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willReturnSelf();
+        $this->commentMock->expects($this->once())
+            ->method('getIsCustomerNotified')
+            ->willReturn(1);
+        $this->commentMock->expects($this->once())
+            ->method('getParentId')
+            ->willReturn($creditmemoId);
+        $this->commentMock->expects($this->once())
+            ->method('getComment')
+            ->willReturn($comment);
+
+        $this->invoiceRepositoryMock->expects($this->once())
+            ->method('get')
+            ->with($creditmemoId)
+            ->willReturn($this->invoiceMock);
+        $this->invoiceCommentSender->expects($this->once())
+            ->method('send')
+            ->willThrowException(new \Exception());
+        $this->loggerMock->expects($this->once())
+            ->method('warning');
+
+        $this->commentRepository->save($this->commentMock);
+    }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/CommentRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/CommentRepositoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..9cab366ef2c33d4833f8efff29fb28adc146247c
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/CommentRepositoryTest.php
@@ -0,0 +1,186 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\Unit\Model\Order\Shipment;
+
+use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
+use Magento\Sales\Api\ShipmentRepositoryInterface;
+use Magento\Sales\Api\Data\ShipmentCommentInterfaceFactory;
+use Magento\Sales\Api\Data\ShipmentCommentSearchResultInterfaceFactory;
+use Magento\Sales\Model\Order\Shipment;
+use Magento\Sales\Model\Order\Shipment\Comment;
+use Magento\Sales\Model\Order\Shipment\CommentRepository;
+use Magento\Sales\Model\Order\Email\Sender\ShipmentCommentSender;
+use Magento\Sales\Model\Spi\ShipmentCommentResourceInterface;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Class CommentRepositoryTest
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class CommentRepositoryTest extends \PHPUnit\Framework\TestCase
+{
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentCommentResourceInterface
+     */
+    private $commentResource;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentCommentInterfaceFactory
+     */
+    private $commentFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentCommentSearchResultInterfaceFactory
+     */
+    private $searchResultFactory;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|CollectionProcessorInterface
+     */
+    private $collectionProcessor;
+
+    /**
+     * @var CommentRepository
+     */
+    private $commentRepository;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentCommentSender
+     */
+    private $shipmentCommentSender;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentRepositoryInterface
+     */
+    private $shipmentRepositoryMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Shipment
+     */
+    private $shipmentMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|Comment
+     */
+    private $commentMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject|LoggerInterface
+     */
+    private $loggerMock;
+
+    protected function setUp()
+    {
+        $this->commentResource = $this->getMockBuilder(ShipmentCommentResourceInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->commentFactory = $this->getMockBuilder(ShipmentCommentInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->searchResultFactory = $this->getMockBuilder(ShipmentCommentSearchResultInterfaceFactory::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->collectionProcessor = $this->getMockBuilder(CollectionProcessorInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->shipmentRepositoryMock = $this->getMockBuilder(ShipmentRepositoryInterface::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->shipmentCommentSender = $this->getMockBuilder(ShipmentCommentSender::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->loggerMock = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
+
+        $this->shipmentMock = $this->getMockBuilder(Shipment::class)->disableOriginalConstructor()->getMock();
+        $this->commentMock = $this->getMockBuilder(Comment::class)->disableOriginalConstructor()->getMock();
+
+        $this->commentRepository = new CommentRepository(
+            $this->commentResource,
+            $this->commentFactory,
+            $this->searchResultFactory,
+            $this->collectionProcessor,
+            $this->shipmentCommentSender,
+            $this->shipmentRepositoryMock,
+            $this->loggerMock
+        );
+    }
+
+    public function testSave()
+    {
+        $comment = "Comment text";
+        $shipmentId = 123;
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willReturnSelf();
+        $this->commentMock->expects($this->once())
+            ->method('getIsCustomerNotified')
+            ->willReturn(1);
+        $this->commentMock->expects($this->once())
+            ->method('getParentId')
+            ->willReturn($shipmentId);
+        $this->commentMock->expects($this->once())
+            ->method('getComment')
+            ->willReturn($comment);
+
+        $this->shipmentRepositoryMock->expects($this->once())
+            ->method('get')
+            ->with($shipmentId)
+            ->willReturn($this->shipmentMock);
+        $this->shipmentCommentSender->expects($this->once())
+            ->method('send')
+            ->with($this->shipmentMock, true, $comment);
+        $this->assertEquals($this->commentMock, $this->commentRepository->save($this->commentMock));
+    }
+
+    /**
+     * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+     * @expectedExceptionMessage Could not save the shipment comment.
+     */
+    public function testSaveWithException()
+    {
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willThrowException(
+                new \Magento\Framework\Exception\CouldNotSaveException(__('Could not save the shipment comment.'))
+            );
+
+        $this->commentRepository->save($this->commentMock);
+    }
+
+    public function testSaveSendCatchException()
+    {
+        $comment = "Comment text";
+        $creditmemoId = 123;
+        $this->commentResource->expects($this->once())
+            ->method('save')
+            ->with($this->commentMock)
+            ->willReturnSelf();
+        $this->commentMock->expects($this->once())
+            ->method('getIsCustomerNotified')
+            ->willReturn(1);
+        $this->commentMock->expects($this->once())
+            ->method('getParentId')
+            ->willReturn($creditmemoId);
+        $this->commentMock->expects($this->once())
+            ->method('getComment')
+            ->willReturn($comment);
+
+        $this->shipmentRepositoryMock->expects($this->once())
+            ->method('get')
+            ->with($creditmemoId)
+            ->willReturn($this->shipmentMock);
+        $this->shipmentCommentSender->expects($this->once())
+            ->method('send')
+            ->willThrowException(new \Exception());
+        $this->loggerMock->expects($this->once())
+            ->method('warning');
+
+        $this->commentRepository->save($this->commentMock);
+    }
+}
diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml
index 8b740bc8d09aecb0f2fe226923a0dc35730a4bf7..a6984b449d944a173aa725a093281c7639211edd 100644
--- a/app/code/Magento/Theme/etc/config.xml
+++ b/app/code/Magento/Theme/etc/config.xml
@@ -45,7 +45,7 @@ Disallow: /*SID=
                 <welcome>Default welcome msg!</welcome>
             </header>
             <footer translate="copyright">
-                <copyright>Copyright &#169; 2013-2018 Magento, Inc. All rights reserved.</copyright>
+                <copyright>Copyright &#169; 2013-present Magento, Inc. All rights reserved.</copyright>
             </footer>
         </design>
         <theme>
diff --git a/app/code/Magento/Theme/i18n/en_US.csv b/app/code/Magento/Theme/i18n/en_US.csv
index daa5c27e75fccec0a767a125ccfaf74dbac6e58a..b454b7222bd1cd5fbb5c6fffaf6a8e4acb8e7171 100644
--- a/app/code/Magento/Theme/i18n/en_US.csv
+++ b/app/code/Magento/Theme/i18n/en_US.csv
@@ -142,7 +142,7 @@ Empty,Empty
 "1 column","1 column"
 Configuration,Configuration
 "Default welcome msg!","Default welcome msg!"
-"Copyright © 2013-2018 Magento, Inc. All rights reserved.","Copyright © 2013-2018 Magento, Inc. All rights reserved."
+"Copyright © 2013-present Magento, Inc. All rights reserved.","Copyright © 2013-present Magento, Inc. All rights reserved."
 "Design Config Grid","Design Config Grid"
 "Rebuild design config grid index","Rebuild design config grid index"
 "Admin empty","Admin empty"
diff --git a/dev/tests/integration/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Config/SaveTest.php b/dev/tests/integration/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Config/SaveTest.php
index 333ffb01b24ec0133b43f5a8a8cb99fc5feaa19a..1ea2b28986d8ae1e4e370defa92e7ac42d73eabd 100644
--- a/dev/tests/integration/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Config/SaveTest.php
+++ b/dev/tests/integration/testsuite/Magento/Theme/Controller/Adminhtml/System/Design/Config/SaveTest.php
@@ -67,7 +67,7 @@ class SaveTest extends AbstractBackendController
             'header_logo_height' => '',
             'header_logo_alt' => '',
             'header_welcome' => 'Default welcome msg!',
-            'footer_copyright' => 'Copyright © 2013-2018 Magento, Inc. All rights reserved.',
+            'footer_copyright' => 'Copyright © 2013-present Magento, Inc. All rights reserved.',
             'footer_absolute_footer' => '',
             'default_robots' => 'INDEX,FOLLOW',
             'custom_instructions' => '',