Skip to content

Commit c6d8074

Browse files
committed
feat: update demo handling to create new feature branches when targeting template feature branches
1 parent 0aece59 commit c6d8074

File tree

4 files changed

+61
-24
lines changed

4 files changed

+61
-24
lines changed

scripts/lint-from-demo.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import typer
1818
from retrocookie.core import retrocookie
1919

20+
from util import DEMO
2021
from util import git
2122
from util import FolderOption
2223
from util import in_new_demo
@@ -40,23 +41,22 @@ def lint_from_demo(
4041
no_cache: Annotated[bool, typer.Option("--no-cache", "-n")] = False
4142
) -> None:
4243
"""Runs precommit in a generated project and matches the template to the results."""
43-
develop_branch: str = os.getenv("COOKIECUTTER_ROBUST_PYTHON_DEVELOP_BRANCH", "develop")
4444
with in_new_demo(
4545
demos_cache_folder=demos_cache_folder,
4646
add_rust_extension=add_rust_extension,
4747
no_cache=no_cache
4848
) as demo_path:
49-
require_clean_and_up_to_date_repo()
50-
git("checkout", develop_branch)
49+
require_clean_and_up_to_date_repo(demo_path=demo_path)
50+
git("checkout", DEMO.develop_branch)
5151
git("branch", "-D", "temp/lint-from-demo", ignore_error=True)
52-
git("checkout", "-b", "temp/lint-from-demo", develop_branch)
52+
git("checkout", "-b", "temp/lint-from-demo", DEMO.develop_branch)
5353
pre_commit.main.main(["run", "--all-files", "--show-diff-on-failure"])
5454

5555
for path in IGNORED_FILES:
5656
git("checkout", "HEAD", "--", path)
5757
git("add", ".")
5858
git("commit", "-m", "meta: lint-from-demo", "--no-verify")
59-
retrocookie(instance_path=demo_path, commits=[f"{develop_branch}..temp/lint-from-demo"])
59+
retrocookie(instance_path=demo_path, commits=[f"{DEMO.develop_branch}..temp/lint-from-demo"])
6060

6161

6262
if __name__ == '__main__':

