Overview

Introduction

Most Organizations have a working CI/CD setup in place already when starting to use the Humanitec products.

While there are some common patterns, they variety of real-world CI/CD processes is vast, as is the range of tools being used along the way.

The Humanitec products do not impose any particular workflow, or the use of any particular tool. Chances are you do not need to change your CI/CD processes a great deal. Rather, there are some natural extension points when using Score and the Platform Orchestrator that we have laid out in this guide.

Most importantly, your developer workflows will undergo little change. Once set up properly, application developers will likely enjoy more automation and more autonomy than before while working the software development lifecycle the familiar way.

Some code references on this page use GitHub as a sample CI/CD system. The patterns work just the same on any other tooling, including Bitbucket, CircleCI, GitLab, Jenkins, Codefresh, and more, and may easily be transferred.

Add Score to your source code and deploy continuously

The “CI” portion is probably the most uniform part of CI/CD workflows across organizations. Commonly, a git push to a workload’s source repository triggers a pipeline with a series of build and test steps, and finally creates a new container image version that is pushed to a container registry.

If you are not just building, but also deploying continuously, then a CD pipeline is usually triggered to deploy the new image to the target environment, or there is a unified CI/CD pipeline. A common pattern will look like this:

flowchart LR
    subgraph ciPipeline[CI pipeline]
        direction LR
        build((Build the\nworkload)) --> tests((Unit tests /\n smoke tests))
        tests --> push((Push image\n to registry))
    end
    developer(fa:fa-person Developer    ) -->|git push| ciPipeline
    subgraph cdPipeline[CD pipeline]
        deploy((Deploy))
    end
    subgraph infra[Infrastructure]
        direction TB
        deployedWorkload(Deployed Workload)
    end
    ciPipeline --> cdPipeline --> infra

You can now switch to deploying your workload along with the required resources via the Platform Orchestrator.

Perform these modifications:

  1. Add a Score file to the workload repository specifying the workload and its required resources, using the image . placeholder:
apiVersion: score.dev/v1b1
metadata:
  name: my-app
...
containers:
  main:
    image: . # Set by pipeline
...
resources:
...
  1. Add these steps to the end of your CI pipeline, replacing the current CD step(s) if any:

The exact steps of your pipeline up to the new steps will vary, but the entire flow will now look similar to this:

flowchart LR
    subgraph ciCdPipeline[CI/CD pipeline]
        direction LR
        build((Build the\nworkload)) --> tests((Unit tests /\n smoke tests))
        tests --> push((Push image\n to registry))
        push --> installCLI((Install\nhumctl CLI))
        installCLI --> deploy((humctl\nscore deploy))
    end
    subgraph infra[Infrastructure]
        direction TB
        deployedWorkload(Deployed Workload)
        subgraph resources[Resources]
            resource1[ ]
            resource2[/ /]
        end
        deployedWorkload -.-> resources
    end
    developer(fa:fa-person Developer    ) -->|git push| build
    deploy --> platformOrchestrator{Platform\nOrchestrator}
    platformOrchestrator --> infra

    class installCLI,deploy,platformOrchestrator,deployedWorkload,resource1,resource2 highlight
    class resources nested

Now, every git push will trigger an updated deployment of your workload. And because the Score file is part of the code, developers control the workload specification including any required resources, which will also be provisioned by the Orchestrator in the way your platform team has configured it.

You can apply this approach to any branching pattern you are using, and deploy to a different Application Environment for each branch. The next section proposes an extremely useful implementation of this pattern.

Use ephemeral environments

Using this pattern is optional, but highly recommended as a next step after implementing your base CI integration.

An “ephemeral environment” is a temporary, on-the-fly instance of an application. It exists solely for the duration of a specific task, such as testing a feature or bug fix via a pull request. Once the task is done, the environment is torn down.

Ephemeral environments are sometimes called “dynamic previews”.

Ephemeral environments are not technically different from other Environments in the Platform Orchestrator. There is no technical flag marking an Environment as “ephemeral”. Their ephemeral nature is a human notion, signifying the limited time span of their existence.

As a developer, you thus get a full-fledged, isolated environment for testing your code, including its interactions with surrounding infrastructure, with zero effort.

To see how to implement ephemeral environments, refer to these guides:

Familiar developer workflow

Attaching the Humanitec tooling to your CI/CD setup leaves the familiar developer workflow unchanged. As a developer, you will continue to perform local development, create branches and PRs, push into branches, and finally merge them. The Humanitec tooling extends the workflow by automated features improving developers’ everday experience.

