作为 DevOps 管理员或开发人员,您可以创建自定义脚本来扩展 Code Stream 的功能。使用您的脚本,可以将 Code Stream 与您自己用于生成、测试和部署应用程序的持续集成 (CI) 和持续交付 (CD) 工具以及 API 集成。如果不想公开您的应用程序 API,则自定义脚本特别有用。

自定义脚本几乎可以执行与生成工具、测试工具和部署工具集成所需的任何操作。例如,自定义脚本可与管道中的工作区配合工作,以支持生成和测试应用程序的 CI 任务以及部署应用程序的 CD 任务。当管道已完成或发生其他许多事件时,自定义脚本可以向 Slack 发送消息。

您可以采用受支持的语言之一编写自定义脚本。在脚本中,可以包括业务逻辑,以及定义输入和输出。输出类型可以包括数字、字符串、文本和密码。可以使用不同的业务逻辑、输入和输出创建自定义脚本的多个版本。

在自定义任务中使用管道运行某个版本的脚本。所创建的脚本位于 Code Stream 实例中。

当管道使用自定义集成时,如果您尝试删除该自定义集成,则会显示一条错误消息,指示无法将其删除。

如果删除自定义集成,将移除自定义脚本的所有版本。如果现有管道的自定义任务使用任何版本的脚本,则该管道将失败。为了确保现有管道不会失败,可以弃用并撤消不再希望使用的脚本版本。如果没有管道使用该版本,便可以将其删除。

表 1. 编写自定义脚本之后执行的操作
执行的操作... 有关该操作的更多信息...

向管道添加自定义任务。

自定义任务:

  • 在与管道中其他 CI 任务相同的容器中运行。
  • 包含输入变量和输出变量,脚本会在管道运行自定义任务之前填充这些变量。
  • 支持您在脚本中定义为输入和输出的多种数据类型和各种元数据类型。

在自定义任务中选择脚本。

在脚本中声明输入属性和输出属性。

保存管道,然后启用并运行管道。

当管道运行时,自定义任务将调用指定版本的脚本并运行其中的业务逻辑,从而将构建工具、测试工具和部署工具与 Code Stream 集成。

管道运行之后,查看执行。

验证管道是否产生预期结果。

使用调用自定义集成版本的自定义任务时,可以在管道工作区选项卡上将自定义环境变量作为名称-值对包括在内。当生成器映像创建运行 CI 任务并部署映像的工作区容器时, Code Stream 会将环境变量传递到该容器。

例如,当您的 Code Stream 实例需要使用 Web 代理,并且使用 Docker 主机为自定义集成创建容器时, Code Stream 将运行管道并将 Web 代理设置变量传递到该容器。

表 2. 环境变量名称-值对示例
名称
HTTPS_PROXY http://10.0.0.255:1234
https_proxy http://10.0.0.255:1234
NO_PROXY 10.0.0.32, *.dept.vsphere.local
no_proxy 10.0.0.32, *.dept.vsphere.local
HTTP_PROXY http://10.0.0.254:1234
http_proxy http://10.0.0.254:1234
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

名称-值对在用户界面中如下所示:

此示例创建的自定义集成将 Code Stream 连接到 Slack 实例并向 Slack 通道发布消息。

前提条件

  • 要编写自定义脚本,请确认您掌握以下语言之一:Python 2、Python 3 或 Node.js,或者掌握以下任意 shell 语言:Bash、sh 或 zsh。
  • 使用已安装的 Node.js 或 Python 运行时生成容器映像。

