2929 fetch-depth : 0
3030 token : ${{ steps.create_token.outputs.token }}
3131
32+ - name : Install uv
33+ uses : astral-sh/setup-uv@v4
34+
3235 - name : Attempt merge and push, or open PR on conflict
3336 env :
3437 GH_TOKEN : ${{ steps.create_token.outputs.token }}
3740 git config user.name "github-actions[bot]"
3841 git config user.email "github-actions[bot]@users.noreply.github.com"
3942
40- git checkout "$BRANCH"
41-
42- if git merge origin/main --no-edit; then
43- echo "Merge succeeded, pushing to $BRANCH"
44- git push origin "$BRANCH"
45- else
46- echo "Merge conflict detected, opening PR"
47- git merge --abort
48-
49- # Create a temporary branch for the PR
43+ open_propagation_pr() {
5044 TEMP_BRANCH="auto-merge/main-to-${BRANCH}-$(date +%Y%m%d%H%M%S)"
5145 git checkout -b "$TEMP_BRANCH" origin/main
5246
@@ -64,4 +58,120 @@ jobs:
6458 🤖 Generated by the propagate workflow
6559 PREOF
6660 )"
61+ }
62+
63+ unresolved_conflicts() {
64+ git diff --name-only --diff-filter=U | sort
65+ }
66+
67+ conflicts_are_modal_overlay() {
68+ [ "$BRANCH" = "modal" ] || return 1
69+
70+ conflicts="$(unresolved_conflicts)"
71+ [ -n "$conflicts" ] || return 1
72+
73+ while IFS= read -r file; do
74+ case "$file" in
75+ pyproject.toml|uv.lock) ;;
76+ *) return 1 ;;
77+ esac
78+ done <<< "$conflicts"
79+ }
80+
81+ add_modal_dependency() {
82+ python3 <<'PY'
83+ from pathlib import Path
84+ import subprocess
85+ import tomllib
86+
87+ def is_modal_dependency(dependency: str) -> bool:
88+ return dependency.split(";", 1)[0].strip().lower().startswith("modal")
89+
90+
91+ def modal_dependency_from_branch() -> str:
92+ try:
93+ result = subprocess.run(
94+ ["git", "show", ":2:pyproject.toml"],
95+ check=True,
96+ capture_output=True,
97+ text=True,
98+ )
99+ except subprocess.CalledProcessError:
100+ return "modal>=0.73.162"
101+
102+ dependencies = tomllib.loads(result.stdout).get("project", {}).get("dependencies", [])
103+ return next((dependency for dependency in dependencies if is_modal_dependency(dependency)), "modal>=0.73.162")
104+
105+
106+ path = Path("pyproject.toml")
107+ text = path.read_text()
108+ data = tomllib.loads(text)
109+
110+ dependencies = data.get("project", {}).get("dependencies", [])
111+ if any(is_modal_dependency(dependency) for dependency in dependencies):
112+ raise SystemExit(0)
113+
114+ lines = text.splitlines()
115+ start = next(
116+ (index for index, line in enumerate(lines) if line.strip() == "dependencies = ["),
117+ None,
118+ )
119+ if start is None:
120+ raise SystemExit("Could not find project dependencies in pyproject.toml")
121+
122+ end = next(
123+ (index for index in range(start + 1, len(lines)) if lines[index].strip() == "]"),
124+ None,
125+ )
126+ if end is None:
127+ raise SystemExit("Could not find end of project dependencies in pyproject.toml")
128+
129+ insert_at = end
130+ for index in range(start + 1, end):
131+ if lines[index].strip().startswith('"psycopg2-binary'):
132+ insert_at = index
133+ break
134+
135+ lines.insert(insert_at, f' "{modal_dependency_from_branch()}",')
136+ path.write_text("\n".join(lines) + "\n")
137+ PY
138+ }
139+
140+ resolve_modal_overlay() {
141+ if unresolved_conflicts | grep -qx "pyproject.toml"; then
142+ git checkout --theirs pyproject.toml
143+ fi
144+
145+ add_modal_dependency
146+
147+ if unresolved_conflicts | grep -qx "uv.lock"; then
148+ git checkout --ours uv.lock
149+ fi
150+
151+ uv lock
152+ git add pyproject.toml uv.lock
153+
154+ remaining_conflicts="$(unresolved_conflicts)"
155+ if [ -n "$remaining_conflicts" ]; then
156+ echo "Conflicts remain after modal overlay resolution:"
157+ echo "$remaining_conflicts"
158+ return 1
159+ fi
160+
161+ git commit --no-edit
162+ git push origin "$BRANCH"
163+ }
164+
165+ git checkout "$BRANCH"
166+
167+ if git merge origin/main --no-edit; then
168+ echo "Merge succeeded, pushing to $BRANCH"
169+ git push origin "$BRANCH"
170+ elif conflicts_are_modal_overlay; then
171+ echo "Merge conflict only affects the modal dependency overlay; resolving automatically"
172+ resolve_modal_overlay
173+ else
174+ echo "Merge conflict detected, opening PR"
175+ git merge --abort
176+ open_propagation_pr
67177 fi
0 commit comments