Skip to content

Commit 29cfbeb

Browse files
committed
test: update github integration tests
based on the last large refactor that involved changing up the data model
1 parent efd09af commit 29cfbeb

File tree

5 files changed

+62
-74
lines changed

5 files changed

+62
-74
lines changed

django/library/metadata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def _common_codebase_fields(cls, codebase) -> dict:
142142
name=codebase.title,
143143
codeRepository=(
144144
codebase.git_remotes.first().url
145-
if codebase.git_remotes.first()
145+
if codebase.pk and codebase.git_remotes.first()
146146
else codebase.repository_url
147147
)
148148
or None,

django/library/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,8 @@ def _get_unique_contributors(self, release_contributors):
12451245
"""
12461246
Returns a unique, unordered set of Contributor objects given an initial filtered set of ReleaseContributors for this Codebase.
12471247
"""
1248+
if not self.pk:
1249+
return Contributor.objects.none()
12481250
return Contributor.objects.filter(
12491251
id__in=release_contributors.for_codebase(self).values("contributor_id")
12501252
)
@@ -1449,6 +1451,7 @@ def create_release_from_source(self, source_release, release_metadata):
14491451
# see https://docs.djangoproject.com/en/4.2/topics/db/queries/#copying-model-instances
14501452
source_release.id = None
14511453
source_release.imported_release_sync_state = None
1454+
source_release.git_ref_sync_state = None
14521455
source_release._state.adding = True
14531456
source_release.__dict__.update(**release_metadata)
14541457
source_release.save()

django/library/tests/test_fs.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
CodebaseGitRepositoryApi,
1919
)
2020
from library.tests.base import CodebaseFactory, TEST_SAMPLES_DIR
21-
from library.models import License
21+
from library.models import License, GitRefSyncState
2222

2323

2424
import logging
@@ -102,7 +102,6 @@ def setUp(self):
102102
self.codebase_factory = CodebaseFactory(submitter=self.submitter)
103103
self.codebase = self.codebase_factory.create()
104104
self.release_1 = self.codebase.create_release()
105-
self.git_mirror = self.codebase.create_git_mirror()
106105

107106
def tearDown(self):
108107
clear_test_shared_folder(settings.REPOSITORY_ROOT)
@@ -116,9 +115,11 @@ def test_repo_build(self):
116115
self.assertEqual(public_release_count, 1)
117116
api = CodebaseGitRepositoryApi(self.codebase)
118117
api.build()
119-
# check that the mirror model is updated and the repo is built
120-
self.assertIsNotNone(self.git_mirror.last_modified)
121-
self.assertEqual(self.git_mirror.built_releases.count(), 1)
118+
# check that the git ref sync states are created and the repo is built
119+
built_releases_count = GitRefSyncState.objects.filter(
120+
release__codebase=self.codebase, built_commit_sha__isnull=False
121+
).count()
122+
self.assertEqual(built_releases_count, 1)
122123
self.assertTrue(os.path.exists(api.repo_dir))
123124
# check git stuff
124125
repo = Repo(api.repo_dir)
@@ -153,7 +154,10 @@ def test_repo_append_releases(self):
153154
self.release_2.publish()
154155
api.append_releases()
155156

156-
self.assertEqual(self.git_mirror.built_releases.count(), 2)
157+
built_releases_count = GitRefSyncState.objects.filter(
158+
release__codebase=self.codebase, built_commit_sha__isnull=False
159+
).count()
160+
self.assertEqual(built_releases_count, 2)
157161
# check git stuff
158162
repo = Repo(api.repo_dir)
159163
self.assertFalse(repo.is_dirty())
@@ -204,7 +208,10 @@ def test_repo_rebuild(self):
204208
self.release_2.publish()
205209
api.build()
206210

207-
self.assertEqual(self.git_mirror.built_releases.count(), 2)
211+
built_releases_count = GitRefSyncState.objects.filter(
212+
release__codebase=self.codebase, built_commit_sha__isnull=False
213+
).count()
214+
self.assertEqual(built_releases_count, 2)
208215
# check git stuff
209216
repo = Repo(api.repo_dir)
210217
self.assertFalse(repo.is_dirty())

django/library/tests/test_github_integration.py

Lines changed: 43 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
CodebaseGitRemote,
1111
GithubIntegrationAppInstallation,
1212
CodebaseRelease,
13+
ImportedReleaseSyncState,
1314
)
1415
from library.tests.base import CodebaseFactory
1516

