-
Notifications
You must be signed in to change notification settings - Fork 15
worker: run repo maintenance during idle time (Bug 2037216) #1135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 10 commits
c588049
02c3eac
7d271d1
9e9bafb
2ef9a61
d19a8ab
3a62160
6fa23f7
da14d67
80563fe
169feeb
6b948be
6463654
51c01e6
290cd8a
adecbf2
3eb51e4
6dbec73
ffdf03f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,7 +31,7 @@ def test_integrated_hgrepo_clean_repo(hg_clone): | |
| repo = HgSCM(hg_clone.strpath) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Could we rename this variable to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It pre-dates the SCM split (; |
||
|
|
||
| with repo.for_pull(), hg_clone.as_cwd(): | ||
| # Create a draft commits to clean. | ||
| # Create a draft commit to clean. | ||
| new_file = hg_clone.join("new-file.txt") | ||
| new_file.write("text", mode="w+") | ||
| repo.run_hg_cmds( | ||
|
|
@@ -43,37 +43,32 @@ def test_integrated_hgrepo_clean_repo(hg_clone): | |
| new_file.write("Extra data", mode="a") | ||
| assert repo.run_hg_cmds([["status"]]) | ||
|
|
||
| # Can clean working directory without nuking commits | ||
| repo.clean_repo(strip_non_public_commits=False) | ||
| # `clean_repo` clears the working directory but leaves drafts in place; | ||
| # stripping is `maintenance`'s job. | ||
| repo.clean_repo() | ||
| assert repo.run_hg_cmds([["outgoing"]]) | ||
| assert not repo.run_hg_cmds([["status"]]) | ||
|
|
||
| # Dirty the working directory again. | ||
| new_file.write("Extra data", mode="a") | ||
| # Dirty the directory again before exiting the context manager. | ||
| new_file.write("extra data", mode="a") | ||
| assert repo.run_hg_cmds([["status"]]) | ||
|
|
||
| # Cleaning should remove commit and clean working directory. | ||
| repo.clean_repo() | ||
| with pytest.raises(HgCommandError, match="no changes found"): | ||
| repo.run_hg_cmds([["outgoing"]]) | ||
| assert not repo.run_hg_cmds([["status"]]) | ||
| with repo.for_pull(), hg_clone.as_cwd(): | ||
|
cgsheeh marked this conversation as resolved.
Outdated
|
||
| assert not repo.run_hg_cmds( | ||
| [["status"]] | ||
| ), "Working directory should be clean after exiting and re-entering the context." | ||
| assert repo.run_hg_cmds( | ||
| [["outgoing"]] | ||
| ), "Draft commits should persist across context exits; `maintenance` strips them." | ||
|
|
||
| # Create a commit and dirty the directory before exiting | ||
| # the context manager as entering a new context should | ||
| # provide a clean repo. | ||
| new_file.write("text", mode="w+") | ||
| repo.run_hg_cmds( | ||
| [["add", new_file.strpath], ["commit", "-m", "new draft commit"]] | ||
| ) | ||
| new_file.write("extra data", mode="a") | ||
| assert repo.run_hg_cmds([["outgoing"]]) | ||
| assert repo.run_hg_cmds([["status"]]) | ||
| repo.maintenance() | ||
|
|
||
| with repo.for_pull(), hg_clone.as_cwd(): | ||
| # New context should be clean. | ||
| with pytest.raises(HgCommandError, match="no changes found"): | ||
| repo.run_hg_cmds([["outgoing"]]) | ||
| assert not repo.run_hg_cmds([["status"]]) | ||
| assert not repo.run_hg_cmds( | ||
| [["status"]] | ||
| ), "Working directory should be clean after `maintenance` runs." | ||
|
|
||
|
|
||
| def test_integrated_hgrepo_can_log(hg_clone): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Generated by Django 6.0.4 on 2026-05-06 01:38 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ("main", "0051_alter_repo_hooks"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AddField( | ||
| model_name="worker", | ||
| name="maintenance_interval_seconds", | ||
| field=models.IntegerField(default=300), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -488,18 +488,38 @@ def update_repo( | |
| ) | ||
| return self.head_ref() | ||
|
|
||
| @override | ||
| def maintenance(self) -> None: | ||
| """Delete leftover `lando-<timestamp>` work branches. | ||
|
|
||
| Each landing creates a fresh work branch in `update_repo`, and they | ||
| accumulate on disk indefinitely. Idle-time cleanup keeps the local | ||
| branch list small without affecting per-job latency. | ||
| """ | ||
| branches = self._git_run( | ||
| "for-each-ref", | ||
| "--format=%(refname:short)", | ||
| "refs/heads/lando-*", | ||
| cwd=self.path, | ||
| ).splitlines() | ||
| if not branches: | ||
| return | ||
|
|
||
| # `git branch -D` refuses to delete the currently checked-out branch, | ||
| # so move off any `lando-*` branch first. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting bit here. In the future it might make more sense to ensure we are back on the default branch after a job is finished. |
||
| if self.get_current_branch().startswith("lando-"): | ||
|
cgsheeh marked this conversation as resolved.
Outdated
|
||
| self._git_run("checkout", "--force", self.default_branch, cwd=self.path) | ||
|
|
||
| self._git_run("branch", "-D", *branches, cwd=self.path) | ||
|
cgsheeh marked this conversation as resolved.
Outdated
|
||
|
|
||
| @override | ||
| def clean_repo( | ||
| self, | ||
| *, | ||
| strip_non_public_commits: bool = True, | ||
| attributes_override: str | None = None, | ||
| ): | ||
| """Reset the local repository to the origin""" | ||
| if strip_non_public_commits: | ||
| self._git_run( | ||
| "reset", "--hard", f"origin/{self.default_branch}", cwd=self.path | ||
| ) | ||
| self._git_run("reset", "--hard", f"origin/{self.default_branch}", cwd=self.path) | ||
|
cgsheeh marked this conversation as resolved.
|
||
|
|
||
| # We need to differentiate between None and "" here, so we know when we were | ||
| # explicitly given an empty string. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.