flowchart TB
    subgraph devWorkflow
        direction LR
        deleteEphemeralEnv --> localDev
        localDev(Local Development) --> creatPR(Create PR) --> createEphemeralEnv(Create\nephemeral\nenvironment) --> deployWorkloadArtefact(Deploy\nworkload\nartefact) --> testAndEvaluate(Develop,\ntest and\nevaluate) --> merge(Merge) --> deleteEphemeralEnv(Delete\nephemeral\nenvironment)
        testAndEvaluate -->|git push| deployWorkloadArtefact
    end
    subgraph key[Key]
        direction LR
        humanitecExtensions(Humanitec\nextensions) ~~~ humanitecExternel(External to Humanitec)
    end
    devWorkflow ~~~ key

    class humanitecExtensions,createEphemeralEnv,deployWorkloadArtefact,deleteEphemeralEnv highlight
    class devWorkflow invisible

CD integration points

While CI setups are often fairly similar, the downstream CD setup varies greatly between organizations.

A common theme is an environment promotion from development to production, with any number of environments in between. An environment promotion is human-driven most of the time, often with an approval step involved.

When you switched to Platform Orchestrator deployments for your CI/CD development loop already and are using ephemeral environments, your setup may now look similar to this:

flowchart TB
    subgraph ciLoop[CI/CD development loop using ephemeral environments]
        direction LR
        subgraph ciInnerLoop[CI/CD pipeline]
            direction LR
            deployWorkloadArtefact --> buildAndPush
            buildAndPush(Build and\npush) --> deployWorkloadArtefact(humctl\nscore\ndeploy)
        end
        ciLoopPlatformOrchestrator{Platform\nOrchestrator}
        subgraph devEnv[Development environment]
            devEnvDeployedWorkload(Deployed\nworkload) -.-> devEnvResources(Resources)
        end
        subgraph ephemeralEnv[Ephemeral Environment]
            ephemeralEnvDeployedWorkload(Deployed\nworkload) -.-> ephemeralEnvResources(Resources)
        end
        ciInnerLoop -->|--env=development| ciLoopPlatformOrchestrator --> devEnv
        ciInnerLoop -->|--env=ephemeral| ciLoopPlatformOrchestrator --> ephemeralEnv
    end
    subgraph envPromotionStaging[CD staging]
        direction LR
        subgraph stagingInnerLoop[CD pipeline]
            direction LR
            promoteStaging(Promote) --> stagingDeployWorkloadArtefact(Deploy)
        end
        subgraph stagingEnv[Staging Environment]
            stagingEnvDeployedWorkload(Deployed\nworkload)
        end
        stagingInnerLoop --> stagingCDtooling(CD tooling) --> stagingEnv
    end
    ciLoop -->|Environment promotion staging| envPromotionStaging
    subgraph envPromotionProduction[CD Production]
        direction LR
        subgraph ProductionInnerLoop[CD pipeline]
            direction LR
            promoteProduction(Promote) --> approve(Approve) --> ProductionDeployWorkloadArtefact(Deploy)
        end
        subgraph ProductionEnv[Production Environment]
            ProductionEnvDeployedWorkload(Deployed\nworkload)
        end
        ProductionInnerLoop --> ProductionCDtooling(CD tooling) --> ProductionEnv
    end
    envPromotionStaging -->|Environment promotion production| envPromotionProduction

    class ciLoopPlatformOrchestrator highlight

The next step is to switch to the Platform Orchestrator for the downstream CD deployments.

Much like for the CI/CD development loop, using the Humanitec products does not impose any particular downstream CD approach. You can continue executing your environment promotion as you designed it.

Follow these steps for your downstream CD integration:

  1. Mirror your environments in the Platform Orchestrator as Application Environments
  2. Ensure that your platform team have prepared the provisioning of all the resources your workload requires by setting up the appropriate Resource Definitions
  3. Use the same Score file across all environments. If you need to make overrides, treat it as “development”, and apply overrides for downstream environments via the Platform Orchestrator like in this example
  4. Switch to deploying via Score and the Platform Orchestrator in your existing CD tooling using the humctl CLI, which you can install into your CD pipeline as shown above

You do not have to switch over to Platform Orchestrator deployment for all environments at once. Advance through your enviornment progression one by one to validate your setup, then proceed to the next.

