如何在Buildbot步骤中"获取"环境?

Sim*_*ack 9 buildbot

在Buildbot中,我需要能够在编译步骤之前"获取"环境.

如果我使用bash从命令行构建应用程序,我将不得不这样做:

. envrionment-set-up-script
build_command
Run Code Online (Sandbox Code Playgroud)

在build bot master.cfg文件中,我尝试了以下内容:

factory.addStep(ShellCommand(command=["source","environment-set-up-script"])
factory.addStep(ShellCommand(command=[".","environment-set-up-script"]))
factory.addStep(Configure(command=["source","environment-set-up-script"]))
factory.addStep(Configure(command=[".","environment-set-up-script"]))
Run Code Online (Sandbox Code Playgroud)

所有这些都失败了,这是因为无法找到命令,这是有道理的,因为它是一个内置的bash.

此外,我不认为这是正确的方法,因为在调用工厂的下一步时不一定会使用环境.

imo*_*lit 8

在使用OpenEmbedded/Yocto时,我们以类似于此的方式解决了问题:

class EnvStep(ShellCommand):
    def __init__(self, command='', **kwargs):
        kwargs['command'] = [
            'bash', '-c', 'source environment-set-up-script; %s' % command
        ]
        ShellCommand.__init__(self, **kwargs)
Run Code Online (Sandbox Code Playgroud)

然后,添加一个EnvStep设置其command参数,foo让我们foo在源环境中运行environment-set-up-script.换句话说,您可以通过调用来使用该步骤

factory.addStep(EnvStep(command='foo'))
Run Code Online (Sandbox Code Playgroud)

采购将自动进行.

我们还有一些其他自定义构建步骤需要build-env来源,因此我们只是让它们子类化EnvStep而不是ShellCommand自动处理环境.


Sim*_*ack 5

经过一些实验,我找到了实现这一目标的方法。你需要:

  • 运行 bash 子 shell,设置该 shell 所使用的环境,即调用 bash,并将环境变量BASH_ENV设置为应源自环境的文件。
  • 在bash中运行env命令来捕获环境
  • 将env命令的结果解析为属性(使用SetProperty步骤)
  • 在后续步骤中使用该属性作为env参数

注意:环境应该被解析为可以用作env参数的字典

    from buildbot.process.factory import BuildFactory
    from buildbot.steps.shell import ShellCommand, SetProperty
    from buildbot.process.properties import Property  

    def glob2list(rc, stdout, stderr):
        ''' Function used as the extrat_fn function for SetProperty class
            This takes the output from env command and creates a dictionary of 
            the environment, the result of which is stored in a property names
            env'''
        if not rc:
            env_list = [ l.strip() for l in stdout.split('\n') ]
            env_dict={ l.split('=',1)[0]:l.split('=',1)[1] for l in 
                          env_list if len(l.split('=',1))==2}
            return {'env':env_dict}

    #This is the equivalent of running source MyWorkdir/my-shell-script then  
    #capturing the environment afterwords.
    factory.addStep(SetProperty(command="bash -c env",
                extract_fn=glob2list,       
                workdir='MyWorkdir',
                env={BASH_ENV':'my-shell-script' }))

    #Do another step with the environment that was sourced from 
    #MyWorkdir/my-shell-script
    factory.addStep(ShellCommand(command=["env"],
                workdir="MyWorkdir",
                env=Property('env')))
Run Code Online (Sandbox Code Playgroud)