Update ical comparison to check only for event components (#1870)
May be related to https://github.com/grafana/oncall/issues/1553. We got feedback about that happening for Google Calendar imported icals. Google Calendar exported ics URL was returning different VTIMEZONE components on different requests, triggering differences in the imported ical. Updated the comparison to only consider events (while keep assuming the sequence will reflect if there are any particular event change).
This commit is contained in:
parent
ab74cd7655
commit
7cf0c4f693
3 changed files with 153 additions and 15 deletions
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve ical comparison when checking for imported ical updates ([1870](https://github.com/grafana/oncall/pull/1870))
|
||||
|
||||
## v1.2.18 (2023-05-03)
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -509,21 +509,15 @@ def is_icals_equal(first, second):
|
|||
second_cal = Calendar.from_ical(second)
|
||||
first_subcomponents = first_cal.subcomponents
|
||||
second_subcomponents = second_cal.subcomponents
|
||||
if len(first_subcomponents) != len(second_subcomponents):
|
||||
return False
|
||||
first_cal_events = {}
|
||||
second_cal_events = {}
|
||||
for cmp in first_cal.subcomponents:
|
||||
first_cal_events[cmp.get("UID", None)] = cmp.get("SEQUENCE", None)
|
||||
for cmp in second_cal.subcomponents:
|
||||
second_cal_events[cmp.get("UID", None)] = cmp.get("SEQUENCE", None)
|
||||
for first_uid, first_seq in first_cal_events.items():
|
||||
if first_uid not in second_cal_events:
|
||||
return False
|
||||
second_seq = second_cal_events.get(first_uid, None)
|
||||
if first_seq != second_seq:
|
||||
return False
|
||||
return True
|
||||
# only consider VEVENT components
|
||||
first_cal_events = {
|
||||
cmp.get("UID", None): cmp.get("SEQUENCE", None) for cmp in first_subcomponents if cmp.name == "VEVENT"
|
||||
}
|
||||
second_cal_events = {
|
||||
cmp.get("UID", None): cmp.get("SEQUENCE", None) for cmp in second_subcomponents if cmp.name == "VEVENT"
|
||||
}
|
||||
# check events and their respective sequences are equal
|
||||
return first_cal_events == second_cal_events
|
||||
|
||||
|
||||
def ical_date_to_datetime(date, tz, start):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import datetime
|
||||
import textwrap
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
|
@ -7,6 +8,7 @@ from django.utils import timezone
|
|||
|
||||
from apps.api.permissions import LegacyAccessControlRole
|
||||
from apps.schedules.ical_utils import (
|
||||
is_icals_equal,
|
||||
list_of_oncall_shifts_from_ical,
|
||||
list_users_to_notify_from_ical,
|
||||
parse_event_uid,
|
||||
|
|
@ -153,3 +155,139 @@ def test_parse_event_uid_fallback():
|
|||
pk, source = parse_event_uid(event_uid)
|
||||
assert pk == event_uid
|
||||
assert source is None
|
||||
|
||||
|
||||
def test_is_icals_equal_compare_events():
|
||||
with_vtimezone = textwrap.dedent(
|
||||
"""
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-TIMEZONE:Europe/Amsterdam
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Europe/Amsterdam
|
||||
X-LIC-LOCATION:Europe/Amsterdam
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:CEST
|
||||
DTSTART:19700329T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:CET
|
||||
DTSTART:19701025T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20230515
|
||||
DTEND;VALUE=DATE:20230522
|
||||
DTSTAMP:20230503T152557Z
|
||||
UID:something@google.com
|
||||
RECURRENCE-ID;VALUE=DATE:20230501
|
||||
CREATED:20230403T073117Z
|
||||
LAST-MODIFIED:20230424T123617Z
|
||||
SEQUENCE:2
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:some@user.com
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
"""
|
||||
)
|
||||
without_vtimezone = textwrap.dedent(
|
||||
"""
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-TIMEZONE:Europe/Amsterdam
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20230515
|
||||
DTEND;VALUE=DATE:20230522
|
||||
DTSTAMP:20230503T162103Z
|
||||
UID:something@google.com
|
||||
RECURRENCE-ID;VALUE=DATE:20230501
|
||||
CREATED:20230403T073117Z
|
||||
LAST-MODIFIED:20230424T123617Z
|
||||
SEQUENCE:2
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:some@user.com
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
"""
|
||||
)
|
||||
assert is_icals_equal(with_vtimezone, without_vtimezone)
|
||||
|
||||
|
||||
def test_is_icals_equal_compare_events_not_equal():
|
||||
with_vtimezone = textwrap.dedent(
|
||||
"""
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-TIMEZONE:Europe/Amsterdam
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Europe/Amsterdam
|
||||
X-LIC-LOCATION:Europe/Amsterdam
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:CEST
|
||||
DTSTART:19700329T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:CET
|
||||
DTSTART:19701025T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20230515
|
||||
DTEND;VALUE=DATE:20230522
|
||||
DTSTAMP:20230503T152557Z
|
||||
UID:something@google.com
|
||||
RECURRENCE-ID;VALUE=DATE:20230501
|
||||
CREATED:20230403T073117Z
|
||||
LAST-MODIFIED:20230424T123617Z
|
||||
SEQUENCE:2
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:some@user.com
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
"""
|
||||
)
|
||||
without_vtimezone = textwrap.dedent(
|
||||
"""
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-TIMEZONE:Europe/Amsterdam
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20230515
|
||||
DTEND;VALUE=DATE:20230522
|
||||
DTSTAMP:20230503T162103Z
|
||||
UID:something@google.com
|
||||
RECURRENCE-ID;VALUE=DATE:20230501
|
||||
CREATED:20230403T073117Z
|
||||
LAST-MODIFIED:20230424T123617Z
|
||||
SEQUENCE:3
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:some@user.com
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
"""
|
||||
)
|
||||
assert not is_icals_equal(with_vtimezone, without_vtimezone)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue