Skip to content

Add Jira sprint support for 'did this sprint' / 'did last sprint' - #475

Open
evakhoni wants to merge 6 commits into
psss:mainfrom
evakhoni:feature/jira-sprint-support
Open

Add Jira sprint support for 'did this sprint' / 'did last sprint'#475
evakhoni wants to merge 6 commits into
psss:mainfrom
evakhoni:feature/jira-sprint-support

Conversation

@evakhoni

Copy link
Copy Markdown
Contributor

Summary

Adds support for sprint-based time periods (did this sprint and did last sprint) by integrating with the Jira Agile API. When used, all configured stats (git, GitHub, GitLab, Confluence, etc.) report against the sprint's date range instead of a calendar-based period.

Motivation

Users working in agile environments track work in sprints, not calendar weeks. This feature enables generating activity reports scoped to sprint boundaries, making it easier to:

  • Prepare sprint retrospectives
  • Track contribution within sprint cycles
  • Align reporting with team workflows

Implementation

Core changes

  1. CLI keyword support (did/cli.py):

    • Added 'sprint' to accepted keywords list
  2. Date period handling (did/base.py):

    • Added elif "sprint" in argument branch in Date.period()
    • Lazy-imports get_sprint_dates() from jira plugin to avoid circular dependency
  3. Jira Agile API integration (did/plugins/jira.py):

    • New get_sprint_dates(last: bool) function:
      • Auto-discovers Scrum board from existing project config via /rest/agile/1.0/board endpoint
      • Falls back to manual sprint_board config for multi-board projects
      • Queries /rest/agile/1.0/board/{boardId}/sprint?state=active|closed
      • Returns (Date(start), Date(end), "sprint name") tuple
    • Reuses existing JiraStatsGroup auth logic (supports GSS, basic, token)
    • Provides actionable error messages for common issues (no boards found, multiple boards, no active sprint)
  4. Documentation (docs/config.rst):

    • Added "Time Periods" section with sprint usage examples
    • Documented sprint_board config option
    • Explained auto-discovery behavior and multi-board scenario
  5. Test coverage (tests/unit/test_base.py):

    • test_sprint_period(): Verifies this sprint period parsing
    • test_last_sprint_period(): Verifies last sprint period parsing
    • test_sprint_keyword_accepted(): Ensures sprint keyword passes validation

Auto-discovery logic

When sprint_board is not explicitly configured:

  1. Extracts first project key from project config (e.g., MYPROJECT from project = MYPROJECT, OTHER)
  2. Queries Agile API for Scrum boards in that project
  3. If 0 boards: error message directs user to create board or set sprint_board
  4. If 1 board: uses it automatically
  5. If 2+ boards: error message lists all board IDs/names and asks user to set sprint_board

Example usage

# With auto-discovery (project already configured)
did this sprint
did last sprint

# With manual board ID (multi-board projects)
# Add to ~/.did/config:
# [jira]
# sprint_board = 42
did this sprint

Testing

All tests pass (33/33):

pytest tests/unit/test_base.py -v

Manual testing verified:

  • did this sprint returns current active sprint with correct date range
  • did last sprint returns most recently closed sprint
  • ✅ Auto-discovery works with existing project config
  • ✅ All stat plugins (git, GitHub, Jira) report within sprint boundaries
  • ✅ Error handling for missing config, no boards, multiple boards

Compatibility

  • Requires existing [jira] config section with project or sprint_board
  • Works with all Jira auth types (GSS, basic, token)
  • Compatible with both Jira Cloud and Server/Data Center
  • No breaking changes to existing functionality

@evakhoni

Copy link
Copy Markdown
Contributor Author

@psss @kwk WDYT?

@evakhoni
evakhoni force-pushed the feature/jira-sprint-support branch from 4b22993 to 9533e28 Compare July 22, 2026 07:39
Comment thread tests/unit/test_base.py Fixed
Comment thread did/base.py
since, until, period = Date.get_month("last" in argument)

elif "sprint" in argument:
from did.plugins.jira import get_sprint_dates

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This cycle is intentional — base.py needs to dispatch did this sprint to the Jira plugin, and the Jira plugin needs Date from base.py. The import is lazy (inside Date.period(), only executed when the user actually requests a sprint period), so the cycle is broken at runtime. This is the standard Python pattern for unavoidable circular dependencies.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@psss I'm not able to verify if this is a pythonic way to handle this. Can you?

Comment thread did/plugins/jira.py Fixed
@evakhoni
evakhoni force-pushed the feature/jira-sprint-support branch from 9533e28 to 6c22ef7 Compare July 22, 2026 07:43
Comment thread did/plugins/jira.py
sprint. For 'last sprint', returns the most recently closed sprint.
"""
# Import Date here to avoid circular dependency (base.py -> jira.py -> base.py)
from did.base import Date

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

same as in #475 (comment) just from the other end

- Add 'sprint' keyword to CLI argument parser
- Implement get_sprint_dates() in jira plugin
- Auto-discover Scrum board from project config
- Support manual sprint_board override for multi-board projects
- Query Agile API for active/closed sprint dates
- Add comprehensive test coverage
- Document sprint usage in config.rst

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@evakhoni
evakhoni force-pushed the feature/jira-sprint-support branch from 7bc1994 to 9420b17 Compare July 22, 2026 08:47
Comment thread tests/unit/test_base.py
Comment thread did/plugins/jira.py Outdated
Comment thread did/plugins/jira.py Outdated
Comment thread did/plugins/jira.py Outdated
Comment thread did/plugins/jira.py Outdated
Comment thread did/plugins/jira.py Outdated
@kwk

kwk commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

@evakhoni why do you force push when this PR is under review?

image

@evakhoni

Copy link
Copy Markdown
Contributor Author

@evakhoni why do you force push when this PR is under review?

@kwk oh sry I haven't noticed that you already started :) there were a few linter CI failures for which I didn't wanted to push a separate commit

evakhoni and others added 5 commits July 22, 2026 12:40
Address autopep8 --hang-closing bracket style, flake8 W505 doc line
length, and pylint cyclic-import warnings:

- Move closing brackets/parens to align with content (autopep8
  --hang-closing style) at 4 locations
- Shorten docstring first line from 73 to 39 chars
- Shorten comment from 79 to 55 chars to stay under 72 char limit
- Add cyclic-import suppression in base.py (the lazy import breaks the
  cycle at runtime)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add return type annotation to get_sprint_dates()
- Document the ``last`` parameter in the docstring
- Rename period_name to sprint_name in docstring
- Use ['this', 'sprint'] in test to match docstring description

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sort all sprints by endDate descending and take the most recent,
regardless of whether we're looking for active or closed sprints.
This removes a separate code path for "this sprint" and makes the
behavior deterministic when parallel sprints are enabled.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Create JiraStatsGroup once upfront instead of conditionally inside
the auto-discover branch and again via try/except NameError later.
Both code paths need the authenticated session, so instantiating
it early simplifies the control flow.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When multiple comma-separated projects are configured and
sprint_board is not set, raise an error instead of silently
using only the first project for board auto-discovery.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@evakhoni

Copy link
Copy Markdown
Contributor Author

the testing-farm failures seems unrelated to my changes

@evakhoni
evakhoni marked this pull request as draft July 30, 2026 07:18
@evakhoni
evakhoni marked this pull request as ready for review July 30, 2026 07:18
@evakhoni

Copy link
Copy Markdown
Contributor Author

@kwk Hi! I have solved the issues, and the CI failure is seems like a temporary outage unrelated to this pr.
any chance that you can relaunch the CI? i have no permissions for that, and I think the PR is ready to merge. ptal 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants