Repository: conda/conda-build

Issue:
File-based configuration needed
We can't currently set any of the flags via config file (other than the ones that conda supports).  We should either add values to condarc, or add an alternative config file.

CC @soapy1 @kalefranz 


Discussion:
Going to punt on this one.  The primary critically important setting is the conda build root, and that is already a condarc setting as document in http://conda.pydata.org/docs/config.html#specify-conda-build-output-root-directory-conda-build

There are currently conda issues with that functionality, however: https://github.com/conda/conda/issues/3744#issuecomment-260044918

Anyone wanting any particular other setting, please post here.  I will try to add the options that the API presents for the 2.1.0 release.

Kicking the can.  3.0.0.

Resolving patch:
diff --git a/conda_build/cli/main_build.py b/conda_build/cli/main_build.py
--- a/conda_build/cli/main_build.py
+++ b/conda_build/cli/main_build.py
@@ -16,7 +16,8 @@
 import conda_build.api as api
 import conda_build.build as build
 import conda_build.utils as utils
-from conda_build.conda_interface import add_parser_channels, url_path, binstar_upload
+from conda_build.conda_interface import (add_parser_channels, url_path, binstar_upload,
+                                         cc_conda_build)
 from conda_build.cli.main_render import get_render_parser
 import conda_build.source as source
 from conda_build.utils import LoggingContext
@@ -59,7 +60,7 @@ def parse_args(args):
         action="store_false",
         help="Don't include the recipe inside the built package.",
         dest='include_recipe',
-        default=True,
+        default=cc_conda_build.get('include_recipe', 'true').lower() == 'true',
     )
     p.add_argument(
         '-s', "--source",
@@ -100,8 +101,9 @@ def parse_args(args):
     p.add_argument(
         '--skip-existing',
         action='store_true',
-        help="""Skip recipes for which there already exists an existing build
-        (locally or in the channels). """
+        help=("Skip recipes for which there already exists an existing build"
+              "(locally or in the channels)."),
+        default=cc_conda_build.get('skip_existing', 'false').lower() == 'true',
     )
     p.add_argument(
         '--keep-old-work',
@@ -119,6 +121,7 @@ def parse_args(args):
         '-q', "--quiet",
         action="store_true",
         help="do not display progress bar",
+        default=cc_conda_build.get('quiet', 'false').lower() == 'true',
     )
     p.add_argument(
         '--debug',
@@ -127,16 +130,18 @@ def parse_args(args):
     )
     p.add_argument(
         '--token',
-        help="Token to pass through to anaconda upload"
+        help="Token to pass through to anaconda upload",
+        default=cc_conda_build.get('anaconda_token'),
     )
     p.add_argument(
         '--user',
-        help="User/organization to upload packages to on anaconda.org or pypi"
+        help="User/organization to upload packages to on anaconda.org or pypi",
+        default=cc_conda_build.get('user'),
     )
     pypi_grp = p.add_argument_group("PyPI upload parameters (twine)")
     pypi_grp.add_argument(
         '--password',
-        help="password to use when uploading packages to pypi"
+        help="password to use when uploading packages to pypi",
     )
     pypi_grp.add_argument(
         '--sign', default=False,
@@ -152,17 +157,19 @@ def parse_args(args):
     )
     pypi_grp.add_argument(
         '--config-file',
-        help="path to .pypirc file to use when uploading to pypi"
+        help="path to .pypirc file to use when uploading to pypi",
+        default=cc_conda_build.get('pypirc'),
     )
     pypi_grp.add_argument(
-        '--repository', '-r', default='pypitest',
-        help="PyPI repository to upload to"
+        '--repository', '-r', help="PyPI repository to upload to",
+        default=cc_conda_build.get('pypi_repository', 'pypitest'),
     )
     p.add_argument(
         "--no-activate",
         action="store_false",
         help="do not activate the build and test envs; just prepend to PATH",
         dest='activate',
+        default=cc_conda_build.get('activate', 'true').lower() == 'true',
     )
     p.add_argument(
         "--no-build-id",
@@ -170,6 +177,8 @@ def parse_args(args):
         help=("do not generate unique build folder names.  Use if having issues with "
               "paths being too long."),
         dest='set_build_id',
+        # note: inverted - dest stores positive logic
+        default=cc_conda_build.get('set_build_id', 'true').lower() == 'true',
     )
     p.add_argument(
         "--croot",
@@ -179,7 +188,8 @@ def parse_args(args):
     p.add_argument(
         "--no-verify",
         action="store_true",
-        help=("do not run verification on recipes or packages when building")
+        help="do not run verification on recipes or packages when building",
+        default=cc_conda_build.get('no_verify', 'false').lower() == 'true',
     )
     p.add_argument(
         "--output-folder",
diff --git a/conda_build/cli/main_render.py b/conda_build/cli/main_render.py
--- a/conda_build/cli/main_render.py
+++ b/conda_build/cli/main_render.py
@@ -9,7 +9,7 @@
 import logging
 import sys
 
-from conda_build.conda_interface import ArgumentParser, add_parser_channels
+from conda_build.conda_interface import ArgumentParser, add_parser_channels, cc_conda_build
 
 from conda_build import __version__, api
 
@@ -101,10 +101,11 @@ def get_render_parser():
     )
     p.add_argument(
         "--old-build-string", dest="filename_hashing", action="store_false",
-        default=True, help=("Disable hash additions to filenames to distinguish package "
-                            "variants from one another.  NOTE: any filename collisions are "
-                            "yours to handle.  Any variants with overlapping names within a "
-                            "build will clobber each other.")
+        default=cc_conda_build.get('filename_hashing', 'true').lower() == 'true',
+        help=("Disable hash additions to filenames to distinguish package "
+              "variants from one another. NOTE: any filename collisions are "
+              "yours to handle. Any variants with overlapping names within a "
+              "build will clobber each other.")
     )
 
     add_parser_channels(p)
diff --git a/conda_build/source.py b/conda_build/source.py
--- a/conda_build/source.py
+++ b/conda_build/source.py
@@ -60,8 +60,8 @@ def download_to_cache(cache_folder, recipe_path, source_dict):
                     url = os.path.normpath(os.path.join(recipe_path, url))
                 url = url_path(url)
             else:
-                if url.startswith('file://~'):
-                    url = 'file://' + expanduser(url[7:]).replace('\\', '/')
+                if url.startswith('file:///~'):
+                    url = 'file:///' + expanduser(url[8:]).replace('\\', '/')
             try:
                 print("Downloading %s" % url)
                 with LoggingContext():


Test patch:
diff --git a/tests/test_source.py b/tests/test_source.py
--- a/tests/test_source.py
+++ b/tests/test_source.py
@@ -91,7 +91,7 @@ def test_source_user_expand(testing_workdir):
             tbz_name = os.path.join(tmp, "cb-test.tar.bz2")
             with tarfile.open(tbz_name, "w:bz2") as tar:
                 tar.add(tbz_srcdir, arcname=os.path.sep)
-            for prefix in ('~', 'file://~'):
+            for prefix in ('~', 'file:///~'):
                 source_dict = {"url": os.path.join(prefix, os.path.basename(tmp), "cb-test.tar.bz2")}
                 with TemporaryDirectory() as tmp2:
                     download_to_cache(tmp2, '', source_dict)