=== modified file 'mojo/phase.py'
--- mojo/phase.py	2019-06-04 13:54:38 +0000
+++ mojo/phase.py	2020-01-13 14:13:44 +0000
@@ -630,6 +630,16 @@
                                            "juju-deployer configuration file "
                                            "{}:\n{}".format(config, e))
 
+    def _only_charmstore_charms(self, configs):
+        """Return True if we're using only charmstore charms"""
+        for config in configs:
+            with open(config) as deploy_file:
+                for line in deploy_file.readlines():
+                    l = line.strip().replace(" ", "")
+                    if l.startswith("charm:") and not l.startswith("charm:cs:"):
+                        return False
+        return True
+
     def _get_configs(self, project, workspace, stage,
                      auto_secrets=True, cli=True):
         """
@@ -697,6 +707,10 @@
 
         # Check the config files are valid YAML or JSON
         self._validate_configs(configs)
+        # If we're not only using charmstore charms, confirm we have a charm
+        # repo
+        if not self._only_charmstore_charms(configs):
+            self._confirm_charm_repo(project, workspace)
 
         return configs
 
@@ -758,7 +772,6 @@
         Display rendered juju-deployer configuration files, optionally
         returning output rather than printing for easier testing
         """
-        self._confirm_charm_repo(project, workspace)
         # Quiet logging to get clean display of YAML
         logger = logging.getLogger()
         logger.setLevel(level='WARNING')