过程

  1. 创建自定义集成。
    1. 单击自定义集成 > 新建,然后输入相关的名称。
    2. 选择首选运行时环境。
    3. 单击创建
      脚本将打开并显示代码,该脚本包含所需的运行时环境。例如, runtime: "nodejs"。脚本必须包含运行时,因为生成器映像使用该运行时来确保添加到管道中的自定义任务在管道运行时将成功。否则,自定义任务将失败。
    自定义集成 YAML 的主要区域包括运行时、代码、输入属性和输出属性。此过程介绍了各种类型和语法。
    自定义集成 YAML 键 说明
    runtime

    Code Stream 运行代码的任务运行时环境,可以是以下不区分大小写的字符串之一:

    • nodejs
    • python2
    • python3
    • shell

    如果未提供任何内容,将默认采用 shell。

    code 作为自定义任务的一部分运行的自定义业务逻辑。
    inputProperties 作为自定义任务配置的一部分进行捕获的输入属性数组。这些属性通常在代码中使用。
    outputProperties 可从自定义任务中导出以传播到管道的输出属性数组。
  2. 使用可用的数据类型和元数据在脚本中声明输入属性。
    输入属性将在 YAML 的 code: 节中作为上下文传入到脚本。
    自定义任务 YAML 输入键 说明 必需
    type 要显示的输入类型:
    • text
    • textarea
    • number
    • checkbox
    • password
    • select
    name 自定义任务的输入的名称或字符串,将插入到自定义集成 YAML 代码中。对于为自定义集成定义的每个输入属性必须唯一。
    title 管道模型画布上自定义任务的输入属性的文本字符串标签。如果留空,默认使用 name
    required 确定用户在配置自定义任务时是否必须填写输入属性。设置为 true 或 false。若为 true,则如果当用户在管道画布上配置自定义任务时未提供值,任务的状态仍为未配置。
    placeHolder 未提供值时输入属性条目区域中的默认文本。映射到 html 占位符属性。仅某些输入属性类型提供此支持。
    defaultValue 当自定义任务在管道模型页面上显示时,用于填充输入属性条目区域的默认值。
    bindable 确定在为管道画布上的自定义任务建模时,输入属性是否接受美元符号变量。在标题旁边添加 $ 指示符。仅某些输入属性类型提供此支持。
    labelMessage 作为用户的帮助工具提示的字符串。在输入标题旁边添加一个工具提示图标 i
    enum 接受显示“选择”输入属性选项的值数组。仅某些输入属性类型提供此支持。

    当用户选择并保存一个选项以用于自定义任务时,inputProperty 的值与此值相对应,并显示在自定义任务建模中。

    例如,值 2015。

    • 2015
    • 2016
    • 2017
    • 2018
    • 2019
    • 2020
    options 使用 optionKeyoptionValue 接受对象数组。
    • optionKey。传播到任务的代码部分的值。
    • optionValue。在用户界面中显示选项的字符串。

    仅某些输入属性类型提供此支持。

    选项:

    optionKey:key1。选择并保存以用于自定义任务后,此 inputProperty 的值将对应于代码部分中的 key1

    optionValue:'Label for 1'。key1 在用户界面中的显示值,不会显示在自定义任务的任何其他位置。

    optionKey:key2

    optionValue:'Label for 2'

    optionKey:key3

    optionValue:'Label for 3'

    minimum 接受作为此输入属性的有效最小值的数字。仅数字类型的输入属性提供此支持。
    maximum 接受作为输入属性的有效最大值的数字。仅数字类型的输入属性提供此支持。
    表 3. 支持用于自定义脚本的数据类型和元数据
    支持的数据类型 支持用于输入的元数据
    • 字符串
    • 文本
    • List:显示为任意类型的列表
    • Map:显示为 map[string]any
    • Secure:显示为密码文本框,在保存自定义任务时进行加密
    • 数字
    • Boolean:显示为文本框
    • URL:与 string 相同,需要进行附加验证
    • 选择和单选按钮
    • type:String 或 Text 中的一种...
    • default:默认值
    • options:要与选择或单选按钮一起使用的选项的列表或映射
    • min:最小值或最小大小
    • max:最大值或最大大小
    • title:文本框的详细名称
    • placeHolder:UI 占位符
    • description:将成为工具提示
    例如:
    inputProperties:
            - name: message
              type: text
              title: Message
              placeHolder: Message for Slack Channel
              defaultValue: Hello Slack
              bindable: true
              labelInfo: true
              labelMessage: This message is posted to the Slack channel link provided in the code
    
  3. 在脚本中声明输出属性。
    脚本将从业务逻辑(脚本的 code: 节)捕获输出属性,您可以在该节中声明输出的上下文。
    当管道运行时,您可以输入任务输出的响应代码。例如, 200
    Code Stream 针对每个 outputProperty 支持的键。
    说明
    type 当前包括 label 的单个值。
    name 自定义集成 YAML 的代码块发出的键。
    title 用户界面中显示 outputProperty 的标签。
    例如:
    outputProperties:
      - name: statusCode
        type: label
        title: Status Code
  4. 要与自定义脚本的输入和输出交互,请使用 context 获取输入属性或设置输出属性。
    对于输入属性: (context.getInput("key"))
    对于输出属性: (context.setOutput("key", "value"))
    对于 Node.js:
    var context = require("./context.js")
    var message = context.getInput("message");
    //Your Business logic
    context.setOutput("statusCode", 200);
    对于 Python:
    from context import getInput, setOutput
    message = getInput('message')
    //Your Business logic
    setOutput('statusCode', '200')
    
    对于 Shell:
    # Input, Output properties are environment variables
    echo ${message} # Prints the input message
    //Your Business logic
    export statusCode=200 # Sets output property statusCode
    
  5. code: 节中,声明自定义集成的所有业务逻辑。
    例如,对于 Node.js 运行时环境:
    code: |
        var https = require('https');
        var context = require("./context.js")
        
        //Get the entered message from task config page and assign it to message var
        var message = context.getInput("message");
        var slackPayload = JSON.stringify(
            {
                text: message
            });
    
        const options = {
            hostname: 'hooks.slack.com',
            port: 443,
            path: '/YOUR_SLACK_WEBHOOK_PATH',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(slackPayload)
            }
        };
        
        // Makes a https request and sets the output with statusCode which 
        // will be displayed in task result page after execution
        const req = https.request(options, (res) => {
            context.setOutput("statusCode", res.statusCode);
        });
    
        req.on('error', (e) => {
            console.error(e);
        });
        req.write(slackPayload);
        req.end();
    
  6. 对自定义集成脚本进行版本控制并发布之前,请下载适用于 Python 或 Node.js 的上下文文件,并测试脚本中包含的业务逻辑。
    1. 将指针放在脚本中,然后单击画布顶部的上下文文件按钮。例如,如果脚本采用 Python,则单击 CONTEXT.PY
    2. 修改并保存文件。
    3. 在开发系统上,借助上下文文件运行并测试自定义脚本。
  7. 将某个版本应用到自定义集成脚本。
    1. 单击版本
    2. 输入版本信息。
    3. 单击发行版本,以在自定义任务中选择脚本。
    4. 要创建版本,请单击创建
      对自定义集成脚本进行版本控制。
  8. 要保存脚本,请单击保存
  9. 在管道中,配置工作区。
    1. 单击工作区选项卡。
    2. 选择 Docker 主机和生成器映像 URL。
      创建自定义集成。
  10. 向管道添加自定义任务并配置该自定义任务。
    1. 单击模型选项卡。
    2. 添加任务,为类型选择自定义,然后输入相关的名称。
    3. 选择您的自定义集成脚本和版本。
    4. 要在 Slack 中显示自定义消息,请输入消息文本。
      输入的任何文本将替代自定义集成脚本中的 defaultValue。例如:
      在管道中添加并配置自定义任务。
  11. 保存并启用管道。
    1. 单击保存
    2. 在“管道”选项卡中,单击启用管道以使圆圈移动到右侧。
  12. 运行管道。
    1. 单击运行
    2. 查看管道执行。
    3. 确认输出包含预期的状态代码、响应代码、状态和已声明的输出。
      您已将 statusCode 定义为输出属性。例如, statusCode 的值为 200 可能表示 Slack 发布成功,而 responseCode 的值为 0 可能表示脚本已成功而未发生错误。
    4. 要确认执行日志中的输出,请单击执行,单击管道的链接,单击该任务,然后查找已记录的数据。例如:
      查看自定义集成的任务输出。
  13. 如果发生错误,请解决问题,然后重新运行管道。
    如果基础映像中缺少某个文件或模块,您必须创建包含缺少的文件的另一个基础映像。然后,提供 Docker 文件,并通过管道推送映像。

结果

恭喜!您已创建一个自定义集成脚本,该脚本将 Code Stream 连接到 Slack 实例并向 Slack 通道发布消息。

后续步骤

继续创建自定义集成以支持在管道中使用自定义任务,以便扩展 Code Stream 在自动执行软件发布生命周期方面的功能。