2013-07-17 27 views
8

Trong Buildbot tôi cần có khả năng "nguồn" một môi trường trước khi thực hiện một bước biên dịch.Làm thế nào bạn có thể "nguồn" một môi trường bên trong một bước Buildbot?

Nếu tôi đang xây dựng các ứng dụng từ dòng lệnh sử dụng bash tôi sẽ phải làm:

. envrionment-set-up-script 
build_command 

Trong tập tin master.cfg build bot Tôi đã thử những điều sau đây:

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"])) 

Tất cả trong đó không thành công, điều này là do lệnh không thể được tìm thấy, có ý nghĩa vì nó là một nội trang bash.

Ngoài ra tôi không nghĩ rằng đây là phương pháp chính xác vì môi trường sẽ không nhất thiết phải được sử dụng khi bước tiếp theo của nhà máy được gọi.

Trả lời

4

Sau một số thử nghiệm, tôi đã tìm được cách để đạt được điều này. Bạn cần phải:

  • chạy một bash tiểu vỏ thiết lập môi trường nên được sử dụng cho vỏ đó, ví dụ: gọi bash với các biến môi trường BASH_ENV thiết lập để các tập tin đó nên được lấy ra môi trường.
  • chạy env lệnh trong bash để nắm bắt môi trường
  • phân tích kết quả của env lệnh vào một tài sản (sử dụng một setProperty bước)
  • sử dụng tài sản trong các bước tiếp theo như env tham số

Lưu ý: rằng môi trường nên được phân tích như một cuốn từ điển có thể được sử dụng như một n env tham số

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'))) 
+0

Trường hợp duy nhất có thể bị lỗi là nếu tập lệnh nguồn bắt đầu một số tiến trình mà a) không tồn tại trong vỏ chết, và b) được tham chiếu bởi môi trường. –

+0

Đó là khá mạnh mẽ, so với một số các tùy chọn đơn giản được mô tả ở đây, nhưng chắc chắn mang lại cho bạn rất nhiều tính linh hoạt. Hãy xem xét khái quát hóa điều này và gửi nó như là một bản vá cho Buildbot? – djmitche

3

Bạn có thể sử dụng tham số env cho bước tạo ShellCommand để thiết lập môi trường cho lệnh của mình. (http://docs.buildbot.net/0.8.1/Using-ShellCommands.html)

Bạn cũng có thể đặt môi trường trước khi bắt đầu xây dựng nô lệ, nếu bạn muốn môi trường áp dụng cho tất cả lệnh xây dựng như nhau.

Về cơ bản một trong hai:

  1. làm việc ra các biến môi trường cần thiết và vượt qua trong trong env.
  2. Nguồn cấu hình trước khi bắt đầu xây dựng nô lệ.
  3. Quấn lệnh nguồn và lệnh xây dựng của bạn (s) là một kịch bản lệnh shell và chạy dưới dạng một bước xây dựng duy nhất.
+0

Tham số _env_ thêm một bộ giá trị môi trường được biết đến khi thực hiện lệnh cụ thể.Tôi rất có thể đi qua kịch bản vỏ mà cần phải được nguồn gốc và tập luyện môi trường. Kịch bản shell trong câu hỏi không phải của tôi mà là một phần của các công cụ nhúng mở. Do đó có khả năng thay đổi trong kiểm soát nguồn ngoài tầm kiểm soát của tôi. Do đó, câu hỏi được hỏi làm thế nào để "nguồn" môi trường và áp dụng điều này để tiếp tục xây dựng các bước. –

+0

Tôi có thể chỉ cần đi với chạy toàn bộ rất nhiều trong một bước xây dựng duy nhất, bằng cách gói tất cả mọi thứ trong một kịch bản shell. –

7

Trong khi làm việc với OpenEmbedded/Yocto, chúng tôi giải quyết vấn đề theo một cách tương tự như sau:

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

Sau đó, thêm một EnvStep mà bộ tham số command của nó để foo phép chúng tôi chạy foo trong môi trường có nguồn gốc với environment-set-up-script. Nói cách khác, bạn sẽ sử dụng bước bằng cách gọi số

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

và tìm nguồn cung ứng sẽ tự động diễn ra.

Chúng tôi cũng có một loạt các bước xây dựng tùy chỉnh khác yêu cầu mã nguồn được tạo, vì vậy chúng tôi chỉ cho phép chúng phân lớp EnvStep thay vì ShellCommand để môi trường được xử lý tự động.

1

Ví dụ về phát triển Visual Studio cũng hữu ích.

Bằng cách sử dụng các tập lệnh công cụ phổ biến, đúng env được đặt cho mỗi máy, nhiều phiên bản của VS có thể được sử dụng bởi cùng một nhà xây dựng và nhiều kiến ​​trúc gốc và chéo được hỗ trợ.

# 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)) 

Cách khác là bắt đầu mỗi lệnh bằng cách cố gắng trích dẫn tệp lô, & và lệnh.

0
steps.ShellCommand(
      name = "Example", 
      command = ["/bin/bash", "-c", "source <BASH SCRIPT>"], 
      haltOnFailure = True, 
      description = "Example" 
    ), 
+0

Không chỉ đăng mã; thêm một lời giải thích. – reformed

0

Tôi giải quyết vấn đề này hơi khác một chút. Tôi cài đặt một tập tin batch trên nhân viên Windows, khi khởi động, gọi tập tin batch cài đặt môi trường, sau đó thực thi lệnh dự định. Đây là, tất nhiên, thực hiện khó khăn hơn bởi thực tế là các tập tin batch là khủng khiếp tại các đối số chuyển tiếp, và bởi thực tế là Visual Studio 2017 của VsDevCmd.bat clobbers cwd của bạn. Tuy nhiên, nếu bạn cài đặt các tập tin sau đây về người lao động, bạn có thể xây dựng với 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% 

Một khi điều này được thực hiện, bạn có thể tạo một hàm trong chủ Logic bulidbot của bạn mà gắn thêm batch file này:

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

Điều này cho phép bạn chạy các lệnh trong đó bạn gọi msbuild.exe, kỳ vọng bằng dấu trong đối số của nó. Chỉ cần chỉ định chúng dưới dạng dấu gạch dưới kép:

withvcvars-2017.bat amd64 msbuild.exe your.sln /p:Configuration__Release /p:Platform__x64 
Các vấn đề liên quan