mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
1302 lines
50 KiB
Python
1302 lines
50 KiB
Python
import unittest
|
|
from datetime import datetime, timedelta, timezone
|
|
from unittest.mock import patch
|
|
|
|
from django.urls import reverse
|
|
|
|
from sentry.api.endpoints.organization_release_details import OrganizationReleaseSerializer
|
|
from sentry.constants import MAX_VERSION_LENGTH
|
|
from sentry.locks import locks
|
|
from sentry.models.activity import Activity
|
|
from sentry.models.environment import Environment
|
|
from sentry.models.files.file import File
|
|
from sentry.models.orgauthtoken import OrgAuthToken
|
|
from sentry.models.release import Release, ReleaseProject, ReleaseStatus
|
|
from sentry.models.releasecommit import ReleaseCommit
|
|
from sentry.models.releasefile import ReleaseFile
|
|
from sentry.models.releaseprojectenvironment import ReleaseProjectEnvironment
|
|
from sentry.models.repository import Repository
|
|
from sentry.silo import SiloMode
|
|
from sentry.testutils.cases import APITestCase
|
|
from sentry.testutils.silo import assume_test_silo_mode, region_silo_test
|
|
from sentry.testutils.skips import requires_snuba
|
|
from sentry.types.activity import ActivityType
|
|
from sentry.utils.security.orgauthtoken_token import generate_token, hash_token
|
|
|
|
pytestmark = [requires_snuba]
|
|
|
|
|
|
@region_silo_test
|
|
class ReleaseDetailsTest(APITestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.user1 = self.create_user(is_staff=False, is_superuser=False)
|
|
|
|
self.organization.flags.allow_joinleave = False
|
|
self.organization.save()
|
|
|
|
self.team1 = self.create_team(organization=self.organization)
|
|
self.project1 = self.create_project(teams=[self.team1], organization=self.organization)
|
|
|
|
def test_simple(self):
|
|
team2 = self.create_team(organization=self.organization)
|
|
|
|
project2 = self.create_project(teams=[team2], organization=self.organization)
|
|
|
|
release = Release.objects.create(organization_id=self.organization.id, version="abcabcabc")
|
|
release2 = Release.objects.create(organization_id=self.organization.id, version="12345678")
|
|
release.add_project(self.project1)
|
|
release2.add_project(project2)
|
|
|
|
environment = Environment.objects.create(organization_id=self.organization.id, name="prod")
|
|
environment.add_project(self.project1)
|
|
environment.add_project(project2)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
ReleaseProject.objects.filter(project=self.project1, release=release).update(new_groups=5)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release.version},
|
|
)
|
|
response = self.client.get(url)
|
|
|
|
assert response.status_code == 200, response.content
|
|
assert response.data["version"] == release.version
|
|
assert response.data["newGroups"] == 5
|
|
|
|
# check for current project meta should be empty if project id is not provided
|
|
assert response.data["currentProjectMeta"] == {}
|
|
|
|
# no access
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release2.version},
|
|
)
|
|
response = self.client.get(url)
|
|
assert response.status_code == 404
|
|
|
|
def test_multiple_projects(self):
|
|
team2 = self.create_team(organization=self.organization)
|
|
|
|
project2 = self.create_project(teams=[team2], organization=self.organization)
|
|
|
|
release = Release.objects.create(organization_id=self.organization.id, version="abcabcabc")
|
|
release.add_project(self.project1)
|
|
release.add_project(project2)
|
|
|
|
self.create_member(
|
|
teams=[self.team1, team2], user=self.user1, organization=self.organization
|
|
)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release.version},
|
|
)
|
|
response = self.client.get(url)
|
|
|
|
assert response.status_code == 200, response.content
|
|
|
|
def test_wrong_project(self):
|
|
project2 = self.create_project(teams=[self.team1], organization=self.organization)
|
|
|
|
release = Release.objects.create(organization_id=self.organization.id, version="abcabcabc")
|
|
release.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release.version},
|
|
)
|
|
|
|
response = self.client.get(url, {"project": project2.id})
|
|
assert response.status_code == 404
|
|
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
|
|
def test_correct_project_contains_current_project_meta(self):
|
|
"""
|
|
Test that shows when correct project id is passed to the request, `sessionsLowerBound`,
|
|
`sessionsUpperBound`, `prevReleaseVersion`, `nextReleaseVersion`, `firstReleaseVersion`
|
|
and `lastReleaseVersion` are present in `currentProjectMeta` key
|
|
"""
|
|
release = Release.objects.create(organization_id=self.organization.id, version="abcabcabc")
|
|
release.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release.version},
|
|
)
|
|
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert "sessionsLowerBound" in response.data["currentProjectMeta"]
|
|
assert "sessionsUpperBound" in response.data["currentProjectMeta"]
|
|
assert "prevReleaseVersion" in response.data["currentProjectMeta"]
|
|
assert "nextReleaseVersion" in response.data["currentProjectMeta"]
|
|
assert "firstReleaseVersion" in response.data["currentProjectMeta"]
|
|
assert "lastReleaseVersion" in response.data["currentProjectMeta"]
|
|
|
|
def test_incorrect_sort_option_should_return_invalid_sort_response(self):
|
|
"""
|
|
Test that ensures a 400 response is returned when an invalid sort option
|
|
is provided
|
|
"""
|
|
release = Release.objects.create(organization_id=self.organization.id, version="abcabcabc")
|
|
release.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "sort": "invalid_sort"})
|
|
assert response.status_code == 400
|
|
|
|
def test_get_prev_and_next_release_to_current_release_on_date_sort(self):
|
|
release_1 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
release_3 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_3.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_2.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] == "[email protected]"
|
|
|
|
# Test for first release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_3.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] is None
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] == "[email protected]"
|
|
|
|
# Test for last release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_1.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] is None
|
|
|
|
def test_get_prev_and_next_release_to_current_release_on_date_sort_with_same_date(self):
|
|
"""
|
|
Test that ensures that in the case we are trying to get prev and next release to a current
|
|
release with exact same date then we fallback to id comparison
|
|
"""
|
|
date_now = datetime.utcnow()
|
|
release_1 = Release.objects.create(
|
|
date_added=date_now, organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = Release.objects.create(
|
|
date_added=date_now, organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_1.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] is None
|
|
|
|
# Test for first release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_2.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] is None
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] == "[email protected]"
|
|
|
|
def test_get_prev_and_next_release_to_current_release_on_date_sort_env_filter_applied(self):
|
|
"""
|
|
Test that ensures that environment filter is applied when fetching prev and next
|
|
releases on date sort order
|
|
"""
|
|
release_1 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
release_3 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_3.add_project(self.project1)
|
|
|
|
environment = Environment.objects.create(organization_id=self.organization.id, name="prod")
|
|
environment.add_project(self.project1)
|
|
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release_3.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release_1.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_3.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "environment": ["prod"]})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] is None
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] == "[email protected]"
|
|
|
|
def test_get_prev_and_next_release_to_current_release_on_date_sort_status_filter_applied(self):
|
|
"""
|
|
Test that ensures that status filter is applied when fetching prev and next
|
|
releases on date sort order
|
|
"""
|
|
release_1 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
release_3 = Release.objects.create(
|
|
organization_id=self.organization.id,
|
|
version="[email protected]",
|
|
status=ReleaseStatus.ARCHIVED,
|
|
)
|
|
release_3.add_project(self.project1)
|
|
|
|
environment = Environment.objects.create(organization_id=self.organization.id, name="prod")
|
|
environment.add_project(self.project1)
|
|
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release_3.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release_1.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_3.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "status": "archived"})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] is None
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] is None
|
|
|
|
def test_get_prev_and_next_release_to_current_release_on_date_sort_query_filter_applied(self):
|
|
"""
|
|
Test that ensures that query filter is applied when fetching prev and next
|
|
releases on date sort order
|
|
"""
|
|
release_1 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
release_3 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_3.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_2.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "query": "foobar@1"})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] is None
|
|
|
|
def test_get_prev_and_next_release_on_date_sort_does_not_apply_stats_period_filter(self):
|
|
"""
|
|
Test that ensures that stats_period filter is applied when fetching prev and next
|
|
releases on date sort order
|
|
"""
|
|
release_1 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = Release.objects.create(
|
|
organization_id=self.organization.id, version="[email protected]"
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
date_added_from_8d = datetime.utcnow() - timedelta(days=8)
|
|
release_3 = Release.objects.create(
|
|
organization_id=self.organization.id,
|
|
version="[email protected]",
|
|
date_added=date_added_from_8d,
|
|
)
|
|
release_3.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_1.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "summaryStatsPeriod": "24h"})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["nextReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["prevReleaseVersion"] == "[email protected]"
|
|
|
|
def test_get_first_and_last_release_on_date_sort(self):
|
|
"""
|
|
Test that ensures that the first release and the last release in terms of `date_added` are
|
|
retrieved correctly
|
|
"""
|
|
release_1 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_2.add_project(self.project1)
|
|
|
|
release_3 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_3.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_1.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["firstReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["lastReleaseVersion"] == "[email protected]"
|
|
|
|
def test_get_first_and_last_release_on_date_sort_with_exact_same_date(self):
|
|
"""
|
|
Test that ensures that the first release and the last release in terms of `date_added` are
|
|
retrieved correctly in the case when all releases have the same exact datetime and we
|
|
need to fallback to comparison with id
|
|
"""
|
|
date_now = datetime.utcnow()
|
|
release_2 = self.create_release(
|
|
project=self.project1, version="[email protected]", date_added=date_now
|
|
)
|
|
release_2.add_project(self.project1)
|
|
|
|
release_1 = self.create_release(
|
|
project=self.project1, version="[email protected]", date_added=date_now
|
|
)
|
|
release_1.add_project(self.project1)
|
|
|
|
release_3 = self.create_release(
|
|
project=self.project1, version="[email protected]", date_added=date_now
|
|
)
|
|
release_3.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_1.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["firstReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["lastReleaseVersion"] == "[email protected]"
|
|
|
|
def test_get_first_and_last_release_on_date_sort_env_filter_applied(self):
|
|
"""
|
|
Test that ensures that environment filter is applied when fetching first and last
|
|
releases on date sort order
|
|
"""
|
|
release_1 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_1.add_project(self.project1)
|
|
|
|
release_2 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_2.add_project(self.project1)
|
|
|
|
release_3 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_3.add_project(self.project1)
|
|
|
|
release_4 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_4.add_project(self.project1)
|
|
|
|
environment = Environment.objects.create(organization_id=self.organization.id, name="prod")
|
|
environment.add_project(self.project1)
|
|
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release_2.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
ReleaseProjectEnvironment.objects.create(
|
|
project_id=self.project1.id,
|
|
release_id=release_3.id,
|
|
environment_id=environment.id,
|
|
new_issues_count=5,
|
|
)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_3.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "environment": ["prod"]})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["firstReleaseVersion"] == "[email protected]"
|
|
assert response.data["currentProjectMeta"]["lastReleaseVersion"] == "[email protected]"
|
|
|
|
def test_get_first_and_last_release_on_non_date_sort(self):
|
|
"""
|
|
Test that ensures that when trying to fetch first and last releases on a sort option that
|
|
is not `date`, then the values of `firstReleaseVersion` and `lastReleaseVersion` are None
|
|
values
|
|
"""
|
|
release_1 = self.create_release(project=self.project1, version="[email protected]")
|
|
release_1.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release_1.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "sort": "sessions"})
|
|
assert response.status_code == 400
|
|
assert response.data["detail"] == "invalid sort"
|
|
|
|
def test_get_first_and_last_release_when_project_has_no_releases(self):
|
|
"""
|
|
Test that ensures that when fetching first and last releases on date sort option in a
|
|
project that contains no matching release for all the filters, then `firstReleaseVersion`
|
|
and `lastReleaseVersion` are None values
|
|
"""
|
|
release = self.create_release(project=self.project1, version="[email protected]")
|
|
release.add_project(self.project1)
|
|
|
|
environment = Environment.objects.create(organization_id=self.organization.id, name="test")
|
|
environment.add_project(self.project1)
|
|
|
|
self.create_member(teams=[self.team1], user=self.user1, organization=self.organization)
|
|
|
|
self.login_as(user=self.user1)
|
|
|
|
# Test for middle release of the list
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release.version},
|
|
)
|
|
response = self.client.get(url, {"project": self.project1.id, "environment": ["test"]})
|
|
assert response.status_code == 200
|
|
assert response.data["currentProjectMeta"]["firstReleaseVersion"] is None
|
|
assert response.data["currentProjectMeta"]["lastReleaseVersion"] is None
|
|
|
|
def test_with_adoption_stages(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.save()
|
|
team1 = self.create_team(organization=org)
|
|
project1 = self.create_project(teams=[team1], organization=org)
|
|
self.create_member(teams=[team1], user=user, organization=org)
|
|
self.login_as(user=user)
|
|
release1 = Release.objects.create(
|
|
organization_id=org.id, version="1", date_added=datetime(2013, 8, 13, 3, 8, 24, 880386)
|
|
)
|
|
release1.add_project(project1)
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": self.organization.slug, "version": release1.version},
|
|
)
|
|
|
|
response = self.client.get(url, format="json")
|
|
|
|
assert response.status_code == 200, response.content
|
|
# Not returned because we don't have `adoptionStages=1`.
|
|
assert "adoptionStages" not in response.data
|
|
response = self.client.get(f"{url}?adoptionStages=1", format="json")
|
|
|
|
assert response.status_code == 200, response.content
|
|
assert "adoptionStages" in response.data
|
|
|
|
|
|
@region_silo_test
|
|
class UpdateReleaseDetailsTest(APITestCase):
|
|
@patch("sentry.tasks.commits.fetch_commits")
|
|
def test_simple(self, mock_fetch_commits):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=org.id, name="example/example", provider="dummy"
|
|
)
|
|
repo2 = Repository.objects.create(
|
|
organization_id=org.id, name="example/example2", provider="dummy"
|
|
)
|
|
|
|
team1 = self.create_team(organization=org)
|
|
team2 = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team1], organization=org)
|
|
project2 = self.create_project(teams=[team2], organization=org)
|
|
|
|
base_release = Release.objects.create(organization_id=org.id, version="000000000")
|
|
base_release.add_project(project)
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
release2 = Release.objects.create(organization_id=org.id, version="12345678")
|
|
release.add_project(project)
|
|
release2.add_project(project2)
|
|
|
|
self.create_member(teams=[team1], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": base_release.version},
|
|
)
|
|
self.client.put(
|
|
url,
|
|
{
|
|
"ref": "master",
|
|
"headCommits": [
|
|
{"currentId": "0" * 40, "repository": repo.name},
|
|
{"currentId": "0" * 40, "repository": repo2.name},
|
|
],
|
|
},
|
|
)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
{
|
|
"ref": "master",
|
|
"refs": [
|
|
{"commit": "a" * 40, "repository": repo.name},
|
|
{"commit": "b" * 40, "repository": repo2.name},
|
|
],
|
|
},
|
|
)
|
|
|
|
mock_fetch_commits.apply_async.assert_called_with(
|
|
kwargs={
|
|
"release_id": release.id,
|
|
"user_id": user.id,
|
|
"refs": [
|
|
{"commit": "a" * 40, "repository": repo.name},
|
|
{"commit": "b" * 40, "repository": repo2.name},
|
|
],
|
|
"prev_release_id": base_release.id,
|
|
}
|
|
)
|
|
|
|
assert response.status_code == 200, response.content
|
|
assert response.data["version"] == release.version
|
|
|
|
release = Release.objects.get(id=release.id)
|
|
assert release.ref == "master"
|
|
|
|
# no access
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release2.version},
|
|
)
|
|
response = self.client.put(url, {"ref": "master"})
|
|
assert response.status_code == 404
|
|
|
|
@patch("sentry.tasks.commits.fetch_commits")
|
|
def test_deprecated_head_commits(self, mock_fetch_commits):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=org.id, name="example/example", provider="dummy"
|
|
)
|
|
repo2 = Repository.objects.create(
|
|
organization_id=org.id, name="example/example2", provider="dummy"
|
|
)
|
|
|
|
team1 = self.create_team(organization=org)
|
|
team2 = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team1], organization=org)
|
|
project2 = self.create_project(teams=[team2], organization=org)
|
|
|
|
base_release = Release.objects.create(organization_id=org.id, version="000000000")
|
|
base_release.add_project(project)
|
|
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
release2 = Release.objects.create(organization_id=org.id, version="12345678")
|
|
release.add_project(project)
|
|
release2.add_project(project2)
|
|
|
|
self.create_member(teams=[team1], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": base_release.version},
|
|
)
|
|
self.client.put(
|
|
url,
|
|
{
|
|
"ref": "master",
|
|
"headCommits": [
|
|
{"currentId": "0" * 40, "repository": repo.name},
|
|
{"currentId": "0" * 40, "repository": repo2.name},
|
|
],
|
|
},
|
|
)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
{
|
|
"ref": "master",
|
|
"headCommits": [
|
|
{"currentId": "a" * 40, "repository": repo.name},
|
|
{"currentId": "b" * 40, "repository": repo2.name},
|
|
],
|
|
},
|
|
)
|
|
|
|
mock_fetch_commits.apply_async.assert_called_with(
|
|
kwargs={
|
|
"release_id": release.id,
|
|
"user_id": user.id,
|
|
"refs": [
|
|
{"commit": "a" * 40, "previousCommit": None, "repository": repo.name},
|
|
{"commit": "b" * 40, "previousCommit": None, "repository": repo2.name},
|
|
],
|
|
"prev_release_id": base_release.id,
|
|
}
|
|
)
|
|
|
|
assert response.status_code == 200, response.content
|
|
assert response.data["version"] == release.version
|
|
|
|
release = Release.objects.get(id=release.id)
|
|
assert release.ref == "master"
|
|
|
|
# no access
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release2.version},
|
|
)
|
|
response = self.client.put(url, {"ref": "master"})
|
|
assert response.status_code == 404
|
|
|
|
def test_commits(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
project = self.create_project(teams=[team], organization=org)
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
release.add_project(project)
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(url, data={"commits": [{"id": "a" * 40}, {"id": "b" * 40}]})
|
|
|
|
assert response.status_code == 200, (response.status_code, response.content)
|
|
|
|
rc_list = list(
|
|
ReleaseCommit.objects.filter(release=release)
|
|
.select_related("commit", "commit__author")
|
|
.order_by("order")
|
|
)
|
|
assert len(rc_list) == 2
|
|
for rc in rc_list:
|
|
assert rc.organization_id == org.id
|
|
|
|
def test_commits_patchset_character_limit_255(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
project = self.create_project(teams=[team], organization=org)
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
release.add_project(project)
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
data={
|
|
"commits": [
|
|
{
|
|
"id": "a" * 40,
|
|
"patch_set": [{"path": "/a/really/long/path/" + ("z" * 255), "type": "A"}],
|
|
}
|
|
]
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 200, (response.status_code, response.content)
|
|
|
|
rc_list = list(
|
|
ReleaseCommit.objects.filter(release=release)
|
|
.select_related("commit", "commit__author")
|
|
.order_by("order")
|
|
)
|
|
assert len(rc_list) == 1
|
|
for rc in rc_list:
|
|
assert rc.organization_id == org.id
|
|
|
|
def test_commits_patchset_character_limit_reached(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
project = self.create_project(teams=[team], organization=org)
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
release.add_project(project)
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
data={
|
|
"commits": [
|
|
{
|
|
"id": "a" * 40,
|
|
"patch_set": [{"path": "z" * (255 * 2 + 1), "type": "A"}],
|
|
}
|
|
]
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 400, (response.status_code, response.content)
|
|
|
|
def test_commits_lock_conflict(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.create_organization()
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
project = self.create_project(name="foo", organization=org, teams=[team])
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
self.login_as(user=user)
|
|
|
|
release = self.create_release(project, self.user, version="1.2.1")
|
|
release.add_project(project)
|
|
|
|
# Simulate a concurrent request by using an existing release
|
|
# that has its commit lock taken out.
|
|
lock = locks.get(Release.get_lock_key(org.id, release.id), duration=10, name="release")
|
|
lock.acquire()
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(url, data={"commits": [{"id": "a" * 40}, {"id": "b" * 40}]})
|
|
assert response.status_code == 409, (response.status_code, response.content)
|
|
assert "Release commits" in response.data["detail"]
|
|
|
|
def test_release_archiving(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team], organization=org)
|
|
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
|
|
release.add_project(project)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(url, data={"status": "archived"})
|
|
|
|
assert response.status_code == 200, (response.status_code, response.content)
|
|
|
|
assert Release.objects.get(id=release.id).status == ReleaseStatus.ARCHIVED
|
|
|
|
def test_activity_generation(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team], organization=org)
|
|
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
|
|
release.add_project(project)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(url, data={"dateReleased": datetime.utcnow().isoformat() + "Z"})
|
|
|
|
assert response.status_code == 200, (response.status_code, response.content)
|
|
|
|
release = Release.objects.get(id=release.id)
|
|
assert release.date_released
|
|
|
|
activity = Activity.objects.filter(
|
|
type=ActivityType.RELEASE.value, project=project, ident=release.version
|
|
)
|
|
assert activity.exists()
|
|
|
|
def test_activity_generation_long_release(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team], organization=org)
|
|
|
|
release = Release.objects.create(organization_id=org.id, version="x" * 65)
|
|
|
|
release.add_project(project)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(url, data={"dateReleased": datetime.utcnow().isoformat() + "Z"})
|
|
|
|
assert response.status_code == 200, (response.status_code, response.content)
|
|
|
|
release = Release.objects.get(id=release.id)
|
|
assert release.date_released
|
|
|
|
activity = Activity.objects.filter(
|
|
type=ActivityType.RELEASE.value, project=project, ident=release.version[:64]
|
|
)
|
|
assert activity.exists()
|
|
|
|
def test_org_auth_token(self):
|
|
org = self.organization
|
|
|
|
with assume_test_silo_mode(SiloMode.CONTROL):
|
|
good_token_str = generate_token(org.slug, "")
|
|
OrgAuthToken.objects.create(
|
|
organization_id=org.id,
|
|
name="token 1",
|
|
token_hashed=hash_token(good_token_str),
|
|
token_last_characters="ABCD",
|
|
scope_list=["org:ci"],
|
|
date_last_used=None,
|
|
)
|
|
|
|
repo = Repository.objects.create(
|
|
organization_id=org.id, name="example/example", provider="dummy"
|
|
)
|
|
|
|
team1 = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team1], organization=org)
|
|
|
|
base_release = Release.objects.create(organization_id=org.id, version="000000000")
|
|
base_release.add_project(project)
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
release.add_project(project)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": base_release.version},
|
|
)
|
|
self.client.put(
|
|
url,
|
|
data={
|
|
"ref": "master",
|
|
"headCommits": [
|
|
{"currentId": "0" * 40, "repository": repo.name},
|
|
],
|
|
},
|
|
HTTP_AUTHORIZATION=f"Bearer {good_token_str}",
|
|
)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
data={
|
|
"ref": "master",
|
|
"refs": [
|
|
{"commit": "a" * 40, "repository": repo.name},
|
|
],
|
|
},
|
|
HTTP_AUTHORIZATION=f"Bearer {good_token_str}",
|
|
)
|
|
|
|
assert response.status_code == 200, response.content
|
|
assert response.data["version"] == release.version
|
|
|
|
release = Release.objects.get(id=release.id)
|
|
assert release.ref == "master"
|
|
|
|
|
|
@region_silo_test
|
|
class ReleaseDeleteTest(APITestCase):
|
|
def test_simple(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team], organization=org)
|
|
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
|
|
release.add_project(project)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
release_file = ReleaseFile.objects.create(
|
|
organization_id=project.organization_id,
|
|
release_id=release.id,
|
|
file=File.objects.create(name="application.js", type="release.file"),
|
|
name="http://example.com/application.js",
|
|
)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.delete(url)
|
|
|
|
assert response.status_code == 204, response.content
|
|
|
|
assert not Release.objects.filter(id=release.id).exists()
|
|
assert not ReleaseFile.objects.filter(id=release_file.id).exists()
|
|
|
|
def test_existing_group(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.organization
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
|
|
project = self.create_project(teams=[team], organization=org)
|
|
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
|
|
release.add_project(project)
|
|
self.create_group(first_release=release)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.delete(url)
|
|
|
|
assert response.status_code == 400, response.content
|
|
|
|
assert Release.objects.filter(id=release.id).exists()
|
|
|
|
def test_bad_repo_name(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.create_organization()
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
project = self.create_project(name="foo", organization=org, teams=[team])
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
|
|
release.add_project(project)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
data={
|
|
"version": "1.2.1",
|
|
"projects": [project.slug],
|
|
"refs": [{"repository": "not_a_repo", "commit": "a" * 40}],
|
|
},
|
|
)
|
|
assert response.status_code == 400
|
|
assert response.data == {"refs": ["Invalid repository names: not_a_repo"]}
|
|
|
|
def test_bad_commit_list(self):
|
|
user = self.create_user(is_staff=False, is_superuser=False)
|
|
org = self.create_organization()
|
|
org.flags.allow_joinleave = False
|
|
org.save()
|
|
|
|
team = self.create_team(organization=org)
|
|
project = self.create_project(name="foo", organization=org, teams=[team])
|
|
Repository.objects.create(organization_id=org.id, name="a_repo")
|
|
release = Release.objects.create(organization_id=org.id, version="abcabcabc")
|
|
|
|
release.add_project(project)
|
|
|
|
self.create_member(teams=[team], user=user, organization=org)
|
|
self.login_as(user=user)
|
|
|
|
url = reverse(
|
|
"sentry-api-0-organization-release-details",
|
|
kwargs={"organization_slug": org.slug, "version": release.version},
|
|
)
|
|
response = self.client.put(
|
|
url,
|
|
data={
|
|
"version": "1.2.1",
|
|
"projects": [project.slug],
|
|
"commits": [{"repository": "a_repo"}],
|
|
},
|
|
)
|
|
assert response.status_code == 400
|
|
assert response.json() == {"commits": {"id": ["This field is required."]}}
|
|
|
|
|
|
@region_silo_test
|
|
class ReleaseSerializerTest(unittest.TestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.repo_name = "repo/name"
|
|
self.repo2_name = "repo2/name"
|
|
self.commits = [{"id": "a" * 40}, {"id": "b" * 40}]
|
|
self.ref = "master"
|
|
self.url = "https://example.com"
|
|
self.dateReleased = "1000-10-10T06:06"
|
|
self.headCommits = [
|
|
{"currentId": "0" * 40, "repository": self.repo_name},
|
|
{"currentId": "0" * 40, "repository": self.repo2_name},
|
|
]
|
|
self.refs = [
|
|
{"commit": "a" * 40, "previousCommit": "", "repository": self.repo_name},
|
|
{"commit": "b" * 40, "previousCommit": "", "repository": self.repo2_name},
|
|
]
|
|
|
|
def test_simple(self):
|
|
serializer = OrganizationReleaseSerializer(
|
|
data={
|
|
"ref": self.ref,
|
|
"url": self.url,
|
|
"dateReleased": self.dateReleased,
|
|
"commits": self.commits,
|
|
"headCommits": self.headCommits,
|
|
"refs": self.refs,
|
|
}
|
|
)
|
|
|
|
assert serializer.is_valid()
|
|
assert set(serializer.fields.keys()) == {
|
|
"ref",
|
|
"url",
|
|
"dateReleased",
|
|
"commits",
|
|
"headCommits",
|
|
"refs",
|
|
"status",
|
|
}
|
|
|
|
result = serializer.validated_data
|
|
assert result["ref"] == self.ref
|
|
assert result["url"] == self.url
|
|
assert result["dateReleased"] == datetime(1000, 10, 10, 6, 6, tzinfo=timezone.utc)
|
|
assert result["commits"] == self.commits
|
|
assert result["headCommits"] == self.headCommits
|
|
assert result["refs"] == self.refs
|
|
|
|
def test_fields_not_required(self):
|
|
serializer = OrganizationReleaseSerializer(data={})
|
|
assert serializer.is_valid()
|
|
|
|
def test_do_not_allow_null_commits(self):
|
|
serializer = OrganizationReleaseSerializer(data={"commits": None})
|
|
assert not serializer.is_valid()
|
|
|
|
def test_do_not_allow_null_head_commits(self):
|
|
serializer = OrganizationReleaseSerializer(data={"headCommits": None})
|
|
assert not serializer.is_valid()
|
|
|
|
def test_do_not_allow_null_refs(self):
|
|
serializer = OrganizationReleaseSerializer(data={"refs": None})
|
|
assert not serializer.is_valid()
|
|
|
|
def test_ref_limited_by_max_version_length(self):
|
|
serializer = OrganizationReleaseSerializer(data={"ref": "a" * MAX_VERSION_LENGTH})
|
|
assert serializer.is_valid()
|
|
serializer = OrganizationReleaseSerializer(data={"ref": "a" * (MAX_VERSION_LENGTH + 1)})
|
|
assert not serializer.is_valid()
|
|
|
|
def test_author_email_patch(self):
|
|
serializer = OrganizationReleaseSerializer(
|
|
data={"commits": [{"id": "a", "author_email": "email[test]@example.org"}]}
|
|
)
|
|
assert serializer.is_valid()
|