@@ -781,7 +794,6 @@
         Display juju-deployer --diff comparing running environment
         to the juju-deployer configuration
         """
-        self._confirm_charm_repo(project, workspace)
         deployer = self._get_command()
         configs = self._get_phase_configs(project, workspace, stage)
         deploy_name = self._get_target(configs)
@@ -798,7 +810,6 @@
     def run(self, project, workspace, stage, auto_secrets=True):
         start_time = time.time()
         self._check_juju_version()
-        self._confirm_charm_repo(project, workspace)
         logging.debug("### Running phase {} with options {}"
                       "".format(self.name, self.options))
         logging.info("Running juju-deployer")
@@ -1334,7 +1345,6 @@
         """
         Display the output of juju --dry-run on the various bundles.
         """
-        self._confirm_charm_repo(project, workspace)
         juju = self._get_command()
         configs = self._get_phase_configs(project, workspace, stage)
 
@@ -1349,7 +1359,6 @@
         """
         Display rendered (template variables replaced) bundle configs.
         """
-        self._confirm_charm_repo(project, workspace)
         logger = logging.getLogger()
         logger.setLevel(level='WARNING')
         configs = self._get_phase_configs(project, workspace, stage)

=== modified file 'mojo/tests/test_phase.py'
--- mojo/tests/test_phase.py	2019-06-04 16:17:47 +0000
+++ mojo/tests/test_phase.py	2020-01-13 14:13:44 +0000
@@ -30,11 +30,13 @@
 
     @mock.patch('mojo.phase.bicommand')
     @mock.patch('mojo.phase.DeployerPhase._confirm_charm_repo')
+    @mock.patch('mojo.phase.DeployerPhase._only_charmstore_charms')
     @mock.patch('mojo.phase.DeployerPhase._get_target')
     @mock.patch('mojo.juju.Status.check_and_wait')
     @mock.patch('mojo.phase.DeployerPhase._get_command')
     def get_deployer_command_for_run(self, phase, workspace, stage, _get_command, _check_wait,
-                                     _get_target, _confirm_charm_repo, _bicommand):
+                                     _get_target, _only_charmstore_charms, _confirm_charm_repo, _bicommand):
+        _only_charmstore_charms.return_value = False
         _get_target.return_value = "testTarget"
         _bicommand.return_value = (0, 'fake-output')
         _get_command.return_value = "juju-deployer"
@@ -46,11 +48,13 @@
 
     @mock.patch('subprocess.call')
     @mock.patch('mojo.phase.DeployerPhase._confirm_charm_repo')
+    @mock.patch('mojo.phase.DeployerPhase._only_charmstore_charms')
     @mock.patch('mojo.phase.DeployerPhase._get_target')
     @mock.patch('mojo.juju.Status.check_and_wait')
     @mock.patch('mojo.phase.DeployerPhase._get_command')
     def get_deployer_command_for_diff(self, phase, workspace, stage, _get_command, _check_wait,
-                                      _get_target, _confirm_charm_repo, _call):
+                                      _get_target, _only_charmstore_charms, _confirm_charm_repo, _call):
+        _only_charmstore_charms.return_value = False
         _get_target.return_value = "testTarget"
         _call.return_value = (0)
         _get_command.return_value = "juju-deployer"
@@ -66,11 +70,13 @@
 
     @mock.patch('subprocess.call')
     @mock.patch('mojo.phase.DeployerPhase._confirm_charm_repo')
+    @mock.patch('mojo.phase.DeployerPhase._only_charmstore_charms')
     @mock.patch('mojo.phase.DeployerPhase._get_target')
     @mock.patch('mojo.juju.Status.check_and_wait')
     @mock.patch('mojo.phase.DeployerPhase._get_command')
     def get_deployer_output_for_show(self, phase, workspace, stage, target, _get_command, _check_wait,
-                                     _get_target, _confirm_charm_repo, _call):
+                                     _get_target, _only_charmstore_charms, _confirm_charm_repo, _call):
+        _only_charmstore_charms.return_value = False
         _get_target.return_value = target
         _call.return_value = (0)
         _get_command.return_value = "juju-deployer"
@@ -299,6 +305,15 @@
         called_methods = [c[0] for c in secrets.mock_calls]
         assert ('().run' in called_methods)
 
+    @mock.patch('mojo.phase.SecretsPhase')
+    def test_only_charmstore_charms(self, _secrets):
+        phase = DeployerPhase(config='services.cfg', target='test')
+        self.assertFalse(phase._only_charmstore_charms(['mojo/tests/testdata/deploy-config-local-charms.yaml']))
+        self.assertTrue(phase._only_charmstore_charms(['mojo/tests/testdata/deploy-config-charmstore-charms.yaml']))
+        # We should return false (i.e. not *only* charmstore charms) if
+        # there's a mix of local and charmstore charms.
+        self.assertFalse(phase._only_charmstore_charms(['mojo/tests/testdata/deploy-config-mixed-charms.yaml']))
+
 
 class BundlePhaseTestCase(TestCase, utils.MojoTestCaseMixin):
 

=== added file 'mojo/tests/testdata/deploy-config-charmstore-charms.yaml'
--- mojo/tests/testdata/deploy-config-charmstore-charms.yaml	1970-01-01 00:00:00 +0000
+++ mojo/tests/testdata/deploy-config-charmstore-charms.yaml	2020-01-13 14:13:44 +0000
@@ -0,0 +1,5 @@
+# vim: set filetype=yaml sw=2:
+sample-service:
+  services:
+    apache2:
+      charm: cs:apache2

=== added file 'mojo/tests/testdata/deploy-config-local-charms.yaml'
--- mojo/tests/testdata/deploy-config-local-charms.yaml	1970-01-01 00:00:00 +0000
+++ mojo/tests/testdata/deploy-config-local-charms.yaml	2020-01-13 14:13:44 +0000
@@ -0,0 +1,5 @@
+# vim: set filetype=yaml sw=2:
+sample-service:
+  services:
+    apache2:
+      charm: apache2

=== added file 'mojo/tests/testdata/deploy-config-mixed-charms.yaml'
--- mojo/tests/testdata/deploy-config-mixed-charms.yaml	1970-01-01 00:00:00 +0000
+++ mojo/tests/testdata/deploy-config-mixed-charms.yaml	2020-01-13 14:13:44 +0000
@@ -0,0 +1,7 @@
+# vim: set filetype=yaml sw=2:
+sample-service:
+  services:
+    apache2:
+      charm: apache2
+    telegraf:
+      charm: cs:telegraf

