【问题标题】:How can you "source" an environment inside a Buildbot step?如何在 Buildbot 步骤中“获取”环境?
【发布时间】:2013-07-17 09:58:23
【问题描述】:

在 Buildbot 中,我需要能够在执行编译步骤之前“获取”环境。

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

. envrionment-set-up-script
build_command

在构建机器人 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"]))

所有这些都失败了,这是因为找不到命令,这是有道理的,因为它是内置的 bash。

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

【问题讨论】:

    标签: buildbot


    【解决方案1】:

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

    • 运行一个 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')))
    

    【讨论】:

    • 唯一可能失败的情况是,如果源脚本启动了某个进程,该进程 a) 无法在其 shell 死亡中幸存,并且 b) 被环境引用。
    • 与这里描述的一些更简单的选项相比,这非常激烈,但肯定会给您很大的灵活性。考虑将其概括并作为补丁提交给 Buildbot?
    【解决方案2】:

    在使用 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)
    

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

    factory.addStep(EnvStep(command='foo'))
    

    并且采购会自动发生。

    我们还有许多其他自定义构建步骤需要获取构建环境,因此我们只是让它们子类化 EnvStep 而不是 ShellCommand 以便自动处理环境。

    【讨论】:

      【解决方案3】:

      Visual Studio 开发示例也很有用。

      使用通用工具脚本,为每台机器设置正确的env,同一个builder可以使用多个版本的VS,支持多种架构native和cross。

      # A raw text string to get around windows quoting problems in buildbot.
      vscomntools=r""""%VS120COMNTOOLS%\VsDevCmd.bat" %PROCESSOR_ARCHITECTURE% & set"""
      
      # Determine MSVC Environment using VS Common Tools for build steps.
      f.addStep(SetProperty(
          command=vscomntools,
          extract_fn=glob2list))
      

      另一种方法是通过尝试引用批处理文件、& 和命令来启动每个命令。

      【讨论】:

        【解决方案4】:

        您可以在 ShellCommand 构建步骤中使用 env 参数来为您的命令设置环境。 (http://docs.buildbot.net/0.8.1/Using-ShellCommands.html)

        如果您希望环境平等地应用于所有构建命令,您还可以在启动构建从属之前设置环境。

        基本上是:

        1. 算出需要的环境变量,传入env。
        2. 在启动构建从属之前获取配置。
        3. 包装源命令,您的构建命令是一个 shell 脚本,并作为单个构建步骤运行。

        【讨论】:

        • env 参数在执行特定命令时将一组已知的环境值添加到环境中。我可以很好地浏览需要获取的 shell 脚本并锻炼环境。有问题的外壳脚本不是我的,而是开放嵌入式工具的一部分。因此很可能在我控制之外的源代码控制中发生变化。因此,问题询问如何“获取”环境并将其应用于进一步的构建步骤。
        • 我可能会在一个构建步骤中运行全部内容,将所有内容包装在一个 shell 脚本中。
        【解决方案5】:
            steps.ShellCommand(
                    name = "Example",
                    command = ["/bin/bash", "-c", "source <BASH SCRIPT>"],
                    haltOnFailure = True,
                    description = "Example"
            ),
        

        【讨论】:

        • 这个问题是下面的构建步骤将产生一个新的 shell 并且不会继承那些源函数。
        【解决方案6】:

        我以不同的方式解决了这个问题。我在 Windows worker 上安装了一个批处理文件,它在启动时调用环境设置批处理文件,然后执行预期的命令。当然,由于批处理文件在转发参数方面很糟糕,而且 Visual Studio 2017 的 VsDevCmd.bat 破坏了您的 cwd,这使得这变得更加困难。但是,如果你在worker上安装以下文件,你可以用VS2017构建:

        @ECHO OFF
        @REM Calls a single command from the environment set from visual studio vcvars.
        @REM Usage:
        @REM withvcvars-2017.bat <arch> [command]
        @REM 
        @REM Run VsDevCmd.bat /help to see available arches
        @REM See below instantiation for more fine grained option setting.
        
        set ARCH=%1
        shift
        
        setlocal enabledelayedexpansion
        
        @rem Replace __ with = in batch files.
        @rem This works around idiotic lack of equals signs in args
        @rem args contains full args string with substitutions in place
        :argloop
        if "%~1" NEQ "" (
        
            set str=%~1
            set out=!str:__==!
            set %~1=!out!
            set args=!args!!out! 
        
            SHIFT
            goto :argloop
        )
        
        @rem Aside from batch files being too moronic to allow for equals signs in args,
        @rem VsDevCmd.bat idiotically clobbers the current working directory when it's called.
        set CWD=%cd%
        
        echo Calling VsDevCmd.bat for arch %ARCH%
        call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=%ARCH% -winsdk=8.1 -app_platform=Desktop -no_logo
        
        @rem Who lets these things out the door?
        cd %CWD%
        
        @ECHO ON
        %args%
        

        完成后,您可以在 bulidbot 主逻辑中创建一个附加此批处理文件的函数:

        def _withvcvars(year, arch, cmd):     
            base_cmd = ["%swithvcvars-%s.bat" % ('\\path\\to\\batchfile\\', year), arch]      
            return base+cmd
        

        这使您可以运行调用 msbuild.exe 的命令,该命令在其参数中需要等号。只需将它们指定为双下划线:

        withvcvars-2017.bat amd64 msbuild.exe your.sln /p:Configuration__Release /p:Platform__x64
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-08-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-27
          • 1970-01-01
          相关资源
          最近更新 更多