Skip to content

Commit

Permalink
Merge pull request #2 from port-labs/PORT-5117-creating-jira-tickets-…
Browse files Browse the repository at this point in the history
…based-on-scorecards

Port 5117 creating jira tickets based on scorecards

Initiatives integration with Jira
  • Loading branch information
matarpeles authored Dec 4, 2023
2 parents 1ee21f1 + 7743ad9 commit c2d5852
Show file tree
Hide file tree
Showing 28 changed files with 842 additions and 171 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/generate-scorecard-reminder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Generate Scorecards Reminders
uses: port-labs/port-sender@v0.1.15
uses: port-labs/port-sender@v0.2.0
with:
message_kind: scorecard_reminder
operation_kind: scorecard_reminder
port_client_id: ${{ secrets.PORT_CLIENT_ID }}
port_client_secret: ${{ secrets.PORT_CLIENT_SECRET }}
slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
blueprint: app
scorecard: productionReadiness
filter_rule: '{"property": "$team","operator": "containsAny","value": ["Backend Team"]}'
filter_rule: '{"property": "$team","operator": "containsAny","value": ["Backend Team"]}'
6 changes: 3 additions & 3 deletions .github/workflows/generate-scorecard-report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Generate Scorecard Report
uses: port-labs/port-sender@v0.1.15
uses: port-labs/port-sender@v0.2.0
with:
message_kind: scorecard_report
operation_kind: scorecard_report
port_client_id: ${{ secrets.PORT_CLIENT_ID }}
port_client_secret: ${{ secrets.PORT_CLIENT_SECRET }}
slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
blueprint: app
scorecard: productionReadiness
scorecard: productionReadiness
25 changes: 25 additions & 0 deletions .github/workflows/sync-jira-issues.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Sync Jira issues based on scorecards


on:
workflow_dispatch:

jobs:
sync-jira-issues:
runs-on: ubuntu-latest
steps:
- name: Sync Jira Issues
uses: port-labs/[email protected]
with:
operation_kind: ticket_handler
port_client_id: ${{ secrets.PORT_CLIENT_ID }}
port_client_secret: ${{ secrets.PORT_CLIENT_SECRET }}
blueprint: app
scorecard: productionReadiness
filter_rule: '{"property": "$team","operator": "containsAny","value": ["AAA"]}'
jira_api_endpoint: https://getport.atlassian.net
jira_email: [email protected]
jira_project_id: DEMO
jira_token: {{ secrets.JIRA_TOKEN }}

target_kind: jira
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ Thumbs.db
# IDE files
.idea
.vscode
*.code-workspace
*.code-workspace

#Pycache
*__pycache__*
.pyc
96 changes: 85 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<img align="right" width="100" height="74" src="https://user-images.githubusercontent.com/8277210/183290025-d7b24277-dfb4-4ce1-bece-7fe0ecd5efd4.svg" />

# Port Message Sender GitHub Action
# Port Initiatives Sender GitHub Action

