diff --git a/dvc/config.py b/dvc/config.py
index dde2cb081..1d96d7555 100644
--- a/dvc/config.py
+++ b/dvc/config.py
@@ -151,6 +151,7 @@ SCHEMA = {
                     Optional("listobjects", default=False): Bool,
                     Optional("use_ssl", default=True): Bool,
                     "sse": str,
+                    "sse_kms_key_id": str,
                     "acl": str,
                     "grant_read": str,
                     "grant_read_acp": str,
diff --git a/dvc/remote/s3.py b/dvc/remote/s3.py
index 0ebb4099f..8d92642e9 100644
--- a/dvc/remote/s3.py
+++ b/dvc/remote/s3.py
@@ -46,6 +46,10 @@ class S3Remote(BaseRemote):
         if self.sse:
             self.extra_args["ServerSideEncryption"] = self.sse
 
+        self.sse_kms_key_id = config.get("sse_kms_key_id")
+        if self.sse_kms_key_id:
+            self.extra_args["SSEKMSKeyId"] = self.sse_kms_key_id
+
         self.acl = config.get("acl")
         if self.acl:
             self.extra_args["ACL"] = self.acl
diff --git a/dvc/stage/cache.py b/dvc/stage/cache.py
index c383d8725..18c2cb2f5 100644
--- a/dvc/stage/cache.py
+++ b/dvc/stage/cache.py
@@ -1,5 +1,6 @@
 import logging
 import os
+from contextlib import contextmanager
 
 import yaml
 from funcy import first
@@ -76,6 +77,45 @@ class StageCache:
 
         return None
 
+    def _create_stage(self, cache):
+        from dvc.stage import create_stage, PipelineStage
+
+        stage = create_stage(
+            PipelineStage,
+            repo=self.repo,
+            path="dvc.yaml",
+            cmd=cache["cmd"],
+            deps=[dep["path"] for dep in cache["deps"]],
+            outs=[out["path"] for out in cache["outs"]],
+        )
+        StageLoader.fill_from_lock(stage, cache)
+        return stage
+
+    @contextmanager
+    def _cache_type_copy(self):
+        cache_types = self.repo.cache.local.cache_types
+        self.repo.cache.local.cache_types = ["copy"]
+        try:
+            yield
+        finally:
+            self.repo.cache.local.cache_types = cache_types
+
+    def _uncached_outs(self, stage, cache):
+        # NOTE: using temporary stage to avoid accidentally modifying original
+        # stage and to workaround `commit/checkout` not working for uncached
+        # outputs.
+        cached_stage = self._create_stage(cache)
+
+        outs_no_cache = [
+            out.def_path for out in stage.outs if not out.use_cache
+        ]
+
+        # NOTE: using copy link to make it look like a git-tracked file
+        with self._cache_type_copy():
+            for out in cached_stage.outs:
+                if out.def_path in outs_no_cache:
+                    yield out
+
     def save(self, stage):
         cache_key = _get_stage_hash(stage)
         if not cache_key:
@@ -84,7 +124,13 @@ class StageCache:
         cache = to_single_stage_lockfile(stage)
         cache_value = _get_cache_hash(cache)
 
-        if self._load_cache(cache_key, cache_value):
+        existing_cache = self._load_cache(cache_key, cache_value)
+        cache = existing_cache or cache
+
+        for out in self._uncached_outs(stage, cache):
+            out.commit()
+
+        if existing_cache:
             return
 
         # sanity check
@@ -104,6 +150,9 @@ class StageCache:
             return
         StageLoader.fill_from_lock(stage, cache)
 
+        for out in self._uncached_outs(stage, cache):
+            out.checkout()
+
     @staticmethod
     def _transfer(func, from_remote, to_remote):
         ret = []
@@ -134,7 +183,6 @@ class StageCache:
 
     def get_used_cache(self, used_run_cache, *args, **kwargs):
         from dvc.cache import NamedCache
-        from dvc.stage import create_stage, PipelineStage
 
         cache = NamedCache()
 
@@ -142,14 +190,6 @@ class StageCache:
             entry = self._load_cache(key, value)
             if not entry:
                 continue
-            stage = create_stage(
-                PipelineStage,
-                repo=self.repo,
-                path="dvc.yaml",
-                cmd=entry["cmd"],
-                deps=[dep["path"] for dep in entry["deps"]],
-                outs=[out["path"] for out in entry["outs"]],
-            )
-            StageLoader.fill_from_lock(stage, entry)
+            stage = self._create_stage(entry)
             cache.update(stage.get_used_cache(*args, **kwargs))
         return cache

tests: erepo upstream should not be its cache
Setting default remote as [repository cache](https://github.com/iterative/dvc/blob/f9d4ef8abd5427b0ec75f7f3c1211abd8528aa99/tests/conftest.py#L152) inside `erepo` is kinda hacky. This is not a real use case, and some test relay on the `erepo` property (that is automatically adding cached files to remote because cache and remote are the same thing). `erepo` remote should not be its cache. 

This issue will probably be obsolete after #2599. In that case, the code responsible for setting remote in `erepo` should be completely removed.

Related #2852 
diff --git a/tests/dir_helpers.py b/tests/dir_helpers.py
index 8e1d87630..3ad9a8bf5 100644
--- a/tests/dir_helpers.py
+++ b/tests/dir_helpers.py
@@ -59,10 +59,10 @@ __all__ = [
     "tmp_dir",
     "scm",
     "dvc",
-    "local_remote",
     "run_copy",
     "erepo_dir",
     "git_dir",
+    "setup_remote",
 ]
 
 
@@ -256,17 +256,6 @@ def _git_init(path):
     git.close()
 
 
-@pytest.fixture
-def local_remote(request, tmp_dir, dvc, make_tmp_dir):
-    path = make_tmp_dir("local-remote")
-    with dvc.config.edit() as conf:
-        conf["remote"]["upstream"] = {"url": fspath(path)}
-        conf["core"]["remote"] = "upstream"
-    if "scm" in request.fixturenames:
-        tmp_dir.scm_add([dvc.config.files["repo"]], commit="add remote")
-    return path
-
-
 @pytest.fixture
 def run_copy(tmp_dir, dvc):
     tmp_dir.gen(
@@ -287,17 +276,7 @@ def run_copy(tmp_dir, dvc):
 
 @pytest.fixture
 def erepo_dir(make_tmp_dir):
-    path = make_tmp_dir("erepo", scm=True, dvc=True)
-
-    # Chdir for git and dvc to work locally
-    with path.chdir():
-        with path.dvc.config.edit() as conf:
-            cache_dir = path.dvc.cache.local.cache_dir
-            conf["remote"]["upstream"] = {"url": cache_dir}
-            conf["core"]["remote"] = "upstream"
-        path.scm_add([path.dvc.config.files["repo"]], commit="add remote")
-
-    return path
+    return make_tmp_dir("erepo", scm=True, dvc=True)
 
 
 @pytest.fixture
@@ -305,3 +284,20 @@ def git_dir(make_tmp_dir):
     path = make_tmp_dir("git-erepo", scm=True)
     path.scm.commit("init repo")
     return path
+
+
+@pytest.fixture
+def setup_remote(make_tmp_dir):
+    def create(repo, url=None, name="upstream", default=True):
+        if not url:
+            url = fspath(make_tmp_dir("local_remote"))
+        with repo.config.edit() as conf:
+            conf["remote"][name] = {"url": url}
+            if default:
+                conf["core"]["remote"] = name
+
+        repo.scm.add(repo.config.files["repo"])
+        repo.scm.commit("add '{}' remote".format(name))
+        return url
+
+    return create
diff --git a/tests/func/test_api.py b/tests/func/test_api.py
index 2f1aef069..cf384971e 100644
--- a/tests/func/test_api.py
+++ b/tests/func/test_api.py
@@ -36,8 +36,8 @@ def test_get_url(tmp_dir, dvc, remote_url):
 
 
 @pytest.mark.parametrize("remote_url", remote_params, indirect=True)
-def test_get_url_external(erepo_dir, remote_url):
-    _set_remote_url_and_commit(erepo_dir.dvc, remote_url)
+def test_get_url_external(erepo_dir, remote_url, setup_remote):
+    setup_remote(erepo_dir.dvc, url=remote_url)
     with erepo_dir.chdir():
         erepo_dir.dvc_gen("foo", "foo", commit="add foo")
 
@@ -71,8 +71,8 @@ def test_open(remote_url, tmp_dir, dvc):
 
 
 @pytest.mark.parametrize("remote_url", all_remote_params, indirect=True)
-def test_open_external(remote_url, erepo_dir):
-    _set_remote_url_and_commit(erepo_dir.dvc, remote_url)
+def test_open_external(remote_url, erepo_dir, setup_remote):
+    setup_remote(erepo_dir.dvc, url=remote_url)
 
     with erepo_dir.chdir():
         erepo_dir.dvc_gen("version", "master", commit="add version")
@@ -106,13 +106,6 @@ def test_missing(remote_url, tmp_dir, dvc):
         api.read("foo")
 
 
-def _set_remote_url_and_commit(repo, remote_url):
-    with repo.config.edit() as conf:
-        conf["remote"]["upstream"]["url"] = remote_url
-    repo.scm.add([repo.config.files["repo"]])
-    repo.scm.commit("modify remote")
-
-
 def test_open_scm_controlled(tmp_dir, erepo_dir):
     erepo_dir.scm_gen({"scm_controlled": "file content"}, commit="create file")
 
diff --git a/tests/func/test_data_cloud.py b/tests/func/test_data_cloud.py
index e17633b1b..21c1ba495 100644
--- a/tests/func/test_data_cloud.py
+++ b/tests/func/test_data_cloud.py
@@ -8,7 +8,7 @@ from unittest import SkipTest
 import pytest
 
 from dvc.cache import NamedCache
-from dvc.compat import fspath, fspath_py35
+from dvc.compat import fspath
 from dvc.data_cloud import DataCloud
 from dvc.external_repo import clean_repos
 from dvc.main import main
@@ -688,14 +688,13 @@ class TestShouldWarnOnNoChecksumInLocalAndRemoteCache(TestDvc):
         assert self.message_bar_part in self._caplog.text
 
 
-def test_verify_checksums(tmp_dir, scm, dvc, mocker, tmp_path_factory):
+def test_verify_checksums(
+    tmp_dir, scm, dvc, mocker, tmp_path_factory, setup_remote
+):
+
+    setup_remote(dvc, name="upstream")
     tmp_dir.dvc_gen({"file": "file1 content"}, commit="add file")
     tmp_dir.dvc_gen({"dir": {"subfile": "file2 content"}}, commit="add dir")
-
-    dvc.config["remote"]["local_remote"] = {
-        "url": fspath(tmp_path_factory.mktemp("local_remote"))
-    }
-    dvc.config["core"]["remote"] = "local_remote"
     dvc.push()
 
     # remove artifacts and cache to trigger fetching
@@ -711,7 +710,7 @@ def test_verify_checksums(tmp_dir, scm, dvc, mocker, tmp_path_factory):
     # Removing cache will invalidate existing state entries
     remove(dvc.cache.local.cache_dir)
 
-    dvc.config["remote"]["local_remote"]["verify"] = True
+    dvc.config["remote"]["upstream"]["verify"] = True
 
     dvc.pull()
     assert checksum_spy.call_count == 3
@@ -784,13 +783,15 @@ def recurse_list_dir(d):
     ]
 
 
-def test_dvc_pull_pipeline_stages(tmp_dir, dvc, local_remote, run_copy):
+def test_dvc_pull_pipeline_stages(tmp_dir, dvc, run_copy, setup_remote):
+    setup_remote(dvc)
     (stage0,) = tmp_dir.dvc_gen("foo", "foo")
     stage1 = run_copy("foo", "bar", single_stage=True)
     stage2 = run_copy("bar", "foobar", name="copy-bar-foobar")
+    dvc.push()
+
     outs = ["foo", "bar", "foobar"]
 
-    dvc.push()
     clean(outs, dvc)
     dvc.pull()
     assert all((tmp_dir / file).exists() for file in outs)
@@ -814,7 +815,8 @@ def test_dvc_pull_pipeline_stages(tmp_dir, dvc, local_remote, run_copy):
     assert set(stats["added"]) == set(outs)
 
 
-def test_pipeline_file_target_ops(tmp_dir, dvc, local_remote, run_copy):
+def test_pipeline_file_target_ops(tmp_dir, dvc, run_copy, setup_remote):
+    remote_path = setup_remote(dvc)
     tmp_dir.dvc_gen("foo", "foo")
     run_copy("foo", "bar", single_stage=True)
 
@@ -829,8 +831,11 @@ def test_pipeline_file_target_ops(tmp_dir, dvc, local_remote, run_copy):
     remove(dvc.stage_cache.cache_dir)
 
     dvc.push()
+
+    outs = ["foo", "bar", "lorem", "ipsum", "baz", "lorem2"]
+
     # each one's a copy of other, hence 3
-    assert len(recurse_list_dir(fspath_py35(local_remote))) == 3
+    assert len(recurse_list_dir(remote_path)) == 3
 
     clean(outs, dvc)
     assert set(dvc.pull(["dvc.yaml"])["added"]) == {"lorem2", "baz"}
@@ -839,13 +844,15 @@ def test_pipeline_file_target_ops(tmp_dir, dvc, local_remote, run_copy):
     assert set(dvc.pull()["added"]) == set(outs)
 
     # clean everything in remote and push
-    clean(local_remote.iterdir())
+    from tests.dir_helpers import TmpDir
+
+    clean(TmpDir(remote_path).iterdir())
     dvc.push(["dvc.yaml:copy-ipsum-baz"])
-    assert len(recurse_list_dir(fspath_py35(local_remote))) == 1
+    assert len(recurse_list_dir(remote_path)) == 1
 
-    clean(local_remote.iterdir())
+    clean(TmpDir(remote_path).iterdir())
     dvc.push(["dvc.yaml"])
-    assert len(recurse_list_dir(fspath_py35(local_remote))) == 2
+    assert len(recurse_list_dir(remote_path)) == 2
 
     with pytest.raises(StageNotFound):
         dvc.push(["dvc.yaml:StageThatDoesNotExist"])
@@ -862,8 +869,10 @@ def test_pipeline_file_target_ops(tmp_dir, dvc, local_remote, run_copy):
         ({}, "Everything is up to date"),
     ],
 )
