Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PORT-5598 | Jira integration - support sprints | Change priority to name #804

Open
wants to merge 85 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
a3d6380
Implemeneted support for sprints
lordsarcastic Jul 10, 2024
2a2811c
Changed priority in issue to be name
lordsarcastic Jul 10, 2024
2d3f527
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Jul 10, 2024
7121711
Implemented support for sprint states and issues source
lordsarcastic Jul 16, 2024
be33aef
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Jul 16, 2024
0367e78
Fix type cast attribute overlap error
lordsarcastic Jul 16, 2024
9307d15
Formatted port-app-config
lordsarcastic Jul 16, 2024
b9abc49
Added new mapping for board url
lordsarcastic Jul 18, 2024
75a090a
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Jul 18, 2024
67966a1
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Jul 23, 2024
6b6cb82
Fixed issues on jira integration
lordsarcastic Jul 26, 2024
58f9984
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Jul 26, 2024
1fe260f
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Jul 31, 2024
ec6c1a0
Implemented processing for all webhook events
lordsarcastic Aug 1, 2024
320caa2
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Aug 1, 2024
32d82d3
Fix unclosed pagination for sprint
lordsarcastic Aug 1, 2024
1a6a376
Fix bugs in webhook
lordsarcastic Aug 1, 2024
90f4071
Fixed bug in deleting entities
lordsarcastic Aug 2, 2024
db696f1
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Aug 6, 2024
5df8c3d
Merge branch 'main' into port-5598
mk-armah Aug 9, 2024
ff31969
Fix Nonetype error
lordsarcastic Aug 14, 2024
41e7fcc
Bumped application version
lordsarcastic Aug 14, 2024
a447370
Update changelog
lordsarcastic Aug 14, 2024
69458cc
Merge branch 'port-5598' of github.com:port-labs/ocean into port-5598
lordsarcastic Aug 19, 2024
91b406d
Remove sourcing issues from boards
lordsarcastic Aug 19, 2024
4362377
Ran formatting
lordsarcastic Aug 19, 2024
df881df
Chore: Removed boards entirely
lordsarcastic Aug 26, 2024
88899ba
Implemeneted support for sprints
lordsarcastic Jul 10, 2024
ac6d419
Changed priority in issue to be name
lordsarcastic Jul 10, 2024
0be072f
Implemented support for sprint states and issues source
lordsarcastic Jul 16, 2024
d9d4f72
Fix type cast attribute overlap error
lordsarcastic Jul 16, 2024
8560691
Formatted port-app-config
lordsarcastic Jul 16, 2024
b19e8b7
Added new mapping for board url
lordsarcastic Jul 18, 2024
d4b0242
Fixed issues on jira integration
lordsarcastic Jul 26, 2024
a616d5b
Implemented processing for all webhook events
lordsarcastic Aug 1, 2024
f72fd3e
Fix unclosed pagination for sprint
lordsarcastic Aug 1, 2024
1158543
Fix bugs in webhook
lordsarcastic Aug 1, 2024
d2fa837
Fixed bug in deleting entities
lordsarcastic Aug 2, 2024
d761c9e
[Integration][Pagerduty] Fix incident default mapping and blueprint …
Tankilevitch Aug 5, 2024
fd9cf23
PORT-9572 Update the default JQL provided by the JIRA integration (#868)
MPTG94 Aug 5, 2024
e97e3ab
[AWS] Bug fix global resources not synced for all accounts (#845)
shalev007 Aug 5, 2024
59cdfa6
[Integration][AWS] throw error if no permissions on region (#889)
shalev007 Aug 8, 2024
012474c
Remove sourcing issues from boards
lordsarcastic Aug 19, 2024
b755efa
Ran formatting
lordsarcastic Aug 19, 2024
52cd217
Chore: Removed boards entirely
lordsarcastic Aug 26, 2024
6a5a123
Merge branch 'port-5598' of github.com:port-labs/ocean into port-5598
lordsarcastic Aug 26, 2024
fd1731d
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Aug 26, 2024
f14d717
Merge branch 'main' into port-5598
PeyGis Sep 4, 2024
6aa8f99
Fix: Fixed ingesting issues with sprint
lordsarcastic Sep 5, 2024
028eb1a
Fix: Single quote causing mapping to not be applied
lordsarcastic Sep 5, 2024
266256a
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Sep 11, 2024
5eb0eb2
Chore: Made ingestion faster
lordsarcastic Sep 11, 2024
04de891
Fix: Lint issues
lordsarcastic Sep 11, 2024
6742a22
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Sep 13, 2024
4423064
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Sep 19, 2024
c9e5345
Added changelog information
lordsarcastic Sep 19, 2024
4fca62a
Bumped version
lordsarcastic Sep 19, 2024
264faa7
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Sep 25, 2024
64ecbd1
Chore: bumped version
lordsarcastic Sep 25, 2024
ebe15f9
Chore: Removed sprints from integration
lordsarcastic Oct 4, 2024
c74edb7
Fix: Bug on params for issues
lordsarcastic Oct 7, 2024
444d177
Fix: Bug on params for issues
lordsarcastic Oct 8, 2024
80b388b
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Oct 10, 2024
a572710
Merge branch 'main' into port-5598
PeyGis Oct 14, 2024
d4f36f6
Fix: Changelog, blueprints and method name
lordsarcastic Oct 14, 2024
4f8ca50
Merge branch 'main' into port-5598
PeyGis Oct 14, 2024
4602bd1
Implemented tests for Jira
lordsarcastic Oct 17, 2024
bb26949
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Oct 18, 2024
1eaf4fb
Merge branch 'main' into port-5598
PeyGis Oct 21, 2024
bd6c269
Fixed bug in tests
lordsarcastic Oct 21, 2024
8b6acc5
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Oct 22, 2024
ec3727f
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Oct 22, 2024
8c9c29a
Bumped integration version and ocean dependency
lordsarcastic Oct 22, 2024
34acfc9
Updated changelog
lordsarcastic Oct 22, 2024
8e34aa1
Fix: Lint errors
lordsarcastic Oct 22, 2024
19f49bb
Fix: Uncomment items in spec.yaml file
lordsarcastic Oct 22, 2024
1879b0b
Fix: commented code
lordsarcastic Oct 22, 2024
52d6a8c
Chore: Adjusted fixtures data
lordsarcastic Oct 22, 2024
bdf93d1
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Oct 23, 2024
f1f8495
Bumped version
lordsarcastic Oct 23, 2024
f6668e6
Chore: Fix lint and lock file
lordsarcastic Oct 23, 2024
bae8656
Chore: Reverted changelog changes
lordsarcastic Oct 23, 2024
8d663f6
Chore: Updated changelog
lordsarcastic Oct 23, 2024
9ae1adc
Merge remote-tracking branch 'origin/main' into port-5598
lordsarcastic Oct 23, 2024
4dd0f85
Bumped integration version due to merge
lordsarcastic Oct 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion integrations/jira/.port/resources/blueprints.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@
"type": "string",
"format": "url",
"description": "URL to the project in Jira"
},
"totalIssues": {
"title": "Total Issues",
"type": "number",
"description": "The total number of issues in the project"
}
}
},
"calculationProperties": {}
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
},
{
"identifier": "jiraIssue",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking maybe we should add a property with sprint, where the description of the property will point the user to the docs?

Expand Down
4 changes: 3 additions & 1 deletion integrations/jira/.port/resources/port-app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ resources:
blueprint: '"jiraProject"'
properties:
url: (.self | split("/") | .[:3] | join("/")) + "/projects/" + .key
totalIssues: .insight.totalIssueCount

- kind: issue
selector:
query: "true"
Expand All @@ -30,7 +32,7 @@ resources:
assignee: .fields.assignee.emailAddress
reporter: .fields.reporter.emailAddress
creator: .fields.creator.emailAddress
priority: .fields.priority.id
priority: .fields.priority.name
labels: .fields.labels
created: .fields.created
updated: .fields.updated
Expand Down
12 changes: 12 additions & 0 deletions integrations/jira/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- towncrier release notes start -->

## 0.1.93 (2024-10-10)


### Features

- Added support for ingesting other fields apart from the default fields (0.1.93)

### Improvements

- Changed issue priority from id to name (0.1.93)


## 0.1.92 (2024-10-09)


Expand Down
154 changes: 154 additions & 0 deletions integrations/jira/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import typing
from typing import Any, AsyncGenerator

import httpx
from httpx import BasicAuth, Timeout
from loguru import logger
from port_ocean.context.ocean import ocean
from port_ocean.utils import http_async_client

PAGE_SIZE = 50
WEBHOOK_NAME = "Port-Ocean-Events-Webhook"
REQUEST_TIMEOUT = 120


CREATE_UPDATE_WEBHOOK_EVENTS = [
"jira:issue_created",
"jira:issue_updated",
"project_created",
"project_updated",
"project_restored_deleted",
"project_restored_archived",
]

DELETE_WEBHOOK_EVENTS = [
"jira:issue_deleted",
"project_deleted",
"project_soft_deleted",
"project_archived",
]

WEBHOOK_EVENTS = [
*CREATE_UPDATE_WEBHOOK_EVENTS,
*DELETE_WEBHOOK_EVENTS,
]


class JiraClient:
def __init__(self, jira_url: str, jira_email: str, jira_token: str) -> None:
self.jira_url = jira_url
self.agile_url = f"{self.jira_url}/rest/agile/1.0"
self.jira_rest_url = f"{self.jira_url}/rest"
self.detail_base_url = f"{self.jira_rest_url}/api/3"

self.jira_api_auth = BasicAuth(jira_email, jira_token)
self.webhooks_url = f"{self.jira_rest_url}/webhooks/1.0/webhook"

self.client = http_async_client
self.client.auth = self.jira_api_auth
self.client.timeout = Timeout(REQUEST_TIMEOUT)

@staticmethod
def _generate_base_req_params(
maxResults: int = 50, startAt: int = 0
) -> dict[str, Any]:
return {
"maxResults": maxResults,
"startAt": startAt,
}

async def _make_paginated_request(
self,
url: str,
params: dict[str, Any] = {},
is_last_function: typing.Callable[
[dict[str, Any]], bool
] = lambda response: response["isLast"],
) -> AsyncGenerator[dict[str, list[dict[str, Any]]], None]:
params = {**self._generate_base_req_params(), **params}
is_last = False
logger.info(f"Making paginated request to {url} with params: {params}")
while not is_last:
try:
response = await self.client.get(url, params=params)
response.raise_for_status()
response_data = response.json()
yield response_data
is_last = is_last_function(response_data)
start = response_data["startAt"] + response_data["maxResults"]
params = {**params, "startAt": start}
logger.info(f"Next page startAt: {start}")
except httpx.HTTPStatusError as e:

logger.error(
f"HTTP error with status code: {e.response.status_code}"
f" and response text: {e.response.text}"
)
raise
except httpx.HTTPError as e:
logger.error(f"HTTP occurred while fetching Jira data {e}")
raise
logger.info("Finished paginated request")
return

async def get_all_projects(self) -> AsyncGenerator[list[dict[str, Any]], None]:
async for projects in self._make_paginated_request(
f"{self.detail_base_url}/project/search"
):
yield projects["values"]

async def get_all_issues(
self,
params: dict[str, Any] = {},
) -> AsyncGenerator[list[dict[str, Any]], None]:
async for issues in self._make_paginated_request(
f"{self.detail_base_url}/search",
params=params,
is_last_function=lambda response: response["startAt"]
+ response["maxResults"]
>= response["total"],
):
yield issues["issues"]

async def _get_single_item(self, url: str) -> dict[str, Any]:
try:
response = await self.client.get(url)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError as e:
logger.error(
f"HTTP error on {url}: {e.response.status_code} - {e.response.text}"
)
raise
except httpx.HTTPError as e:
logger.error(f"HTTP occurred while fetching Jira data {e}")
raise

async def get_single_project(self, project: str) -> dict[str, Any]:
return await self._get_single_item(f"{self.detail_base_url}/project/{project}")

async def get_single_issue(self, issue: str) -> dict[str, Any]:
return await self._get_single_item(f"{self.agile_url}/issue/{issue}")

async def create_events_webhook(self, app_host: str) -> None:
webhook_target_app_host = f"{app_host}/integration/webhook"
webhook_check_response = await self.client.get(f"{self.webhooks_url}")
webhook_check_response.raise_for_status()
webhook_check = webhook_check_response.json()

for webhook in webhook_check:
if webhook["url"] == webhook_target_app_host:
logger.info("Ocean real time reporting webhook already exists")
return

body = {
"name": f"{ocean.config.integration.identifier}-{WEBHOOK_NAME}",
"url": webhook_target_app_host,
"events": WEBHOOK_EVENTS,
}

webhook_create_response = await self.client.post(
f"{self.webhooks_url}", json=body
)
webhook_create_response.raise_for_status()
logger.info("Ocean real time reporting webhook created")
29 changes: 28 additions & 1 deletion integrations/jira/integration.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
from typing import Literal

from port_ocean.core.handlers.port_app_config.api import APIPortAppConfig
from port_ocean.core.handlers.port_app_config.models import (
PortAppConfig,
ResourceConfig,
Selector,
)
from port_ocean.core.integrations.base import BaseIntegration
from pydantic.fields import Field


class JiraIssueSelector(Selector):
jql: str | None = Field(
description="Jira Query Language (JQL) query to filter issues",
)
fields: str | None = Field(
description="Additional fields to be included in the API response",
default="*all",
)


class JiraIssueResourceConfig(ResourceConfig):
kind: Literal["issue"]
selector: JiraIssueSelector


from jira.overrides import JiraPortAppConfig
class JiraPortAppConfig(PortAppConfig):
resources: list[JiraIssueResourceConfig | ResourceConfig] = Field(
default_factory=list
)


class JiraIntegration(BaseIntegration):
Expand Down
Empty file.
147 changes: 0 additions & 147 deletions integrations/jira/jira/client.py

This file was deleted.

Loading