Introducing the artefact endpoint

In many cases, using the humctl score deploy command in your CD tooling will be all you need.

This command deploys to one specific Application Environment only by design and requires both Application (--app) and Environment (--env) to be named.

flowchart LR
    subgraph pipeline[CD pipeline]
        deploy(humctl\nscore\ndeploy)
    end
    subgraph env[Target environment]
            devEnvDeployedWorkload(Deployed\nworkload) -.-> devEnvResources(Resources)
    end
    pipeline -->|--app=my-app\n--env=target-env| env

This also means that

  • the CD tooling needs to know which Application Environment(s) to deploy to
  • it must make separate calls for each target Environment

While this works well for simple and linear cases, you may have more complex setups where an updated workload needs to be deployed to several Environments or even several Applications. A network of interdependent pipelines can become hard to maintain.

In such scenarios, there is another option you can use which shifts control over to the Platform Orchestrator and can greatly simplify your CD setup. Basically, instead of submitting this chain of commands out of your CD tooling:

Deploy the workload defined by this Score file to Environment A of App1, and then to B of App1, and then to C of App2 …

you can submit this single command:

Deploy the workload defined by this Score file to every relevant Application and Environment

where “relevant” is decided by the Platform Orchestrator based on the workload’s attributes (name, source reference) provided with the command.

This option uses the CLI command humctl create artefact-version ( reference ). It triggers all Humanitec Artefact Automation Pipelines in any Application whose triggers match the workload’s attributes. They will all be triggered asynchronously.

This approach shifts the responsibility for determining deployment targets from the CI/CD system into the Applications themselves and introduces a loose coupling between the two which can help untangle a network of CD pipeline dependencies.

This sample setup shows how a single command out of a CD pipeline triggers the deployment of an updated workload into two separate Applications, where App2 deploys into two regional Environments. The CD pipeline does not require any knowledge about each Application’s deployment pattern, and should it change, does not need to be adjusted.

---
title: Using the Artefact endpoint for a complex deployment scenario
---
flowchart LR
    subgraph cdPipeline[CD pipeline]
        deployWorkloadArtefact(humctl create\nartefact-version\n--type=workload)
    end
    subgraph app2[App2]
        subgraph productionApp2EnvA[Production Environment Region A]
            productionApp2EnvADeployedWorkload(Deployed\nworkload) -.-> productionApp2EnvAResources(Resources)
        end
        subgraph productionApp2EnvB[Production Environment Region B]
            productionApp2EnvBDeployedWorkload(Deployed\nworkload) -.-> productionApp2EnvBResources(Resources)
        end
        artefactAutomationPipelineApp2(Artefact Automation Pipeline) -->|deploy| productionApp2EnvA
        artefactAutomationPipelineApp2 -->|deploy| productionApp2EnvB
    end
    subgraph app1[App1]
        subgraph productionApp1EnvA[Production Environment]
            productionApp1EnvADeployedWorkload(Deployed\nworkload) -.-> productionApp1EnvAResources(Resources)
        end
        artefactAutomationPipelineApp1(Artefact Automation Pipeline) -->|deploy| productionApp1EnvA
    end
    cdPipeline -->|--name my-org/my-service\n--ref=refs/heads/main| platformOrchestrator{Platform\nOrchestrator}
    platformOrchestrator -->|trigger| artefactAutomationPipelineApp1
    platformOrchestrator -->|trigger| artefactAutomationPipelineApp2

Again, using the humctl create artefact-version command (the “Artefact endpoint”) in place of humctl score deploy (the “Deployment endpoint”) is optional and depends on your use case, and how you wish to distribute resposibilities among the teams involved. You may even use both approaches depending on the complexity of each deployment stage.

The table below summarizes the differences between the two variants.

Deployment endpoint Artefact endpoint
CLI command humctl score deploy
-f score.yaml
--app my-app
--env target-env
humctl create artefact-version --type workload
--spec score.yaml
--name my-org/my-service
--refs refs/heads/main
--version 1.2.7
Reference CLI Score integration Workload artefacts
Target Applications(s) Must be known to pipeline/CD tooling
Passed in as --app parameter
Exactly one
Determined by Platform Orchestrator based on workload attributes (--name, --ref)
Can be more than one
Target Environment(s) Must be known to pipeline/CD tooling
Passed in as --env parameter
Exactly one
Determined by Platform Orchestrator based on workload attributes (--name, --ref)
Can be more than one
Use of Humanitec Pipelines Works with any Deployment Pipeline including the default one Requires an Artefact Automation Pipeline
Batching By your pipeline/CD tooling By Platform Orchestrator
Approvals In your pipeline/CD tooling In your pipeline/CD tooling
OR in Platform Orchestrator Pipeline (see approvals action )
Responsibility Centralized (CI/CD tooling) Decentralized (Applications)
Example Deploy and run automated tests Promote between Environments after approval