-def test_push_stats(tmp_dir, dvc, fs, msg, local_remote, caplog):
+def test_push_stats(tmp_dir, dvc, fs, msg, caplog, setup_remote):
+    setup_remote(dvc)
     tmp_dir.dvc_gen(fs)
+
     caplog.clear()
     with caplog.at_level(level=logging.INFO, logger="dvc"):
         main(["push"])
@@ -878,7 +887,8 @@ def test_push_stats(tmp_dir, dvc, fs, msg, local_remote, caplog):
         ({}, "Everything is up to date."),
     ],
 )
-def test_fetch_stats(tmp_dir, dvc, fs, msg, local_remote, caplog):
+def test_fetch_stats(tmp_dir, dvc, fs, msg, caplog, setup_remote):
+    setup_remote(dvc)
     tmp_dir.dvc_gen(fs)
     dvc.push()
     clean(list(fs.keys()), dvc)
@@ -888,7 +898,8 @@ def test_fetch_stats(tmp_dir, dvc, fs, msg, local_remote, caplog):
     assert msg in caplog.text
 
 
-def test_pull_stats(tmp_dir, dvc, local_remote, caplog):
+def test_pull_stats(tmp_dir, dvc, caplog, setup_remote):
+    setup_remote(dvc)
     tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"})
     dvc.push()
     clean(["foo", "bar"], dvc)
