Files
dvc/tests/func/experiments/test_remote.py
T
6dd435eefe Push running checkpoint to remote (#6332)
* Push running checkpoint to remote

Fix #6182

* Update dvc/repo/experiments/executor/base.py

Co-authored-by: Peter Rowlands (변기호) <[email protected]>

* Get the branch name

* Finish this PR

1. move env name to dvc/env.py.
2. add some tests for it.

* Update after finally commit

* Some problems found in the review

1. change the behavior of self remote
2. do not use string DVC_EXP_AUTO_PUSH
3. downgrade the logger level in auto push
4. use full branch ref

* Update dvc/repo/experiments/executor/base.py

Co-authored-by: Peter Rowlands (변기호) <[email protected]>

* add a remote check before auto push

* Split current one env into two

* Rename DVC_EXP_CHECKPOINT_PUSH to DVC_EXP_AUTO_PUSH

* value error

* Remove getenv_bool switch to env2bool

* Better on handling Dulwich exceptions

* Name changing removing prints

* Update dvc/env.py

Co-authored-by: Peter Rowlands (변기호) <[email protected]>

* Some changes in review

* Add validation to repo URL

* Add new type of SCMError

* Update dvc/repo/experiments/executor/base.py

Co-authored-by: Peter Rowlands (변기호) <[email protected]>

* Use spy tests call counts and args

* Update dvc/scm/git/backend/base.py

Co-authored-by: Peter Rowlands (변기호) <[email protected]>

* Update dvc/scm/git/backend/dulwich.py

Co-authored-by: Peter Rowlands (변기호) <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Remove validate_git_repo to validate_git_remote

Co-authored-by: Peter Rowlands (변기호) <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2021-08-12 15:17:08 +08:00

255 lines
8.8 KiB
Python

import os
import pytest
from funcy import first
from dvc.exceptions import DvcException
from dvc.repo.experiments.utils import exp_refs_by_rev
@pytest.mark.parametrize("use_url", [True, False])
def test_push(tmp_dir, scm, dvc, git_upstream, exp_stage, use_url):
from dvc.exceptions import InvalidArgumentError
remote = git_upstream.url if use_url else git_upstream.remote
with pytest.raises(InvalidArgumentError):
dvc.experiments.push(remote, "foo")
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
exp = first(results)
ref_info = first(exp_refs_by_rev(scm, exp))
dvc.experiments.push(remote, ref_info.name)
assert git_upstream.scm.get_ref(str(ref_info)) == exp
git_upstream.scm.remove_ref(str(ref_info))
dvc.experiments.push(remote, str(ref_info))
assert git_upstream.scm.get_ref(str(ref_info)) == exp
def test_push_diverged(tmp_dir, scm, dvc, git_upstream, exp_stage):
git_upstream.scm_gen("foo", "foo", commit="init")
remote_rev = git_upstream.scm.get_rev()
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
exp = first(results)
ref_info = first(exp_refs_by_rev(scm, exp))
git_upstream.scm.set_ref(str(ref_info), remote_rev)
with pytest.raises(DvcException):
dvc.experiments.push(git_upstream.remote, ref_info.name)
assert git_upstream.scm.get_ref(str(ref_info)) == remote_rev
dvc.experiments.push(git_upstream.remote, ref_info.name, force=True)
assert git_upstream.scm.get_ref(str(ref_info)) == exp
def test_push_checkpoint(tmp_dir, scm, dvc, git_upstream, checkpoint_stage):
results = dvc.experiments.run(
checkpoint_stage.addressing, params=["foo=2"]
)
exp_a = first(results)
ref_info_a = first(exp_refs_by_rev(scm, exp_a))
dvc.experiments.push(git_upstream.remote, ref_info_a.name, force=True)
assert git_upstream.scm.get_ref(str(ref_info_a)) == exp_a
results = dvc.experiments.run(
checkpoint_stage.addressing, checkpoint_resume=exp_a
)
exp_b = first(results)
ref_info_b = first(exp_refs_by_rev(scm, exp_b))
tmp_dir.scm_gen("new", "new", commit="new")
dvc.experiments.push(git_upstream.remote, ref_info_b.name, force=True)
assert git_upstream.scm.get_ref(str(ref_info_b)) == exp_b
def test_push_ambiguous_name(tmp_dir, scm, dvc, git_upstream, exp_stage):
from dvc.exceptions import InvalidArgumentError
remote = git_upstream.remote
results = dvc.experiments.run(
exp_stage.addressing, params=["foo=2"], name="foo"
)
exp_a = first(results)
ref_info_a = first(exp_refs_by_rev(scm, exp_a))
tmp_dir.scm_gen("new", "new", commit="new")
results = dvc.experiments.run(
exp_stage.addressing, params=["foo=3"], name="foo"
)
exp_b = first(results)
ref_info_b = first(exp_refs_by_rev(scm, exp_b))
dvc.experiments.push(remote, "foo")
assert git_upstream.scm.get_ref(str(ref_info_b)) == exp_b
tmp_dir.scm_gen("new", "new 2", commit="new 2")
with pytest.raises(InvalidArgumentError):
dvc.experiments.push(remote, "foo")
dvc.experiments.push(remote, str(ref_info_a))
assert git_upstream.scm.get_ref(str(ref_info_a)) == exp_a
@pytest.mark.parametrize("use_url", [True, False])
def test_list_remote(tmp_dir, scm, dvc, git_downstream, exp_stage, use_url):
baseline_a = scm.get_rev()
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
exp_a = first(results)
ref_info_a = first(exp_refs_by_rev(scm, exp_a))
results = dvc.experiments.run(exp_stage.addressing, params=["foo=3"])
exp_b = first(results)
ref_info_b = first(exp_refs_by_rev(scm, exp_b))
tmp_dir.scm_gen("new", "new", commit="new")
baseline_c = scm.get_rev()
results = dvc.experiments.run(exp_stage.addressing, params=["foo=4"])
exp_c = first(results)
ref_info_c = first(exp_refs_by_rev(scm, exp_c))
remote = git_downstream.url if use_url else git_downstream.remote
assert git_downstream.scm.get_ref("HEAD") != scm.get_ref("HEAD")
downstream_exp = git_downstream.dvc.experiments
assert downstream_exp.ls(git_remote=remote) == {}
exp_list = downstream_exp.ls(rev=baseline_a, git_remote=remote)
assert {key: set(val) for key, val in exp_list.items()} == {
baseline_a: {ref_info_a.name, ref_info_b.name}
}
exp_list = downstream_exp.ls(all_=True, git_remote=remote)
assert {key: set(val) for key, val in exp_list.items()} == {
baseline_a: {ref_info_a.name, ref_info_b.name},
baseline_c: {ref_info_c.name},
}
@pytest.mark.parametrize("use_url", [True, False])
def test_pull(tmp_dir, scm, dvc, git_downstream, exp_stage, use_url):
from dvc.exceptions import InvalidArgumentError
remote = git_downstream.url if use_url else git_downstream.remote
downstream_exp = git_downstream.dvc.experiments
with pytest.raises(InvalidArgumentError):
downstream_exp.pull(remote, "foo")
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
exp = first(results)
ref_info = first(exp_refs_by_rev(scm, exp))
downstream_exp.pull(remote, ref_info.name)
assert git_downstream.scm.get_ref(str(ref_info)) == exp
git_downstream.scm.remove_ref(str(ref_info))
downstream_exp.pull(remote, str(ref_info))
assert git_downstream.scm.get_ref(str(ref_info)) == exp
def test_pull_diverged(tmp_dir, scm, dvc, git_downstream, exp_stage):
git_downstream.scm_gen("foo", "foo", commit="init")
remote_rev = git_downstream.scm.get_rev()
results = dvc.experiments.run(exp_stage.addressing, params=["foo=2"])
exp = first(results)
ref_info = first(exp_refs_by_rev(scm, exp))
git_downstream.scm.set_ref(str(ref_info), remote_rev)
downstream_exp = git_downstream.dvc.experiments
with pytest.raises(DvcException):
downstream_exp.pull(git_downstream.remote, ref_info.name)
assert git_downstream.scm.get_ref(str(ref_info)) == remote_rev
downstream_exp.pull(git_downstream.remote, ref_info.name, force=True)
assert git_downstream.scm.get_ref(str(ref_info)) == exp
def test_pull_checkpoint(tmp_dir, scm, dvc, git_downstream, checkpoint_stage):
results = dvc.experiments.run(
checkpoint_stage.addressing, params=["foo=2"]
)
exp_a = first(results)
ref_info_a = first(exp_refs_by_rev(scm, exp_a))
downstream_exp = git_downstream.dvc.experiments
downstream_exp.pull(git_downstream.remote, ref_info_a.name, force=True)
assert git_downstream.scm.get_ref(str(ref_info_a)) == exp_a
results = dvc.experiments.run(
checkpoint_stage.addressing, checkpoint_resume=exp_a
)
exp_b = first(results)
ref_info_b = first(exp_refs_by_rev(scm, exp_b))
downstream_exp.pull(git_downstream.remote, ref_info_b.name, force=True)
assert git_downstream.scm.get_ref(str(ref_info_b)) == exp_b
def test_pull_ambiguous_name(tmp_dir, scm, dvc, git_downstream, exp_stage):
from dvc.exceptions import InvalidArgumentError
results = dvc.experiments.run(
exp_stage.addressing, params=["foo=2"], name="foo"
)
exp_a = first(results)
ref_info_a = first(exp_refs_by_rev(scm, exp_a))
tmp_dir.scm_gen("new", "new", commit="new")
results = dvc.experiments.run(
exp_stage.addressing, params=["foo=3"], name="foo"
)
exp_b = first(results)
ref_info_b = first(exp_refs_by_rev(scm, exp_b))
remote = git_downstream.remote
downstream_exp = git_downstream.dvc.experiments
with pytest.raises(InvalidArgumentError):
downstream_exp.pull(remote, "foo")
downstream_exp.pull(remote, str(ref_info_b))
assert git_downstream.scm.get_ref(str(ref_info_b)) == exp_b
with git_downstream.scm.detach_head(ref_info_a.baseline_sha):
downstream_exp.pull(remote, "foo")
assert git_downstream.scm.get_ref(str(ref_info_a)) == exp_a
def test_push_pull_cache(
tmp_dir, scm, dvc, git_upstream, checkpoint_stage, local_remote
):
from dvc.utils.fs import remove
from tests.func.test_diff import digest
remote = git_upstream.remote
results = dvc.experiments.run(
checkpoint_stage.addressing, params=["foo=2"]
)
exp = first(results)
ref_info = first(exp_refs_by_rev(scm, exp))
dvc.experiments.push(remote, ref_info.name, push_cache=True)
for x in range(2, checkpoint_stage.iterations + 1):
hash_ = digest(str(x))
path = os.path.join(local_remote.url, hash_[:2], hash_[2:])
assert os.path.exists(path)
assert open(path).read() == str(x)
remove(dvc.odb.local.cache_dir)
dvc.experiments.pull(remote, ref_info.name, pull_cache=True)
for x in range(2, checkpoint_stage.iterations + 1):
hash_ = digest(str(x))
path = os.path.join(dvc.odb.local.cache_dir, hash_[:2], hash_[2:])
assert os.path.exists(path)
assert open(path).read() == str(x)