Understanding and Leveraging Deployment Processors
Applicable to CrafterCMS 4.1Russ Danner
Deployment Processors are an excellent way to extend your CrafterCMS project with new channel support, workflow events and better monitoring. In the blog / vlog we'll cover everything you need to know to get started building customer deployment extentions.
In this video blog we cover:
- What a the deployer is and how it works
- Deployment targets and processors
- How to write and configure your own deployment processor
- Best practices for accessing content inside the deployment processor
Important Documentation Links:
- Deployer Documentation: https://docs.craftercms.org/en/4.1/reference/modules/deployer/index.html
- Out of the box processors: https://docs.craftercms.org/en/4.1/reference/modules/deployer/index.html#deployer-processors
- Script Processor: https://docs.craftercms.org/en/4.1/reference/modules/deployer/index.html#groovy-script-processor
Code examples discussed in the video:
Basic Deployment Processor:
Elaborated Example:
The following example demonstrates:
- How to access the input stream for deployed content items properly
- How to get configuration values from the deployment target
- Basic code factoring
Please see the video for the full explanation.
def contextFactory = applicationContext.getBean("contextFactory")
def contentStoreService = applicationContext.getBean("crafter.contentStoreService")
def context = contextFactory.getObject()
def contentAccessHelper = new ContentAccessHelper(contentStoreService, context)
def someTargValue = applicationContext.getEnvironment().getProperty('target.myCustomParams.myParam')
logger.info("invoking example deployer processor")
logger.info("Target value: {}", someTargValue)
for(path : originalChangeSet.getCreatedFiles()) {
if(contentAccessHelper.isAsset(path)) {
def is
try {
is = contentAccessHelper.retrieveStaticAsset(path)
logger.info("CREATE w bytes: {} {}", path, is.available())
}
finally {
if(is) is.close()
}
}
}
for(path : originalChangeSet.getUpdatedFiles()) {
// Note: Update is only called if the file is different.
// The deployer ignores repeated deployments of the same file
if(contentAccessHelper.isAsset(path)) {
def is
try {
is = contentAccessHelper.retrieveStaticAsset(path)
logger.info("UPDATE w bytes: {} {}", path, is.available())
}
finally {
if(is) is.close()
}
}
}
// don't do anything with deleted files
// for(path : originalChangeSet.getDeletedFiles()) {
// }
logger.info("invoking example deployer processor complete")
/**
* Helper class for dealing with assets
*/
protected class ContentAccessHelper {
def contentStoreService
def context
def remoteAssetPattern = ""
def ContentAccessHelper(contentStoreService, context) {
this.contentStoreService = contentStoreService
this.context = context
}
/**
* get the input stream of an asset
* This service should be used to get asset input streams for the following 3 reasosns:
* 1. This code works with blob store and without
* 2. This code does not assume direct access to system resources (which is
* disabled for scripting)
* 3. This code future proofs your code for other repository updates
*/
def retrieveStaticAsset(binaryPath)
throws Exception {
if(!isRemoteAsset(binaryPath)) {
// item is in our repository
def binaryContent = contentStoreService.findContent(this.context, binaryPath)
if(binaryContent != null) {
return binaryContent.getInputStream()
}
else {
throw new Exception("Content at path returned null via findContent {}", binaryPath)
}
}
else {
// item is remote
throw new Exception("Remote assets not supported by processor at this time {}", binaryPath)
}
}
/**
* @return true if asset is a remote asset
*/
def isRemoteAsset(path) {
return false
}
/**
* @return true if path is an asset
*/
def isAsset(contentPath) {
return (contentPath) ? contentPath.startsWith("/static-assets") : false
}
}
Configuring the Deployment Processor in a Target
Related Posts
Migrating From Adobe Experience Manager (AEM) to CrafterCMS
Amanda Jones
Enhancing a Headless CMS With Content Analytics
Amanda Jones
Scaling Your Business with a Multi-Tenant CMS: Tips and Best Practices
Sara Williams
What is Modular Content?
Amanda Lee
Related Resources
-
Introducing CrafterCMS v4.0
Webcast
-
How to Easily Migrate from Drupal to CrafterCMS
Webcast
-
The Hire Street: Powering Private Events and Catering E-Commerce with CrafterCMS
Case Study
-
Future-Proofing Your Organization in the New Normal
Webcast
-
Choosing a CMS for Building Content-Driven Sites and Apps on AWS
White Paper