Classify gov changes by hashtag, not topic
Gerrit hashtags are additive and support multiple tags per change, making them better suited for classifying governance changes. Older versions of git-review set the local branch name as the topic on each push, causing topic mangling — an issue that persists if submitters haven't updated their git-review package. See discussion on #openstack-tc [1]. [1] https://meetings.opendev.org/irclogs/%23openstack-tc/%23openstack-tc.2026-03-24.log.html Change-Id: Ib585ab64b7c4b53025b407828c6da5e040d89c1a Signed-off-by: Goutham Pacha Ravi <gouthampravi@gmail.com>
This commit is contained in:
+7
-4
@@ -91,13 +91,16 @@ Status & Tracking
|
||||
OR
|
||||
:Etherpad: <put the link to etherpad where progress is tracked>
|
||||
|
||||
Gerrit Topic
|
||||
------------
|
||||
Gerrit Tracking
|
||||
---------------
|
||||
|
||||
To facilitate tracking, commits related to this goal should use the
|
||||
gerrit topic::
|
||||
gerrit hashtag or topic::
|
||||
|
||||
<insert topic here>
|
||||
<insert hashtag here>
|
||||
|
||||
Hashtags are preferred over topics because they are additive and
|
||||
support multiple tags per change.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
@@ -118,7 +118,7 @@ votes (ties mean the motion is rejected), and a minimum of positive votes of at
|
||||
least one third of the total number of TC members (rounded up: in a 13-member
|
||||
committee that means a minimum of 5 approvers).
|
||||
|
||||
Patches with motions should use the gerrit topic tag ``formal-vote``.
|
||||
Patches with motions should use the gerrit hashtag ``formal-vote``.
|
||||
|
||||
Election for PTL seats
|
||||
======================
|
||||
@@ -327,5 +327,5 @@ motion, which needs to be approved by the affirmative vote of at least
|
||||
two-thirds of the total number of TC members (rounded up: in a 13-member
|
||||
committee that means a minimum of 9 approvers).
|
||||
|
||||
Patches with charter amendments should use the gerrit topic tag
|
||||
Patches with charter amendments should use the gerrit hashtag
|
||||
``charter-change``.
|
||||
|
||||
@@ -22,7 +22,7 @@ by other means.
|
||||
Typo fixes
|
||||
----------
|
||||
|
||||
:Gerrit topic: ``typo-fix``
|
||||
:Gerrit hashtag: ``typo-fix``
|
||||
|
||||
When the change fixes content that is obviously wrong (updates a PTL email
|
||||
address, fixes a typo...) then any TC member (who is not the proposer) can
|
||||
@@ -31,7 +31,7 @@ directly approve them.
|
||||
Community-wide goal proposals
|
||||
-----------------------------
|
||||
|
||||
:Gerrit topic: ``goal-proposal``
|
||||
:Gerrit hashtag: ``goal-proposal``
|
||||
|
||||
The `process for choosing community goals`_ has two stages relevant to Gerrit
|
||||
changes: defining goal proposals and selecting goals for a cycle. For changes
|
||||
@@ -51,7 +51,7 @@ requires a formal-vote.
|
||||
Code changes
|
||||
------------
|
||||
|
||||
:Gerrit topic: ``code-change``
|
||||
:Gerrit hashtag: ``code-change``
|
||||
|
||||
The `openstack/governance` repository also contains code to build and publish
|
||||
pages on the governance.openstack.org website. For those we apply the normal
|
||||
@@ -63,7 +63,7 @@ point.
|
||||
Documentation changes
|
||||
---------------------
|
||||
|
||||
:Gerrit topic: ``documentation-change``
|
||||
:Gerrit hashtag: ``documentation-change``
|
||||
|
||||
The `openstack/governance` repository also contains documentation
|
||||
related to internal operations of the TC but that does not represent
|
||||
@@ -77,7 +77,7 @@ than the change owner) are posted (and no `RollCall-1`).
|
||||
Election Results
|
||||
----------------
|
||||
|
||||
:Gerrit topic: ``election-results``
|
||||
:Gerrit hashtag: ``election-results``
|
||||
|
||||
The results of elections are documented in the `openstack/governance`
|
||||
repository, but are not subject to "review" or "approval" by the TC,
|
||||
@@ -92,7 +92,7 @@ RollCall votes being considered +-2): change will be approved once 2
|
||||
Delegated metadata
|
||||
------------------
|
||||
|
||||
:Gerrit topic: ``release-management``
|
||||
:Gerrit hashtag: ``release-management``
|
||||
|
||||
The ``release-management`` setting for a deliverable is delegated to
|
||||
the PTL of the Release Management team. When proposed or approved by
|
||||
@@ -101,9 +101,9 @@ the PTL, changes can be directly approved by the chair.
|
||||
Other project team updates
|
||||
--------------------------
|
||||
|
||||
:Gerrit topic: ``project-update``
|
||||
:Gerrit hashtag: ``project-update``
|
||||
|
||||
This topic is used for other changes within an existing project team, like
|
||||
This hashtag is used for other changes within an existing project team, like
|
||||
addition of a new git repository or retirement of an existing repository
|
||||
maintained by a project team.
|
||||
|
||||
@@ -130,7 +130,7 @@ project, they can propose a revert which would then be discussed by our usual
|
||||
Goal Updates from PTLs
|
||||
----------------------
|
||||
|
||||
:Gerrit topic: ``goal-update``
|
||||
:Gerrit hashtag: ``goal-update``
|
||||
|
||||
PTLs will acknowledge community-wide goals at the start of each cycle
|
||||
by providing links to artifacts for tracking the work, or an
|
||||
|
||||
@@ -25,7 +25,7 @@ TC Chair Election
|
||||
|
||||
* In case of single nomination, no election is needed and candidate can propose
|
||||
a patch to the member list to add "chair" status next to their name and use
|
||||
`election-results` as gerrit topic name.
|
||||
`election-results` as gerrit hashtag.
|
||||
|
||||
* If there are multiple nominations, select a TC member who is not running for
|
||||
the TC chair to establish a CIVS poll to choose the single winner.
|
||||
@@ -37,4 +37,4 @@ TC Chair Election
|
||||
voted.
|
||||
|
||||
* Winner will propose a patch to the member list to add "chair" status next to
|
||||
their name and use `election-results` as gerrit topic name.
|
||||
their name and use `election-results` as gerrit hashtag.
|
||||
|
||||
@@ -187,8 +187,25 @@ def all_changes():
|
||||
break
|
||||
|
||||
|
||||
KNOWN_CATEGORIES = {
|
||||
'on-hold',
|
||||
'formal-vote',
|
||||
'charter-change',
|
||||
'goal-proposal',
|
||||
'code-change',
|
||||
'documentation-change',
|
||||
'election-results',
|
||||
'typo-fix',
|
||||
'project-update',
|
||||
'new-project',
|
||||
'goal-update',
|
||||
}
|
||||
|
||||
|
||||
def get_one_status(change, delegates, tc_members):
|
||||
topic = change.get('topic', 'unknown topic')
|
||||
hashtags = change.get('hashtags', [])
|
||||
matching = [h for h in hashtags if h in KNOWN_CATEGORIES | delegates.keys()]
|
||||
hashtag = matching[0] if matching else 'Missing hashtag'
|
||||
subject = change.get('subject')
|
||||
owner = change.get('owner', {}).get('name')
|
||||
url = 'https://review.opendev.org/{}\n'.format(change['_number'])
|
||||
@@ -216,10 +233,10 @@ def get_one_status(change, delegates, tc_members):
|
||||
can_approve = 'NO, verification failure'
|
||||
earliest = 'when passing'
|
||||
|
||||
elif topic == 'on-hold':
|
||||
elif hashtag == 'on-hold':
|
||||
can_approve = 'on hold'
|
||||
|
||||
elif topic == 'formal-vote':
|
||||
elif hashtag == 'formal-vote':
|
||||
# https://governance.openstack.org/tc/reference/charter.html#motions
|
||||
parts = []
|
||||
|
||||
@@ -274,7 +291,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
|
||||
can_approve = ',\n'.join(parts)
|
||||
|
||||
elif topic == 'charter-change':
|
||||
elif hashtag == 'charter-change':
|
||||
# https://governance.openstack.org/tc/reference/charter.html#amendment
|
||||
parts = []
|
||||
|
||||
@@ -314,7 +331,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
|
||||
can_approve = ',\n'.join(parts)
|
||||
|
||||
elif topic in (
|
||||
elif hashtag in (
|
||||
'goal-proposal',
|
||||
'code-change',
|
||||
'documentation-change',
|
||||
@@ -336,9 +353,9 @@ def get_one_status(change, delegates, tc_members):
|
||||
else:
|
||||
can_approve = 'CAN APPROVE'
|
||||
|
||||
elif topic in delegates.keys():
|
||||
elif hashtag in delegates.keys():
|
||||
# https://governance.openstack.org/tc/reference/house-rules.html#delegated-metadata
|
||||
approver_name = delegates[topic]
|
||||
approver_name = delegates[hashtag]
|
||||
can_approve = 'delegated to {}'.format(approver_name)
|
||||
if has_approved(approver_name, change):
|
||||
can_approve += '\nYES'
|
||||
@@ -347,7 +364,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
elif has_commented(approver_name, change):
|
||||
can_approve += '\ndelegate has commented'
|
||||
|
||||
elif topic in ('project-update', 'new-project'):
|
||||
elif hashtag in ('project-update', 'new-project'):
|
||||
# https://governance.openstack.org/tc/reference/house-rules.html#other-project-team-updates
|
||||
|
||||
if votes[-1] or code_reviews[-1]:
|
||||
@@ -357,7 +374,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
else:
|
||||
can_approve = 'CAN APPROVE'
|
||||
|
||||
elif topic == 'goal-update':
|
||||
elif hashtag == 'goal-update':
|
||||
# https://governance.openstack.org/tc/reference/house-rules.html#goal-updates-from-ptls
|
||||
|
||||
# At least 7 days old.
|
||||
@@ -371,8 +388,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
can_approve = 'CAN APPROVE'
|
||||
|
||||
else:
|
||||
topic = 'unknown topic'
|
||||
can_approve = 'unknown topic'
|
||||
can_approve = ''
|
||||
|
||||
votes = '\n'.join([
|
||||
'CR:' + format_votes(code_reviews),
|
||||
@@ -396,7 +412,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
)
|
||||
|
||||
return {
|
||||
'Topic': topic,
|
||||
'Hashtag': hashtag,
|
||||
'Subject': subject,
|
||||
'Summary': '\n'.join([
|
||||
subject.strip(),
|
||||
@@ -409,7 +425,7 @@ def get_one_status(change, delegates, tc_members):
|
||||
'Age': age.days,
|
||||
'Date': latest_created.date(),
|
||||
'Can Approve': can_approve,
|
||||
'Status': '\n'.join([topic, can_approve,
|
||||
'Status': '\n'.join([hashtag, can_approve,
|
||||
'{} days old'.format(age.days),
|
||||
'earliest: {}'.format(earliest)]),
|
||||
'Earliest': earliest,
|
||||
@@ -451,7 +467,7 @@ def main():
|
||||
'release-management': release_team.ptl['name'],
|
||||
}
|
||||
for tag, name in sorted(delegates.items()):
|
||||
print('Delegating {} tags to {}'.format(tag, name))
|
||||
print('Delegating {} hashtag to {}'.format(tag, name))
|
||||
|
||||
status = sorted(
|
||||
(get_one_status(change, delegates, tc_members)
|
||||
|
||||
Reference in New Issue
Block a user