scripts/release-demo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def release_demo(
4040
demo_path: Path = demos_cache_folder / demo_name
4141

4242
with work_in(demo_path):
43-
require_clean_and_up_to_date_repo()
43+
require_clean_and_up_to_date_repo(demo_path)
4444
git("checkout", DEMO.develop_branch)
4545
try:
4646
nox("setup-release", "--", "MINOR")

scripts/update-demo.py

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@
1010

1111
import sys
1212
from pathlib import Path
13+
from subprocess import CompletedProcess
1314
from typing import Annotated
15+
from typing import Optional
1416

1517
import cruft
1618
import typer
1719
from cookiecutter.utils import work_in
1820

21+
from scripts.util import TEMPLATE
22+
from util import DEMO
1923
from util import is_ancestor
2024
from util import get_current_branch
2125
from util import get_current_commit
@@ -46,9 +50,10 @@ def update_demo(
4650
current_branch: str = get_current_branch()
4751
template_commit: str = get_current_commit()
4852

49-
_validate_is_feature_branch(branch=current_branch)
50-
_set_demo_to_clean_develop(demo_path=demo_path)
51-
last_update_commit: str = _get_last_demo_develop_cruft_update(demo_path=demo_path)
53+
_validate_template_main_not_checked_out(branch=current_branch)
54+
require_clean_and_up_to_date_repo(demo_path=demo_path)
55+
_checkout_demo_develop_or_existing_branch(demo_path=demo_path, branch=current_branch)
56+
last_update_commit: str = get_last_cruft_update_commit(demo_path=demo_path)
5257

5358
if not is_ancestor(last_update_commit, template_commit):
5459
raise ValueError(
@@ -83,23 +88,53 @@ def update_demo(
8388
sys.exit(1)
8489

8590

86-
def _set_demo_to_clean_develop(demo_path: Path) -> None:
87-
"""Checks out the demo development branch and validates it is up to date."""
91+
def _checkout_demo_develop_or_existing_branch(demo_path: Path, branch: str) -> None:
92+
"""Checkout either develop or an existing demo branch."""
8893
with work_in(demo_path):
89-
require_clean_and_up_to_date_repo()
94+
if __has_existing_local_demo_branch(demo_path=demo_path, branch=branch):
95+
typer.secho(f"Local demo found, updating demo from base {branch}")
96+
git("checkout", branch)
97+
return
98+
99+
if __has_existing_remote_demo_branch(demo_path=demo_path, branch=branch):
100+
remote_branch: str = f"{DEMO.remote}/{branch}"
101+
typer.secho(f"Remote demo found, updating demo from base {remote_branch}")
102+
git("checkout", "-b", branch, remote_branch)
103+
return
104+
90105
git("checkout", "develop")
91106

92107

93-
def _get_last_demo_develop_cruft_update(demo_path: Path) -> str:
94-
"""Gets the last cruft update commit for the demo project's develop branch."""
95-
last_update_commit: str = get_last_cruft_update_commit(demo_path=demo_path)
96-
return last_update_commit
108+
def __has_existing_local_demo_branch(demo_path: Path, branch: str) -> bool:
109+
"""Returns whether a local branch has been made for the given branch."""
110+
with work_in(demo_path):
111+
local_result: Optional[CompletedProcess] = git("branch", "--list", branch, text=True)
112+
return local_result is not None and branch in local_result.stdout
113+
114+
115+
def __has_existing_remote_demo_branch(demo_path: Path, branch: str) -> bool:
116+
"""Returns whether a remote branch has been made for the given branch."""
117+
with work_in(demo_path):
118+
remote_result: Optional[CompletedProcess] = git("ls-remote", DEMO.remote, branch, text=True)
119+
return remote_result is not None and branch in remote_result.stdout
120+
121+
122+
def _set_demo_to_clean_branch(demo_path: Path, branch: str) -> None:
123+
"""Checks out the demo branch and validates it is up to date."""
124+
with work_in(demo_path):
125+
git("checkout", "develop")
126+
97127

128+
def _validate_template_main_not_checked_out(branch: str) -> None:
129+
"""Validates that the cookiecutter isn't currently on main.
98130
99-
def _validate_is_feature_branch(branch: str) -> None:
100-
"""Validates that the cookiecutter has a feature branch checked out."""
101-
if not branch.startswith("feature/"):
102-
raise ValueError(f"Received branch '{branch}' is not a feature branch.")
131+
We allow direct develop commits (although avoid it usually), but never direct main. This may change later if the
132+
template moves to a trunk based structure, but for now options are being kept open due to the possibility of a
133+
package release handling demo creation one day.
134+
"""
135+
main_like_names: list[str] = ["main", "master"]
136+
if branch == TEMPLATE.main_branch or branch in main_like_names:
137+
raise ValueError(f"Updating demos directly to main is not allowed currently.")
103138

104139

105140
if __name__ == '__main__':

scripts/util.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,13 @@ def run_command(command: str, *args: str, ignore_error: bool = False) -> Optiona
127127
gh: partial[subprocess.CompletedProcess] = partial(run_command, "gh")
128128

129129

130-
def require_clean_and_up_to_date_repo() -> None:
130+
def require_clean_and_up_to_date_repo(demo_path: Path) -> None:
131131
"""Checks if the repo is clean and up to date with any important branches."""
132-
git("fetch")
133-
git("status", "--porcelain")
134-
validate_is_synced_ancestor(ancestor=DEMO.main_branch, descendent=DEMO.develop_branch)
132+
with work_in(demo_path):
133+
git("fetch")
134+
git("status", "--porcelain")
135+
validate_is_synced_ancestor(ancestor=DEMO.main_branch, descendent=DEMO.develop_branch)
136+
typer.secho
135137

136138

137139
def validate_is_synced_ancestor(ancestor: str, descendent: str) -> None:

0 commit comments

Comments
 (0)