Plugins¶
Modules in this directory are searched for available stats. Each
plugin should contain a single class inheriting from StatsGroup.
Stats from this group will be included in the report if enabled in
user config. Name of the plugin should match config section type.
Attribute order defines the order in the final report.
In addition to built-in plugins it is also possible to define your own stats. In order to enable such custom plugins add path to the python modules into the General section of the config file.
This is the default plugin order:
header
000
050
nitrate
100
bugzilla
200
git
300
github
330
gerrit
350
phabricator
360
gitlab
380
pagure
390
trac
400
bodhi
410
koji
420
trello
450
rt
500
redmine
550
jira
600
sentry
650
zammad
680
wiki
700
items
800
footer
900
bodhi¶
Bodhi stats
Config example:
[bodhi]
type = bodhi
url = https://bodhi.fedoraproject.org/
login = <username>
- class did.plugins.bodhi.BodhiStats(option, name=None, parent=None, user=None)¶
Bodhi work
- order = 410¶
- class did.plugins.bodhi.Update(data)¶
Bodhi update
bugzilla¶
Bugzilla stats such as filed, fixed or verified bugs
This plugin uses python-bugzilla module to gather the stats.
By default reports contain only publicly available issues. Use the
bugzilla login command to initialize Bugzilla cookies or get
an API key from the Preferences and store it in the config file
.config/python-bugzilla/bugzillarc:
[bugzilla.redhat.com]
api_key=YOUR-API-KEY
Config example:
[bz]
type = bugzilla
prefix = BZ
url = https://bugzilla.redhat.com/xmlrpc.cgi
resolutions = notabug, duplicate
- Resolutions:
List of resolutions to be displayed at the end of the summary if bug is closed. By default
notabugandduplicateare shown. Useallto always display resolution if available ornoneto turn off the feature completely.
Available options:
- --bz-filed
Bugs filed
- --bz-patched
Bugs patched
- --bz-posted
Bugs posted
- --bz-fixed
Bugs fixed
- --bz-returned
Bugs returned
- --bz-verified
Bugs verified
- --bz-commented
Bugs commented
- --bz-subscribed
Bugs subscribed
- --bz-closed
Bugs closed
- --bz
All above
- class did.plugins.bugzilla.Bug(bug, history, comments, parent)¶
Bugzilla search
- closed(user)¶
Moved to CLOSED and not later moved to ASSIGNED
- commented(user)¶
True if comment was added in given time frame
- fixed()¶
Moved to MODIFIED and not later moved to ASSIGNED
- property logs¶
Return relevant who-did-what pairs from the bug history
- patched(user)¶
True if Patch was added to Keywords field by given user
- posted()¶
True if bug was moved to POST in given time frame
- returned(user)¶
Moved to ASSIGNED by given user (but not from NEW)
- subscribed(user)¶
True if CC was added in given time frame
- property summary¶
Bug summary including resolution if enabled
- verified()¶
True if bug was verified in given time frame
- class did.plugins.bugzilla.Bugzilla(parent)¶
Bugzilla investigator
- search(query, options)¶
Perform Bugzilla search
- property server¶
Connection to the server
- class did.plugins.bugzilla.BugzillaStats(option, name=None, parent=None, user=None)¶
Bugzilla stats
- order = 200¶
- class did.plugins.bugzilla.ClosedBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs closed
Bugs which have been moved to the
CLOSEDstate in given time frame and later have not been moved back to theASSIGNEDstate (which would suggest the bug was not closed for a proper reason).- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.bugzilla.CommentedBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs commented
All bugs commented by given user in requested time frame.
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.bugzilla.FiledBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs filed
Newly created bugs by given user, marked as the
Reporter.- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.bugzilla.FixedBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs fixed
Bugs which have been moved to the
MODIFIEDstate in given time frame and later have not been moved back to theASSIGNEDstate (which would suggest an incomplete fix).- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.bugzilla.PatchedBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs patched
Gathers bugs with keyword
Patchadded by given user, denoting the patch for the issue is available (e.g. attached to the bug or pushed to a feature git branch).- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.bugzilla.PostedBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs posted
Bugs with patches posted for review, detected by their status change to
POSTand given user set asAssignee.- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.bugzilla.ReturnedBugs(option, name=None, parent=None, user=None, options=None)¶
Bugs returned
Returned bugs are those which were returned by given user to the
ASSIGNEDstatus, meaning the fix for the issue is not correct or complete.- fetch()¶
Fetch the stats (to be implemented by respective class).
confluence¶
Confluence stats such as created pages and comments
Configuration example (GSS authentication):
[confluence]
type = confluence
url = https://docs.jboss.org/
Configuration example (basic authentication):
[jboss]
type = confluence
url = https://docs.jboss.org/
auth_url = https://docs.jboss.org/rest/auth/latest/session
auth_type = basic
auth_username = username
auth_password = password
auth_password_file = ~/.did/confluence_password
Notes:
Optional parameter
ssl_verifycan be used to enable/disable SSL verification (default: true)auth_urlparameter is optional. If not provided,url + "/step-auth-gss"will be used for authentication.auth_typeparameter is optional, default value isgss.auth_username,auth_passwordandauth_password_fileare only valid for basic authentication,auth_passwordorauth_password_filemust be provided,auth_passwordhas a higher priority.
- class did.plugins.confluence.CommentAdded(option, name=None, parent=None, user=None, options=None)¶
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.confluence.Confluence¶
Confluence investigator
- static search(query, stats, expand=None)¶
Perform page/comment search for given stats instance
- class did.plugins.confluence.ConfluenceComment(comment)¶
Confluence comment results
- class did.plugins.confluence.ConfluencePage(page)¶
Confluence page results
gerrit¶
Gerrit stats such as submitted, review or merged changes
Config example:
[gerrit]
type = gerrit
url = https://example.org/gerrit/
prefix = GR
# optional, True by default; set to False if the gerrit server
# does not support wip as search criteria.
wip = True
- class did.plugins.gerrit.AbandonedChanges(option, name=None, parent=None, base_url=None, prefix=None)¶
Changes abandoned
- fetch()¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
- class did.plugins.gerrit.AddedPatches(option, name=None, parent=None, base_url=None, prefix=None)¶
Additional patches added to existing changes
- fetch()¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
- class did.plugins.gerrit.Change(ticket, prefix, changelog=None)¶
Request gerrit change
- class did.plugins.gerrit.Gerrit(baseurl, prefix)¶
curl -s ‘https://REPOURL/gerrit/changes/?q=is:abandoned+age:7d’
- get_changelog(chg)¶
- get_query_result(url)¶
- static join_URL_frags(base, query)¶
- search(query)¶
- class did.plugins.gerrit.GerritStats(option, name=None, parent=None, user=None)¶
Gerrit
- order = 350¶
- class did.plugins.gerrit.GerritUnit(option, name=None, parent=None, base_url=None, prefix=None)¶
General mother class offering general services for querying Gerrit repo.
- fetch(query_string='', common_query_options=None, limit_since=False)¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
- static get_gerrit_date(instr)¶
- class did.plugins.gerrit.MergedChanges(option, name=None, parent=None, base_url=None, prefix=None)¶
Changes successfully merged
- fetch()¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
- class did.plugins.gerrit.ReviewedChanges(option, name=None, parent=None, base_url=None, prefix=None)¶
Review of a change (for reviewers)
- fetch()¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
- class did.plugins.gerrit.SubmitedChanges(option, name=None, parent=None, base_url=None, prefix=None)¶
Changes submitted for review
- fetch()¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
- class did.plugins.gerrit.WIPChanges(option, name=None, parent=None, base_url=None, prefix=None)¶
Work in progress changes
- fetch()¶
Backend for the actual gerrit query.
- query_string:
basic query terms, e.g., ‘status:abandoned’
- common_query_options:
[optional] rest of the query string; if omitted, the default one is used (limit by the current user and since option); if empty, nothing will be added to query_string
- limit_since:
[optional] Boolean (defaults to False) post-process the results to eliminate items created after since option.
git¶
Git commits
Config example:
[tools]
type = git
did = ~/git/did
edd = ~/git/edd
fmf = ~/git/fmf
[tests]
type = git
fedora = ~/tests/fedora/*
rhel = ~/tests/rhel/*
Note that using an * you can enable multiple git repositories at
once. Non git directories from the expansion are silently ignored.
- class did.plugins.git.GitCommits(option, name=None, parent=None, path=None)¶
Git commits
- fetch()¶
Fetch the stats (to be implemented by respective class).
- header()¶
Show summary header.
github¶
GitHub stats such as created and closed issues
Config example:
[github]
type = github
url = https://api.github.com/
token = <authentication-token>
login = <username>
The authentication token is optional. However, unauthenticated
queries are limited. For more details see GitHub API docs.
Use login to override the default email address for searching.
See the Config documentation for details on using aliases.
Alternatively to token you can use token_file to have the
token stored in a file rather than in your did config file.
- class did.plugins.github.GitHub(url, token)¶
GitHub Investigator
- search(query)¶
Perform GitHub query
- class did.plugins.github.GitHubStats(option, name=None, parent=None, user=None)¶
GitHub work
- order = 330¶
- class did.plugins.github.Issue(data)¶
GitHub Issue
- class did.plugins.github.IssueCommented(option, name=None, parent=None, user=None, options=None)¶
Issues commented
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.github.IssuesClosed(option, name=None, parent=None, user=None, options=None)¶
Issues closed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.github.IssuesCreated(option, name=None, parent=None, user=None, options=None)¶
Issues created
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.github.PullRequestsClosed(option, name=None, parent=None, user=None, options=None)¶
Pull requests closed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.github.PullRequestsCommented(option, name=None, parent=None, user=None, options=None)¶
Pull requests commented
- fetch()¶
Fetch the stats (to be implemented by respective class).
gitlab¶
GitLab stats such as created and closed issues
Config example:
[gitlab]
type = gitlab
url = https://gitlab.com/
token = <authentication-token>
token_file = <authentication-token-file>
login = <username>
ssl_verify = true
The authentication token is required. Create it in the GitLab web
interface (select api as the desired scope). See the GitLab API
documentation for details.
Use login to override user name detected from the email address.
See the Config documentation for details on using aliases.
Use ssl_verify to enable/disable SSL verification (default: true)
- class did.plugins.gitlab.GitLab(url, token, ssl_verify=True)¶
GitLab Investigator
- get_project(project_id)¶
- get_project_issue(project_id, issue_id)¶
- get_project_issues(project_id)¶
- get_project_mr(project_id, mr_id)¶
- get_project_mrs(project_id)¶
- get_user(username)¶
- search(user, since, until, target_type, action_name)¶
Perform GitLab query
- user_events(user_id, since, until)¶
- class did.plugins.gitlab.GitLabStats(option, name=None, parent=None, user=None)¶
GitLab work
- order = 380¶
- class did.plugins.gitlab.IssuesClosed(option, name=None, parent=None, user=None, options=None)¶
Issue closed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.gitlab.IssuesCommented(option, name=None, parent=None, user=None, options=None)¶
Issue commented
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.gitlab.IssuesCreated(option, name=None, parent=None, user=None, options=None)¶
Issue created
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.gitlab.MergeRequestsApproved(option, name=None, parent=None, user=None, options=None)¶
Merge requests approved
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.gitlab.MergeRequestsClosed(option, name=None, parent=None, user=None, options=None)¶
Merge requests closed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.gitlab.MergeRequestsCommented(option, name=None, parent=None, user=None, options=None)¶
MergeRequests commented
- fetch()¶
Fetch the stats (to be implemented by respective class).
google¶
Google stats such as attended events, completed tasks or sent emails
Config example:
[google]
type = google
client_id = <client_id>
client_secret = <client_secret>
apps = calendar,tasks
storage = ~/.did/google-api-credentials.json
Make sure you have additional dependencies of the google plugin installed on your system:
sudo dnf install python3-google-api-client python3-oauth2client # dnf
pip install did[google] # pip
To retrieve data via Google API, you will need to create access
credentials (client_id and client_secret) first. Perform the
following steps to create such a pair:
Open https://console.developers.google.com/flows/enableapi?apiid=calendar,tasks
In the drop-down menu, select Create project and click Continue
Click Go to credentials
In the Where will you be calling the API from? drop-down menu, choose Other UI (e.g. Windows, CLI tool)
In What data will you be accessing?, choose User data
Click What credentials do I need?
Input ‘did credentials’ in the Name field and click Create client ID
In Product name shown to users, type ‘did’
Click Continue, then Done
Click the did credentials link to display the credentials
The apps configuration option defines the scope of user data the
application will request (read-only) access to. Currently, the only
supported values are calendar and tasks.
During the first run, user will be asked to grant the plugin access
rights to selected apps. If the user approves the request, this decision
is remembered by creating a credential storage file. The path to the
storage can be customized by configuring the storage option.
If you want to store the client_id and client_secret not as
plain text within your config file, use client_id_file and
client_secret_file to point to files with the corresponding files.
- class did.plugins.google.Event(dict)¶
Google Calendar Event
- attended_by(email)¶
Check if user attended the event
- created_by(email)¶
Check if user created the event
- organized_by(email)¶
Check if user created the event
- class did.plugins.google.GoogleCalendar(http)¶
Google Calendar functions
- events(**kwargs)¶
Fetch events meeting specified criteria
- class did.plugins.google.GoogleEventsAttended(option, name=None, parent=None)¶
Events attended
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.google.GoogleEventsOrganized(option, name=None, parent=None)¶
Events organized
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.google.GoogleStatsBase(option, name=None, parent=None)¶
Base class containing common code
- property events¶
All events in calendar within specified time range
- property tasks¶
All completed tasks within specified time range
- class did.plugins.google.GoogleStatsGroup(option, name=None, parent=None, user=None)¶
Google stats group
- order = 50¶
- class did.plugins.google.GoogleTasks(http)¶
Google Tasks functions
- tasks(**kwargs)¶
Fetch tasks specified criteria
- class did.plugins.google.GoogleTasksCompleted(option, name=None, parent=None)¶
Tasks completed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.google.Task(dict)¶
Google Tasks task
- did.plugins.google.authorized_http(client_id, client_secret, apps, file=None)¶
Start an authorized HTTP session.
Try fetching valid user credentials from storage. If nothing has been stored, or if the stored credentials are invalid, complete the OAuth2 flow to obtain new credentials.
header¶
Customizable header
Config example:
[header]
type = header
highlights = Highlights
joy = Joy of the week ;-)
items¶
Custom section with multiple items
Config example:
[projects]
type = items
header = Work on projects
item1 = Project One
item2 = Project Two
item3 = Project Three
jira¶
Jira stats such as created, updated or resolved issues
Configuration example (token):
[issues]
type = jira
url = https://issues.redhat.com/
auth_type = token
token_file = ~/.did/jira-token
token_expiration = 7
token_name = did-token
Either token or token_file has to be defined.
- token
Token string directly included in the config. Has a higher priority over
token_file.- token_file
Path to the file where the token is stored.
- token_expiration
Print warning if token with provided
token_nameexpires within specified number ofdays.- token_name
Name of the token to check for expiration in
token_expirationdays. This has to match the name as seen in your Jira profile.
Configuration example (GSS authentication):
[issues]
type = jira
url = https://issues.redhat.org/
ssl_verify = true
Configuration example (basic authentication):
[issues]
type = jira
url = https://issues.redhat.org/
auth_url = https://issues.redhat.org/rest/auth/latest/session
auth_type = basic
auth_username = username
auth_password = password
auth_password_file = ~/.did/jira_password
Keys auth_username, auth_password and auth_password_file are
only valid for basic authentication. Either auth_password or
auth_password_file must be provided, auth_password has a higher
priority.
Configuration example limiting report only to a single project, using an alternative username and a custom identifier prefix:
[issues]
type = jira
project = ORG
prefix = JIRA
login = alt_username
url = https://issues.redhat.org/
ssl_verify = true
Notes:
If your JIRA does not have scriptrunner installed you must set
use_scriptrunnerto false.You must provide
loginvariable that matches username if it doesn’t match email/JIRA account.Optional parameter
ssl_verifycan be used to enable/disable SSL verification (default: true).The
auth_urlparameter is optional. If not provided,url + "/step-auth-gss"will be used for authentication. Its value is ignored fortokenauth_type.The
auth_typeparameter is optional, default value isgss. Other values arebasicandtoken.
- class did.plugins.jira.Issue(issue=None, prefix=None)¶
Jira issue investigator
- static search(query, stats)¶
Perform issue search for given stats instance
- updated(user, options)¶
True if the issue was commented by given user
- class did.plugins.jira.JiraCreated(option, name=None, parent=None, user=None, options=None)¶
Created issues
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.jira.JiraResolved(option, name=None, parent=None, user=None, options=None)¶
Resolved issues
- fetch()¶
Fetch the stats (to be implemented by respective class).
koji¶
Finished Koji builds
Config example:
[koji]
type = koji
url = https://koji.example.org/kojihub
login = testuser
name = Example koji server
nitrate¶
Nitrate stats such as created test plans, runs, cases
Config example:
[nitrate]
type = nitrate
- class did.plugins.nitrate.AutomatedCases(option, name=None, parent=None, user=None, options=None)¶
Automated cases created
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.nitrate.AutoproposedCases(option, name=None, parent=None, user=None, options=None)¶
Cases proposed for automation
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.nitrate.CopiedCases(option, name=None, parent=None, user=None, options=None)¶
Test cases copied
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.nitrate.ManualCases(option, name=None, parent=None, user=None, options=None)¶
Manual cases created
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.nitrate.NitrateStats(option, name=None, parent=None, user=None)¶
Nitrate stats
- property cases¶
All test cases created by the user
- property copies¶
All test case copies created by the user
- order = 100¶
pagure¶
Pagure stats such as created/closed issues and pull requests.
Config example:
[pagure]
type = pagure
url = https://pagure.io/api/0/
login = <username>
token = <authentication-token>
Use login to override the default email address for searching.
See the Config documentation for details on using aliases.
The authentication token is optional and can be stored in a file
pointed to by token_file instead of token.
- class did.plugins.pagure.Issue(data)¶
Pagure Issue or Pull Request
- class did.plugins.pagure.IssuesClosed(option, name=None, parent=None, user=None, options=None)¶
Issues closed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.pagure.IssuesCreated(option, name=None, parent=None, user=None, options=None)¶
Issues created
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.pagure.Pagure(url, token)¶
Pagure Investigator
- search(query, pagination, result_field)¶
Perform Pagure query
phabricator¶
Phabricator stats for authored and reviewed differentials, aka reviews.
Config example:
[phabricator]
type = phabricator
url = https://reviews.llvm.org/api/
token = <authentication-token>
token_file = <file-with-authentication-token>
login = <username1>,<username2>
The authentication token is not optional. Go to https://reviews.llvm.org/settings/user/<username>/page/apitokens/ and get yourself a “Conduit API token”. The token and the actual users for which we query stats are decoupled, allowing you to specify more than one username.
We use these endpoints for the most part:
https://secure.phabricator.com/conduit/method/differential.revision.search/
https://secure.phabricator.com/conduit/method/transaction.search/
- class did.plugins.phabricator.Differential(data)¶
Phabricator Differential
Here’s an example:
{ "id": 134852, "type": "DREV", "phid": "PHID-DREV-6vyvvzlqatx6a4oveqkw", "fields": { "title": "[clang-format][NFC] Clean up class HeaderIncludes", "uri": "https://reviews.llvm.org/D134852", "authorPHID": "PHID-USER-vou2cb5rty2zlopptj5z", "status": { "value": "published", "name": "Closed", "closed": true, "color.ansi": "cyan" }, "repositoryPHID": "PHID-REPO-f4scjekhnkmh7qilxlcy", "diffPHID": "PHID-DIFF-6qic23rkxpwvkp6g4wdg", "summary": "", "testPlan": "", "isDraft": false, "holdAsDraft": false, "dateCreated": 1664433452, "dateModified": 1665032091, "policy": { "view": "public", "edit": "users" } }, "attachments": {} }
- property id: str¶
Returns the Phabricator ID for the differential as a string
- property phid: str¶
Returns the Phabricator ID for the differential as a string
- property title: str¶
Returns the Phabricator title for the differential as a string
- property uri: str¶
Returns the Phabricator URI for the differential as a string
- class did.plugins.phabricator.DifferentialsAccepted(**kwargs)¶
Differentials accepted
- fetch()¶
To be implemented by subclasses
- class did.plugins.phabricator.DifferentialsBaseStats(**kwargs)¶
Represent the base class of phabricator statistics
- diffs_accepted = {}¶
- diffs_closed = {}¶
- diffs_commented = {}¶
- diffs_created = {}¶
- diffs_requested_changes = {}¶
- fetch()¶
To be implemented by subclasses
- fetch_all_relevant_diffs()¶
Fetches all differentials that we possibly need for all phabricator stats.
- got_diffs = False¶
- verbose = False¶
- class did.plugins.phabricator.DifferentialsClosed(**kwargs)¶
Differentials closed
- fetch()¶
To be implemented by subclasses
- class did.plugins.phabricator.DifferentialsCommented(**kwargs)¶
Differentials commented
- fetch()¶
To be implemented by subclasses
- class did.plugins.phabricator.DifferentialsCreated(**kwargs)¶
Differentials created
- fetch()¶
To be implemented by subclasses
- class did.plugins.phabricator.DifferentialsRequestedChanges(**kwargs)¶
Differentials where changes were requested
- fetch()¶
To be implemented by subclasses
- class did.plugins.phabricator.EventType(value)¶
EventType defines what type of transaction events we support.
- ACCEPT = 'accept'¶
- CLOSE = 'close'¶
- COMMENT = 'comment'¶
- CREATE = 'create'¶
- INLINE = 'inline'¶
- PROJECTS = 'projects'¶
- REQUEST_CHANGES = 'request-changes'¶
- REQUEST_REVIEW = 'request-review'¶
- REVIEWERS = 'reviewers'¶
- STATUS = 'status'¶
- SUBSCRIBERS = 'subscribers'¶
- SUMMARY = 'summary'¶
- TITLE = 'title'¶
- UNDEFINED = ''¶
- UPDATE = 'update'¶
- class did.plugins.phabricator.Phabricator(url, token, logins)¶
Phabricator Investigator
- MAX_PAGE_SIZE = 100¶
- property login_phids: List[str]¶
Returns the PHIDs for the login usernames.
- Returns:
List[str]: The phabricator PHIDs for the login names
- TODO(kwk): The return type could be just list[str] but the
Copr epel builder currently only has python 3.6 where this is not possible.
- search_diffs(since: Optional[date] = None, until: Optional[date] = None, author_phids: Optional[List[str]] = None, subscriber_phids: Optional[List[str]] = None, responsible_phids: Optional[List[str]] = None, reviewer_phids: Optional[List[str]] = None) Set[Differential]¶
Find Phabricator Differentials
- search_transactions(diff: Differential, author_phids: Optional[List[str]] = None) Set[TransactionEvent]¶
Returns all the transaction events for a given differential object. If given you can search for events by certain authors.
- class did.plugins.phabricator.PhabricatorStats(option, name=None, parent=None, user=None)¶
Phabricator work
- order = 360¶
- class did.plugins.phabricator.TransactionEvent(data)¶
Phabricator Transaction event.
See https://reviews.llvm.org/conduit/method/transaction.search/.
Here’re examples:
{ "id": 4077171, "phid": "PHID-XACT-DREV-7grkcftntvxf24c", "type": "create", "authorPHID": "PHID-USER-m46saogacat2jslbykue", "objectPHID": "PHID-DREV-ypgxje4hhhdefuy4d6sz", "dateCreated": 1674573526, "dateModified": 1674573526, "groupID": "dr3e2g6tx6ztr6zivk343kytk7uk7yng", "comments": [], "fields": {} } { "id": 4077175, "phid": "PHID-XACT-DREV-zconyio2dw2y7ne", "type": "reviewers", "authorPHID": "PHID-USER-m46saogacat2jslbykue", "objectPHID": "PHID-DREV-ypgxje4hhhdefuy4d6sz", "dateCreated": 1674573526, "dateModified": 1674573526, "groupID": "dr3e2g6tx6ztr6zivk343kytk7uk7yng", "comments": [], "fields": { "operations": [ { "operation": "add", "phid": "PHID-USER-aigeqxvzdke5r36hodix", "oldStatus": null, "newStatus": "added", "isBlocking": false }, { "operation": "add", "phid": "PHID-USER-7rdtwvftotyrjl5bf7gy", "oldStatus": null, "newStatus": "added", "isBlocking": false }, { "operation": "add", "phid": "PHID-USER-icssaf6rtj6ahq4lchay", "oldStatus": null, "newStatus": "added", "isBlocking": false } ] } },
- property author_phid: str¶
Returns the author’s PHID
- is_in_date_range(since: Optional[date] = None, until: Optional[date] = None) bool¶
Returns true if the event happend in the given timestamp range, including the boundaries.
redmine¶
Redmine stats
Config example:
[redmine]
type = redmine
url = https://redmine.example.com/
login = <user_db_id>
activity_days = 30
Use login to set the database user id in Redmine (number not login
name). See the Config docs for details on using aliases. Use
activity_days to override the default 30 days of activity paging,
this has to match to the server side setting, otherwise the plugin will
miss entries.
- class did.plugins.redmine.Activity(data)¶
Redmine Activity
rt¶
Request Tracker stats such as reported and resolved tickets
Config example:
[rt]
type = rt
prefix = RT
url = https://tracker.org/rt/Search/Results.tsv
- class did.plugins.rt.ReportedTickets(option, name=None, parent=None, user=None, options=None)¶
Tickets reported
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.rt.RequestTracker(parent)¶
Request Tracker Investigator
- get(path)¶
Perform a GET request with GSSAPI authentication
- search(query)¶
Perform request tracker search
- class did.plugins.rt.RequestTrackerStats(option, name=None, parent=None, user=None)¶
Request Tracker
- order = 500¶
- class did.plugins.rt.ResolvedTickets(option, name=None, parent=None, user=None, options=None)¶
Tickets resolved
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.rt.Ticket(record, parent)¶
Request tracker ticket
sentry¶
Sentry stats such as commented and resolved issues.
Configuration example:
[sentry]
type = sentry
url = https://sentry.io/api/0/
organization = team
token = ...
You need to generate authentication token at the server. The only
scope you need to enable is org:read. If you prefer to store the
token in a file, use token_file to point to the file that has
your token.
- class did.plugins.sentry.Activity(activity)¶
Sentry Activity
- class did.plugins.sentry.CommentedIssues(option, name=None, parent=None, user=None, options=None)¶
Issues commented
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.sentry.Issue(issue)¶
Sentry Issue
- class did.plugins.sentry.ResolvedIssues(option, name=None, parent=None, user=None, options=None)¶
Issues resolved
- fetch()¶
Fetch the stats (to be implemented by respective class).
trac¶
Trac stats such as created, accepted, updated and closed tickets
Config example:
[trac]
type = trac
prefix = TT
url = https://some.trac.com/trac/project/rpc
- class did.plugins.trac.Trac(ticket=None, changelog=None, parent=None, options=None)¶
Trac investigator
- accepted(user)¶
True if ticket was accepted in given time frame
- closed()¶
True if ticket was closed in given time frame
- history(user=None)¶
Return relevant who-did-what logs from the ticket history
- static search(query, parent, options)¶
Perform Trac search
- updated(user)¶
True if the user commented the ticket in given time frame
- class did.plugins.trac.TracAccepted(option, name=None, parent=None)¶
Accepted tickets
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trac.TracClosed(option, name=None, parent=None)¶
Closed tickets
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trac.TracCommon(option, name=None, parent=None)¶
Common Trac Stats object for saving prefix & proxy
- class did.plugins.trac.TracCreated(option, name=None, parent=None)¶
Created tickets
- fetch()¶
Fetch the stats (to be implemented by respective class).
trello¶
Trello actions such as created, moved or closed cards
Config example (public):
[tools]
type = trello
user = member
Config example (private):
[tools]
type = trello
apikey = ...
token = ...
Optional arguments:
board_links = g9mdhdzg
filters = createCard, updateCard,
updateCard:idList, updateCard:closed,
updateCheckItemStateOnCard
apikey
https://trello.com/app-key
token
http://stackoverflow.com/questions/17178907
token_file
the token stored in a file
boards
default: all
filters
default: all
- class did.plugins.trello.TrelloAPI(stats, config)¶
Trello API
- board_links_to_ids()¶
Convert board links to ids
- get_actions(filters, since=None, before=None, limit=1000)¶
Example of data structure: https://api.trello.com/1/members/ben/actions?limit=2
- class did.plugins.trello.TrelloCardsClosed(trello, filt, option, name=None, parent=None)¶
Trello cards closed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trello.TrelloCardsCommented(trello, filt, option, name=None, parent=None)¶
Trello cards commented
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trello.TrelloCardsCreated(trello, filt, option, name=None, parent=None)¶
Trello cards created
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trello.TrelloCardsMoved(trello, filt, option, name=None, parent=None)¶
Trello cards moved
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trello.TrelloCardsUpdated(trello, filt, option, name=None, parent=None)¶
Trello cards updated
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trello.TrelloCheckItem(trello, filt, option, name=None, parent=None)¶
Trello checklist items completed
- fetch()¶
Fetch the stats (to be implemented by respective class).
- class did.plugins.trello.TrelloStats(trello, filt, option, name=None, parent=None)¶
Trello stats
wiki¶
MoinMoin wiki stats about updated pages
Config example:
[wiki]
type = wiki
wiki test = http://moinmo.in/
The optional key ‘api’ can be used to change the default xmlrpc api endpoint:
[wiki]
type = wiki
api = ?action=xmlrpc2
wiki test = http://moinmo.in/
zammad¶
Zammad stats such as updated tickets
Config example:
[zammad]
type = zammad
url = https://zammad.example.com/api/v1/
token = <authentication-token>
Optionally use token_file to store the token in a file instead
of plain in the config file.
- class did.plugins.zammad.Ticket(data)¶
Zammad Ticket
- class did.plugins.zammad.TicketsUpdated(option, name=None, parent=None, user=None, options=None)¶
Tickets updated
- fetch()¶
Fetch the stats (to be implemented by respective class).