diff --git a/tests/func/test_external_repo.py b/tests/func/test_external_repo.py
index 34236b418..d6f951f79 100644
--- a/tests/func/test_external_repo.py
+++ b/tests/func/test_external_repo.py
@@ -43,9 +43,11 @@ def test_source_change(erepo_dir):
     assert old_rev != new_rev
 
 
-def test_cache_reused(erepo_dir, mocker):
+def test_cache_reused(erepo_dir, mocker, setup_remote):
+    setup_remote(erepo_dir.dvc)
     with erepo_dir.chdir():
         erepo_dir.dvc_gen("file", "text", commit="add file")
+    erepo_dir.dvc.push()
 
     download_spy = mocker.spy(LocalRemote, "download")
 
@@ -63,6 +65,8 @@ def test_cache_reused(erepo_dir, mocker):
 
 
 def test_known_sha(erepo_dir):
+    erepo_dir.scm.commit("init")
+
     url = "file://{}".format(erepo_dir)
     with external_repo(url) as repo:
         rev = repo.scm.get_rev()
@@ -92,7 +96,7 @@ def test_pull_subdir_file(tmp_dir, erepo_dir):
     assert dest.read_text() == "contents"
 
 
-def test_relative_remote(erepo_dir, tmp_dir):
+def test_relative_remote(erepo_dir, tmp_dir, setup_remote):
     # these steps reproduce the script on this issue:
     # https://github.com/iterative/dvc/issues/2756
     with erepo_dir.chdir():
@@ -100,13 +104,8 @@ def test_relative_remote(erepo_dir, tmp_dir):
 
     upstream_dir = tmp_dir
     upstream_url = relpath(upstream_dir, erepo_dir)
-    with erepo_dir.dvc.config.edit() as conf:
-        conf["remote"]["upstream"] = {"url": upstream_url}
-        conf["core"]["remote"] = "upstream"
+    setup_remote(erepo_dir.dvc, url=upstream_url, name="upstream")
 