@@ -77,62 +78,65 @@ def setUp(self):
7778
github_user_id=123,
7879
)
7980
self.codebase = CodebaseFactory(submitter=self.user).create()
80-
mirror = self.codebase.create_git_mirror()
8181
self.remote = CodebaseGitRemote.objects.create(
82-
mirror=mirror,
82+
codebase=self.codebase,
8383
owner="testuser",
8484
repo_name="test-repo",
8585
is_user_repo=True,
86+
is_active=True,
8687
)
8788
self.payload = SAMPLE_PAYLOAD.copy()
89+
# create sync state from payload
90+
self.sync_state = ImportedReleaseSyncState.for_github_release(
91+
self.remote, self.payload["release"]
92+
)
8893

8994
def test_init_success(self):
90-
# should initialize successfully with a valid payload
91-
importer = GitHubReleaseImporter(self.payload)
95+
# should initialize successfully with a valid remote and release id
96+
importer = GitHubReleaseImporter(self.remote, "12345")
9297
self.assertEqual(importer.github_release_id, "12345")
9398
self.assertEqual(importer.codebase, self.codebase)
94-
self.assertTrue(importer.is_new_github_release)
9599

96100
def test_init_failures(self):
97-
# test various invalid payloads that should raise ValueError
98-
test_cases = {
99-
"draft": ("release", "draft", True),
100-
"prerelease": ("release", "prerelease", True),
101-
"private": ("repository", "private", True),
102-
"wrong_action": ("action", None, "created"),
103-
"no_remote": ("repository", "name", "non-existent-repo"),
104-
}
105-
for name, (key1, key2, value) in test_cases.items():
106-
with self.subTest(name=name):
107-
bad_payload = self.payload.copy()
108-
if key2:
109-
bad_payload[key1] = bad_payload[key1].copy()
110-
bad_payload[key1][key2] = value
111-
else:
112-
bad_payload[key1] = value
113-
with self.assertRaises(ValueError):
114-
GitHubReleaseImporter(bad_payload)
101+
# test various invalid scenarios that should raise ValueError
102+
# missing sync state
103+
with self.assertRaises(ValueError):
104+
GitHubReleaseImporter(self.remote, "99999")
105+
106+
# sync state without download_url
107+
bad_sync_state = ImportedReleaseSyncState.objects.create(
108+
remote=self.remote,
109+
github_release_id="88888",
110+
download_url="", # empty download url
111+
)
112+
with self.assertRaises(ValueError):
113+
GitHubReleaseImporter(self.remote, "88888")
115114

116115
def test_extract_semver(self):
117116
# test semantic version extraction
118-
importer = GitHubReleaseImporter(self.payload)
117+
importer = GitHubReleaseImporter(self.remote, "12345")
119118
self.assertEqual(importer.extract_semver("v1.2.3"), "1.2.3")
120119
self.assertEqual(importer.extract_semver("1.2.3"), "1.2.3")
121120
self.assertEqual(importer.extract_semver("version 1.2.3-beta"), "1.2.3")
122121
self.assertIsNone(importer.extract_semver("1.2"))
123122
self.assertIsNone(importer.extract_semver("invalid-version"))
124123

124+
@patch("library.github_integration.GitHubApi.get_repo_raw_for_remote")
125125
@patch("library.models.CodebaseRelease.get_fs_api")
126126
@patch("library.github_integration.GitHubApi.get_user_installation_access_token")
127-
def test_import_new_release(self, mock_get_token, mock_get_fs_api):
127+
def test_import_new_release(self, mock_get_token, mock_get_fs_api, mock_get_repo):
128128
# mock token and fs_api calls
129129
mock_get_token.return_value = "fake-token"
130+
mock_get_repo.return_value = {"name": "test-repo", "full_name": "testuser/test-repo"}
130131
mock_fs_api = MagicMock()
131132
mock_fs_api.import_release_package.return_value = ({}, {}) # codemeta, cff
132133
mock_get_fs_api.return_value = mock_fs_api
133134

135+
# create sync state first
136+
ImportedReleaseSyncState.for_github_release(self.remote, self.payload["release"])
137+
134138
# import a new release
135-
importer = GitHubReleaseImporter(self.payload)
139+
importer = GitHubReleaseImporter(self.remote, "12345")
136140
success = importer.import_new_release()
137141

138142
# check that it was successful and objects were created
@@ -147,17 +151,25 @@ def test_import_new_release(self, mock_get_token, mock_get_fs_api):
147151
self.assertEqual(release.submitter, self.codebase.submitter)
148152
mock_fs_api.import_release_package.assert_called_once()
149153

