Skip to content

Commit 0b94084

Browse files
authored
fix: always add branch in gh pages changes (#450)
* fix: always add branch in gh pages changes applying changes to gh pages always requires the source branch in the payload. this change make sure that source branch is always added Signed-off-by: Kairo Araujo <kairo@dearaujo.nl> * fixup! fix: always add branch in gh pages changes Signed-off-by: Kairo Araujo <kairo@dearaujo.nl> * test: add full coverage for new function Signed-off-by: Kairo Araujo <kairo@dearaujo.nl> --------- Signed-off-by: Kairo Araujo <kairo@dearaujo.nl>
1 parent 66d8a7a commit 0b94084

6 files changed

Lines changed: 142 additions & 48 deletions

File tree

otterdog/models/repository.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,13 +1050,6 @@ def generate_live_patch(
10501050
web_commit_signoff_required, web_commit_signoff_required
10511051
)
10521052

1053-
# FIXME: needed to add this hack to ensure that gh_pages_source_path is also present in
1054-
# the modified data as GitHub needs the path as well when the branch is changed.
1055-
# this needs to make clean to support making the diff operation generic as possible.
1056-
if "gh_pages_source_branch" in modified_repo:
1057-
gh_pages_source_path = cast(Repository, coerced_object).gh_pages_source_path
1058-
modified_repo["gh_pages_source_path"] = Change(gh_pages_source_path, gh_pages_source_path)
1059-
10601053
# similar fix as above for squash_merge_commit_title and squash_merge_commit_message as well
10611054
squash_merge_commit_title_present = "squash_merge_commit_title" in modified_repo
10621055
squash_merge_commit_message_present = "squash_merge_commit_message" in modified_repo
@@ -1156,6 +1149,26 @@ def generate_live_patch(
11561149
handler,
11571150
)
11581151

1152+
@staticmethod
1153+
def _include_gh_pages_patch_required_properties(patch: LivePatch[Repository]) -> LivePatch[Repository]:
1154+
"""
1155+
Ensure that the gh_pages_source_branch and gh_pages_source_path are set when
1156+
the patch contains gh_pages change.
1157+
"""
1158+
if patch.changes:
1159+
gh_pages_source_branch_present = "gh_pages_source_branch" in patch.changes
1160+
gh_pages_source_path_present = "gh_pages_source_path" in patch.changes
1161+
1162+
if gh_pages_source_path_present and not gh_pages_source_branch_present:
1163+
gh_pages_source_branch = cast(Repository, patch.current_object).gh_pages_source_branch
1164+
patch.changes["gh_pages_source_branch"] = Change(gh_pages_source_branch, gh_pages_source_branch)
1165+
1166+
if gh_pages_source_branch_present and not gh_pages_source_path_present:
1167+
gh_pages_source_path = cast(Repository, patch.current_object).gh_pages_source_path
1168+
patch.changes["gh_pages_source_path"] = Change(gh_pages_source_path, gh_pages_source_path)
1169+
1170+
return patch
1171+
11591172
@classmethod
11601173
async def apply_live_patch(
11611174
cls,
@@ -1188,6 +1201,7 @@ async def apply_live_patch(
11881201
await provider.delete_repo(org_id, unwrap(patch.current_object).name)
11891202

11901203
case LivePatchType.CHANGE:
1204+
cls._include_gh_pages_patch_required_properties(patch)
11911205
expected_object = unwrap(patch.expected_object)
11921206
github_settings = await cls.changes_to_provider(org_id, unwrap(patch.changes), provider)
11931207

poetry.lock

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pytest = ">=8.0"
112112
pytest-asyncio = ">=0.24"
113113
parameterized = ">=0.9"
114114
pytest-cov = ">=6.1.1"
115+
pretend = "^1.0.9"
115116

116117
[tool.poetry.group.typing.dependencies]
117118
mypy = ">=1.8.0"

tests/conftest.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from collections.abc import Mapping
2+
from typing import Any
3+
4+
import pytest
5+
6+
from otterdog.jsonnet import JsonnetConfig
7+
from otterdog.models import ModelObject
8+
from otterdog.models.repository import Repository
9+
from tests.models import ModelTest
10+
11+
12+
@pytest.fixture()
13+
def repository_test():
14+
class RepositoryTest(ModelTest):
15+
def create_model(self, data: Mapping[str, Any]) -> ModelObject:
16+
return Repository.from_model_data(data)
17+
18+
@property
19+
def template_function(self) -> str:
20+
return JsonnetConfig.create_repo
21+
22+
@property
23+
def model_data(self):
24+
return self.load_json_resource("otterdog-repo.json")
25+
26+
@property
27+
def provider_data(self):
28+
return self.load_json_resource("github-repo.json")
29+
30+
return RepositoryTest()

tests/models/resources/otterdog-repo.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@
2222
"allow_auto_merge": false,
2323
"merge_commit_message": "PR_TITLE",
2424
"secret_scanning": "enabled",
25-
"dependabot_alerts_enabled": true
25+
"dependabot_alerts_enabled": true,
26+
"gh_pages_source_path": "/",
27+
"gh_pages_source_branch": "gh-pages"
2628
}

tests/models/test_repository.py

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,16 @@
66
# SPDX-License-Identifier: EPL-2.0
77
# *******************************************************************************
88

9-
from collections.abc import Mapping
10-
from typing import Any
9+
import pretend
10+
import pytest
1111

12-
from otterdog.jsonnet import JsonnetConfig
13-
from otterdog.models import ModelObject
14-
from otterdog.models.repository import Repository
12+
from otterdog.models.repository import LivePatch, Repository
1513
from otterdog.utils import UNSET, Change, query_json
1614

17-
from . import ModelTest
1815

19-
20-
class RepositoryTest(ModelTest):
21-
def create_model(self, data: Mapping[str, Any]) -> ModelObject:
22-
return Repository.from_model_data(data)
23-
24-
@property
25-
def template_function(self) -> str:
26-
return JsonnetConfig.create_repo
27-
28-
@property
29-
def model_data(self):
30-
return self.load_json_resource("otterdog-repo.json")
31-
32-
@property
33-
def provider_data(self):
34-
return self.load_json_resource("github-repo.json")
35-
36-
def test_load_from_model(self):
37-
repo = Repository.from_model_data(self.model_data)
16+
class TestRepository:
17+
def test_load_from_model(self, repository_test):
18+
repo = Repository.from_model_data(repository_test.model_data)
3819

3920
assert repo.name == "otterdog-defaults"
4021
assert repo.description is None
@@ -65,8 +46,8 @@ def test_load_from_model(self):
6546
assert repo.post_process_template_content == []
6647
assert repo.auto_init is False
6748

68-
def test_load_from_provider(self):
69-
repo = Repository.from_provider_data(self.org_id, self.provider_data)
49+
def test_load_from_provider(self, repository_test):
50+
repo = Repository.from_provider_data(repository_test.org_id, repository_test.provider_data)
7051

7152
assert repo.id == 605555050
7253
assert repo.node_id == "R_kgDOJBgJag"
@@ -95,22 +76,22 @@ def test_load_from_provider(self):
9576
assert repo.secret_scanning_push_protection == "disabled"
9677
assert repo.dependabot_alerts_enabled is True
9778

98-
async def test_to_provider(self):
99-
repo = Repository.from_model_data(self.model_data)
79+
async def test_to_provider(self, repository_test):
80+
repo = Repository.from_model_data(repository_test.model_data)
10081

10182
repo.description = UNSET
10283

103-
provider_data = await repo.to_provider_data(self.org_id, self.provider)
84+
provider_data = await repo.to_provider_data(repository_test.org_id, repository_test.provider)
10485

10586
assert len(provider_data) == 22
10687
assert provider_data["name"] == "otterdog-defaults"
10788
assert provider_data.get("description") is None
10889

10990
assert query_json("security_and_analysis.secret_scanning.status", provider_data) or "" == "enabled"
11091

111-
async def test_changes_to_provider(self):
112-
current = Repository.from_model_data(self.model_data)
113-
other = Repository.from_model_data(self.model_data)
92+
async def test_changes_to_provider(self, repository_test):
93+
current = Repository.from_model_data(repository_test.model_data)
94+
other = Repository.from_model_data(repository_test.model_data)
11495

11596
other.name = "other"
11697
other.has_wiki = False
@@ -124,10 +105,10 @@ async def test_changes_to_provider(self):
124105
assert provider_data["has_wiki"] is True
125106
assert query_json("security_and_analysis.secret_scanning.status", provider_data) or "" == "enabled"
126107

127-
def test_patch(self):
128-
current = Repository.from_model_data(self.model_data)
108+
def test_patch(self, repository_test):
109+
current = Repository.from_model_data(repository_test.model_data)
129110

130-
default = Repository.from_model_data(self.model_data)
111+
default = Repository.from_model_data(repository_test.model_data)
131112

132113
default.name = None
133114
default.web_commit_signoff_required = True
@@ -138,9 +119,9 @@ def test_patch(self):
138119
assert patch["name"] == current.name
139120
assert patch["web_commit_signoff_required"] is current.web_commit_signoff_required
140121

141-
def test_difference(self):
142-
current = Repository.from_model_data(self.model_data)
143-
other = Repository.from_model_data(self.model_data)
122+
def test_difference(self, repository_test):
123+
current = Repository.from_model_data(repository_test.model_data)
124+
other = Repository.from_model_data(repository_test.model_data)
144125

145126
other.name = "other"
146127
other.has_wiki = False
@@ -150,3 +131,57 @@ def test_difference(self):
150131
assert len(diff) == 2
151132
assert diff["name"] == Change(other.name, current.name)
152133
assert diff["has_wiki"] == Change(other.has_wiki, current.has_wiki)
134+
135+
@pytest.mark.parametrize(
136+
"gh_pages_source_path, gh_pages_source_branch, expected_changes",
137+
[
138+
(
139+
"/docs",
140+
None,
141+
{
142+
"gh_pages_source_path": Change("/", "/docs"),
143+
"gh_pages_source_branch": Change("gh-pages", "gh-pages"),
144+
},
145+
),
146+
(
147+
None,
148+
"main",
149+
{"gh_pages_source_branch": Change("gh-pages", "main"), "gh_pages_source_path": Change("/", "/")},
150+
),
151+
(None, None, {}),
152+
(
153+
"/docs",
154+
"main",
155+
{"gh_pages_source_path": Change("/", "/docs"), "gh_pages_source_branch": Change("gh-pages", "main")},
156+
),
157+
],
158+
)
159+
def test__include_gh_pages_patch_required_properties(
160+
self, repository_test, gh_pages_source_path, gh_pages_source_branch, expected_changes
161+
):
162+
current = Repository.from_model_data(repository_test.model_data)
163+
default = Repository.from_model_data(repository_test.model_data)
164+
165+
# build changes using parametrization if not none
166+
changes = {}
167+
if gh_pages_source_path is not None:
168+
current.gh_pages_source_path = gh_pages_source_path
169+
changes["gh_pages_source_path"] = Change(default.gh_pages_source_path, gh_pages_source_path)
170+
if gh_pages_source_branch is not None:
171+
current.gh_pages_source_branch = gh_pages_source_branch
172+
changes["gh_pages_source_branch"] = Change(default.gh_pages_source_branch, gh_pages_source_branch)
173+
174+
test_livepatch = LivePatch(
175+
patch_type=3,
176+
expected_object=current,
177+
current_object=default,
178+
changes=changes,
179+
parent_object=None,
180+
forced_update=False,
181+
fn=pretend.stub(),
182+
changes_object_to_readonly=False,
183+
)
184+
# Call the function under test
185+
current._include_gh_pages_patch_required_properties(test_livepatch)
186+
187+
assert test_livepatch.changes == expected_changes

0 commit comments

Comments
 (0)