-    erepo_dir.scm_add(
-        erepo_dir.dvc.config.files["repo"], commit="Update dvc config"
-    )
     erepo_dir.dvc.push()
 
     (erepo_dir / "file").unlink()
diff --git a/tests/func/test_gc.py b/tests/func/test_gc.py
index 6eace936c..050548334 100644
--- a/tests/func/test_gc.py
+++ b/tests/func/test_gc.py
@@ -238,18 +238,18 @@ def test_gc_without_workspace_raises_error(tmp_dir, dvc):
         dvc.gc(force=True, workspace=False)
 
 
-def test_gc_cloud_with_or_without_specifier(tmp_dir, erepo_dir):
+def test_gc_cloud_with_or_without_specifier(tmp_dir, erepo_dir, setup_remote):
     dvc = erepo_dir.dvc
-    with erepo_dir.chdir():
-        from dvc.exceptions import InvalidArgumentError
+    setup_remote(dvc)
+    from dvc.exceptions import InvalidArgumentError
 
-        with pytest.raises(InvalidArgumentError):
-            dvc.gc(force=True, cloud=True)
+    with pytest.raises(InvalidArgumentError):
+        dvc.gc(force=True, cloud=True)
 
-        dvc.gc(cloud=True, all_tags=True)
-        dvc.gc(cloud=True, all_commits=True)
-        dvc.gc(cloud=True, all_branches=True)
-        dvc.gc(cloud=True, all_commits=False, all_branches=True, all_tags=True)
+    dvc.gc(cloud=True, all_tags=True)
+    dvc.gc(cloud=True, all_commits=True)
+    dvc.gc(cloud=True, all_branches=True)
+    dvc.gc(cloud=True, all_commits=False, all_branches=True, all_tags=True)
 
 
 def test_gc_without_workspace_on_tags_branches_commits(tmp_dir, dvc):
@@ -295,13 +295,8 @@ def test_gc_with_possible_args_positive(tmp_dir, dvc):
         assert main(["gc", "-vf", flag]) == 0
 
 
-def test_gc_cloud_positive(tmp_dir, dvc, tmp_path_factory):
-    with dvc.config.edit() as conf:
-        storage = fspath(tmp_path_factory.mktemp("test_remote_base"))
-        conf["remote"]["local_remote"] = {"url": storage}
-        conf["core"]["remote"] = "local_remote"
-
-    dvc.push()
+def test_gc_cloud_positive(tmp_dir, dvc, tmp_path_factory, setup_remote):
+    setup_remote(dvc)
 
     for flag in ["-cw", "-ca", "-cT", "-caT", "-cwT"]:
         assert main(["gc", "-vf", flag]) == 0
diff --git a/tests/func/test_get.py b/tests/func/test_get.py
index b05d06b69..3ee57aced 100644
--- a/tests/func/test_get.py
+++ b/tests/func/test_get.py
@@ -197,9 +197,11 @@ def test_get_file_from_dir(tmp_dir, erepo_dir):
     assert (tmp_dir / "X").read_text() == "foo"
 
 
-def test_get_url_positive(tmp_dir, erepo_dir, caplog):
+def test_get_url_positive(tmp_dir, erepo_dir, caplog, setup_remote):
+    setup_remote(erepo_dir.dvc)
     with erepo_dir.chdir():
         erepo_dir.dvc_gen("foo", "foo")
+    erepo_dir.dvc.push()
 
     caplog.clear()
     with caplog.at_level(logging.ERROR, logger="dvc"):
@@ -225,15 +227,17 @@ def test_get_url_git_only_repo(tmp_dir, scm, caplog):
 
 
 def test_get_pipeline_tracked_outs(
-    tmp_dir, dvc, scm, git_dir, local_remote, run_copy
+    tmp_dir, dvc, scm, git_dir, run_copy, setup_remote
 ):
     from dvc.dvcfile import PIPELINE_FILE, PIPELINE_LOCK
 
+    setup_remote(dvc)
     tmp_dir.gen("foo", "foo")
     run_copy("foo", "bar", name="copy-foo-bar")
+    dvc.push()
+
     dvc.scm.add([PIPELINE_FILE, PIPELINE_LOCK])
     dvc.scm.commit("add pipeline stage")
-    dvc.push()
 
     with git_dir.chdir():
         Repo.get("file:///{}".format(fspath(tmp_dir)), "bar", out="baz")
diff --git a/tests/func/test_import.py b/tests/func/test_import.py
index 6ca40fb3c..f2b22e007 100644
--- a/tests/func/test_import.py
+++ b/tests/func/test_import.py
@@ -309,17 +309,20 @@ def test_pull_no_rev_lock(erepo_dir, tmp_dir, dvc):
     assert (tmp_dir / "foo_imported").read_text() == "contents"
 
 
-def test_import_from_bare_git_repo(tmp_dir, make_tmp_dir, erepo_dir):
+def test_import_from_bare_git_repo(
+    tmp_dir, make_tmp_dir, erepo_dir, setup_remote
+):
     import git
 
     git.Repo.init(fspath(tmp_dir), bare=True)
 
+    setup_remote(erepo_dir.dvc)
     with erepo_dir.chdir():
         erepo_dir.dvc_gen({"foo": "foo"}, commit="initial")
-        erepo_dir.dvc.push()
+    erepo_dir.dvc.push()
 
-        erepo_dir.scm.repo.create_remote("origin", fspath(tmp_dir))
-        erepo_dir.scm.repo.remote("origin").push("master")
+    erepo_dir.scm.repo.create_remote("origin", fspath(tmp_dir))
+    erepo_dir.scm.repo.remote("origin").push("master")
 
     dvc_repo = make_tmp_dir("dvc-repo", scm=True, dvc=True)
     with dvc_repo.chdir():
@@ -327,15 +330,17 @@ def test_import_from_bare_git_repo(tmp_dir, make_tmp_dir, erepo_dir):
 
 
 def test_import_pipeline_tracked_outs(
-    tmp_dir, dvc, scm, erepo_dir, local_remote, run_copy
+    tmp_dir, dvc, scm, erepo_dir, run_copy, setup_remote
 ):
     from dvc.dvcfile import PIPELINE_FILE, PIPELINE_LOCK
 
