Using CTO.ai Commands lets you configure containerized workflows that your team can use from our CLI or our Slack integration. For more complex development processes, Commands can be integrated with each other, as well as with Pipelines and Services workflows, to build a reliable, interactive DevOps playbooks for your team.
ℹ️
Commands Overview
For a high-level overview of our Commands workflows and their use cases, be sure to have a look at our Commands Overview in the Getting Started section of our docs.
We currently offer Commands SDKs with support for Python, Node, Go, and Bash runtimes. Our SDKs provide a straightforward way to send Lifecycle Event data to your CTO.ai Dashboard, prompt users interactively, and integrate with other systems.
Structure of Commands Workflows
There are three main components that comprise any given workflow:
ops.yml
Dockerfile (and a corresponding .dockerignore file)
Your custom code
For a deeper explanation of the ops init subcommand and the scaffolding generated by our CLI, our Workflows Overview document has you covered.
Commands Workflow Reference
To help you better understand how Commands workflows are structured, we have included an explanation of the scaffolding template generated for each of our SDK languages below. Let’s have a look at what is generated when we create a new Commands workflow with our CLI.
Create a Commands Workflow (ops init)
The CTO.ai ops CLI provides a subcommand to create scaffolding files for your workflow: ops init. You can use the -k flag to specify the kind as a command workflow, as well as pass an optional argument to give the workflow a name (example-command, in this case):
Usage Example: ops init
ops init -k command example-command
After you respond to the CLI’s interactive prompting, it will generate template code for your new Commands workflow.
Workflow Scaffolding Code
This section explains the scaffolding code that’s generated when you choose Bash as the language for your new workflow.
ops.yml and Custom Code
The values submitted in response to the interactive prompts are reflected in a newly-generated ops.yml file.
The value of the run key in a workflow definition (e.g. bash /ops/main.sh in the example below) should be the shell command that the final container image needs to run to execute your custom workflow code. We provide a basic example workflow as part of the scaffolding template generated by our CLI (a script called main.sh for our Bash template, also included here):
version: "1"commands:
- name: example-command:0.1.0description: Base Bash Command scaffolding for reference.run: bash /ops/main.sh
#!/bin/bash
repo=$(ux prompt input \
--message "Which application do you want to deploy?"\
--name "repo")ls -asl
echo "Here is how you can send logs"ux print "🚀 You reported that ${repo}'s deployment succeeded!"sdk track ""\
event_name:deployment \
event_action:succeeded \
repo:"${repo}"\
branch:"main"
Dockerfile and Dependencies
This is accompanied by a base Dockerfile that defines the execution environment of our workflow, and the dependencies to be installed in the final container image (via the Debian package manager or another method):
############################# Final container############################FROM registry.cto.ai/official_images/bash:2-buster-slimWORKDIR /opsADD --chown=ops:9999 . .############################################################################### As a security best practice the container will always run as non-root user.##############################################################################USER ops
.gitignore
ops.yml
This section explains the scaffolding code that’s generated when you choose Python as the language for your new workflow.
ops.yml and Custom Code
The values submitted in response to the interactive prompts are reflected in a newly-generated ops.yml file.
The value of the run key in a workflow definition (e.g. python3 /ops/main.py in the example below) should be the shell command that the final container image needs to run to execute your custom workflow code. We provide a basic example workflow as part of the scaffolding template generated by our CLI (a script called main.py for our Python template, also included here):
version: "1"commands:
- name: example-command:0.1.0description: Base Python Command scaffolding for reference.run: python3 /ops/main.py
import os
from cto_ai import ux, prompt, sdk
defmain():
repo = prompt.input(
name="repo",
message="Which application do you want to deploy?",
allowEmpty=False )
# Add your workflow code here os.system('ls -asl')
sdk.log('Here is how you can send logs')
ux.print(f'🚀 {repo}\'s successful deployment has been recorded!')
event = {
"event_name": "deployment",
"event_action": "succeeded",
"branch": "main",
"repo": repo
}
sdk.track([], "", event)
if __name__ =="__main__":
main()
Dockerfile and Dependencies
This is accompanied by a base Dockerfile that defines the execution environment of our workflow, and the dependencies to be included in the final container image (specified as a requirements.txt for our Python template):
############################# Final container############################FROM registry.cto.ai/official_images/python:2-3.7-buster-slimWORKDIR /opsADD --chown=ops:9999 requirements.txt .RUN pip3 install -r requirements.txtADD --chown=ops:9999 . .############################################################################### As a security best practice the container will always run as non-root user.##############################################################################USER ops
cto-ai
.gitignore
ops.yml
This section explains the scaffolding code that’s generated when you choose JavaScript as the language for your new workflow.
ops.yml and Custom Code
The values submitted in response to the interactive prompts are reflected in a newly-generated ops.yml file.
The value of the run key in a workflow definition (e.g. node /ops/index.js in the example below) should be the shell command that the final container image needs to run to execute your custom workflow code. We provide a basic example workflow as part of the scaffolding template generated by our CLI (a script called index.js for our JavaScript template, also included here):
version: "1"commands:
- name: example-command:0.1.0description: Base JavaScript Command scaffolding for reference.run: node /ops/index.js
const {ux, sdk} =require("@cto.ai/sdk")
asyncfunctionmain() {
constprompt_res=awaitux.prompt({
type:"input",
name:"repo",
message:"Which application do you want to deploy?",
})
// Add your workflow code
const {stdout} =awaitsdk.exec("ls -asl")
sdk.log(stdout)
sdk.log("Here is how you can send logs")
awaitux.print(`🚀 ${prompt_res.repo}'s successful deployment has been recorded!`)
constevent= {
event_name:"deployment",
event_action:"succeeded",
branch:"main",
repo:prompt_res.repo,
}
sdk.track([], event)
}
main().catch((err) => {
sdk.log(err)
process.exit(1)
})
Dockerfile and Dependencies
This is accompanied by a base Dockerfile that defines the execution environment of our workflow, and the dependencies to be included in the final container image (specified as a package.json for our JavaScript template):
############################# Final container############################FROM registry.cto.ai/official_images/node:2.7.4-12.13.1-buster-slimWORKDIR /opsADD --chown=ops:9999 package.json .RUN npm installADD --chown=ops:9999 . .############################################################################### As a security best practice the container will always run as non-root user.##############################################################################USER ops
This section explains the scaffolding code that’s generated when you choose Go as the language for your new workflow.
ops.yml and Custom Code
The values submitted in response to the interactive prompts are reflected in a newly-generated ops.yml file.
The value of the run key in a workflow definition (e.g. /ops/main in the example below) should be the shell command that the final container image needs to run to execute your custom workflow code. We provide a basic example workflow as part of the scaffolding template generated by our CLI (a code file called main.go for our Go template, also included here):
version: "1"commands:
- name: example-command:0.1.0description: Base Go Command scaffolding for reference.run: /ops/main
packagemainimport (
"fmt""os/exec"ctoai"github.com/cto-ai/sdk-go/v2")
funcmain() {
client:=ctoai.NewClient()
repo, err:=client.Prompt.Input("repo", "Which application do you want to deploy?", ctoai.OptInputAllowEmpty(false))
iferr!=nil {
panic(err)
}
cmd:=exec.Command("ls", "-asl")
stdout, err:=cmd.Output()
iferr!=nil {
panic(err.Error())
}
err = client.Sdk.Log(string(stdout))
iferr!=nil {
panic(err)
}
err = client.Sdk.Log("\nHere is how you can send logs\n")
iferr!=nil {
panic(err)
}
err = client.Ux.Print(fmt.Sprintf("🚀 %s's successful deployment has been recorded!", repo))
iferr!=nil {
panic(err)
}
event:=map[string]interface{}{
"event_name": "deployment",
"event_action": "succeeded",
"branch": "main",
"repo": repo,
}
err = client.Sdk.Track([]string{}, "", event)
iferr!=nil {
panic(err)
}
}
Dockerfile and Dependencies
This is accompanied by a base Dockerfile that defines the execution environment of our workflow, and the dependencies to be included in the final container image (specified as a go.mod for our Go template):
############################# Build container############################FROM golang:1.14.0-buster AS depWORKDIR /opsADD go.mod go.sum ./RUN go get ./...ADD . .RUN go build -ldflags="-s -w" -o main && strip -s main && chmod 777 main############################# Final container############################FROM registry.cto.ai/official_images/base:2-buster-slimWORKDIR /opsENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/listsCOPY --chown=ops:9999 --from=dep /ops/main .############################################################################### As a security best practice the container will always run as non-root user.##############################################################################USER ops
module github.com/cto-ai/sharedgo
go 1.14
require github.com/cto-ai/sdk-go/v2 v2.2.3