Issue #2566


Retroactively set "Verified" flag on issues

Added by semyers over 6 years ago. Updated over 4 years ago.

Start date:
Due date:
Estimated time:
2. Medium
Platform Release:
Sprint Candidate:
Pulp 2


This was discussed on pulp-dev:

With the introduction of the new "Verified" flag, we should retroactively set that flag on issues that have been verified in the past. My strategy for this is to find issues in a closed state whose previous state was VERIFIED, which should prevent the flag from being set on potential outliers, such as issues that potentially had a VERIFIED status but were later set back to a pre-MODIFIED state and are no longer verified.

Related issues

Blocked by Pulp - Task #2564: Add new fields to Redmine to track issue verificationCLOSED - CURRENTRELEASEsemyers

Actions #1

Updated by semyers over 6 years ago

  • Related to Task #2564: Add new fields to Redmine to track issue verification added
Actions #2

Updated by semyers over 6 years ago

  • Related to deleted (Task #2564: Add new fields to Redmine to track issue verification)
Actions #3

Updated by semyers over 6 years ago

  • Blocked by Task #2564: Add new fields to Redmine to track issue verification added
Actions #4

Updated by semyers over 6 years ago

  • Status changed from NEW to ASSIGNED
Actions #5

Updated by semyers over 6 years ago

This is running now:

import redmine

redmine_api_key = open('redmine-verifier-key').read().strip()

redmine_api = redmine.Redmine('', key=redmine_api_key)

def url(id):
    return '{}'.format(id)

def filter_issue(issue):
    # if the issue isn't a story or task, skip it
    # can only filter issues by one tracker type, so filter here
    if not in (tracker_i, tracker_s):
        return True

    # if the issue is already verified, skip it
    # .filtering by the value of the "Verified" custom field seems broken, so filter here
    for field in issue.custom_fields:
        if == field_v and field.value == "1":
            return True

    return False

# these resources don't support filtering, so ghettofilter out the things we want
for status in redmine_api.issue_status.all():
        # ccr = closed current release
        status_ccr =
    elif == 'VERIFIED':
        status_v =

for tracker in redmine_api.tracker.all():
    if == 'Issue':
        tracker_i =
    elif == 'Story':
        tracker_s =

for custom_field in redmine_api.custom_field.all():
    if == 'Verified':
        field_v =

# filter outs issues that aren't current CLOSED - CURRENTRELEASE, and aren't marked verified
filter_kwargs = { 
    'status_id': status_ccr,
closed_issues = redmine_api.issue.filter(**filter_kwargs)

# known closed issue for debugging
# closed_issues = [redmine_api.issue.get(161)]
errors = []

for issue in filter(filter_issue, closed_issues):
    # re-get the issue with journals to get status history
    issue = redmine_api.issue.get(, include='journals')

    print('processing {}'.format(url(

    for issue_change in reversed(issue.journals):
        for detail in issue_change.details:
            if detail['name'] == 'status_id':
                old_value, new_value = (int(v) for v in (detail['old_value'], detail['new_value']))

            # these might not get set in the detail loop, so go around again if we have to
            old_value, new_value
        except NameError:
            # heh
        # this should never happen
        print(' Unable to determine last status change for {}?'.format(url(

    if old_value == status_v and new_value == status_ccr:
        # issue's last status transition was from VERIFIED to C - CR, mark verified
        print(' {} marked verified.'.format(url(

        # actually do the thing
            redmine_api.issue.update(, custom_fields=[{'id': field_v, 'value': '1'}])
        except redmine.exception.BaseRedmineException as ex:
            print(' {} error on update'.format(url(
            errors.append((issue, ex))
        print(' {} not marked verified.'.format(url(

    # a newline for good luck

for issue, ex in errors:
    print('{} raised {} in processing and needs manual intervention'.format(, type(ex).__name__)

As you might imagine, the "redmine_api_key" file contains a redmine api key. :)

The script should be idempotent, which is useful in case we need to run this again during the transition from using the VERIFIED status to using the Verified custom field.

(Edited Feb 2 with minor script tweaks.)

Actions #6

Updated by semyers over 6 years ago

The script failed with a ValidationError on #792, so I'll tweak it and try again later.

Actions #7

Updated by bmbouter over 6 years ago

This is very nice. I was not aware of the journals option. Thank you for this. Extra points for having the user reflect it was done w/ automation by using the pulpbot name.

Actions #8

Updated by semyers over 6 years ago

Thanks :)

I updated the script to continue if errors occur, and log them after the fact. I also tweaked some of the filtering logic to prevent hitting the API to grab the journals before filtering units out based on info that was already available.

As of now, issues from 1-2564 have been processed and retroactively verified where appropriate. Since the process docs have not yet been updated (#2565) to reflect the proper usage, I plan to leave this open and run it again once the process is "officially" changed.

Actions #9

Updated by semyers over 6 years ago

  • Status changed from ASSIGNED to CLOSED - CURRENTRELEASE

The errors that were occuring were due to issues #792 and earlier not having "Severity" set, which is a required field. Temporarily setting this field to not be required while the redmine updater ran allowed it to finish updating all issues in all trackers. With ability to transition future issues to VERIFIED removed as a result of #2572, it should not be necessary to run this script again.

Actions #10

Updated by bmbouter over 4 years ago

  • Tags Pulp 2 added

Also available in: Atom PDF