2013-07-17 11 views
8

W Buildbot potrzebuję być w stanie "źródło" środowiska przed wykonaniem kroku kompilacji.Jak można "pozyskać" środowisko wewnątrz kroku Buildbot?

Gdybym budowanie aplikacji z linii poleceń za pomocą bash musiałbym zrobić:

. envrionment-set-up-script 
build_command 

w pliku master.cfg budować bot Próbowałem następujące:

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

Wszystko z których to się nie uda, dzieje się tak dlatego, że polecenia nie można znaleźć, co ma sens, ponieważ jest to wbudowane bash.

Również nie sądzę, że jest to właściwe podejście, ponieważ środowisko niekoniecznie będzie używane, gdy zostanie wywołany następny etap fabryki.

Odpowiedz

4

Po kilku eksperymentach znalazłem sposób, aby to osiągnąć. Musisz:

  • prowadzony bash ustawienie środowiska, które powinny być wykorzystywane do tego płaszcza sub-shell, czyli wywołać bash ze zmiennej środowiskowej BASH_ENV zestaw do pliku, który powinien być pozyskiwany do środowiska.
  • uruchomić polecenia env bash uchwycić środowiska
  • analizowania wynik polecenia env do właściwości (przy użyciu SetProperty etapie)
  • wykorzystania właściwości w dalszych etapach, jak env parametr

Uwaga:, że środowisko powinno być analizowane jak słownik, który może być używany jako n env parametr

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

Jedynym przypadkiem, który może się nie powieść, jest sytuacja, w której skrypt źródłowy rozpoczyna jakiś proces, w którym a) nie przeżywa śmierci powłoki, a b) jest przywoływany przez środowisko. –

+0

To dość intensywne, w porównaniu do niektórych z prostszych opcji opisanych tutaj, ale z pewnością daje dużą elastyczność. Rozważ uogólnienie tego i przesłanie go jako poprawki do Buildbota? – djmitche

3

Możesz użyć parametru env do kroku kompilacji ShellCommand, aby skonfigurować środowisko dla swojego polecenia. (http://docs.buildbot.net/0.8.1/Using-ShellCommands.html)

Możesz również ustawić środowisko przed uruchomieniem budowania slave, jeśli chcesz, aby środowisko miało zastosowanie do wszystkich poleceń budowania jednakowo.

Zasadniczo albo:

  1. wypracować wymagane zmienne środowiskowe i przepustkę w env.
  2. Źródło konfiguracji przed uruchomieniem budowania slave.
  3. Zawiń polecenie source, a twoje komendy budowania są skryptem powłoki i działają jako pojedynczy krok kompilacji.
+0

Parametr _env_ dodaje do środowiska znanego zestawu wartości środowiska podczas wykonywania określonego polecenia.Mógłbym bardzo dobrze przejść przez skrypt powłoki, który musi być pozyskiwany i ćwiczyć środowisko. Omawiany skrypt powłoki nie jest moim, ale częścią otwartych narzędzi osadzonych. Dlatego prawdopodobnie zmieni się w kontroli źródła poza moją kontrolą. Stąd pytanie, w jaki sposób "pozyskać" środowisko i zastosować je do dalszego budowania kroków. –

+0

Prawdopodobnie po prostu uruchomiłbym całą partię w jednym kroku kompilacji, zawijając wszystko w skrypcie powłoki. –

7

Pracując z OpenEmbedded/Yocto, możemy rozwiązać ten problem w sposób podobny do tego:

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

Następnie dodanie EnvStep, który ustawia swój command parametr do foo pozwala prowadzimy foo w środowisku pochodzącym z environment-set-up-script. Innymi słowy, użyłbyś kroku, dzwoniąc pod numer

Mamy również mnóstwo innych niestandardowych kroków, które wymagają źródła build-env, więc po prostu pozwolimy im podklasę EnvStep zamiast ShellCommand, aby środowisko było automatycznie przetwarzane.

1

Przydaje się również przykład rozwoju Visual Studio.

Używając typowych skryptów narzędziowych, prawe środowisko jest ustawione dla każdego komputera, wiele wersji VS może być używanych przez te same konstruktory, a wiele architektur natywnych i krzyżowych jest obsługiwanych.

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

Alternatywą jest, aby rozpocząć każde polecenie, starając się podać plik wsadowy, & i polecenia.

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

Nie wystarczy opublikować kod; dodaj wyjaśnienie. – reformed

0

Rozwiązałem ten problem trochę inaczej. Instaluję plik wsadowy w systemie Windows, który po uruchomieniu wywołuje plik wsadowy ustawienia środowiska, a następnie wykonuje zamierzone polecenie. Jest to oczywiście utrudnione przez fakt, że pliki wsadowe są okropne w przekazywaniu argumentów, oraz fakt, że VsDevCmd.bat Visual Studio 2017 blokuje twój cwd. Jeśli jednak zainstalować następujący plik na pracownika, można zbudować z 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% 

Gdy to nastąpi, można utworzyć funkcję w swojej bulidbot mistrza logiki, która dołącza ten plik wsadowy:

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

Umożliwia to uruchamianie poleceń, w których wywoływany jest plik msbuild.exe, który oczekuje znaków równości w swoich argumentach. Po prostu określ je jako podwójne podkreślenia:

withvcvars-2017.bat amd64 msbuild.exe your.sln /p:Configuration__Release /p:Platform__x64 
Powiązane problemy