Skip to main content

Custom CI

How does Horizon CI work

Horizon CI works based on tekton pipeline and tekton triggers. A tekton pipeline will be triggered for an incoming buildDeploy request to perform typical steps, such as compiling and pushing image. Then, the pipeline output that holds artifact image url and other information will be returned to Horizon core by calling back http post request. Horizon CI pipeline includes four steps that is shown below: pipeline

  • Git step: use token to pull source code.
  • Compile step: compile and package the source code, such as mvn clean package, go build, docker build, etc.
  • Image step: build image from dockerfile to store artifact and push it to registry.
  • Deploy step: assemble pipeline output and callback horizon api.

How to customize your CI

In order to customize CI, you may prepare two parts of modification.

Build config

Build config holds user's build configurations of application or application instance, which is characterized as json object pipelineJSONBlob in pipeline. You can customize your own build based on json schema that contains two parts: json schema and ui schema. Override them in values.yaml of horizon chart, which has the following structure:

build_schema:
build_json_schema: |
# your json schema, for example:
{
"type": "object",
"required": [
"buildType"
],
"properties": {
"buildType": {
"type": "string",
"title": "Build type",
"oneOf": [
{
"enum": [
"dockerfile"
],
"title": "Dockerfile build"
}
],
"default": "dockerfile"
}
},
"dependencies": {...}
}
build_ui_schema: |
# your ui schema, for example:
{
"ui:order": [
"buildType",
"dockerfile",
"buildArgs"
],
"dockerfile": {
"content": {
"ui:widget": "textarea",
"ui:options": {
"rows": 18
}
}
},
"buildType": {
"ui:widget": "radio",
"ui:options": {
"inline": true
}
}
}

You can refer to json schema and json schema in horizon template for more information.

Step scripts

The step scripts in values.yaml also can be overridden to perform various pipelines according to user's build config above. The associated file structure is as follows:

tektonci-resources:
horizon:
script:
git: |
# your custom script of git step...
compile: |
# your custom script of compile step...
image: |
# your custom script of image step...
deploy: |
# your custom script of deploy step...

The steps can retrieve the following build parameters from horizon core:

paramsdescriptionnote
tokenJWT token used to callback horizon apiusage: add "X-Horizon-JWT-Token: $TOKEN" header to HTTP request
applicationapplication name
instanceapplication instance name
instanceIDapplication instance ID
environmentenvironment name
gitRepositoryUrlgit repository url of source code
gitSubfoldersub folder from context
gitCommitgit commit of revision
gitBranchgit branch of revision
gitTaggit tag of revision
pipelineJSONBlobjson string of build configyou can parse it by json parser, such as jq
imageURLartifact image urlthe generated artifact image will be push to the url
pipelinerunIDcurrent pipelinerun ID in horizon core
requestIDcurrent request ID

You can access above parameters by variable substitutions in your scripts. For example:

export TOKEN="$(params.token)"
echo "token: ${TOKEN}"

Configurations

Image of step

If your script uses some tools that are not in the default image, you can override the images of build step in values.yaml. For example:

tektonci-resources:
horizon:
buildTask:
image:
gitStep: ubuntu:18.04
compileStep: xxx
imageStep: xxx
deployTask:
image:
deployStep: xxx

Git authentication

Pulling user's source code with token or ssh-auth is supported in the default git step. You can config git repository tokens and ssh private keys in values.yaml. For example:

tektonci-resources:
gitRepos:
http:
- url: https://github.com
token: KL4U5Y6HF14EOJ4IE==
- url: https://gitlab.com
token: DS4U5Y6HF54GOE5JF==
ssh:
- url: github.com
privateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----

Callback in deploy step

You need callback horizon api /apis/internal/v2/clusters/$CLUSTER_ID/deploy with token to pass back the pipeline output you generate in your custom deploy step script. For example:

curl -k -sSL -X POST \
-H "Content-Type: application/json" \
-H "X-Horizon-JWT-Token: $TOKEN" \
-d "$REQUEST_BODY"
-o $OUTPUT "$DEPLOY_URL"

where the REQUEST_BODY is structured as follows:

{
"output": {
"image": "harbor.server.org/artifact-image/demo:v1.0",
...
},
"pipelinerunID": 2435
}

The output can be used to pass the CI results to CD based on horizon template. For example:

# deployment.yaml
kind: Deployment
spec:
template:
spec:
containers:
- name: xxx
image: {{ .Values.image }}

which specifies output.image as the container image in deployment template.

Volume Mounts

You can configure extraVolumeMounts in values.yaml to mount volumes into step container. Volume type persistentVolumeClaim, hostPath and emptyDir (default) is supported. For example:

tektonci-resources:
extraVolumeMounts:
# persistentVolumeClaim
- name: persistent-volume
existingClaim: ci-claim
mountPath: /persistent_volume
readOnly: true
# hostPath
- name: m2
hostPath: /root/.m2
mountPath: /root/.m2
# emptyDir, if neither persistentVolumeClaim nor hostPath
- name: maven-repository
mountPath: /root/.m2
subPath: repository
readOnly: false