Skip to content

Commit 4abeb6f

Browse files
DEVOPS-66 Initial Commit
1 parent a6ff6c4 commit 4abeb6f

File tree

8 files changed

+739
-3
lines changed

8 files changed

+739
-3
lines changed

.github/dependabot.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "pip"
4+
directory: /
5+
schedule:
6+
interval: "weekly"
7+
day: wednesday
8+
time: "11:20"
9+
timezone: Asia/Kolkata
10+
# Assignees to set on pull requests
11+
assignees:
12+
- "githubofkrishnadhas"
13+
# prefix specifies a prefix for all commit messages. When you specify a prefix for commit messages,
14+
# GitHub will automatically add a colon between the defined prefix and the commit message provided the
15+
# defined prefix ends with a letter, number, closing parenthesis, or closing bracket.
16+
commit-message:
17+
prefix: "dependabot python package"
18+
# Use reviewers to specify individual reviewers or teams of reviewers for all pull requests raised for a package manager.
19+
reviewers:
20+
- "devwithkrishna/admin"
21+
# Raise pull requests for version updates to pip against the `main` branch
22+
target-branch: "main"
23+
# Labels on pull requests for version updates only
24+
labels:
25+
- "pip dependencies"
26+
- "pip-package"
27+
# Increase the version requirements for Composer only when required
28+
versioning-strategy: increase-if-necessary
29+
# Dependabot opens a maximum of five pull requests for version updates. Once there are five open pull requests from Dependabot,
30+
# Dependabot will not open any new requests until some of those open requests are merged or closed.
31+
# Use open-pull-requests-limit to change this limit.
32+
open-pull-requests-limit: 10
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Jira Issue Creation
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
TYPE_OF_ISSUE:
7+
description: 'Type of Jira issue to be created (Epic, Task, Subtask)'
8+
type: choice
9+
options:
10+
- "Epic"
11+
- "Task"
12+
- "Subtask"
13+
required: true
14+
JIRA_BOARD:
15+
description: 'Your Jira board key'
16+
type: string
17+
required: true
18+
ISSUE_SUMMARY:
19+
description: 'Issue summary'
20+
type: string
21+
required: true
22+
ISSUE_DESCRIPTION:
23+
description: 'Issue description'
24+
type: string
25+
required: true
26+
EPIC_KEY:
27+
description: 'Jira EPIC id to attach issue'
28+
type: string
29+
required: false
30+
STORY_KEY:
31+
type: string
32+
description: 'Jira story key to attach sub task'
33+
required: false
34+
35+
jobs:
36+
create-jira-issue:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@v4
41+
42+
- name: Set up Python
43+
uses: actions/setup-python@v4
44+
with:
45+
python-version: '3.11' # Specify the Python version you need
46+
47+
- name: Install dependencies
48+
run: |
49+
pip install poetry
50+
poetry install
51+
52+
- name: Run Jira Issue Creation Script
53+
env:
54+
JIRA_URL: ${{ secrets.JIRA_URL }}
55+
JIRA_USERNAME: ${{ secrets.JIRA_USERNAME }}
56+
JIRA_PASSWORD: ${{ secrets.JIRA_PASSWORD }}
57+
EPIC_KEY_OPTION: ${{ github.event.inputs.EPIC_KEY && format('--epic_key {}', github.event.inputs.EPIC_KEY) || '' }}
58+
STORY_KEY_OPTION: ${{ github.event.inputs.STORY_KEY && format('--story_key {}', github.event.inputs.STORY_KEY) || '' }}
59+
60+
run: |
61+
poetry run python3 jira.py --type_of_issue ${{ github.event.inputs.TYPE_OF_ISSUE }} \
62+
--jira_board ${{ github.event.inputs.JIRA_BOARD }} \
63+
--summary "${{ github.event.inputs.ISSUE_SUMMARY }}" \
64+
--description "${{ github.event.inputs.ISSUE_DESCRIPTION }}" \
65+
$EPIC_KEY_OPTION \
66+
$STORY_KEY_OPTION
67+
- name: Process completed
68+
run: |
69+
echo "Script execution completed"

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,4 @@ cython_debug/
157157
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158158
# and can be added to the global gitignore or merged into this file. For a more nuclear
159159
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
160-
#.idea/
160+
.idea/

