|
23 | 23 | GITHUB_PULL_REQUEST_REOPENED,
|
24 | 24 | GITHUB_PULL_REQUEST_CLOSED,
|
25 | 25 | GITHUB_PULL_REQUEST_SYNC,
|
| 26 | + GITLAB_MERGE_REQUEST, |
| 27 | + GITLAB_MERGE_REQUEST_CLOSE, |
| 28 | + GITLAB_MERGE_REQUEST_MERGE, |
| 29 | + GITLAB_MERGE_REQUEST_OPEN, |
| 30 | + GITLAB_MERGE_REQUEST_REOPEN, |
| 31 | + GITLAB_MERGE_REQUEST_UPDATE, |
26 | 32 | GITLAB_NULL_HASH,
|
27 | 33 | GITLAB_PUSH,
|
28 | 34 | GITLAB_TAG_PUSH,
|
@@ -794,6 +800,16 @@ def setUp(self):
|
794 | 800 | }
|
795 | 801 | }
|
796 | 802 | }
|
| 803 | + self.gitlab_merge_request_payload = { |
| 804 | + "object_kind": GITLAB_MERGE_REQUEST, |
| 805 | + "object_attributes": { |
| 806 | + "iid": '2', |
| 807 | + "last_commit": { |
| 808 | + "id": self.commit |
| 809 | + }, |
| 810 | + "action": "open" |
| 811 | + }, |
| 812 | + } |
797 | 813 | self.gitlab_payload = {
|
798 | 814 | 'object_kind': GITLAB_PUSH,
|
799 | 815 | 'ref': 'master',
|
@@ -1536,6 +1552,291 @@ def test_gitlab_skip_token_validation(self, trigger_build):
|
1536 | 1552 | )
|
1537 | 1553 | self.assertEqual(resp.status_code, 200)
|
1538 | 1554 |
|
| 1555 | + @mock.patch('readthedocs.core.utils.trigger_build') |
| 1556 | + def test_gitlab_merge_request_open_event(self, trigger_build, core_trigger_build): |
| 1557 | + client = APIClient() |
| 1558 | + |
| 1559 | + resp = client.post( |
| 1560 | + reverse( |
| 1561 | + 'api_webhook_gitlab', |
| 1562 | + kwargs={'project_slug': self.project.slug} |
| 1563 | + ), |
| 1564 | + self.gitlab_merge_request_payload, |
| 1565 | + format='json', |
| 1566 | + ) |
| 1567 | + # get the created external version |
| 1568 | + external_version = self.project.versions( |
| 1569 | + manager=EXTERNAL |
| 1570 | + ).get(verbose_name='2') |
| 1571 | + |
| 1572 | + self.assertEqual(resp.status_code, status.HTTP_200_OK) |
| 1573 | + self.assertTrue(resp.data['build_triggered']) |
| 1574 | + self.assertEqual(resp.data['project'], self.project.slug) |
| 1575 | + self.assertEqual(resp.data['versions'], [external_version.verbose_name]) |
| 1576 | + core_trigger_build.assert_called_once_with( |
| 1577 | + force=True, project=self.project, |
| 1578 | + version=external_version, commit=self.commit |
| 1579 | + ) |
| 1580 | + self.assertTrue(external_version) |
| 1581 | + |
| 1582 | + @mock.patch('readthedocs.core.utils.trigger_build') |
| 1583 | + def test_gitlab_merge_request_reopen_event(self, trigger_build, core_trigger_build): |
| 1584 | + client = APIClient() |
| 1585 | + |
| 1586 | + # Update the payload for `reopen` webhook event |
| 1587 | + merge_request_number = '5' |
| 1588 | + payload = self.gitlab_merge_request_payload |
| 1589 | + payload["object_attributes"]["action"] = GITLAB_MERGE_REQUEST_REOPEN |
| 1590 | + payload["object_attributes"]["iid"] = merge_request_number |
| 1591 | + |
| 1592 | + resp = client.post( |
| 1593 | + reverse( |
| 1594 | + 'api_webhook_gitlab', |
| 1595 | + kwargs={'project_slug': self.project.slug} |
| 1596 | + ), |
| 1597 | + payload, |
| 1598 | + format='json', |
| 1599 | + ) |
| 1600 | + # get the created external version |
| 1601 | + external_version = self.project.versions( |
| 1602 | + manager=EXTERNAL |
| 1603 | + ).get(verbose_name=merge_request_number) |
| 1604 | + |
| 1605 | + self.assertEqual(resp.status_code, status.HTTP_200_OK) |
| 1606 | + self.assertTrue(resp.data['build_triggered']) |
| 1607 | + self.assertEqual(resp.data['project'], self.project.slug) |
| 1608 | + self.assertEqual(resp.data['versions'], [external_version.verbose_name]) |
| 1609 | + core_trigger_build.assert_called_once_with( |
| 1610 | + force=True, project=self.project, |
| 1611 | + version=external_version, commit=self.commit |
| 1612 | + ) |
| 1613 | + self.assertTrue(external_version) |
| 1614 | + |
| 1615 | + @mock.patch('readthedocs.core.utils.trigger_build') |
| 1616 | + def test_gitlab_merge_request_update_event(self, trigger_build, core_trigger_build): |
| 1617 | + client = APIClient() |
| 1618 | + |
| 1619 | + merge_request_number = '6' |
| 1620 | + prev_identifier = '95790bf891e76fee5e1747ab589903a6a1f80f23' |
| 1621 | + # create an existing external version for merge request |
| 1622 | + version = get( |
| 1623 | + Version, |
| 1624 | + project=self.project, |
| 1625 | + type=EXTERNAL, |
| 1626 | + built=True, |
| 1627 | + uploaded=True, |
| 1628 | + active=True, |
| 1629 | + verbose_name=merge_request_number, |
| 1630 | + identifier=prev_identifier |
| 1631 | + ) |
| 1632 | + |
| 1633 | + # Update the payload for merge request `update` webhook event |
| 1634 | + payload = self.gitlab_merge_request_payload |
| 1635 | + payload["object_attributes"]["action"] = GITLAB_MERGE_REQUEST_UPDATE |
| 1636 | + payload["object_attributes"]["iid"] = merge_request_number |
| 1637 | + |
| 1638 | + resp = client.post( |
| 1639 | + reverse( |
| 1640 | + 'api_webhook_gitlab', |
| 1641 | + kwargs={'project_slug': self.project.slug} |
| 1642 | + ), |
| 1643 | + payload, |
| 1644 | + format='json', |
| 1645 | + ) |
| 1646 | + # get updated external version |
| 1647 | + external_version = self.project.versions( |
| 1648 | + manager=EXTERNAL |
| 1649 | + ).get(verbose_name=merge_request_number) |
| 1650 | + |
| 1651 | + self.assertEqual(resp.status_code, status.HTTP_200_OK) |
| 1652 | + self.assertTrue(resp.data['build_triggered']) |
| 1653 | + self.assertEqual(resp.data['project'], self.project.slug) |
| 1654 | + self.assertEqual(resp.data['versions'], [external_version.verbose_name]) |
| 1655 | + core_trigger_build.assert_called_once_with( |
| 1656 | + force=True, project=self.project, |
| 1657 | + version=external_version, commit=self.commit |
| 1658 | + ) |
| 1659 | + # `update` webhook event updated the identifier (commit hash) |
| 1660 | + self.assertNotEqual(prev_identifier, external_version.identifier) |
| 1661 | + |
| 1662 | + @mock.patch('readthedocs.core.utils.trigger_build') |
| 1663 | + def test_gitlab_merge_request_close_event(self, trigger_build, core_trigger_build): |
| 1664 | + client = APIClient() |
| 1665 | + |
| 1666 | + merge_request_number = '7' |
| 1667 | + identifier = '95790bf891e76fee5e1747ab589903a6a1f80f23' |
| 1668 | + # create an existing external version for merge request |
| 1669 | + version = get( |
| 1670 | + Version, |
| 1671 | + project=self.project, |
| 1672 | + type=EXTERNAL, |
| 1673 | + built=True, |
| 1674 | + uploaded=True, |
| 1675 | + active=True, |
| 1676 | + verbose_name=merge_request_number, |
| 1677 | + identifier=identifier |
| 1678 | + ) |
| 1679 | + |
| 1680 | + # Update the payload for `closed` webhook event |
| 1681 | + payload = self.gitlab_merge_request_payload |
| 1682 | + payload["object_attributes"]["action"] = GITLAB_MERGE_REQUEST_CLOSE |
| 1683 | + payload["object_attributes"]["iid"] = merge_request_number |
| 1684 | + payload["object_attributes"]["last_commit"]["id"] = identifier |
| 1685 | + |
| 1686 | + resp = client.post( |
| 1687 | + reverse( |
| 1688 | + 'api_webhook_gitlab', |
| 1689 | + kwargs={'project_slug': self.project.slug} |
| 1690 | + ), |
| 1691 | + payload, |
| 1692 | + format='json', |
| 1693 | + ) |
| 1694 | + external_version = self.project.versions( |
| 1695 | + manager=EXTERNAL |
| 1696 | + ).filter(verbose_name=merge_request_number) |
| 1697 | + |
| 1698 | + # external version should be deleted |
| 1699 | + self.assertFalse(external_version.exists()) |
| 1700 | + self.assertEqual(resp.status_code, status.HTTP_200_OK) |
| 1701 | + self.assertTrue(resp.data['version_deleted']) |
| 1702 | + self.assertEqual(resp.data['project'], self.project.slug) |
| 1703 | + self.assertEqual(resp.data['versions'], [version.verbose_name]) |
| 1704 | + core_trigger_build.assert_not_called() |
| 1705 | + |
| 1706 | + @mock.patch('readthedocs.core.utils.trigger_build') |
| 1707 | + def test_gitlab_merge_request_merge_event(self, trigger_build, core_trigger_build): |
| 1708 | + client = APIClient() |
| 1709 | + |
| 1710 | + merge_request_number = '8' |
| 1711 | + identifier = '95790bf891e76fee5e1747ab589903a6a1f80f23' |
| 1712 | + # create an existing external version for merge request |
| 1713 | + version = get( |
| 1714 | + Version, |
| 1715 | + project=self.project, |
| 1716 | + type=EXTERNAL, |
| 1717 | + built=True, |
| 1718 | + uploaded=True, |
| 1719 | + active=True, |
| 1720 | + verbose_name=merge_request_number, |
| 1721 | + identifier=identifier |
| 1722 | + ) |
| 1723 | + |
| 1724 | + # Update the payload for `merge` webhook event |
| 1725 | + payload = self.gitlab_merge_request_payload |
| 1726 | + payload["object_attributes"]["action"] = GITLAB_MERGE_REQUEST_MERGE |
| 1727 | + payload["object_attributes"]["iid"] = merge_request_number |
| 1728 | + payload["object_attributes"]["last_commit"]["id"] = identifier |
| 1729 | + |
| 1730 | + resp = client.post( |
| 1731 | + reverse( |
| 1732 | + 'api_webhook_gitlab', |
| 1733 | + kwargs={'project_slug': self.project.slug} |
| 1734 | + ), |
| 1735 | + payload, |
| 1736 | + format='json', |
| 1737 | + ) |
| 1738 | + external_version = self.project.versions( |
| 1739 | + manager=EXTERNAL |
| 1740 | + ).filter(verbose_name=merge_request_number) |
| 1741 | + |
| 1742 | + # external version should be deleted |
| 1743 | + self.assertFalse(external_version.exists()) |
| 1744 | + self.assertEqual(resp.status_code, status.HTTP_200_OK) |
| 1745 | + self.assertTrue(resp.data['version_deleted']) |
| 1746 | + self.assertEqual(resp.data['project'], self.project.slug) |
| 1747 | + self.assertEqual(resp.data['versions'], [version.verbose_name]) |
| 1748 | + core_trigger_build.assert_not_called() |
| 1749 | + |
| 1750 | + def test_gitlab_merge_request_no_action(self, trigger_build): |
| 1751 | + client = APIClient() |
| 1752 | + |
| 1753 | + payload = { |
| 1754 | + "object_kind": GITLAB_MERGE_REQUEST, |
| 1755 | + "object_attributes": { |
| 1756 | + "iid": 2, |
| 1757 | + "last_commit": { |
| 1758 | + "id": self.commit |
| 1759 | + }, |
| 1760 | + }, |
| 1761 | + } |
| 1762 | + |
| 1763 | + resp = client.post( |
| 1764 | + reverse( |
| 1765 | + 'api_webhook_gitlab', |
| 1766 | + kwargs={'project_slug': self.project.slug} |
| 1767 | + ), |
| 1768 | + payload, |
| 1769 | + format='json', |
| 1770 | + ) |
| 1771 | + self.assertEqual(resp.status_code, 200) |
| 1772 | + self.assertEqual(resp.data['detail'], 'Unhandled webhook event') |
| 1773 | + |
| 1774 | + def test_gitlab_merge_request_open_event_invalid_payload(self, trigger_build): |
| 1775 | + client = APIClient() |
| 1776 | + |
| 1777 | + payload = { |
| 1778 | + "object_kind": GITLAB_MERGE_REQUEST, |
| 1779 | + "object_attributes": { |
| 1780 | + "action": GITLAB_MERGE_REQUEST_CLOSE |
| 1781 | + }, |
| 1782 | + } |
| 1783 | + resp = client.post( |
| 1784 | + reverse( |
| 1785 | + 'api_webhook_gitlab', |
| 1786 | + kwargs={'project_slug': self.project.slug} |
| 1787 | + ), |
| 1788 | + payload, |
| 1789 | + format='json', |
| 1790 | + ) |
| 1791 | + |
| 1792 | + self.assertEqual(resp.status_code, 400) |
| 1793 | + |
| 1794 | + def test_gitlab_merge_request_close_event_invalid_payload(self, trigger_build): |
| 1795 | + client = APIClient() |
| 1796 | + |
| 1797 | + payload = { |
| 1798 | + "object_kind": GITLAB_MERGE_REQUEST, |
| 1799 | + "object_attributes": { |
| 1800 | + "action": GITLAB_MERGE_REQUEST_CLOSE |
| 1801 | + }, |
| 1802 | + } |
| 1803 | + |
| 1804 | + resp = client.post( |
| 1805 | + reverse( |
| 1806 | + 'api_webhook_gitlab', |
| 1807 | + kwargs={'project_slug': self.project.slug} |
| 1808 | + ), |
| 1809 | + payload, |
| 1810 | + format='json', |
| 1811 | + ) |
| 1812 | + |
| 1813 | + self.assertEqual(resp.status_code, 400) |
| 1814 | + |
| 1815 | + @mock.patch('readthedocs.core.utils.trigger_build') |
| 1816 | + def test_gitlab_merge_request_event_no_feature_flag(self, trigger_build, core_trigger_build): |
| 1817 | + # delete feature flag |
| 1818 | + self.feature_flag.delete() |
| 1819 | + |
| 1820 | + client = APIClient() |
| 1821 | + |
| 1822 | + resp = client.post( |
| 1823 | + reverse( |
| 1824 | + 'api_webhook_gitlab', |
| 1825 | + kwargs={'project_slug': self.project.slug} |
| 1826 | + ), |
| 1827 | + self.gitlab_merge_request_payload, |
| 1828 | + format='json', |
| 1829 | + ) |
| 1830 | + # get external version |
| 1831 | + external_version = self.project.versions( |
| 1832 | + manager=EXTERNAL |
| 1833 | + ).filter(verbose_name='2').first() |
| 1834 | + |
| 1835 | + self.assertEqual(resp.status_code, 200) |
| 1836 | + self.assertEqual(resp.data['detail'], 'Unhandled webhook event') |
| 1837 | + core_trigger_build.assert_not_called() |
| 1838 | + self.assertFalse(external_version) |
| 1839 | + |
1539 | 1840 | def test_bitbucket_webhook(self, trigger_build):
|
1540 | 1841 | """Bitbucket webhook API."""
|
1541 | 1842 | client = APIClient()
|
|
0 commit comments