+    setup_remote(dvc)
     tmp_dir.gen("foo", "foo")
     run_copy("foo", "bar", name="copy-foo-bar")
+    dvc.push()
+
     dvc.scm.add([PIPELINE_FILE, PIPELINE_LOCK])
     dvc.scm.commit("add pipeline stage")
-    dvc.push()
 
     with erepo_dir.chdir():
         erepo_dir.dvc.imp(
diff --git a/tests/func/test_remote.py b/tests/func/test_remote.py
index a8d30d819..8e349efb9 100644
--- a/tests/func/test_remote.py
+++ b/tests/func/test_remote.py
@@ -173,10 +173,8 @@ def test_dir_checksum_should_be_key_order_agnostic(tmp_dir, dvc):
     assert checksum1 == checksum2
 
 
-def test_partial_push_n_pull(tmp_dir, dvc, tmp_path_factory):
-    url = fspath(tmp_path_factory.mktemp("upstream"))
-    dvc.config["remote"]["upstream"] = {"url": url}
-    dvc.config["core"]["remote"] = "upstream"
+def test_partial_push_n_pull(tmp_dir, dvc, tmp_path_factory, setup_remote):
+    setup_remote(dvc, name="upstream")
 
     foo = tmp_dir.dvc_gen({"foo": "foo content"})[0].outs[0]
     bar = tmp_dir.dvc_gen({"bar": "bar content"})[0].outs[0]
@@ -212,11 +210,10 @@ def test_partial_push_n_pull(tmp_dir, dvc, tmp_path_factory):
         assert download_error_info.value.amount == 3
 
 
-def test_raise_on_too_many_open_files(tmp_dir, dvc, tmp_path_factory, mocker):
-    storage = fspath(tmp_path_factory.mktemp("test_remote_base"))
-    dvc.config["remote"]["local_remote"] = {"url": storage}
-    dvc.config["core"]["remote"] = "local_remote"
-
+def test_raise_on_too_many_open_files(
+    tmp_dir, dvc, tmp_path_factory, mocker, setup_remote
+):
+    setup_remote(dvc)
     tmp_dir.dvc_gen({"file": "file content"})
 
     mocker.patch.object(
@@ -245,11 +242,8 @@ def test_external_dir_resource_on_no_cache(tmp_dir, dvc, tmp_path_factory):
         dvc.run(deps=[fspath(external_dir)], single_stage=True)
 
 
-def test_push_order(tmp_dir, dvc, tmp_path_factory, mocker):
-    url = fspath(tmp_path_factory.mktemp("upstream"))
-    dvc.config["remote"]["upstream"] = {"url": url}
-    dvc.config["core"]["remote"] = "upstream"
-
+def test_push_order(tmp_dir, dvc, tmp_path_factory, mocker, setup_remote):
+    setup_remote(dvc)
     tmp_dir.dvc_gen({"foo": {"bar": "bar content"}})
     tmp_dir.dvc_gen({"baz": "baz content"})
 
diff --git a/tests/unit/remote/test_s3.py b/tests/unit/remote/test_s3.py
index c32091e0a..b9ee1ebd3 100644
--- a/tests/unit/remote/test_s3.py
+++ b/tests/unit/remote/test_s3.py
@@ -53,3 +53,8 @@ def test_grants_mutually_exclusive_acl_error(dvc, grants):
 
         with pytest.raises(ConfigError):
             S3Remote(dvc, config)
+
+
+def test_sse_kms_key_id(dvc):
+    remote = S3Remote(dvc, {"url": url, "sse_kms_key_id": "key"})
+    assert remote.extra_args["SSEKMSKeyId"] == "key"
diff --git a/tests/unit/test_stage.py b/tests/unit/test_stage.py
index dcfb771c4..09121da2b 100644
--- a/tests/unit/test_stage.py
+++ b/tests/unit/test_stage.py
@@ -106,22 +106,36 @@ def test_always_changed(dvc):
 
 def test_stage_cache(tmp_dir, dvc, run_copy, mocker):
     tmp_dir.gen("dep", "dep")
-    stage = run_copy("dep", "out", single_stage=True)
+    tmp_dir.gen(
+        "script.py",
+        (
+            'open("out", "w+").write("out"); '
+            'open("out_no_cache", "w+").write("out_no_cache")'
+        ),
+    )
+    stage = dvc.run(
+        cmd="python script.py",
+        deps=["script.py", "dep"],
+        outs=["out"],
+        outs_no_cache=["out_no_cache"],
+        single_stage=True,
+    )
 
     with dvc.lock, dvc.state:
         stage.remove(remove_outs=True, force=True)
 
     assert not (tmp_dir / "out").exists()
+    assert not (tmp_dir / "out_no_cache").exists()
     assert not (tmp_dir / "out.dvc").exists()
 
     cache_dir = os.path.join(
         dvc.stage_cache.cache_dir,
-        "75",
-        "75f8a9097d76293ff4b3684d52e4ad0e83686d31196f27eb0b2ea9fd5085565e",
+        "10",
+        "10b45372fdf4ec14d3f779c5b256378d7a12780e4c7f549a44138e492f098bfe",
     )
     cache_file = os.path.join(
         cache_dir,
-        "c1747e52065bc7801262fdaed4d63f5775e5da304008bd35e2fea4e6b1ccb272",
+        "bb32e04c6da96a7192513390acedbe4cd6123f8fe5b0ba5fffe39716fe87f6f4",
     )
 
     assert os.path.isdir(cache_dir)
@@ -137,4 +151,6 @@ def test_stage_cache(tmp_dir, dvc, run_copy, mocker):
     assert checkout_spy.call_count == 1
 
     assert (tmp_dir / "out").exists()
-    assert (tmp_dir / "out").read_text() == "dep"
+    assert (tmp_dir / "out_no_cache").exists()
+    assert (tmp_dir / "out").read_text() == "out"
+    assert (tmp_dir / "out_no_cache").read_text() == "out_no_cache"

pip install -e .[all]
parse_log_pytest
pytest
pytest pytest-cov pytest-xdist pytest-mock pytest-lazy-fixture flaky mock xmltodict awscli google-compute-engine Pygments collective.checkdocs flake8 psutil flake8-docstrings pydocstyle jaraco.windows mock-ssh-server moto rangehttpserver beautifulsoup4 flake8-bugbear flake8-comprehensions flake8-string-format pylint pylint-pytest pylint-plugin-utils wget filelock
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aliyun-python-sdk-core==2.16.0
aliyun-python-sdk-core-v3==2.13.33
aliyun-python-sdk-kms==2.16.5
appdirs==1.4.4
astroid==2.15.8
atpublic==3.1.2
attrs @ file:///croot/attrs_1668696182826/work
autocommand==2.2.2
awscli==1.31.13
azure-common==1.1.28
azure-storage-blob==2.1.0
azure-storage-common==2.1.0
bcrypt==4.2.1
beautifulsoup4==4.13.3
boto==2.49.0
boto3==1.33.13
botocore==1.33.13
cachetools==4.2.4
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
charset-normalizer==3.4.1
collective.checkdocs==0.2
colorama==0.4.4
configobj==5.0.9
coverage==7.2.7
crcmod==1.7
cryptography==44.0.2
decorator==5.1.1
dill==0.3.7
distro==1.9.0
docutils==0.16
dpath==2.2.0
-e git+https://github.com/iterative/dvc.git@2c026066db5292e4c0421716473b7dc58ce48741#egg=dvc
execnet==2.0.2
filelock==3.12.2
flake8==5.0.4
flake8-bugbear==23.3.12
flake8-comprehensions==3.13.0
flake8-docstrings==1.7.0
flake8-string-format==0.3.0
flaky==3.8.1
flatten-json==0.1.14
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
flufl.lock==7.1.1
funcy==2.0
future==1.0.0
gitdb==4.0.12
GitPython==3.1.44
google-api-core==2.10.2
google-api-python-client==2.166.0
google-auth==1.35.0
google-auth-httplib2==0.2.0
google-cloud-core==1.7.3
google-cloud-storage==1.19.0
google-compute-engine==2.8.13
google-crc32c==1.5.0
google-resumable-media==2.7.2
googleapis-common-protos==1.69.2
grandalf==0.6
httplib2==0.22.0
humanize==4.6.0
idna==3.10
importlib-metadata==4.2.0
importlib-resources==5.12.0
inflect==3.0.2
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
isort==5.11.5
jaraco.classes==3.2.3
jaraco.collections==4.2.0
jaraco.context==4.3.0
jaraco.functools==3.7.0
jaraco.structures==2.1.0
jaraco.text==3.11.1
jaraco.ui==2.3.0
jaraco.windows==5.7.0
Jinja2==3.1.6
jmespath==0.10.0
jsonpath-ng==1.7.0
lazy-object-proxy==1.9.0
MarkupSafe==2.1.5
mccabe==0.7.0
mock==5.2.0
mock-ssh-server==0.9.1
more-itertools==9.1.0
moto==4.2.14
nanotime==0.5.2
networkx==2.3
numpy==1.21.6
oauth2client==4.1.3
oss2==2.6.1
packaging @ file:///croot/packaging_1671697413597/work
paramiko==3.5.1
path==16.6.0
pathspec==0.11.2
platformdirs==4.0.0
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
ply==3.11
protobuf==4.24.4
psutil==7.0.0
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyarrow==0.15.1
pyasn1==0.5.1
pyasn1-modules==0.3.0
pycodestyle==2.9.1
pycparser==2.21
pycryptodome==3.22.0
pydantic==1.10.21
pydocstyle==6.3.0
pydot==2.0.0
PyDrive2==1.15.4
pyflakes==2.5.0
Pygments==2.17.2
pygtrie==2.3.2
pylint==2.17.7
pylint-plugin-utils==0.8.2
pylint-pytest==1.1.8
PyNaCl==1.5.0
pyOpenSSL==25.0.0
pyparsing==3.1.4
pytest==7.1.2
pytest-cov==4.1.0
pytest-lazy-fixture==0.6.3
pytest-mock==3.11.1
pytest-xdist==3.5.0
python-dateutil==2.9.0.post0
PyYAML==5.3.1
rangehttpserver==1.4.0
requests==2.31.0
responses==0.23.3
rsa==4.7.2
ruamel.yaml==0.18.10
ruamel.yaml.clib==0.2.8
s3transfer==0.8.2
shortuuid==1.0.13
six==1.17.0
smmap==5.0.2
snowballstemmer==2.2.0
soupsieve==2.4.1
tabulate==0.9.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
tomlkit==0.12.5
tqdm==4.67.1
treelib==1.7.1
typed-ast==1.5.5
types-PyYAML==6.0.12.12
typing_extensions==4.7.1
uritemplate==4.1.1
urllib3==1.26.20
voluptuous==0.14.1
Werkzeug==2.2.3
wget==3.2
wrapt==1.16.0
xmltodict==0.14.2
zc.lockfile==3.0.post1
zipp @ file:///croot/zipp_1672387121353/work

name: dvc
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aliyun-python-sdk-core==2.16.0
      - aliyun-python-sdk-core-v3==2.13.33
      - aliyun-python-sdk-kms==2.16.5
      - appdirs==1.4.4
      - astroid==2.15.8
      - atpublic==3.1.2
      - autocommand==2.2.2
      - awscli==1.31.13
      - azure-common==1.1.28
      - azure-storage-blob==2.1.0
      - azure-storage-common==2.1.0
      - bcrypt==4.2.1
      - beautifulsoup4==4.13.3
      - boto==2.49.0
      - boto3==1.33.13
      - botocore==1.33.13
      - cachetools==4.2.4
      - cffi==1.15.1
      - charset-normalizer==3.4.1
      - collective-checkdocs==0.2
      - colorama==0.4.4
      - configobj==5.0.9
      - coverage==7.2.7
      - crcmod==1.7
      - cryptography==44.0.2
      - decorator==5.1.1
      - dill==0.3.7
      - distro==1.9.0
      - docutils==0.16
      - dpath==2.2.0
      - dvc==1.0.0a1+2c0260
      - execnet==2.0.2
      - filelock==3.12.2
      - flake8==5.0.4
      - flake8-bugbear==23.3.12
      - flake8-comprehensions==3.13.0
      - flake8-docstrings==1.7.0
      - flake8-string-format==0.3.0
      - flaky==3.8.1
      - flatten-json==0.1.14
      - flufl-lock==7.1.1
      - funcy==2.0
      - future==1.0.0
      - gitdb==4.0.12
      - gitpython==3.1.44
      - google-api-core==2.10.2
      - google-api-python-client==2.166.0
      - google-auth==1.35.0
      - google-auth-httplib2==0.2.0
      - google-cloud-core==1.7.3
      - google-cloud-storage==1.19.0
      - google-compute-engine==2.8.13
      - google-crc32c==1.5.0
      - google-resumable-media==2.7.2
      - googleapis-common-protos==1.69.2
      - grandalf==0.6
      - httplib2==0.22.0
      - humanize==4.6.0
      - idna==3.10
      - importlib-metadata==4.2.0
      - importlib-resources==5.12.0
      - inflect==3.0.2
      - isort==5.11.5
      - jaraco-classes==3.2.3
      - jaraco-collections==4.2.0
      - jaraco-context==4.3.0
      - jaraco-functools==3.7.0
      - jaraco-structures==2.1.0
      - jaraco-text==3.11.1
      - jaraco-ui==2.3.0
      - jaraco-windows==5.7.0
      - jinja2==3.1.6
      - jmespath==0.10.0
      - jsonpath-ng==1.7.0
      - lazy-object-proxy==1.9.0
      - markupsafe==2.1.5
      - mccabe==0.7.0
      - mock==5.2.0
      - mock-ssh-server==0.9.1
      - more-itertools==9.1.0
      - moto==4.2.14
      - nanotime==0.5.2
      - networkx==2.3
      - numpy==1.21.6
      - oauth2client==4.1.3
      - oss2==2.6.1
      - paramiko==3.5.1
      - path==16.6.0
      - pathspec==0.11.2
      - platformdirs==4.0.0
      - ply==3.11
      - protobuf==4.24.4
      - psutil==7.0.0
      - pyarrow==0.15.1
      - pyasn1==0.5.1
      - pyasn1-modules==0.3.0
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pycryptodome==3.22.0
      - pydantic==1.10.21
      - pydocstyle==6.3.0
      - pydot==2.0.0
      - pydrive2==1.15.4
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pygtrie==2.3.2
      - pylint==2.17.7
      - pylint-plugin-utils==0.8.2
      - pylint-pytest==1.1.8
      - pynacl==1.5.0
      - pyopenssl==25.0.0
      - pyparsing==3.1.4
      - pytest-cov==4.1.0
      - pytest-lazy-fixture==0.6.3
      - pytest-mock==3.11.1
      - pytest-xdist==3.5.0
      - python-dateutil==2.9.0.post0
      - pyyaml==5.3.1
      - rangehttpserver==1.4.0
      - requests==2.31.0
      - responses==0.23.3
      - rsa==4.7.2
      - ruamel-yaml==0.18.10
      - ruamel-yaml-clib==0.2.8
      - s3transfer==0.8.2
      - shortuuid==1.0.13
      - six==1.17.0
      - smmap==5.0.2
      - snowballstemmer==2.2.0
      - soupsieve==2.4.1
      - tabulate==0.9.0
      - tomlkit==0.12.5
      - tqdm==4.67.1
      - treelib==1.7.1
      - typed-ast==1.5.5
      - types-pyyaml==6.0.12.12
      - typing-extensions==4.7.1
      - uritemplate==4.1.1
      - urllib3==1.26.20
      - voluptuous==0.14.1
      - werkzeug==2.2.3
      - wget==3.2
      - wrapt==1.16.0
      - xmltodict==0.14.2
      - zc-lockfile==3.0.post1
prefix: /opt/conda/envs/dvc

tests/unit/remote/test_s3.py::test_sse_kms_key_id tests/unit/test_stage.py::test_stage_cache
tests/unit/test_stage.py::TestPathConversion::test
tests/func/test_api.py::test_get_url_requires_dvc tests/func/test_api.py::test_open[Local] tests/func/test_api.py::test_open_external[Local] tests/func/test_api.py::test_missing[Local] tests/func/test_api.py::test_open_scm_controlled tests/func/test_api.py::test_open_not_cached tests/func/test_data_cloud.py::TestDataCloud::test tests/func/test_data_cloud.py::TestLocalRemote::test tests/func/test_data_cloud.py::TestSSHRemoteMocked::test tests/func/test_data_cloud.py::TestHTTPRemote::test tests/func/test_data_cloud.py::TestLocalRemoteCLI::test tests/func/test_data_cloud.py::TestDataCloudErrorCLI::test_error tests/func/test_data_cloud.py::TestWarnOnOutdatedStage::test tests/func/test_data_cloud.py::TestRecursiveSyncOperations::test tests/func/test_data_cloud.py::test_checksum_recalculation tests/func/test_data_cloud.py::TestShouldWarnOnNoChecksumInLocalAndRemoteCache::test tests/func/test_data_cloud.py::test_verify_checksums tests/func/test_data_cloud.py::test_pull_git_imports[git_dir] tests/func/test_data_cloud.py::test_pull_git_imports[erepo_dir] tests/func/test_data_cloud.py::test_pull_external_dvc_imports tests/func/test_data_cloud.py::test_dvc_pull_pipeline_stages tests/func/test_data_cloud.py::test_pipeline_file_target_ops tests/func/test_data_cloud.py::test_push_stats[fs0-2 tests/func/test_data_cloud.py::test_push_stats[fs1-1 tests/func/test_data_cloud.py::test_push_stats[fs2-Everything tests/func/test_data_cloud.py::test_fetch_stats[fs0-2 tests/func/test_data_cloud.py::test_fetch_stats[fs1-1 tests/func/test_data_cloud.py::test_fetch_stats[fs2-Everything tests/func/test_data_cloud.py::test_pull_stats tests/func/test_external_repo.py::test_external_repo tests/func/test_external_repo.py::test_source_change tests/func/test_external_repo.py::test_cache_reused tests/func/test_external_repo.py::test_known_sha tests/func/test_external_repo.py::test_pull_subdir_file tests/func/test_external_repo.py::test_relative_remote tests/func/test_gc.py::TestGC::test_api tests/func/test_gc.py::TestGC::test_cli tests/func/test_gc.py::TestGCBranchesTags::test tests/func/test_gc.py::TestGCMultipleDvcRepos::test tests/func/test_gc.py::test_all_commits tests/func/test_gc.py::test_gc_no_dir_cache tests/func/test_gc.py::test_gc_no_unpacked_dir tests/func/test_gc.py::test_gc_without_workspace_raises_error tests/func/test_gc.py::test_gc_cloud_with_or_without_specifier tests/func/test_gc.py::test_gc_without_workspace_on_tags_branches_commits tests/func/test_gc.py::test_gc_without_workspace tests/func/test_gc.py::test_gc_cloud_without_any_specifier tests/func/test_gc.py::test_gc_with_possible_args_positive tests/func/test_gc.py::test_gc_cloud_positive tests/func/test_gc.py::test_gc_cloud_remove_order tests/func/test_gc.py::test_gc_not_collect_pipeline_tracked_files tests/func/test_get.py::test_get_repo_file tests/func/test_get.py::test_get_repo_dir tests/func/test_get.py::test_get_git_file tests/func/test_get.py::test_get_git_dir tests/func/test_get.py::test_cache_type_is_properly_overridden tests/func/test_get.py::test_get_repo_rev tests/func/test_get.py::test_get_from_non_dvc_repo tests/func/test_get.py::test_get_a_dvc_file tests/func/test_get.py::test_get_full_dvc_path tests/func/test_get.py::test_non_cached_output tests/func/test_get.py::test_absolute_file_outside_repo tests/func/test_get.py::test_absolute_file_outside_git_repo tests/func/test_get.py::test_unknown_path tests/func/test_get.py::test_get_to_dir[.] tests/func/test_get.py::test_get_to_dir[dir] tests/func/test_get.py::test_get_to_dir[dir/subdir] tests/func/test_get.py::test_get_from_non_dvc_master tests/func/test_get.py::test_get_file_from_dir tests/func/test_get.py::test_get_url_positive tests/func/test_get.py::test_get_url_not_existing tests/func/test_get.py::test_get_url_git_only_repo tests/func/test_get.py::test_get_pipeline_tracked_outs tests/func/test_import.py::test_import tests/func/test_import.py::test_import_git_file[True] tests/func/test_import.py::test_import_git_file[False] tests/func/test_import.py::test_import_cached_file tests/func/test_import.py::test_import_git_dir[True] tests/func/test_import.py::test_import_git_dir[False] tests/func/test_import.py::test_import_dir tests/func/test_import.py::test_import_file_from_dir tests/func/test_import.py::test_import_non_cached tests/func/test_import.py::test_import_rev tests/func/test_import.py::test_pull_imported_stage tests/func/test_import.py::test_cache_type_is_properly_overridden tests/func/test_import.py::test_pull_imported_directory_stage tests/func/test_import.py::test_download_error_pulling_imported_stage tests/func/test_import.py::test_import_to_dir[.] tests/func/test_import.py::test_import_to_dir[dir] tests/func/test_import.py::test_import_to_dir[dir/subdir] tests/func/test_import.py::test_pull_non_workspace tests/func/test_import.py::test_import_non_existing tests/func/test_import.py::test_pull_no_rev_lock tests/func/test_import.py::test_import_from_bare_git_repo tests/func/test_import.py::test_import_pipeline_tracked_outs tests/func/test_import.py::test_local_import tests/func/test_remote.py::TestRemote::test tests/func/test_remote.py::TestRemote::test_overwrite tests/func/test_remote.py::TestRemote::test_referencing_other_remotes tests/func/test_remote.py::TestRemote::test_relative_path tests/func/test_remote.py::test_remove_default tests/func/test_remote.py::TestRemoteRemove::test tests/func/test_remote.py::TestRemoteDefault::test tests/func/test_remote.py::test_show_default tests/func/test_remote.py::TestRemoteShouldHandleUppercaseRemoteName::test tests/func/test_remote.py::test_dir_checksum_should_be_key_order_agnostic tests/func/test_remote.py::test_partial_push_n_pull tests/func/test_remote.py::test_raise_on_too_many_open_files tests/func/test_remote.py::test_modify_missing_remote tests/func/test_remote.py::test_external_dir_resource_on_no_cache tests/func/test_remote.py::test_push_order tests/func/test_remote.py::test_remote_modify_validation tests/func/test_remote.py::test_remote_modify_default tests/unit/remote/test_s3.py::test_init tests/unit/remote/test_s3.py::test_grants tests/unit/remote/test_s3.py::test_grants_mutually_exclusive_acl_error tests/unit/test_stage.py::test_stage_checksum tests/unit/test_stage.py::test_wdir_default_ignored tests/unit/test_stage.py::test_wdir_non_default_is_not_ignored tests/unit/test_stage.py::test_meta_ignored tests/unit/test_stage.py::test_stage_update tests/unit/test_stage.py::test_stage_run_ignore_sigint tests/unit/test_stage.py::test_always_changed
dvc/config.py dvc/stage/cache.py dvc/remote/s3.py
dvc/config.py dvc/stage/cache.py dvc/remote/s3.py