I have written release notes every sprint for a few years. Writing was never the slow part. The slow part was finding out what actually shipped.
These are the five queries I run before I write anything. Each one takes under a minute. Most teams find a problem in the first two.
Replace PROJ with your project key. Replace X.Y with the release you are writing. Replace X.W with the release before it. Use your own sprint name.
1. Shipped in the sprint, but never tagged with a version
project = PROJ AND sprint = "Sprint 42" AND statusCategory = Done AND fixVersion IS EMPTY ORDER BY resolved DESC
The work is in the build. It is not in your notes. Nobody tagged the ticket.
So a customer finds the feature before you announce it. Or someone promises it for next quarter, and it went out three weeks ago.
No sprints? Replace the sprint line with resolved >= -14d. Match the number of days to your release cycle.
2. Tagged for the release, but not finished
project = PROJ AND fixVersion = "X.Y" AND statusCategory != Done ORDER BY status ASC, assignee ASC
Two problems here, and both are bad.
Either you are about to announce something that is not in the build. Or the work is done and nobody moved the ticket. In that case your notes are too short and you do not know it.
Run this query again just before you publish. People close tickets while you write.
3. Done, in scope, and nothing you can publish
project = PROJ AND fixVersion = "X.Y" AND statusCategory = Done AND type != Sub-task AND description IS EMPTY ORDER BY key ASC
This is where the whole afternoon goes. You open twelve tickets. Each one has a single line, written by a developer for themselves. Then you start messaging people who moved on a week ago.
Run this query early. Send one message with the full list. People answer a list. They ignore many small questions.
There is a permanent fix. Add a "Release Note" field to your issue types. Whoever closes the ticket fills it in, while they still remember what they built. This is the best process change I have made to release notes.
4. Promised for this release, then quietly moved out
project = PROJ AND fixVersion WAS "X.Y" AND fixVersion != "X.Y" ORDER BY updated DESC
This one has saved me several times.
WAS reads the change history. So it finds work that really was tagged for this release, and then moved. The sprint ran long, someone retagged it, and nobody said anything.
For every result, ask one question. Did anyone outside the team hear this was coming? If it was on a roadmap slide, or in an email to a customer, people will notice it is missing.
To see everything that moved, in both directions:
project = PROJ AND fixVersion CHANGED AFTER -21d ORDER BY updated DESC
5. Came in late from the release before
project = PROJ AND fixVersion = "X.Y" AND fixVersion WAS "X.W" ORDER BY key ASC
This is about wording. "New in X.Y" is wrong if you announced it for X.W. The people who waited for it know it is not new.
Write "Now available" for everything this query returns.
Five minutes here will save you an hour. I wish someone had told me this part first.
1. Check your status categories. Run project = PROJ AND statusCategory = Done. Does the count look right? If a step like "Released" or "Verified" is mapped to the wrong category, every query above will miss tickets.
Always use statusCategory, not status. Teams rename statuses and add new steps often. A query with a status name in it will quietly miss half a release the first time someone adds a step. Status category keeps working.
2. Use field IDs, not field names. Names get renamed. IDs do not. Find the ID in Jira admin and write cf[10050] instead of "Release Note".
3. Test subtaskIssueTypes(). Some instances reject it. If yours does, use type != Sub-task.
4. Use parent, and check "Epic Link" if you are on an older instance. Test whichever one your instance accepts before you build filters on it.
5. Test any query that uses text ~. Text indexing is not identical everywhere, especially if you also run Data Center. Run it against a ticket you know contains the words, and check that it comes back.
Run query 1 at the start of every sprint. Not on release day.
An untagged ticket is quick to fix on day one. It is expensive to fix on release day. I stopped getting release-day surprises after about two months of weekly checks.
Save these as filters, not browser bookmarks. Give them the same prefix: RN — 01 Leak, RN — 02 Liar, and so on. They sort together in your filter list. The next release becomes copy and paste.
I wrote the five up as a PDF, with what each one finds and what to do with the results: https://tatevkh.gumroad.com/l/kplvks
It is free. To be clear: I also sell a longer version with templates and rules for sorting tickets into sections. So treat that link as self-promotion and skip it if you prefer. The five queries above are all these five do.
What do you run before you write release notes? The part I still have not solved is query 3. Finding tickets with no description is easy. Getting people to write one at close time is hard.
Thanks, glad it helped.
And yeah, agreed. A query gives you the same answer every time, and you can save it and run it again next release. That's most of the value right there.
I do use AI for the writing part. Turning "fix NPE in export handler" into something a customer can read is a different job. But finding out what shipped is just data. A query does that better.
Recommended Learning For You
Level up your skills with Atlassian learning
Learning Path
Improve user experience across Jira with global settings
Learn how to set up and configure a Jira site, manage Jira permissions, and configure Jira apps and integrations.
Learning Path
Streamline projects across Jira with shared configurations
Build Jira work items with reusable configurations called schemes, and reduce administrative work with automation.
Learning Path
Become an effective Jira software project admin
Set up software projects and configure tools and agile boards to meet your team's needs.