Modify how the stages and steps work #1
20
README.rst
20
README.rst
@ -20,28 +20,26 @@ Install bou with pip:
|
||||
Running bou
|
||||
-----------
|
||||
|
||||
To run bou, simply call it:
|
||||
To run bou, simply run the command. The build file will be automatically detected.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ bou
|
||||
|
||||
To specify a build configuration file, use the ``-f`` option:
|
||||
To specify a build configuration file, use the ``-f`` option.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ bou -f /path/to/build.yaml
|
||||
|
||||
To specify a stage or a step to run, just add it to the command
|
||||
To specify a stage or a step to run, just add it to the command. Stages take priority over steps, so if you have a
|
||||
stage and a step with the same name, the stage will be run.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ bou build
|
||||
$ bou test
|
||||
|
||||
.. note::
|
||||
|
||||
By default, all stages are run, and stages are run in the order in the build configuration file.
|
||||
|
||||
Task Configuration
|
||||
------------------
|
||||
@ -90,6 +88,16 @@ variables are set.
|
||||
- $PYTHON $SOURCE/setup.py build
|
||||
|
||||
|
||||
Stages and Steps
|
||||
----------------
|
||||
|
||||
If no steps or stages are specified, by default bou will attempt to run the following, in order:
|
||||
|
||||
1. All of the stages in the ``stages`` section of the task configuration
|
||||
2. If no stages are specified in the task config, all of the stages discovered in the steps
|
||||
3. If no stages are found, all of the steps
|
||||
|
||||
|
||||
Source Code
|
||||
-----------
|
||||
|
||||
|
94
bou.py
94
bou.py
@ -13,6 +13,11 @@ ENV_VAR = re.compile(r'(\$([A-Za-z0-9_]+))')
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""
|
||||
Parse command line arguments, and return an object with all the arguments
|
||||
|
||||
:return: A namespace object with all the supplied arguments
|
||||
"""
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('-f', '--file', dest='build_file', help='Path to the build file')
|
||||
parser.add_argument('stage_or_step', nargs='?', default=None, help='Run a particular stage or step')
|
||||
@ -20,7 +25,14 @@ def parse_args():
|
||||
|
||||
|
||||
def setup_env(env, base_path):
|
||||
"""Set up the environment dictionary, resolving shell variables"""
|
||||
"""
|
||||
Set up the environment dictionary, resolving shell variables
|
||||
|
||||
:param env: The environment list or dictionary
|
||||
:param base_path: The base path that the build runs in
|
||||
|
||||
:return: A merged dictionary of environment variables
|
||||
"""
|
||||
if isinstance(env, list):
|
||||
env = {pair.split('=')[0]: pair.split('=')[1] for pair in env}
|
||||
env = dict(BASE_DIR=str(base_path), **env)
|
||||
@ -33,13 +45,28 @@ def setup_env(env, base_path):
|
||||
|
||||
|
||||
def setup_step(config, step_name):
|
||||
"""Prepare a step for usage"""
|
||||
"""
|
||||
Prepare a step for usage
|
||||
|
||||
:param config: The build configuration
|
||||
:param step_name: The name of the step to prepare
|
||||
|
||||
:return: A step object
|
||||
"""
|
||||
step = config['steps'][step_name]
|
||||
step['environment'] = config.get('environment', []) + step.get('environment', [])
|
||||
return step
|
||||
|
||||
|
||||
def get_steps_for_stage(config, stage_name):
|
||||
"""
|
||||
Get all the steps for a particular stage
|
||||
|
||||
:param config: The build configuration
|
||||
:param stage_name: The name of the stage
|
||||
|
||||
:return: A list of step objects
|
||||
"""
|
||||
steps = []
|
||||
for step_name in config['steps'].keys():
|
||||
if config['steps'][step_name]['stage'] == stage_name:
|
||||
@ -48,6 +75,14 @@ def get_steps_for_stage(config, stage_name):
|
||||
|
||||
|
||||
def run_step(step, base_path):
|
||||
"""
|
||||
Run a particular step
|
||||
|
||||
:param step: The step (as a dictionary)
|
||||
:param base_path: The base path to run this in
|
||||
|
||||
:return: Return True if the step passed, or False if the step failed
|
||||
"""
|
||||
script = step['script']
|
||||
if isinstance(script, list):
|
||||
script = os.linesep.join(script)
|
||||
@ -60,14 +95,49 @@ def run_step(step, base_path):
|
||||
|
||||
|
||||
def run_stage(config, stage_name, base_path):
|
||||
"""
|
||||
Run all the steps in a particular stage
|
||||
|
||||
:param config: The build configuration
|
||||
:param stage_name: The stage to run
|
||||
:param base_path: The base path of the build
|
||||
"""
|
||||
for step in get_steps_for_stage(config, stage_name):
|
||||
result = run_step(step, base_path)
|
||||
if not result:
|
||||
break
|
||||
|
||||
|
||||
def get_all_stages(config):
|
||||
"""
|
||||
Return all the stages available in the build configuration
|
||||
|
||||
:param config: The build configuration
|
||||
|
||||
:return: A list of stages
|
||||
"""
|
||||
stages = config.get('stages', [])
|
||||
for step_name, step in config['steps'].items():
|
||||
if step['stage'] not in stages:
|
||||
stages.append(step['stage'])
|
||||
return stages
|
||||
|
||||
|
||||
def get_all_steps(config):
|
||||
"""
|
||||
Return all the steps available in the build configuration
|
||||
|
||||
:param config: The build configuration
|
||||
|
||||
:return: A list of steps
|
||||
"""
|
||||
return list(config.get('steps', {}).keys())
|
||||
|
||||
|
||||
def get_build_file():
|
||||
"""Determine the local build file"""
|
||||
"""
|
||||
Determine the local build file
|
||||
"""
|
||||
base_path = Path.cwd()
|
||||
for child in base_path.iterdir():
|
||||
if child.name in BUILD_FILES:
|
||||
@ -76,7 +146,9 @@ def get_build_file():
|
||||
|
||||
|
||||
def main():
|
||||
"""Run the build system"""
|
||||
"""
|
||||
Run the build system
|
||||
"""
|
||||
args = parse_args()
|
||||
if args.build_file:
|
||||
build_file = Path(args.build_file).resolve()
|
||||
@ -87,18 +159,26 @@ def main():
|
||||
return 1
|
||||
base_path = build_file.parent
|
||||
config = yaml.full_load(build_file.open())
|
||||
all_stages = get_all_stages(config)
|
||||
all_steps = get_all_steps(config)
|
||||
if args.stage_or_step:
|
||||
if args.stage_or_step in config['stages']:
|
||||
if args.stage_or_step in all_stages:
|
||||
run_stage(config, args.stage_or_step, base_path)
|
||||
elif args.stage_or_step in config['steps'].keys():
|
||||
elif args.stage_or_step in all_steps:
|
||||
step = setup_step(config, args.stage_or_step)
|
||||
run_step(config, step, base_path)
|
||||
else:
|
||||
print('"{stage}" is not a valid stage or step name'.format(stage=args.stage_or_step))
|
||||
return 2
|
||||
else:
|
||||
for stage_name in config['stages']:
|
||||
stages = config.get('stages', all_stages)
|
||||
if stages:
|
||||
for stage_name in stages:
|
||||
run_stage(config, stage_name, base_path)
|
||||
else:
|
||||
for step_name in all_steps:
|
||||
step = setup_step(config, step_name)
|
||||
run_step(config, step, base_path)
|
||||
return 0
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user