README.md

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,74 @@
1-
# programatically-create-jira-issues-from-github
2-
Create jira issues like stories epic sub tasks etc from GitHub
1+
# programatically-create-jira-issues-from-githu
2+
Programatically create jira issues from Github
3+
4+
# What code does
5+
6+
* The code leverages `atlassian-python-api`sdk along with python to create jira issues like `Task (Story)`, `Sub Task`, `Epic`
7+
8+
# Parameters required for program
9+
10+
| Argument | Description | Mandatory or not |
11+
| ---------|---------------------------------------------------|------------------|
12+
| type_of_issue | Type of issue like Epic, sub task or story (Task) ||
13+
| jira_board | In which Jira board you want to create issues ||
14+
| epic_key | Epic id if story needs to be attached ||
15+
| summary | Issue summary ||
16+
| description | Issue description ||
17+
| story_key | Jira story key to attach sub task ||
18+
19+
## Installation (How to use it locally)
20+
21+
1. Clone the repository:
22+
23+
```bash
24+
git clone <repository-url>
25+
cd <repository-directory>
26+
```
27+
28+
2. Install the required Python packages:
29+
30+
* If poetry is not installed locally, do `pip install poetry`
31+
32+
then,
33+
```bash
34+
poetry install
35+
```
36+
37+
have a look here - https://python-poetry.org/
38+
39+
3. Create a `.env` file in the root directory and add your Jira credentials:
40+
41+
```plaintext
42+
JIRA_URL=<your-jira-url>
43+
JIRA_USERNAME=<your-jira-username>
44+
JIRA_PASSWORD=<your-jira-password>
45+
```
46+
##### **_Ensure that your Jira credentials are correctly set in the .env file._**
47+
48+
49+
## Usage
50+
51+
To run the script, use the following command:
52+
53+
```bash
54+
python <script_name>.py --type_of_issue <issue_type> --jira_board <board_key> --summary <issue_summary> --description <issue_description> [--epic_key <epic_key>] [--story_key <story_key>]
55+
```
56+
57+
## Example Commands
58+
Create an Epic:
59+
60+
```bash
61+
python create_jira_issue.py --type_of_issue Epic --jira_board BOARD_KEY --summary "Epic Summary" --description "Epic Description"
62+
```
63+
64+
Create a Task under an Epic:
65+
66+
```bash
67+
python create_jira_issue.py --type_of_issue Task --jira_board BOARD_KEY --epic_key EPIC_KEY --summary "Task Summary" --description "Task Description"
68+
```
69+
70+
Create a Subtask under a Task:
71+
72+
```bash
73+
python create_jira_issue.py --type_of_issue Subtask --jira_board BOARD_KEY --story_key STORY_KEY --summary "Subtask Summary" --description "Subtask Description"
74+
```

date_time.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from datetime import datetime
2+
3+
def date_time():
4+
"""return current date time formatted"""
5+
now = datetime.now()
6+
formatted_datetime = now.strftime("%d-%B-%Y %H:%M")
7+
return formatted_datetime
8+
# print(formatted_datetime)
9+
10+
def main():
11+
""" test code """
12+
date_time()
13+
14+
if __name__ == "__main__":
15+
main()