[![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge&logo=slack&logoColor=white)](https://join.slack.com/t/devex-community/shared_invite/zt-1bmf5621e-GGfuJdMPK2D8UN58qL4E_g)

Expand Down Expand Up @@ -44,7 +44,7 @@ Action to send a scorecard report to a Slack channel about the current state and
| `slack_webhook_url` | Slack Webhook URL | true | |
| `blueprint` | Blueprint identifier | true | |
| `scorecard` | Scorecard identifier | true | |
| `message_kind` | Message kind to send, to send Scorecard Report, pass - `scorecard_report` | true | |
| `operation_kind` | Message kind to send, to send Scorecard Report, pass - `scorecard_report` | true | |
| `filter_rule` | The [rule filter](https://docs.getport.io/search-and-query/#rules) to apply on the data queried from Port | false | |

This action will send a scorecard report to a Slack channel about the current state and progress in a scorecard.
Expand Down Expand Up @@ -86,15 +86,15 @@ A call to action to remind the team that some of their services didn't reach Gol
### Usage
| Input | Description | Required | Default |
|----------------------|------------------------------------------------------------------------------|----------|---------|
| `port_client_id` | Port Client ID | true | |
| `port_client_secret` | Port Client Secret | true | |
| `port_region` | Port Region to use, if not provided will use the default region of Port | false | eu |
| `slack_webhook_url` | Slack Webhook URL | true | |
| `blueprint` | Blueprint identifier | true | |
| `scorecard` | Scorecard identifier | true | |
| `message_kind` | Message kind to send, to send Scorecard Reminder, pass - `scorecard_reminder` | true | |
| Input | Description | Required | Default |
|----------------------|-----------------------------------------------------------------------------------------------------------|----------|---------|
| `port_client_id` | Port Client ID | true | |
| `port_client_secret` | Port Client Secret | true | |
| `port_region` | Port Region to use, if not provided will use the default region of Port | false | eu |
| `slack_webhook_url` | Slack Webhook URL | true | |
| `blueprint` | Blueprint identifier | true | |
| `scorecard` | Scorecard identifier | true | |
| `operation_kind` | Opetation kind to perform, to send Scorecard Reminder, pass - `scorecard_reminder` | true | |
| `filter_rule` | The [rule filter](https://docs.getport.io/search-and-query/#rules) to apply on the data queried from Port | false | |

This example will send a scheduled reminder to a Slack channel about all the services that didn't reach the Gold level in the `productionReadiness` scorecard for the Backend Team.
Expand Down Expand Up @@ -127,4 +127,78 @@ jobs:
filter_rule: '{"property": "$team","operator": "containsAny","value": ["Backend Team"]}'
```


## Manage scorecards with Jira issues
A call to action to sync Jira issues (create/reopen/resolve) with scorecards and rules.

For every scorecard level that is not completed, a Jira task will be created and Subtasks for the level rules.

### Output example

Generated Scorecard task for the bronze level:
![Jira Task](docs/assets/jira-sync-task.png)

Generated subtasks for the task:
![Jira Subtask](docs/assets/jira-sync-subtask.png)



### Usage

| Input | Description | Required | Default |
|------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|---------|
| `port_client_id` | Port Client ID | true | |
| `port_client_secret` | Port Client Secret | true | |
| `port_region` | Port Region to use, if not provided will use the default region of Port | false | eu |
| `slack_webhook_url` | Slack Webhook URL | true | |
| `blueprint` | Blueprint identifier | true | |
| `scorecard` | Scorecard identifier | true | |
| `opeation_kind` | Message kind to send, to send Scorecard Reminder, pass - `scorecard_reminder` | true | |
| `filter_rule` | The [rule filter](https://docs.getport.io/search-and-query/#rules) to apply on the data queried from Port | false | |
| `jira_project_id` | The [project id](https://confluence.atlassian.com/jirakb/how-to-get-project-id-from-the-jira-user-interface-827341414.html) in Jira for tasks updating | true | |
| `jira_api_endpoint` | The URL of your Jira organization | true | |
| `jira_token` | The [Jira API token ](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/)for using Jira's REST API. | true | |
| `jira_email` | The Jira email of the user account for using Jira's REST API. | true | |
| `jira_resolve_transition_id` | The Jira [transition](https://support.atlassian.com/jira-software-cloud/docs/transition-an-issue/) ID used for resolving issues. If not inserted will use the default transition for the "Done" status. | false | |
| `jira_reopen_transition_id` | The Jira [transition](https://support.atlassian.com/jira-software-cloud/docs/transition-an-issue/) ID used for resolving issues. If not inserted will use the default transition for the "To Do" status. | false | |

This example will create a Jira task for every service in every level that are not completed in the `productionReadiness` scorecard for the Backend Team.
For every rule in the scorecard that is not completed, a subtask under the relevant task in Jira will be created.
Once the scorecard is completed, the tasks and subtasks will be resolved (passed to Done status).

You can modify the schedule to run the reminder on a daily/weekly/monthly basis. For more information about scheduling, refer to the [GitHub Actions documentation](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule).

You can also modify the filter rule to filter the services, ideally you would want to filter by team, so that each team will get a reminder about their services.

```yaml
name: Sync Jira Issues with Scorecard Initiatives
on:
schedule:
## run every day at 9am
- cron: '0 9 * * *'
workflow_dispatch:
jobs:
sync-jira-issues:
runs-on: ubuntu-latest
steps:
- name: Sync Jira Issues
uses: port-labs/[email protected]
with:
operation_kind: ticket_handler
port_client_id: ${{ secrets.PORT_CLIENT_ID }}
port_client_secret: ${{ secrets.PORT_CLIENT_SECRET }}
blueprint: app
scorecard: productionReadiness
filter_rule: '{"property": "$team","operator": "containsAny","value": ["Backend Team"]}'
jira_api_endpoint: https://example.atlassian.net
jira_email: [email protected]
jira_project_id: EXAMPLE
jira_token: MY-JIRA-TOKEN
target_kind: jira
```

You can find more examples in the [examples folder](docs/examples/)
18 changes: 13 additions & 5 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
from enum import Enum
from typing import List, Union, Optional
from typing import List, Union

from pydantic import Field, BaseModel
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings


class MessageKind(str, Enum):
class OperationKind(str, Enum):
scorecard_reminder = "scorecard_reminder"
scorecard_report = "scorecard_report"
ticket_creator = "ticket_handler"


class TargetKind(str, Enum):
slack = "slack"
jira = "jira"


class FilterRule(BaseModel):
Expand All @@ -23,12 +25,18 @@ class FilterRule(BaseModel):
class Settings(BaseSettings):
port_client_id: str
port_client_secret: str
slack_webhook_url: str
slack_webhook_url: str = ""
jira_project_id: str = ""
jira_api_endpoint: str = "https://jira.com"
jira_email: str = ""
jira_resolve_transition_id: str = ""
jira_reopen_transition_id: str = ""
jira_token: str = ""
port_region: str = "eu"
blueprint: str
scorecard: str
filter_rule: Union[FilterRule, str, None] = Field(default=None)
message_kind: MessageKind = MessageKind.scorecard_reminder
operation_kind: OperationKind = OperationKind.scorecard_reminder
target_kind: TargetKind = TargetKind.slack

class Config:
Expand Down
37 changes: 37 additions & 0 deletions core/base_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import logging

from config import settings
from port.client import PortClient

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class BaseHandler:
def __init__(self):
logger.info("Initializing Port client")
port_client = PortClient(
settings.port_region,
settings.port_client_id,
settings.port_client_secret
)
logger.info(
f"Fetching entities for query:"
f" {settings.filter_rule},"
f" blueprint {settings.blueprint},"
f" scorecard {settings.scorecard}"
)
search_query = {
"combinator": "and",
"rules": [
{"property": "$blueprint",
"operator": "=", "value": settings.blueprint}
],
}
if settings.filter_rule:
search_query["rules"].append(settings.filter_rule.dict())

self.entities = port_client.search_entities(search_query)
self.scorecard = port_client.get_scorecard(
settings.blueprint, settings.scorecard
).get("scorecard")
84 changes: 0 additions & 84 deletions core/handler.py

This file was deleted.

Loading

0 comments on commit c2d5852

Please sign in to comment.