Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix recursion with env fail #1739

Merged
merged 2 commits into from
Feb 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 43 additions & 35 deletions conda_build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1428,9 +1428,9 @@ def build_tree(recipe_list, config, build_only=False, post=False, notest=False,
subprocess.call('del /s /q "{0}\\*.*" >nul 2>&1'.format(trash_dir), shell=True)
# delete_trash(None)

already_built = set()
extra_help = ""
built_packages = []
retried_recipes = []

while recipe_list:
# This loop recursively builds dependencies if recipes exist
Expand Down Expand Up @@ -1499,7 +1499,7 @@ def build_tree(recipe_list, config, build_only=False, post=False, notest=False,
pkg = pkg.strip().split(' ')[0]

if pkg in to_build_recursive:
raise RuntimeError("Can't build {0} due to unsatisfiable dependencies:\n"
raise RuntimeError("Can't build {0} due to environment creation error:\n"
.format(recipe) + error_str + "\n" + extra_help)

if pkg in skip_names:
Expand All @@ -1519,46 +1519,52 @@ def build_tree(recipe_list, config, build_only=False, post=False, notest=False,
else:
raise RuntimeError("Can't build {0} due to unsatisfiable dependencies:\n{1}"
.format(recipe, e.pkgs) + "\n\n" + extra_help)
if retried_recipes.count(recipe) >= len(metadata.ms_depends('build')):
raise RuntimeError("Can't build {0} due to environment creation error:\n"
.format(recipe) + error_str + "\n" + extra_help)
retried_recipes.append(recipe)
recipe_list.extendleft(add_recipes)

# outputs message, or does upload, depending on value of args.anaconda_upload
if post in [True, None]:
for f in built_packages:
# TODO: could probably use a better check for pkg type than this...
if f.endswith('.tar.bz2'):
handle_anaconda_upload(f, config=config)
elif f.endswith('.whl'):
handle_pypi_upload(f, config=config)
already_built.add(f)

if post in [True, None]:
# TODO: could probably use a better check for pkg type than this...
tarballs = [f for f in built_packages if f.endswith('.tar.bz2')]
wheels = [f for f in built_packages if f.endswith('.whl')]
handle_anaconda_upload(tarballs, config=config)
handle_pypi_upload(wheels, config=config)
return built_packages


def handle_anaconda_upload(path, config):
def handle_anaconda_upload(paths, config):
from conda_build.os_utils.external import find_executable

paths = utils.ensure_list(paths)

upload = False
# this is the default, for no explicit argument.
# remember that anaconda_upload takes defaults from condarc
if config.anaconda_upload is None:
pass
elif config.token or config.user:
upload = True
# rc file has uploading explicitly turned off
elif config.anaconda_upload is False:
print("# Automatic uploading is disabled")
upload = False
else:
upload = True

if config.token or config.user:
upload = True

no_upload_message = """\
# If you want to upload this package to anaconda.org later, type:
#
# $ anaconda upload %s
#
# If you want to upload package(s) to anaconda.org later, type:

"""
for package in paths:
no_upload_message += "anaconda upload {}\n".format(package)

no_upload_message += """\

# To have conda build upload to anaconda.org automatically, use
# $ conda config --set anaconda_upload yes
""" % path
"""
if not upload:
print(no_upload_message)
return
Expand All @@ -1571,23 +1577,23 @@ def handle_anaconda_upload(path, config):
# Try:
# $ conda install anaconda-client
''')
print("Uploading to anaconda.org")
cmd = [anaconda, ]

if config.token:
cmd.extend(['--token', config.token])
cmd.extend(['upload', '--force'])
if config.user:
cmd.extend(['--user', config.user])
cmd.append(path)
try:
subprocess.call(cmd)
except:
print(no_upload_message)
raise
for package in paths:
try:
print("Uploading {} to anaconda.org".format(os.path.basename(package)))
subprocess.call(cmd + [package])
except subprocess.CalledProcessError:
print(no_upload_message)
raise


def handle_pypi_upload(f, config):
def handle_pypi_upload(wheels, config):
args = ['twine', 'upload', '--sign-with', config.sign_with, '--repository', config.repository]
if config.user:
args.extend(['--user', config.user])
Expand All @@ -1602,12 +1608,14 @@ def handle_pypi_upload(f, config):
if config.repository:
args.extend(['--repository', config.repository])

args.append(f)
try:
utils.check_call_env(args)
except:
logging.getLogger(__name__).warn("wheel upload failed - is twine installed?"
" Is this package registered?")
wheels = utils.ensure_list(wheels)

for f in wheels:
try:
utils.check_call_env(args + [f])
except:
logging.getLogger(__name__).warn("wheel upload failed - is twine installed?"
" Is this package registered?")


def print_build_intermediate_warning(config):
Expand Down
3 changes: 3 additions & 0 deletions tests/test-recipes/metadata/_post-link-fails/meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package:
name: _post-link-fails
version: 1.0
2 changes: 2 additions & 0 deletions tests/test-recipes/metadata/_post-link-fails/post-link.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
echo failing post link
exit 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package:
name: conda-build-test-post-link-build-error
version: 1.0

requirements:
build:
- post-link-fails
9 changes: 9 additions & 0 deletions tests/test-recipes/metadata/_post_link_exits_tests/meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package:
name: conda-build-test-post-link-test-error
version: 1.0

test:
requires:
- _post-link-fails
commands:
- echo 'weeee'
40 changes: 33 additions & 7 deletions tests/test_api_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,22 @@ def test_recipe_builds(recipe, test_config, testing_workdir, monkeypatch):
api.build(recipe, config=test_config)


def test_token_upload(testing_workdir):
def test_token_upload(testing_workdir, test_metadata):
folder_uuid = uuid.uuid4().hex
# generated with conda_test_account user, command:
# anaconda auth --create --name CONDA_BUILD_UPLOAD_TEST --scopes 'api repos conda'
args = AnacondaClientArgs(specs="conda_test_account/empty_sections_" + folder_uuid,
token="co-79de533f-926f-4e5e-a766-d393e33ae98f",
args = AnacondaClientArgs(specs="conda_build_test/test_token_upload_" + folder_uuid,
token="co-143399b8-276e-48db-b43f-4a3de839a024",
force=True)

with pytest.raises(NotFound):
show.main(args)

metadata, _, _ = api.render(empty_sections, activate=False)
metadata.meta['package']['name'] = '_'.join([metadata.name(), folder_uuid])
metadata.config.token = args.token
test_metadata.meta['package']['name'] = '_'.join([test_metadata.name(), folder_uuid])
test_metadata.config.token = args.token

# the folder with the test recipe to upload
api.build(metadata)
api.build(test_metadata)

# make sure that the package is available (should raise if it doesn't)
show.main(args)
Expand Down Expand Up @@ -856,3 +855,30 @@ def test_copy_read_only_file_with_xattr(test_config, testing_workdir):
subprocess.check_call('setfattr -n user.attrib -v somevalue {}'.format(ro_file), shell=True)
subprocess.check_call('chmod 400 {}'.format(ro_file), shell=True)
api.build(recipe, config=test_config)


@pytest.mark.serial
def test_env_creation_fail_exits_build(test_config):
recipe = os.path.join(metadata_dir, '_post_link_exits_after_retry')
with pytest.raises(RuntimeError):
api.build(recipe, config=test_config)

recipe = os.path.join(metadata_dir, '_post_link_exits_tests')
with pytest.raises(RuntimeError):
api.build(recipe, config=test_config)


@pytest.mark.serial
def test_recursion_packages(test_config):
"""Two packages that need to be built are listed in the recipe

make sure that both get built before the one needing them gets built."""
recipe = os.path.join(metadata_dir, '_recursive-build-two-packages')
api.build(recipe, config=test_config)


@pytest.mark.serial
def test_recursion_layers(test_config):
"""go two 'hops' - try to build a, but a needs b, so build b first, then come back to a"""
recipe = os.path.join(metadata_dir, '_recursive-build-two-layer')
api.build(recipe, config=test_config)