jira.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import os
2+
import argparse
3+
from dotenv import load_dotenv
4+
from atlassian import Jira
5+
from date_time import date_time
6+
7+
8+
def create_story_under_epic(epic_key: str, summary:str, description:str, jira_board:str):
9+
"""
10+
create a story (Task) attaching it to a specific epic
11+
:param epic_key:
12+
:param summary:
13+
:param description:
14+
:param jira_board:
15+
:return:
16+
"""
17+
# Initialize Jira
18+
JIRA_URL = os.getenv('JIRA_URL')
19+
JIRA_USERNAME = os.getenv('JIRA_USERNAME')
20+
JIRA_PASSWORD = os.getenv('JIRA_PASSWORD')
21+
jira = Jira(url=os.getenv('JIRA_URL'), username=os.getenv('JIRA_USERNAME'), password=os.getenv('JIRA_PASSWORD'),
22+
cloud=True)
23+
24+
issue_dict = {
25+
'project': {'key': jira_board },
26+
'summary': summary,
27+
'description': description,
28+
'issuetype': {'name': 'Task'},
29+
'parent': {
30+
"key": epic_key
31+
}
32+
}
33+
new_issue = jira.issue_create(fields=issue_dict)
34+
35+
return new_issue
36+
37+
def create_epic(summary:str, description:str, jira_board:str):
38+
"""
39+
Create an Epic under a specific Jira board
40+
:param summary:
41+
:param description:
42+
:param jira_board:
43+
:return:
44+
"""
45+
# Initialize Jira
46+
JIRA_URL = os.getenv('JIRA_URL')
47+
JIRA_USERNAME = os.getenv('JIRA_USERNAME')
48+
JIRA_PASSWORD = os.getenv('JIRA_PASSWORD')
49+
jira = Jira(url=os.getenv('JIRA_URL'), username=os.getenv('JIRA_USERNAME'), password=os.getenv('JIRA_PASSWORD'),
50+
cloud=True)
51+
52+
issue_dict = {
53+
'project': {'key': jira_board },
54+
'summary': summary,
55+
'description': description,
56+
'issuetype': {'name': 'Epic'}
57+
}
58+
new_issue = jira.issue_create(fields=issue_dict)
59+
60+
return new_issue
61+
62+
63+
def create_subtask_under_story( summary:str, description:str, jira_board:str, story_key:str):
64+
"""
65+
Create a sub task on a Jira story
66+
:param summary:
67+
:param description:
68+
:param jira_board:
69+
:param story_key:
70+
:return:
71+
"""
72+
# Initialize Jira
73+
JIRA_URL = os.getenv('JIRA_URL')
74+
JIRA_USERNAME = os.getenv('JIRA_USERNAME')
75+
JIRA_PASSWORD = os.getenv('JIRA_PASSWORD')
76+
jira = Jira(url=os.getenv('JIRA_URL'), username=os.getenv('JIRA_USERNAME'), password=os.getenv('JIRA_PASSWORD'),
77+
cloud=True)
78+
79+
issue_dict = {
80+
'project': {'key': jira_board },
81+
'summary': summary,
82+
'description': description,
83+
'issuetype': {'name': 'Subtask'},
84+
'parent': {
85+
"key": story_key
86+
}
87+
}
88+
new_issue = jira.issue_create(fields=issue_dict)
89+
90+
return new_issue
91+
92+
93+
def main():
94+
"""testing script"""
95+
# Initializing jira client
96+
load_dotenv()
97+
parser = argparse.ArgumentParser("Programatically create Jira Issues")
98+
parser.add_argument("--type_of_issue", help="Type of Jira issue to be created", choices=["Epic", "Task", "Subtask"], required=True)
99+
parser.add_argument("--jira_board", help="Your Jira board Key", required=True, type=str)
100+
parser.add_argument("--epic_key", help="Jira EPIC id to attach issue", required=False, type=str)
101+
parser.add_argument("--summary", help="Issue summary", required=True, type=str)
102+
parser.add_argument("--description", help="Issue description", required=True, type=str)
103+
parser.add_argument("--story_key", help="Jira story key to attach sub task", type=str, required=False)
104+
105+
args = parser.parse_args()
106+
jira_board = args.jira_board
107+
epic_key = args.epic_key
108+
summary = args.summary
109+
description = args.description
110+
story_key = args.story_key
111+
type_of_issue = args.type_of_issue
112+
113+
if type_of_issue == 'Epic':
114+
# Create Epic
115+
epic = create_epic(summary, description, jira_board)
116+
print(f"Created Epic {epic['key']} on jira board {jira_board} at {date_time()} IST")
117+
elif type_of_issue == "Task":
118+
if not epic_key:
119+
raise ValueError("epic_key is required for creating a Task")
120+
# Create the story attaching to an epic
121+
story = create_story_under_epic(epic_key, summary, description, jira_board)
122+
print(f"Created story {story['key']} with epic {epic_key} at {date_time()} IST")
123+
else:
124+
if not story_key:
125+
raise ValueError("story_key is required for creating a Subtask")
126+
# Create Sub task under a story
127+
sub_task = create_subtask_under_story(summary, description, jira_board, story_key=story_key)
128+
print(f"Created story {sub_task['key']} under epic {epic_key} at {date_time()} IST")
129+
130+
131+
132+
if __name__ == "__main__":
133+
main()

0 commit comments

Comments
 (0)