Automating Kontent By Kentico Projects Foundation Using Migrations As Code.

Automating Kontent By Kentico Projects Foundation Using Migrations As Code.

For companies utilizing a headless CMS there are some important items to consider when scaffolding a projects foundation and content structure.

Consistency

How can a business roll out a consistent foundation for projects going forwards ensuring this foundation is futureproof, best practice, adaptable, and abides to business standards and regulations? It is especially important when leveraging internal integrations that require a specific setup and have sole responsibility of delivering content by bridging the gap between the application and the headless CMS.

Automation

How can the projects foundation creation be automated, so it is re-runnable for new empty projects? How can it be Integrated into CI/CD processes? How can we reduce the requirement of manual user intervention which could require specific CMS knowledge? These types of manual actions performed by a user will not be transparent to other users. Most importantly; can this implementation flow through multiple environments to reduce risk, allow collaboration and manual or automated testing?

Review Process

Can this implementation be integrated into existing Software Development Lifecycle Processes (SDLC), planning, design, pull requests, testing etc to improve quality and reduce risk?

Kontent by Kentico have got this spot on, they have a provided a quick start kontent migrations boilerplate which follows a migration approach, rolling out structure, such as content items, content types etc. This approach is extremely similar to something I have used in the past within a enterprise environment, where we used DbUp for rolling out a SQL databases schema and data. The Kontent Migrations Boilerplate provides a great developer best practice experience and really compliments the kontent-cli with how easy it is to use, integrate and store migrations into existing applications.

Migrations can be created in both JavaScript and Typescript but remember if using Typescript remember to transpile them back to JavaScript as this is required by the cli.

The migrations boilerplate has everything out of the box to get started with building a great foundation, if you look in the Migrations folder you will see example of how you can migrate and manipulate content, insert and update, content types, content items, language variations etc. You can even link new pages into Web Spotlight so they are visible as subpages in the site root. You can also manage environment configuration at GitHub Action runtime so the .environments.json is dynamic and does not need secrets to be checked in, this is covered in an example towards the end of the post.

Example migration that adds a page content type below.

import { MigrationModule } from '@kentico/kontent-cli';
import {
    ContentTypeElementsBuilder,
    ContentTypeModels,
    ManagementClient,
} from '@kentico/kontent-management';

/**
 * Creates content type Page.
 * This content type has the element foundation for pages.
 */
const migration: MigrationModule = {
    order: 1,
    run: async (apiClient: ManagementClient) => {
        await apiClient.addContentType().withData(BuildPage).toPromise();
    },
};

const BuildPage = (
    builder: ContentTypeElementsBuilder
): ContentTypeModels.IAddContentTypeData => {
    return {
        name: 'Page',
        codename: 'page',
        content_groups: [
            {
                name: 'Content',
                codename: 'page_content',
            },
            {
                name: 'Configuration',
                codename: 'page_config',
            }
        ],
        elements: [
            //Content Group
            builder.linkedItemsElement({
                name: 'Page Blocks',
                guidelines: 'The blocks of the content for the page.',
                codename: 'page_blocks',
                type: 'modular_content',
                content_group: {
                    codename: 'page_content',
                },
            }),

            //Configuration Group
            builder.urlSlugElement({
                name: 'Page URL',
                guidelines:
                    'The URL slug element specifies an SEO-friendly text that you can use in the URLs of your content items. The element generates its value based on the text element of your choice.',
                codename: 'page_url',
                type: 'url_slug',
                depends_on: {
                    element: {
                        codename: 'page_text'
                    },
                },
                content_group: {
                    codename: 'page_config',
                },
            })
        ],
    };
};

export default migration;

Conclusion

Following a Kontent as code approach using the Kontent Migrations Boilerplate as a starting point, will provide consistency through code, resulting also to CMS consistency, it can be automated into a GitHub Action (See below for example). Migrations can be automatically triggered and run on multiple Kontent Environments & Projects, a status.json file is outputted providing feedback, allowing the run results to be tracked and stored for which migrations have completed successfully against which Kontent Environments projectId. This means you don’t have to re-run them, and an incremental approach can be followed, once the foundation is built. All code can be stored in source control such as GitHub, integrated into SDLC processes, provoking team discussion, collaboration and reducing risk, whilst also maintaining a code first approach.

The benefit of the Kontent CLI is that all of the things I’ve mentioned above, can be achieved without logging into the UI and allowing for the developer, code first approach.

Bonus – GitHub action below to install the kontent-cli as a global dependency on the action runner, run a step to add a dynamic environment of dev, with the correct secrets and run all migrations for this environment on a manual trigger for POC from the Github Action Screen.

name: Deploy Kontent Migrations
on:
  workflow_dispatch:

jobs:
  deploy-migrations:
    name: Deploy Migrations
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install Global Dependencies
        run: |
          yarn global add @kentico/kontent-cli

      - name: Deploy Kontent Migrations
        run: |
          cd src/web
          kontent  environment add --name DEV --project-id ${{ secrets.KONTENT_DEV_PROJECTID }} --api-key ${{ secrets.KONTENT_DEV_MANAGEMENT_KEY }}
          kontent migration run --all --environment DEV

Note – this should also be enhanced to store the output (status.json) from what migration has successfully run for each environment.