mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
experiments: auto push experiments (#10323)
* add auto_push for experiment on run and on save. add config.exp.auto_push and config.exp.git_remote * add func tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * separate auto_push behaviour out of commit --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Saugat Pachhai (सौगात) <[email protected]>
This commit is contained in:
co-authored by
pre-commit-ci[bot]
Saugat Pachhai
parent
3b2e031e60
commit
cd1e228e55
@@ -336,6 +336,8 @@ SCHEMA = {
|
|||||||
"params": str,
|
"params": str,
|
||||||
"plots": str,
|
"plots": str,
|
||||||
"live": str,
|
"live": str,
|
||||||
|
"auto_push": Bool,
|
||||||
|
"git_remote": str,
|
||||||
},
|
},
|
||||||
"parsing": {
|
"parsing": {
|
||||||
"bool": All(Lower, Choices("store_true", "boolean_optional")),
|
"bool": All(Lower, Choices("store_true", "boolean_optional")),
|
||||||
|
|||||||
@@ -297,13 +297,16 @@ class BaseExecutor(ABC):
|
|||||||
exp_hash = cls.hash_exp(stages)
|
exp_hash = cls.hash_exp(stages)
|
||||||
if include_untracked:
|
if include_untracked:
|
||||||
dvc.scm.add(include_untracked, force=True) # type: ignore[call-arg]
|
dvc.scm.add(include_untracked, force=True) # type: ignore[call-arg]
|
||||||
cls.commit(
|
|
||||||
dvc.scm, # type: ignore[arg-type]
|
with cls.auto_push(dvc):
|
||||||
exp_hash,
|
cls.commit(
|
||||||
exp_name=info.name,
|
dvc.scm, # type: ignore[arg-type]
|
||||||
force=force,
|
exp_hash,
|
||||||
message=message,
|
exp_name=info.name,
|
||||||
)
|
force=force,
|
||||||
|
message=message,
|
||||||
|
)
|
||||||
|
|
||||||
ref: Optional[str] = dvc.scm.get_ref(EXEC_BRANCH, follow=False)
|
ref: Optional[str] = dvc.scm.get_ref(EXEC_BRANCH, follow=False)
|
||||||
exp_ref = ExpRefInfo.from_ref(ref) if ref else None
|
exp_ref = ExpRefInfo.from_ref(ref) if ref else None
|
||||||
untracked = dvc.scm.untracked_files()
|
untracked = dvc.scm.untracked_files()
|
||||||
@@ -460,9 +463,6 @@ class BaseExecutor(ABC):
|
|||||||
from dvc.repo.checkout import checkout as dvc_checkout
|
from dvc.repo.checkout import checkout as dvc_checkout
|
||||||
from dvc.ui import ui
|
from dvc.ui import ui
|
||||||
|
|
||||||
auto_push = env2bool(DVC_EXP_AUTO_PUSH)
|
|
||||||
git_remote = os.getenv(DVC_EXP_GIT_REMOTE, None)
|
|
||||||
|
|
||||||
if queue is not None:
|
if queue is not None:
|
||||||
queue.put((rev, os.getpid()))
|
queue.put((rev, os.getpid()))
|
||||||
if log_errors and log_level is not None:
|
if log_errors and log_level is not None:
|
||||||
@@ -483,9 +483,6 @@ class BaseExecutor(ABC):
|
|||||||
message=message,
|
message=message,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) as dvc:
|
) as dvc:
|
||||||
if auto_push:
|
|
||||||
cls._validate_remotes(dvc, git_remote)
|
|
||||||
|
|
||||||
args, kwargs = cls._repro_args(dvc)
|
args, kwargs = cls._repro_args(dvc)
|
||||||
if args:
|
if args:
|
||||||
targets: Optional[Union[list, str]] = args[0]
|
targets: Optional[Union[list, str]] = args[0]
|
||||||
@@ -519,8 +516,6 @@ class BaseExecutor(ABC):
|
|||||||
dvc,
|
dvc,
|
||||||
info,
|
info,
|
||||||
exp_hash,
|
exp_hash,
|
||||||
auto_push,
|
|
||||||
git_remote,
|
|
||||||
repro_force,
|
repro_force,
|
||||||
message=message,
|
message=message,
|
||||||
)
|
)
|
||||||
@@ -550,20 +545,18 @@ class BaseExecutor(ABC):
|
|||||||
dvc,
|
dvc,
|
||||||
info,
|
info,
|
||||||
exp_hash,
|
exp_hash,
|
||||||
auto_push,
|
|
||||||
git_remote,
|
|
||||||
repro_force,
|
repro_force,
|
||||||
message: Optional[str] = None,
|
message: Optional[str] = None,
|
||||||
) -> tuple[Optional[str], Optional["ExpRefInfo"], bool]:
|
) -> tuple[Optional[str], Optional["ExpRefInfo"], bool]:
|
||||||
cls.commit(
|
with cls.auto_push(dvc):
|
||||||
dvc.scm,
|
cls.commit(
|
||||||
exp_hash,
|
dvc.scm,
|
||||||
exp_name=info.name,
|
exp_hash,
|
||||||
force=repro_force,
|
exp_name=info.name,
|
||||||
message=message,
|
force=repro_force,
|
||||||
)
|
message=message,
|
||||||
if auto_push:
|
)
|
||||||
cls._auto_push(dvc, dvc.scm, git_remote)
|
|
||||||
ref: Optional[str] = dvc.scm.get_ref(EXEC_BRANCH, follow=False)
|
ref: Optional[str] = dvc.scm.get_ref(EXEC_BRANCH, follow=False)
|
||||||
exp_ref: Optional["ExpRefInfo"] = ExpRefInfo.from_ref(ref) if ref else None
|
exp_ref: Optional["ExpRefInfo"] = ExpRefInfo.from_ref(ref) if ref else None
|
||||||
if cls.WARN_UNTRACKED:
|
if cls.WARN_UNTRACKED:
|
||||||
@@ -672,15 +665,30 @@ class BaseExecutor(ABC):
|
|||||||
kwargs = {}
|
kwargs = {}
|
||||||
return args, kwargs
|
return args, kwargs
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@contextmanager
|
||||||
|
def auto_push(cls, dvc: "Repo") -> Iterator[None]:
|
||||||
|
exp_config = dvc.config.get("exp", {})
|
||||||
|
auto_push = env2bool(DVC_EXP_AUTO_PUSH, exp_config.get("auto_push", False))
|
||||||
|
if not auto_push:
|
||||||
|
yield
|
||||||
|
return
|
||||||
|
|
||||||
|
git_remote = os.getenv(
|
||||||
|
DVC_EXP_GIT_REMOTE, exp_config.get("git_remote", "origin")
|
||||||
|
)
|
||||||
|
cls._validate_remotes(dvc, git_remote)
|
||||||
|
yield
|
||||||
|
cls._auto_push(dvc, git_remote)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _auto_push(
|
def _auto_push(
|
||||||
dvc: "Repo",
|
dvc: "Repo",
|
||||||
scm: "Git",
|
|
||||||
git_remote: Optional[str],
|
git_remote: Optional[str],
|
||||||
push_cache=True,
|
push_cache=True,
|
||||||
run_cache=True,
|
run_cache=True,
|
||||||
):
|
):
|
||||||
branch = scm.get_ref(EXEC_BRANCH, follow=False)
|
branch = dvc.scm.get_ref(EXEC_BRANCH, follow=False)
|
||||||
try:
|
try:
|
||||||
dvc.experiments.push(
|
dvc.experiments.push(
|
||||||
git_remote,
|
git_remote,
|
||||||
@@ -708,6 +716,7 @@ class BaseExecutor(ABC):
|
|||||||
message: Optional[str] = None,
|
message: Optional[str] = None,
|
||||||
):
|
):
|
||||||
"""Commit stages as an experiment and return the commit SHA."""
|
"""Commit stages as an experiment and return the commit SHA."""
|
||||||
|
|
||||||
rev = scm.get_rev()
|
rev = scm.get_rev()
|
||||||
if not scm.is_dirty(untracked_files=False):
|
if not scm.is_dirty(untracked_files=False):
|
||||||
logger.debug("No changes to commit")
|
logger.debug("No changes to commit")
|
||||||
|
|||||||
@@ -372,3 +372,40 @@ def test_push_pull_invalid_workspace(
|
|||||||
dvc.experiments.push(git_upstream.remote, push_cache=True)
|
dvc.experiments.push(git_upstream.remote, push_cache=True)
|
||||||
dvc.experiments.pull(git_upstream.remote, pull_cache=True)
|
dvc.experiments.pull(git_upstream.remote, pull_cache=True)
|
||||||
assert "failed to collect" not in caplog.text
|
assert "failed to collect" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"auto_push, expected_key", [(True, "up_to_date"), (False, "success")]
|
||||||
|
)
|
||||||
|
def test_auto_push_on_run(
|
||||||
|
tmp_dir, scm, dvc, git_upstream, local_remote, exp_stage, auto_push, expected_key
|
||||||
|
):
|
||||||
|
remote = git_upstream.remote
|
||||||
|
|
||||||
|
with dvc.config.edit() as conf:
|
||||||
|
conf["exp"]["auto_push"] = auto_push
|
||||||
|
conf["exp"]["git_remote"] = remote
|
||||||
|
|
||||||
|
exp_name = "foo"
|
||||||
|
dvc.experiments.run(exp_stage.addressing, params=["foo=2"], name=exp_name)
|
||||||
|
|
||||||
|
assert first(dvc.experiments.push(name=exp_name, git_remote=remote)) == expected_key
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"auto_push, expected_key", [(True, "up_to_date"), (False, "success")]
|
||||||
|
)
|
||||||
|
def test_auto_push_on_save(
|
||||||
|
tmp_dir, scm, dvc, git_upstream, local_remote, exp_stage, auto_push, expected_key
|
||||||
|
):
|
||||||
|
remote = git_upstream.remote
|
||||||
|
exp_name = "foo"
|
||||||
|
dvc.experiments.run(exp_stage.addressing, params=["foo=2"], name=exp_name)
|
||||||
|
|
||||||
|
with dvc.config.edit() as conf:
|
||||||
|
conf["exp"]["auto_push"] = auto_push
|
||||||
|
conf["exp"]["git_remote"] = remote
|
||||||
|
|
||||||
|
dvc.experiments.save(name=exp_name, force=True)
|
||||||
|
|
||||||
|
assert first(dvc.experiments.push(name=exp_name, git_remote=remote)) == expected_key
|
||||||
|
|||||||
Reference in New Issue
Block a user