154+
@patch("library.github_integration.GitHubApi.get_release_raw_for_remote")
155+
@patch("library.github_integration.GitHubApi.get_repo_raw_for_remote")
150156
@patch("library.models.CodebaseRelease.get_fs_api")
151157
@patch("library.github_integration.GitHubApi.get_user_installation_access_token")
152-
def test_reimport_release(self, mock_get_token, mock_get_fs_api):
158+
def test_reimport_release(self, mock_get_token, mock_get_fs_api, mock_get_repo, mock_get_release):
153159
# mock token and fs_api calls
154160
mock_get_token.return_value = "fake-token"
161+
mock_get_repo.return_value = {"name": "test-repo", "full_name": "testuser/test-repo"}
155162
mock_fs_api = MagicMock()
156163
mock_fs_api.import_release_package.return_value = ({}, {}) # codemeta, cff
157164
mock_get_fs_api.return_value = mock_fs_api
158165

166+
# create sync state first
167+
sync_state = ImportedReleaseSyncState.for_github_release(
168+
self.remote, self.payload["release"]
169+
)
170+
159171
# first, import a new release
160-
importer = GitHubReleaseImporter(self.payload)
172+
importer = GitHubReleaseImporter(self.remote, "12345")
161173
importer.import_or_reimport()
162174

163175
self.assertEqual(CodebaseRelease.objects.count(), 1)
@@ -175,8 +187,10 @@ def test_reimport_release(self, mock_get_token, mock_get_fs_api):
175187
"https://api.github.com/repos/testuser/test-repo/zipball/v1.0.0-updated"
176188
)
177189
reimport_payload["release"]["zipball_url"] = new_url
190+
# mock get_release_raw_for_remote to return the updated payload
191+
mock_get_release.return_value = reimport_payload["release"]
178192

179-
importer2 = GitHubReleaseImporter(reimport_payload)
193+
importer2 = GitHubReleaseImporter(self.remote, "12345")
180194
success = importer2.import_or_reimport()
181195

182196
# assert that the re-import was successful and the release was updated
@@ -191,40 +205,4 @@ def test_reimport_release(self, mock_get_token, mock_get_fs_api):
191205
# release version number should NOT have changed
192206
self.assertEqual(release.version_number, "1.0.0")
193207

194-
# re-importing with no change does nothing
195-
importer3 = GitHubReleaseImporter(reimport_payload)
196-
success_no_change = importer3.import_or_reimport()
197-
self.assertFalse(success_no_change)
198-
# should still be 2, not called again
199-
self.assertEqual(mock_fs_api.import_release_package.call_count, 2)
200-
201-
# re-importing a published release does nothing
202-
release.status = CodebaseRelease.Status.PUBLISHED
203-
release.save()
204-
published_reimport_payload = reimport_payload.copy()
205-
published_reimport_payload["release"][
206-
"zipball_url"
207-
] = "https://another.url/zipball.zip"
208-
importer4 = GitHubReleaseImporter(published_reimport_payload)
209-
success_published = importer4.import_or_reimport()
210-
self.assertFalse(success_published)
211-
# fs_api should not be called again
212-
self.assertEqual(mock_fs_api.import_release_package.call_count, 2)
213-
self.remote.refresh_from_db()
214208

215-
# re-importing an under_review release should work
216-
release.status = CodebaseRelease.Status.UNDER_REVIEW
217-
release.save()
218-
review_reimport_payload = self.payload.copy()
219-
review_reimport_payload["action"] = "edited"
220-
review_reimport_payload["release"] = review_reimport_payload["release"].copy()
221-
review_url = (
222-
"https://api.github.com/repos/testuser/test-repo/zipball/v1.0.0-review"
223-
)
224-
review_reimport_payload["release"]["zipball_url"] = review_url
225-
importer5 = GitHubReleaseImporter(review_reimport_payload)
226-
success_review = importer5.import_or_reimport()
227-
self.assertTrue(success_review)
228-
self.assertEqual(mock_fs_api.import_release_package.call_count, 3)
229-
release.refresh_from_db()
230-
self.assertEqual(release.imported_release_sync_state.download_url, review_url)

django/library/tests/test_views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ def test_installation_webhook_no_matching_social_account(self):
788788
}
789789
request = self._create_signed_request(payload)
790790
response = github_sync_webhook(request)
791-
self.assertEqual(response.status_code, 202)
791+
self.assertEqual(response.status_code, 404)
792792
self.assertEqual(GithubIntegrationAppInstallation.objects.count(), 0)
793793

794794
@override_settings(GITHUB_INTEGRATION_APP_WEBHOOK_SECRET="test-secret")

0 commit comments

Comments
 (0)