Python ile Jira Zaman Takibi Otomasyonu: Günlük API ve Cron Tabanlı Çözüm
Hazırlayan: Burak Ceviz — DevSecOps Engineer — Sekom
Jira üzerinde günlük zaman takibini manuel olarak yapmak hem zaman kaybına neden olur hem de hata riskini artırır. Bu yazıda, Python ile geliştirilen bir otomasyon script’i aracılığıyla Jira’daki işlerinize otomatik olarak zaman kaydı nasıl yapılır, adım adım öğreneceksiniz.
Script, Jira REST API, cron zamanlayıcı, resmî tatil kontrolü, e-posta ve Microsoft Teams bildirimleri gibi özelliklerle donatılmıştır. Böylece hafta içi her gün, tanımladığınız Jira görevlerine çalışma süresi otomatik olarak işlenir. Üstelik bu çözüm, teknik bilgi seviyesi ne olursa olsun her ekip üyesi tarafından kolaylıkla uygulanabilir.
Otomasyon şu özellikleri içerecek:
● Hafta içi günlerinde otomatik zaman girişi
● Resmî tatillere duyarlı çalışma
● Günlük e-posta bilgilendirmeleri
● Cron kullanılarak zamanlanmış çalıştırma
Microsoft Teams bildirimleri (e-posta alternatifi olarak) sayesinde, Jira REST API kullanılarak belirli Jira işlerine günlük çalışma süresi otomatik olarak kaydedilir. Otomasyon şu işlevleri içerir:
● Hafta içi günlerinde otomatik zaman kaydı
● Resmî tatil günlerine duyarlılık
● Günlük e-posta bildirimleri
● Cron ile zamanlanmış çalıştırma
Bu eğitimin sonunda, Jira ile sorunsuz şekilde entegre olan sağlam bir günlük takip çözümüne sahip olacaksınız.
✨ Kullanılan Teknolojiler
● Python 3
● Jira REST API
● Crontab (Linux)
● SMTP (e-posta uyarıları için)
● Microsoft Teams Giriş Webhook’u (opsiyonel e-posta alternatifi)
🔑 Ön Koşul: Jira API Token Oluşturma
Jira REST API’yi kullanabilmek için Atlassian hesabınızdan bir API token oluşturmanız gerekir.
Token oluşturma adımları:
- https://id.atlassian.com/manage/api-tokens adresine gidin
- “Create API token” butonuna tıklayın
- “jira-worklog-script” gibi bir etiket verin
- “Create” ve ardından “Copy” butonlarına tıklayın
- Token’ı güvenli bir yerde saklayın — bu token’ı şifre yerine kullanacaksınız
Bu token, Jira API istekleri sırasında Basic Auth yönteminde şifre olarak kullanılacak. Kullanıcı adınız ise e-posta adresiniz olacak.
Olası Güvenlik Riskleri ve API Token Yönetimi
Script’te API_TOKEN, EMAIL gibi hassas bilgiler düz metin olarak yazıldığında güvenlik riski doğar. Bu nedenle çevresel değişken (.env) kullanımı tavsiye edilir.
🔐 dotenv Kullanımı:
1).env dosyası oluştur:
ini
JIRA_EMAIL=you@example.com
JIRA_API_TOKEN=abc123xyz456
2) python-dotenv ile içeri aktar:
from dotenv import load_dotenv
import os
load_dotenv()
EMAIL = os.getenv("JIRA_EMAIL")
API_TOKEN = os.getenv("JIRA_API_TOKEN")
Böylece token’lar kaynak koddan ayrılır ve sürüm kontrolüne dahil edilmez.
📅 Script’in Genel Yapısı
Python dosyasında tanımlanan Jira görev listesi şu alanları içerir:
● key: Jira iş anahtarı (örneğin: Project-46)
● hour: Başlangıç saati
● duration: Harcanan süre (örn: “30m”)
● comment: Jira iş kaydına eklenecek açıklama
ISSUES = [
{"key": "Project-46", "hour": time(9, 30), "duration": "30m", "comment": "Daily stand-up meeting."}, {"key": "DEVSECOPS-4646", "hour": time(10, 0), "duration": "40m", "comment": "Documentation and planning."}, {"key": "Operation-160", "hour": time(11, 0), "duration": "20m", "comment": "Email reviews and responses."}]
Script, /rest/api/3/issue/{issueIdOrKey}/worklog endpoint’ini kullanarak bu girişleri Jira’ya işler. Hafta sonu veya resmi tatillerde giriş yapılmaz. Başarılı girişlerin özeti günlük e-posta ile gönderilir.
Yılın son günü (31 Aralık) için özel bir uyarı da eklidir:
📌 Yeni yıl için tatil listesi güncellenmeli!
Jira İş Anahtarları Otomatik Olarak Nasıl Alınır?
Statik ISSUES = […] listesi yerine, Jira’dan aktif işleri çekmek mümkündür. Örneğin belirli bir kullanıcıya atanan işleri çekmek için aşağıdaki gibi bir JQL kullanılabilir:
🧠 Örnek Python Fonksiyonu:
def get_user_issues(email, token):
jql = 'assignee = currentUser() AND statusCategory != Done ORDER BY updated DESC'
url = f"{JIRA_URL}/rest/api/3/search?jql={jql}"
headers = {"Content-Type": "application/json"}
response = requests.get(url, headers=headers, auth=(email, token))
issues = response.json().get("issues", [])
return [{"key": i["key"], "summary": i["fields"]["summary"]} for i in issues]
Bu yöntemle ISSUES listesini otomatik doldurabilir, zaman kaydı dinamikleştirilebilir.
🔧 Tam Python Script’i
Belgedeki tam script dilersen Türkçe açıklamalarla birlikte de hazırlanabilir. Kod içerisinde SMTP ayarları, Teams entegrasyonu, tarih kontrolü ve hata yönetimi dahil birçok ayrıntı yer alıyor.
import requests
import smtplib
from email.mime.text import MIMEText
from datetime import datetime, time, timedelta, timezone
JIRA_URL = "https://yourcompany.atlassian.net"
EMAIL = "your.email@company.com"
API_TOKEN = "your_api_token_here"ISSUES = [
{"key": "Project-46", "hour": time(9, 30), "duration": "30m", "comment": "Daily stand-up meeting."},
{"key": "DEVSECOPS-4646", "hour": time(10, 0), "duration": "40m", "comment": "Documentation and planning."},
{"key": "Operation-160", "hour": time(11, 0), "duration": "20m", "comment": "Email reviews and responses."}
]SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 587
MAIL_USERNAME = "your.email@company.com"
MAIL_PASSWORD = "your_app_password"
MAIL_TO = "your.email@company.com"
MAIL_FROM = "your.email@company.com"HOLIDAYS = [
"2025-04-01", "2025-04-23", "2025-05-01", "2025-05-19",
"2025-06-05", "2025-06-06", "2025-06-09", "2025-07-15",
"2025-10-28", "2025-10-29", "2025-12-31"
]turkey_tz = timezone(timedelta(hours=3))
today = datetime.now(turkey_tz)
today_str = today.strftime("%Y-%m-%d")if today.weekday() >= 5 or today_str in HOLIDAYS:
print("Today is a holiday or weekend. Exiting.")
exit()def send_email(subject, body):
msg = MIMEText(body)
msg["Subject"] = subject
msg["From"] = MAIL_FROM
msg["To"] = MAIL_TO
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.starttls()
server.login(MAIL_USERNAME, MAIL_PASSWORD)
server.sendmail(MAIL_FROM, MAIL_TO, msg.as_string())
server.quit()def get_issue_summary(issue_key):
issue_url = f"{JIRA_URL}/rest/api/3/issue/{issue_key}"
response = requests.get(issue_url, auth=(EMAIL, API_TOKEN))
if response.status_code == 200:
return response.json()["fields"]["summary"]
return "Summary could not be retrieved"new_year_warning = "\n📌 Remember to update the official holiday list for the new year!\n" if today_str == "2025-12-31" else ""log_messages = []
for item in ISSUES:
started_datetime = datetime.combine(today.date(), item["hour"]).replace(tzinfo=turkey_tz)
started_str = started_datetime.strftime("%Y-%m-%dT%H:%M:%S.000%z") payload = {
"started": started_str,
"timeSpent": item["duration"],
"comment": {
"type": "doc",
"version": 1,
"content": [{
"type": "paragraph",
"content": [{"text": item["comment"], "type": "text"}]
}]
}
} headers = {"Content-Type": "application/json"}
response = requests.post(
f"{JIRA_URL}/rest/api/3/issue/{item['key']}/worklog",
json=payload, headers=headers, auth=(EMAIL, API_TOKEN)
) summary = get_issue_summary(item["key"])
if response.status_code == 201:
log_messages.append(f"Issue: {item['key']} - {summary}\nDuration: {item['duration']}\n")
else:
send_email(f"❌ Jira Worklog ERROR - {item['key']}",
f"Issue: {item['key']}\nStatus Code: {response.status_code}\nResponse: {response.text}")if log_messages:
mail_body = f"""{today_str} Jira worklog entries completed. If today is a personal leave, please remove them manually in Jira.\n\n"""
mail_body += "\n".join(log_messages) + new_year_warning
send_email("✅ Jira Worklog Completed", mail_body)
Jira Worklog API Nasıl Çalışır?
Jira’nın worklog endpoint’i, belirli bir iş (issue) için zaman kaydı yapılmasına olanak tanır. Bu işlem, projelerde yapılan işi belgelemek, raporlamak ve faturalamak açısından kritik öneme sahiptir. Python script’inde kullanılan POST /rest/api/3/issue/{issueIdOrKey}/worklog endpoint’i sayesinde, belirli bir iş için manuel giriş yapmadan zaman kaydı otomatik olarak işlenebilir.
🔧 API Kullanım Mantığı
Aşağıdaki örnek, bir iş kaydına 30 dakikalık bir zaman girdisini gösterir:
POST /rest/api/3/issue/DEV-123/worklog
Authorization: Basic <email:api_token>
Content-Type: application/json
JSON Payload Örneği:
{
"started": "2025-04-22T09:30:00.000+0300",
"timeSpent": "30m",
"comment": {
"type": "doc",
"version": 1,
"content": [{
"type": "paragraph",
"content": [{
"type": "text",
"text": "Daily stand-up meeting."
}]
}]
}
}
🧠 Bilmeniz Gerekenler
● started: ISO 8601 formatında zaman. Saat dilimi (+0300) dahil edilmelidir.
● timeSpent: Dakika (m), saat (h) veya gün (d) cinsinden süre.
● comment: Jira’nın yeni nesil zengin metin formatına (ADF — Atlassian Document Format) göre tanımlanır.
✅ Başarılı Yanıt
Başarılı bir işlem sonucunda Jira 201 Created status kodu döner. Yanıt, girilen iş kaydının id’sini içerir.
Resmî Tatil Günleri Python ile Nasıl Kontrol Edilir?
Script’in içerisinde sabit HOLIDAYS = […] listesi bulunur. Ancak tatiller yıllık olarak değiştiği için bu yaklaşım uzun vadede sürdürülebilir değildir. Bunun yerine bir tatil API’sinden dinamik veri çekilebilir.
🔄 Örnek : Nager.Date API ile Tatil Kontrolü
import requests
def is_today_holiday(country_code="TR"):
today_str = datetime.now().strftime("%Y-%m-%d")
year = datetime.now().year
response = requests.get(f"https://date.nager.at/api/v3/PublicHolidays/{year}/{country_code}")
if response.status_code == 200:
holidays = response.json()
return any(h["date"] == today_str for h in holidays)
return False
Bu fonksiyon sayesinde, tatiller sabit değil — dinamik olarak kontrol edilir.
🚜 Script’in Zamanlanması
Otomatik çalıştırma için crontab kullanıyoruz:
crontab -e
Script’in her gün saat 09:30'da çalışması için aşağıdaki satırı ekleyin:
30 9 * * * /usr/bin/python3 /path/to/your/worklog.py >> /path/to/your/worklog.log 2>&1
Bu yapılandırma sayesinde, script her gün çalışır; ancak yalnızca gün hafta içiyse ve resmi tatil değilse zaman kaydı yapılır.
Windows Kullanıcıları İçin Alternatif Zamanlayıcı (Task Scheduler)
Linux’ta crontab kullanmak mümkünken, Windows kullanıcıları için en yaygın çözüm Görev Zamanlayıcı (Task Scheduler) aracılığıyla script’i belirli saatlerde çalıştırmaktır.
🔧 Adımlar:
- Windows’ta “Görev Zamanlayıcı”yı açın
- “Temel Görev Oluştur” seçeneğini seçin
- Script’i tetikleyecek bir saat belirleyin
Eylem olarak:
Program: python
Argument: C:\Users\SeninAdin\Desktop\worklog.py
Script’in düzgün çalışabilmesi için Python’ın sistem PATH’ine ekli olması gerekir.
💳 Sağladığı Faydalar
● Zaman girişlerini manuel yapma derdi sona erer
● Ekipler arası tutarlılık sağlanır
● Tatil ve hafta sonları göz önüne alındığı için hatalar engellenir
● Günlük e-posta raporları ile bilgilendirme yapılır
📱 Opsiyonel: Microsoft Teams Entegrasyonu (E-posta Alternatifi)
Zaman girişi bildirimlerini e-posta yerine veya yanı sıra Microsoft Teams üzerinden almak isterseniz, “Incoming Webhooks” özelliğini kullanabilirsiniz.
MS notification
Adım 1: Teams’te Webhook Oluştur
- Teams’te ilgili kanalın yanındaki … → “Bağlayıcılar” → “Incoming Webhook”
- Bir isim verin, isterseniz bir ikon yükleyin
- Oluşan Webhook URL’sini kopyalayın
Adım 2: Script’e send_teams_message Fonksiyonunu Ekleyin
def send_teams_message(text):
TEAMS_WEBHOOK_URL = "https://your.webhook.office.com/..." # Use your real URL
headers = {"Content-Type": "application/json"}
payload = {"text": text}
try:
response = requests.post(TEAMS_WEBHOOK_URL, json=payload, headers=headers)
if response.status_code == 200:
print("📢 Teams notification sent.")
else:
print("❌ Teams notification failed:", response.text)
except Exception as e:
print("❌ Teams exception:", e)
Adım 3: E-posta Bildirimine Ekleme Yapın veya Yerine Geçin
Zaman kaydı başarılı şekilde yapıldıktan sonra, fonksiyonu aşağıdaki gibi çağırabilirsiniz:
body = f"Worklog successfully submitted on {today_str} at 09:30. If you were on leave today, please remove the worklog manually from Jira.
Issue: {ISSUE_KEY} - {issue_summary}
Duration: {TIME_SPENT}{new_year_warning}"send_email("✅ Jira Worklog successful", body)
send_teams_message(body)
Ayrıca, isterseniz Teams mesajlarını yalnızca hata durumlarında da gönderebilirsiniz.
Python Script’in Docker ile Çalıştırılması
Script’i Docker container içinde çalıştırmak, zamanlama, dağıtım ve taşınabilirlik açısından büyük avantaj sağlar.
🐳 Örnek Dockerfile:
FROM python:3.11
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "worklog.py"]
Terminal Komutları:
docker build -t jira-worklog .
docker run --env-file .env jira-worklog
.env dosyasını — env-file ile dahil ederek güvenli çalıştırma sağlanabilir.
📊 Sonuç
Bu otomasyon, Jira, Python ve basit zamanlama mantığını entegre ederek günlük iş akışınıza verimlilik katar. Yalnızca birkaç yapılandırma ile zaman kayıtlarınızın zamanında, tutarlı ve düzenli şekilde yapılmasını sağlayabilirsiniz.
İster birden fazla Jira görevi yönetin, ister sadece zamanınızı daha etkili şekilde kaydetmek isteyin — bu çözüm ihtiyaçlarınıza göre ölçeklenebilir.
Jira Zaman Takibi Otomasyonu Hakkında Sıkça Sorulan Sorular
Bu script yalnızca Jira Cloud ile mi uyumlu?
Evet, bu script Jira Cloud REST API v3 ile uyumlu çalışır. Jira Server veya Data Center sürümleri farklı endpoint’ler kullanabileceğinden uyarlama gerektirebilir. Cloud ortamında çalışan takımlar için doğrudan entegre şekilde kullanılabilir.
API token’ımı güvenli şekilde nasıl saklamalıyım?
Token’ınızı doğrudan script içine yazmak güvenli değildir. Bunun yerine .env dosyası içinde saklayarak python-dotenv kütüphanesi ile script’e dahil etmeniz önerilir. Bu yöntemle token’ınız sürüm kontrolüne girmez.
Script farklı kullanıcılar için zaman girişi yapabilir mi?
Hayır. Jira API, yalnızca oturum açan yani token sahibi kullanıcının kendi adına zaman kaydı yapmasına izin verir. Başka kullanıcılar için işlem yapılabilmesi için her birinin ayrı token’ı ile giriş yapılmalıdır.
Script’i Windows ortamında nasıl zamanlayabilirim?
Windows kullanıcıları script’i “Görev Zamanlayıcı (Task Scheduler)” aracıyla zamanlayabilir. Python kurulu olmalı ve script tam dosya yolu ile tanımlanmalıdır. Linux’taki crontab işlevinin Windows alternatifi olarak çalışır.
Zaman kaydı yapılırken saat dilimi hatası alırsam ne yapmalıyım?
Script’te kullanılan started alanı içinde mutlaka saat dilimi bilgisi (örneğin +0300) yer almalıdır. Bu bilgi eksikse Jira varsayılan olarak UTC saatini kullanır ve girişler yanlış zamanda görünür.