The diagram below shows a sample setup where the ealier stages “development”, “ephemeral” and “staging” are handled using the Deployment endpoint, and the production stage using the Artefact endpoint. In particular, the production deployment is targeting two Environments representing different regions. Note that the diagram is omitting test steps, approvals, and other variations for brevity.

---
title: Sample CI/CD flow
---
flowchart TB
    subgraph ciLoop[CI/CD base loop using ephemeral environments]
        direction LR
        subgraph ciInnerLoop[CI/CD inner loop]
            deployWorkloadArtefact --> buildAndPush
            buildAndPush(Build and\npush) --> deployWorkloadArtefact(humctl\nscore\ndeploy)
        end
        ciLoopPlatformOrchestrator{Platform\nOrchestrator}
        subgraph devEnv[Development environment]
            devEnvDeployedWorkload(Deployed\nworkload) -.-> devEnvResources(Resources)
        end
        subgraph ephemeralEnv[Ephemeral Environment]
            ephemeralEnvDeployedWorkload(Deployed\nworkload) -.-> ephemeralEnvResources(Resources)
        end
        ciInnerLoop -->|--app=App1\n--env=development| ciLoopPlatformOrchestrator -->|Default\nDeployment\nPipeline| devEnv
        ciInnerLoop -->|--app=App1\n--env=ephemeral| ciLoopPlatformOrchestrator -->|Default\nDeployment\nPipeline| ephemeralEnv
    end
    subgraph envPromotionStaging[CD staging]
        direction LR
        subgraph stagingInnerLoop[Staging loop]
            direction TB
            promoteStaging(Promote) --> stagingDeployWorkloadArtefact(humctl\nscore\ndeploy)
        end
        subgraph stagingEnv[Staging Environment]
            stagingEnvDeployedWorkload(Deployed\nworkload) -.-> stagingEnvResources(Resources)
        end
        stagingInnerLoop -->|--app=App1\n--env=staging| stagingPlatformOrchestrator{Platform\nOrchestrator} -->|Default\nDeployment\nPipeline| stagingEnv
    end
    ciLoop -->|Environment promotion staging| envPromotionStaging
    subgraph envPromotionProduction[CD production]
        direction LR
        subgraph productionInnerLoop[Production loop]
            direction TB
            promoteProduction(Promote) --> approve(Approve) --> productionDeployWorkloadArtefact(humctl create\nartefact-version\n--type=workload)
        end
        subgraph productionEnvA[Production Environment Region A]
            productionEnvADeployedWorkload(Deployed\nworkload) -.-> productionEnvAResources(Resources)
        end
        subgraph productionEnvB[Production Environment Region B]
            productionEnvBDeployedWorkload(Deployed\nworkload) -.-> productionEnvBResources(Resources)
        end
        productionInnerLoop -->|--name my-org/my-service\n--ref=refs/heads/main| productionPlatformOrchestrator{Platform\nOrchestrator} -->|Artefact\nAutomation\nPipeline| pipelineDummy( ) --> productionEnvA
        pipelineDummy --> productionEnvB
    end
    envPromotionStaging -->|Environment promotion production| envPromotionProduction

    class ciInnerLoop,devEnv,ephemeralEnv,stagingEnv,productionEnvA,productionEnvB nested
    class stagingInnerLoop,productionInnerLoop,pipelineDummy invisible
    class ciLoopPlatformOrchestrator,stagingPlatformOrchestrator,productionPlatformOrchestrator highlight

Recap

While every organization’s CI/CD setup is different, there are a number of clear patterns for integrating the Humanitec tooling into it.

The CI part can most often be augmented in a standard fashion by adding automated deployments via the Orchestrator. Offering ephemeral environments is a valuable next step.

The downstream CD portion can be extended gradually. You can add Orchestrator-based deployments to your setup while keeping workflows unchanged, and optionally shift more responsibility to the Humanitec tooling at your discretion in further steps.

Top