Is Software Development Just a Side Quest? A Jira Story
You're not alone if you've ever felt like software development is just a side quest in a much larger game—where stakeholders are NPCs, deadlines are boss fights, and your Jira board is the quest log. But what if we told you that mastering Jira isn’t just about checking boxes? It’s about turning chaos into clarity, one ticket at a time.
In this beginner-friendly, code-heavy tutorial, we’ll walk through how to go from a blank Jira board to a fully automated workflow using real-world tools. You’ll learn how to:
- Create and manage Jira issues programmatically
- Automate status transitions
- Integrate with GitHub using webhooks
- Turn your dev work into a tracked, repeatable process
Let’s turn that side quest into the main story.
Step 1: Set Up Your Jira Project
First, log into your Jira instance (we’ll assume you’re using Jira Cloud). Create a new project:
- Click Projects → Create Project
- Choose Software Development
- Name it
QuestTracker - Select Scrum or Kanban (we’ll use Scrum)
Now, you have a board. But we want to automate it.
Step 2: Generate an API Token
To interact with Jira via code, you need authentication.
- Go to https://id.atlassian.com/manage-profile/security/api-tokens
- Click Create API token
- Name it
quest-automation - Copy the generated token
Store this securely. We’ll use it in code.
Step 3: Install Required Tools
We’ll use Python and the jira library. Install it:
pip install jira
Create a .env file to store credentials:
JIRA_SERVER=https://your-domain.atlassian.net
JIRA_EMAIL=your-email@example.com
JIRA_TOKEN=your-api-token-here
Install python-dotenv:
pip install python-dotenv
Step 4: Connect to Jira and Create a "Bug Hunt" Issue
Create a file jira_quest.py:
from jira import JIRA
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Jira connection
jira = JIRA(
server=os.getenv("JIRA_SERVER"),
basic_auth=(os.getenv("JIRA_EMAIL"), os.getenv("JIRA_TOKEN"))
)
# Create a new issue
issue = jira.create_issue(
project="QT", # Your project key (e.g., QuestTracker → QT)
summary="Fix login timeout bug",
description="Users report being logged out after 2 minutes. Should be 30 mins.",
issuetype={"name": "Bug"},
priority={"name": "High"}
)
print(f"Issue {issue.key} created: {issue.permalink()}")
Run it:
python jira_quest.py
Output:
Issue QT-1 created: https://your-domain.atlassian.net/browse/QT-1
You’ve just turned a vague complaint into a tracked quest.
Step 5: Automate Status Transitions
Let’s move the issue from "To Do" to "In Progress" when you start coding.
Add this to your script:
# Transition issue to "In Progress"
transition_id = None
transitions = jira.transitions(issue)
for t in transitions:
if t['name'] == 'Start Progress':
transition_id = t['id']
break
if transition_id:
jira.transition_issue(issue, transition_id)
print(f"Issue {issue.key} moved to In Progress")
else:
print("No 'Start Progress' transition found")
Now your code reflects your workflow.
Step 6: Link GitHub Commits to Jira
Jira auto-links commits if your branch or commit message contains the issue key.
Create a branch:
git checkout -b fix/QT-1-login-timeout
Make a change in your code (e.g., auth.py):
# auth.py
SESSION_TIMEOUT_MINUTES = 30 # Was 2
Commit with the issue key:
git add auth.py
git commit -m "Fix QT-1: Extend session timeout to 30 minutes"
git push origin fix/QT-1-login-timeout
Go to your Jira issue QT-1. You’ll see:
Linked commits:
fix QT-1: Extend session timeout...onfix/QT-1-login-timeout
Magic? No. Just discipline.
Step 7: Auto-Close Issue on Pull Request Merge
We’ll simulate a webhook that closes the issue when a PR is merged.
Create webhook_handler.py:
python
from flask import Flask, request
import requests
import json
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def jira_webhook():
data = request.json
# Check if it's a merged PR
if data.get('action') == 'closed' and data.get('pull_request', {}).get('merged'):
pr_title = data['pull_request']['title']
repo_name = data['repository']['name']
# Extract issue key (e.g., QT-1)
import re
match = re.search(r'(QT-\d+)', pr_title)
if match
---
☕ We're building a community of innovators and problem-solvers together, and every cup of coffee purchased at
Top comments (0)