Welcome to Jirafs’s documentation!¶
Pronounced like ‘giraffes’, but totally unrelated to wildlife, this
library lets you stay out of Jira as much as possible by letting
you edit your Jira issues as a collection of text files using an
interface inspired by git
and hg
.
Getting Started¶
Installation¶
It is recommended that you install the program using pip
while in a
Python 3 virtualenv; you can install using pip
by running:
pip install jirafs
After Jirafs successfully installs, you’ll have access to the jirafs
command that you can use for interacting with Jira.
Working with a Jira issue¶
First, you’ll need to “clone” the issue you want to work with using
Jirafs by running the following
(replacing http://my.jira.server/browse/MYISSUE-1024
with the
issue url you are concerned about):
jirafs clone http://my.jira.server/browse/MYISSUE-1024
The first time you run this command, Jirafs will ask you for a series of details
that it will use for communicating with Jira; don’t worry: although all of this
information will be stored in a plaintext file at ~/.jirafs_config
, Jirafs will
not store your password unless you give it permission to do so.
Once the command runs successfully, it will have created a new folder named after the issue you’ve cloned, and inside that folder it will place a series of text files representing the issue’s contents in Jira as well as copies of all attachments currently attached to the issue in Jira.
The following text files are created:
fields.jira
: This file will show all currently-set field values for this Jira issue (except fields written to their own files; seedescription.jira
below). You can change field values here by editing the field values in the file. See Editing Issue Fields for more information.description.jira
: This file will show the issue’s current description. You can change the issue’s description by editing the contents of this file.links.jira
: This file lists all of the links associated with this Jira issue. You can add new links (or remove links) by adding or removing bulleted items from this list; see Adding, Removing or Changing Links for more information.comments.read_only.jira
: This file shows all comments currently posted to this issue. Note that you cannot edit the comments in this file.new_comment.jira
: This file starts out empty, but if you would like to add a new comment, you can create one by entering text into this file.
In order to update any of the above data or upload an asset, either
make the change to a field in fields.jira
, edit the issue’s
description in description.jira
, write a comment into
new_comment.jira
, or copy a new asset into this folder, then run:
jirafs status
to see both what changes you’ve marked as ready for being submitted to Jira as well as which changes you have made, but not yet committed.
Note
Unlike when working with a git repository, you do not need to ‘stage’ files using a command analogous to git’s “add” command when working with a Jira issue using Jirafs. All uncommitted files will automatically be included in any commit made.
Once you’re satisfied with the changes that are about to be submitted to Jira, run:
jirafs submit
Note
jirafs submit
really just runs jirafs commit
followed by
jirafs push
(which itself runs jirafs pull
to get your
local copy up-to-date with what it saw in Jira), so although
jirafs submit
is probably the path you want to take, feel
free to use the lower-level more-git-like commands if you want.
Please consider this to be just a simple overview – there are a variety of other commands you can run to have finer-grained control over how the issue folder is synchronized with Jira; see Common Commands for more details.
Note
If you are a VIM user, there is a VIM Plugin available that provides syntax highlighting for Jira/Confluence’s wikimarkup.
Editing Issue Fields¶
In most cases, you can simply edit the field’s contents directly – just make sure to indent the field contents by four spaces.
For text fields, editing field contents is as simple as typing-in a new
value, but many issue fields are are JSON dictionaries or lists that
require you to edit the data in a more-structured way. If the data
you enter is not valid JSON, when push
-ing up changes, you will
receive an error, but don’t worry – if you encounter such an error, edit
the contents to be valid JSON, commit
, and push
again. You
may need to consult with Jira’s documentation to develop an understanding
of how to change these values.
Note
You don’t always need to enter values for every field in a JSON dictionary; in some cases, Jira will infer the missing information for you.
Adding, Removing or Changing Links¶
Each line of links.jira
starts with a bullet (*
), and although
links to other issues (in Jira terminology – “issue links”) and links
to arbitrary URLs (“remote links”) appear similar, they have slightly
different formats.
Issue Links¶
You can link other issues to your Jira issue by adding bulleted lines in the following format:
* LINK TYPE: TICKET NUMBER
So, if there is an issue relationship named “blocks”, and your Jira issue is blocked by a ticket numbered “JFS-284”, you could add a line:
* Blocks: JFS-284
Note
Both the issue relationship and ticket number are case-insensitive,
but that if you enter a relationship name that does not exist, you will
receive an error message when push
-ing up your changes. If you see
such an error message, don’t fret – just change your relationship name
to one of the suggested names, commit
, and push
again.
Remote Links¶
You can add links to arbitrary URLs by adding bulleted lines in the following format:
* NAME: URL
If you, for example, wanted to add a link to your issue that pointed users toward your favorite cat video, you could, for example, add a line:
* Cat scares compilation: https://www.youtube.com/watch?v=DBRgFLHra48
Macros¶
One of the most powerful features of Jirafs is how it can make your workflow easier if you ever need to do common things like insert tables, graphs, or charts in your issues. There are a handful of macros available, and writing your own macro plugin is easy. See Using Macros for more information.
Migrating from 1.0¶
There were a lot of changes between Jirafs v1 and Jirafs v2; so you might be under the impression that you may need to take special care with how you migrate forward to v2. Fortunately, though, ticket folders created with Jirafs v1 are fully-compatible with those created by Jirafs v2. You do, though, need to make one change to how you work with jirafs: the syntax used for macros has changed, and the macro API has been updated and will require you to upgrade the macros you currently use to their latest versions.
If you had a macro named list-table
installed, you previously
would have used that macro by using Jira-style curly-brace syntax:
{list-table}
*
** One
** Two
* A
** B
** C
{list-table}
As of Jirafs v2, we use an xml-inspired syntax for a variety of reasons, most importantly that it makes it easier for Jirafs to tell the difference between when you’re intending to use Jira markup and when you’re intending that Jirafs run a macro for you:
<jirafs:list-table>
*
** One
** Two
* A
** B
** C
</jirafs:list-table>
Otherwise, behaviors will generally be the same.
Common Commands¶
The following commands are sure to be commonly used. Be sure to check out Advanced Commands if you are curious about less-commonly-used functionality.
Note
Commands marked with an asterisk can be ran from either an issue folder, or from within a folder containing many issue folders.
In the latter case, the command will be ran for every subordinate issue folder.
clone <source>
¶
Requires a single parameter (source
) indicating what to clone.
Possible forms include:
clone http://my.jira.server/browse/MYISSUE-1024 [PATH]
clone MYISSUE-1024 [PATH]
(will use default Jira instance)
Create a new issue folder for MYISSUE-1024
(replace MYISSUE-1024
with
an actual Jira issue number), and clone the relevant issue into this folder.
Note that you may specify a full URL pointing to an issue, but if you do not specify a full URL, your default Jira instance will be used; if you have not yet set one, you will be asked to specify one.
Although by default, the issue will be cloned into a folder matching the name
of the issue, you may specify a path into which the issue should be cloned
by specifying an additional parameter (PATH
in the example forms above).
preview [<field name>]
¶
Render the content of the field named field_name
via your
Jira instance’s Wiki Markup renderer. This is useful for
helping you ensure that your wiki markup is correct and previewing
content generated by any macro plugins you might be using. If no field name
is specified, a message overview will be displayed showing you a preview
of the message description, summary, new comment, and historical
comments.
Note that you can also access subkeys in fields containing JSON by using a dotpath, and can render the following special fields:
new_comment
: The formatted contents of your unsubmitted comment.comments
: The comments for this issue.
submit
¶
Commit outstanding changes, push them to the remote server, and pull outstanding changes.
This is exactly equivalent to running a commit
followed by a push
.
commit
¶
From within an issue folder, commits local changes and marks them for
submission to Jira next time push
is run.
Note
Unlike git (but like mercurial), you do not need to stage files by running a command analogous to git’s ‘add’ before committing. The commit operation will automatically commit changes to all un-committed files.
pull
*¶
From within an issue folder, fetches remote changes from Jira and merges
the changes into your local copy. This command is identical to running
fetch
followed by merge
.
push
*¶
From within an issue folder, discovers any local changes, and pushes your local changes to Jira.
status
*¶
From within an issue folder, will report both any changes you have not
yet committed, as well as any changes that would take place were you to
run jirafs push
.
open
*¶
From within an issue folder, opens the current Jira issue in your default web browser.
subtask <summary>
¶
From within an issue folder, creates a new subtask of the current Jira issue.
assign [<username>]
¶
Change the assignee of the Jira issue to the username specified. If one does not specify a username, the assignee will be set to the currently authenticated user.
transition
¶
From within an issue folder, allows you to transition an issue into any state available in your workflow.
Possible forms include:
transition
: The user will be presented with state options for selection at runtime.transition 10
: Transition into the state with the ID of ‘10’.transition "closed"
: Transition into the state with the name “closed”. Note that state names are case-insensitive.
Note
Note that the options available are dependent upon the user account used for authentication.
Advanced Commands¶
You will probably not have a need to use the below commands, but they are available for adventurous users.
fetch
¶
Fetch upstream changes from Jira, but do not apply them to your local
copy. To apply the fetched changes to your local copy, run merge
.
merge
¶
From within an issue folder, merges previously-fetched but unmerged changes into your local copy.
diff
¶
From within an issue folder, will display any local changes that you have made.
field <field name>
¶
Write the content of the field named field name
to the console. Useful
in scripts for gathering, for example, the ticket’s summary
field.
Note that you can also access subkeys in fields containing JSON by using a dotpath, and can access the following special fields:
new_comment
: The formatted contents of your unsubmitted comment.links
: Returns a JSON structure representing this issue’s links.fields
: Returns a JSON structure representing all field contents.
setfield <field name> <value>
¶
Set the value of the field named field name
to the value value
.
This is useful for programmatically changing the status of various fields.
Note that you can also access subkeys in fields containing JSON by using a dotpath.
match <field name> <value>
¶
Return a status code of 0
if the field field name
matches the value
value
. This is useful for allowing you to programmatically perform
certain actions on fields matching certain values – for example: moving
resolved issues into an archive folder.
As with all commands, check --help
for this command; you’ll find
utilities allowing you to invert the check (for returning 0
when
the check does not match) and utilities for executing a command
when the field does not match.
Note that you can also access subkeys in fields containing JSON by using a dotpath.
log
¶
From within an issue folder, will print out the log file recording actions Jirafs has performed for this ticket folder.
config
¶
Get, set, or list configuration values. Requires use of one of the following sub-options:
--get <SETTING_NAME>
: Get the value of this specific parameter name.--set <SETTING_NAME> <VALUE>
: Set the value of this specific parameter.--list
: List all settings currently configured in the current context. When used within an issue folder, will list this issue’s settings, but when used outside of an issue folder, will display only global configuration.
You may also use the --global
argument to ensure that configuration
changes or lists use or affect only the global configuration.
plugins
¶
List, activate, or deactivate plugins by name.
Plugins provides several sub-options:
--verbose
: Display information about each plugin along with its name.--enabled-only
: List only plugins that are currently enabled.--disabled-only
: List only plugins that are available, but not currently enabled.--enable=PLUGIN_NAME
: Enable a plugin by name for the current issue folder.--disable=PLUGIN_NAME
: Disable a plugin by name for the current issue folder.--global
: Used with--enable
or--disable
above, will enable or disable a plugin globally. Note: per-folder settings always take priority.
git
¶
From within an issue folder, will provide direct access to this issue folder’s internal git repository. This interface is not intended for non-developer use; please make sure you know what you’re doing before performing git operations directly.
debug
¶
From within an issue folder, will open up a python shell having access
to a variable named folder
holding the Python object representing
the ticket folder you are currently within.
search_users <term>
¶
Search for users matching the specified search term. This is particularly useful if you’re not sure what somebody’s username and you were hoping to mention them in a ticket so they get an e-mail notification.
create
¶
Creates a new issue. Provides the following options:
--summary
: The summary to use for your new issue.--description
: The description to use for your new issue.--issuetype
: The issue type to use for your new issue (defaults to ‘Task’).--project
: The project key to use for your new issue. This is the short, capitalized string you see next to issues. For example, if your tickets were named something like KITTENS-12084, ‘KITTENS’ is the project key.--quiet
: Do not prompt user to provide values interactively.
If any of the above values are not specified, the user will be prompted to provide them interactively.
Configuration¶
Settings affecting all issues are set in the following files:
~/.jirafs_config
: Global configuration values affecting all issues.~/.jirafs_ignore
: Global list of patterns to ignore completely; these files differ from.jirafs_local
below in that they will not be tracked in the underlying git repository. See Ignore File Format for details.~/.jirafs_local
: Global list of patterns to ignore when looking through issue directories for files to upload to Jira. Note that these files will continue to be tracked in the underlying git repository. See Ignore File Format for details.~/.jirafs_remote_ignore
: A list of patterns to ignore when looking through files attached to a Jira issue. Files matching any of these patterns will not be downloaded. See Ignore File Format for details.
You may also add any of the below files into any issue directory (in this
example, MYISSUE-1024
):
MYISSUE-1024/.jirafs/config
: Configuration overrides for this specific issue folder. Settings set in this file will override – for this folder only – any values you have set in~/.jirafs_config
.MYISSUE-1024/.jirafs_ignore
: A list of patterns to ignore completely; these files differ from.jirafs_local
below in that they will not be tracked in the underlying git repository. See Ignore File Format for details.MYISSUE-1024/.jirafs_local
: A list of patterns to ignore when looking through this specific issue directory. This list of patterns is in addition to patterns entered into~/.jirafs_ignore
above. Note that these files will continue to be tracked in the underlying git repository. See Ignore File Format for details.MYISSUE-1024/.jirafs_remote_ignore
: A list of patterns to ignore when looking through files attached to this specific Jira issue. Files matching any of these patterns will not be downloaded. These patterns are in addition to the patterns entered into~/.jirafs_remote_ignore
above. See Ignore File Format for details.
Using an untrusted HTTPS certificate¶
If your Jira instance uses a self-signed certificate or you are working in an enterprise environment having a non-standard certificate authority, you can manually configure your Jira connection to either not verify the certificate, or to instead use a non-standard certificate authority certificate.
- First, find the configuration section in your
~/.jirafs_config
named after the address of your Jira server. - Then, after the lines starting with
username
andpassword
, add a line readingverify = <VALUE>
replacing<VALUE>
with one of two options:- If your Jira instance uses a self-signed certificate: the string
false
. - If your Jira instance’s certificate uses a non-standard certificate authority, the absolute path to a place on your computer where your certificate authority’s certificate is stored.
- If your Jira instance uses a self-signed certificate: the string
For example:
1 2 3 4 | [https://jira.mycompany.org]
username = myusername
password = mypassword
verify = /path/to/certificate/or/false
|
Disabling “Save Jira Password” prompt¶
If you would never like to save your Jira password in Jirafs, you can disable
the “Save Jira Password” prompt by setting the ask_to_save
setting to false
in the main
section of your ~/.jirafs_config
file.
For example:
1 2 | [main]
ask_to_save = false
|
Setting a Date Format for Rendered Comments¶
By default, Jirafs will render a date using the following international date format:
%Y-%m-%d at %H:%M:%S %Z
But you can configure the format to one more familiar to you by setting the
main.date_format
configuration setting using the formatting codes
described here: `https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes`_
1 2 | [main]
date_format = %d %B %Y at %h:%M %p
|
Using Plugins¶
Enable the plugin for a given ticket folder:
jirafs plugins --enable=my_plugin_name
Enable the plugin globally:
jirafs plugins --global --enable=my_plugin_name
Writing your own Plugins¶
Jirafs plugins come in two different varieties:
- “Folder Plugins” are used for altering the behavior of existing commands when interacting with a Ticket Folder. They can be disabled or enabled on a per-folder basis, too.
- “Command Plugins” are used for adding new commands to Jirafs. These are always enabled when installed.
Note
All existing Jirafs commands (‘clone’, ‘pull’, ‘push’, etc.) are “Command Plugins”.
Writing Plugins¶
For a working example of a folder plugin, check out Jirafs-Pandoc’s Github Repository.
Setuptools Entrypoint¶
Add a setuptools entrypoint to your plugin’s
setup.py
:entry_points={ 'jirafs_plugins': [ "my_plugin_name = module.path:ClassName" ] }
Write a subclass of
jirafs.plugin.Plugin
implementing one or more methods using the interface described in Folder Plugin API.
Folder Plugin API¶
The following properties must be defined:
MIN_VERSION
: The string version number representing the minimum version of Jirafs that this plugin will work with.MAX_VERSION
: The string version number representing the first version at which your plugin would not be guaranteed to becompatible. Note that this means that your Jirafs version must be below this number, and that users running a version of Jirafs matching this will see an error message. Note: Jirafs uses semantic versioning, so you should set this value to the next major version about the highest version you’ve tested.
Pre/Post Command Methods¶
All commands (including user-installed commands) can have plugins altering
their behavior by defining pre_*COMMAND*
and post_*COMMAND*
methods.
For the below, please replace *COMMAND*
with the command your plugin
would like to alter the behavior of.
pre_*COMMAND*(**kwargs)
:- Executed before handling
*COMMAND*
. Receives (as**kwargs
) all parameters that will be passed-in to the underlying command. - You may alter the parameters that will be passed-in to the underlying
command by returning a new or altered
**kwargs
dictionary. - Return
None
or the original**kwargs
dictionary to pass original arguments to the command without alteration.
- Executed before handling
post_*COMMAND*(returned)
:- Executed after handling
*COMMAND*
. Receives as an argument the result returned by the underlying command.
- Executed after handling
Note
Although the return values of commands are not in the scope of this
specification, many commands return a jirafs.utils.PostStatusResponse
instance.
Such an instance is a named tuple containing two properties:
- (bool)
new
: Whether the command’s action had an effect on the underlying git repository. - (string)
hash
: The hash of the relevant repository branch’s head commit following the action.
Properties¶
The plugin will have the following properties and methods at its disposal:
self.ticketfolder
: An instance ofjirafs.ticketfolder.TicketFolder
representing the jira issue that this plugin is currently operating upon.self.get_configuration()
: Returns a dictionary of configuration settings for this plugin.self.metadata
: Returns a dictionary containing metadata stored for this plugin. This dictionary is modifyable, and will be preserved between plugin executions.
Methods¶
execute_macro(data: str, attrs: Dict, config: Dict) -> str
: REQUIRED Your macro function. It will receive a series of parameters:data
: The content of your macro.attrs
: Any attributes of your macro.config
: Jirafs config parameters.
and is expected to return a string of text that your macro will be replaced when when sending content to Jira.
execute_macro_reversal(data: str) -> str
: If provided, will be expected to perform the reversal ofexecute_macro
above. It will receive as parameters the full text of each field.cleanup()
: Perform any cleanup following macro processing for a ticket folder. If you need more-granular control, you can define methods forcleanup_pre_process()
andcleanup_post_process()
if you need to segment your cleanup process between before and after running macro processing methods.
Macro Plugins¶
Macro plugins are special kinds of folder plugins that are instead subclasses of jirafs.plugin.MacroPlugin
but same setuptools entrypoints apply as are described in Setuptools Entrypoint.
Macros can be executed using either a block element format; for example:
<jirafs:my-macro>
Some content
</jirafs:my-macro>
Note
See Reserved Attributes for more information about attributes and
the special src
attribute.
or as a void element:
<jirafs:my-macro src="some_file_to_read_as_content.ext" />
Note
The trailing slash at the end of your macro is important!
Your execute_macro
method is expected to return text that should be sent
to Jira instead of your macro. Note that the method signature remains
identical to that of a block element macro, but instead of receiving
the content of the block, you will receive None
.
Reserved Attributes¶
src
: All macro plugins can be provided in either a block or void elements. When using a block element version of your macro, you provide content directly within the content of your tag. If you would like the content to be imported from a file instead, you can provide the path to the file to import via thesrc
attribute.
Attributes¶
Both block and void elements can receive any number of attributes; they’re specified following the same conventions you might use for providing an HTML tag with attributes; for example:
<jirafs:flag-image country_code=”US” size=300 alternate=True /> {flag-image:country_code=US|size=300|alternate}
country_code
:US
(string)size
:300.0
(float)alternate
:True
(boolean)
Example Macro Plugin¶
The following plugin isn’t exactly useful, but it does demonstrate the basic functionality of a plugin:
class Plugin(MacroPlugin):
TAG_NAME = 'upper-cased'
def execute_macro(self, data, prefix='', **kwargs):
return prefix + data.upper()
When you enter the following text into a Jira ticket field:
<jirafs:upper-cased prefix="Hello, ">my name is Adam.</jirafs:upper-cased>
the following content will be sent to Jira instead:
Hello, MY NAME IS ADAM.
Warning
Note that it’s always a good idea to make sure your execute_macro
method has a final parameter of **kwargs
! In future versions of
Jirafs, we may add more keyword arguments that will be sent automatically.
Automatically-Reversed Macro Plugins¶
It’s not a ton of fun to have to handle reversing your own macros; so
if your macro’s content will produce unique content for provided input,
you can use the AutomaticReversalMacroPlugin
as your base class
instead of MacroPlugin
. If you do so, your macro will automatically
be reversed when returning content from Jira by scanning the content
received from Jira and replacing any output generated by your macro
during the most recent run with the macro content that generated that
output.
In general, you won’t need to make any special modifications, but there are useful methods for overriding in special circumstances:
should_rerender(data: str, cache_entry: Dict, config: Dict) -> bool
: Control whether this given input content (data
) should be re-rendered. By default,should_rerender
returnsTrue
only ifcache_entry
is empty. Values available in thecache_entry
dictionary include:filenames
: A list of filenames generated by your macro while during processing of this input text.attrs
: Macro attributes set for your macro when running for this input text.replacement
: The replacement text generated by your macro for this input text.is_temp
: Whether or not this macro result was the result of generating content for your current working directory (is_temp==False
), or if it was the result of processing historical content for identifying changes (is_temp==True
).
See Methods for other methods that may be necessary for your macro.
Examples¶
See one of the following repositories for an example of this type of macro:
Image Macros¶
A particularly powerful Macro type is the “Image Macro”. Use of a macro
of this type will allow you to automatically generate and embed images
in your Jira content by passing your macro’s contents through a tool
like Graphviz’ dot
or plantuml
.
In the case of this type of macro, you need to define just one method:
get_extension_and_image_data(data: str, attrs: Dict) -> Tuple[str, bytes]
: For a given input text (data
) and macro attributes (attrs
), return a 2-tuple of the file extension to use for the file to be created, and the bytes of that file.
See Methods for other methods that may be necessary for your macro.
Note
Unlike most subclasses of MacroPlugin
, you should not define
your own execute_macro
method!
Examples¶
See one of the following repositories for an example of this type of macro:
Note
Image Macros are automatically reversed.
Writing Command Plugins¶
For a working example of a command plugin, check out the source of Jirafs existing commands.
Setuptools Entrypoint¶
Add a setuptools entrypoint to your plugin’s
setup.py
:entry_points={ 'jirafs_commands': [ "my_command_name = module.path:ClassName" ] }
Write a subclass of
jirafs.plugin.CommandPlugin
implementing one or more methods using the interface described in Plugin API.
Plugin API¶
The following properties must be defined:
MIN_VERSION
: The string version number representing the minimum version of Jirafs that this plugin will work with.MAX_VERSION
: The string version number representing the first version at which your plugin would not be guaranteed to becompatible. Note that this means that your Jirafs version must be below this number, and that users running a version of Jirafs matching this will see an error message. Note: Jirafs uses semantic versioning, so you should set this value to the next major version about the highest version you’ve tested.
The following methods may be defined to control the behavior of your command plugin:
handle(self, args, folder, jira, path, **kwargs)
: (REQUIRED) This method (and methods called from here) is where you should write the bulk of your plugin’s functionality.handle
receives several keyword arguments:args
: An instance ofargparse.Namespace
holding arguments specified on the command line. Seeadd_arguments
andparse_arguments
for details.folder
: Ajirafs.ticketfolder.TicketFolder
instance corresponding with the current path. If you are writing a command that does not require a ticketfolder, set an attribute on your class namedAUTOMATICALLY_INSTANTIATE_FOLDER
toFalse
(Note that this option makes the value ofTRY_SUBFOLDERS
irrelevant) and this value will always beNone
whether or not your command was invoked from within a ticket folder.jira
: A callable (accepting, optionally, the string domain of a Jira instance) which will return an instance ofjira.client.JIRA
corresponding with the domain you’ve specified, or the default Jira connection if no Jira domain was specified.path
: The string path from which this command was called. This can be used to create ajirafs.ticketfolder.TicketFolder
instance representing the current ticket folder if so desired.**kwargs
: Keyword arguments may be added in the future; it is extremely important that yourhandle
method accept arbitrary keyword arguments in order to prevent your plugin from breaking when new keyword arguments are added in the future.
add_arguments(self, parser)
: Using this method, you can add arguments that your command requires. Follow the guidelines in Python’sargparse
documentation for an overview of how arguments are handled.parser
: Anargparse.ArgumentParser
instance.
parse_arguments(self, parser, extra_arguments)
: Potentially useful as a method to place argument validation.parser
: Anargparse.ArgumentParser
instance. Note that this instance will have already had attached all arguments added in theadd_arguments
method above.extra_arguments
: A list of string arguments unused by Jirafs.
You may also use any of the following properties to alter the behavior of Jirafs:
TRY_SUBFOLDERS
: Set this class property toTrue
if this command should be applied to all Jirafs ticket folders in subdirectories in the event that the current folder is not a ticket folder.RUN_FOR_SUBTASKS
: Set this class property toTrue
if you would like your command to be automatically executed for subtask when being executed for a ticket having subtasks.
Example Plugin¶
import pydoc
from jirafs.plugin import CommandPlugin
class Command(CommandPlugin):
""" Run a git command against this ticketfolder's underlying GIT repo """
MIN_VERSION = "2.0.0"
MAX_VERSION = "3.0.0"
def handle(self, args, folder, **kwargs):
return self.cmd(folder, *self.git_arguments)
def parse_arguments(self, parser, extra_args):
args, git_arguments = parser.parse_known_args(extra_args)
self.git_arguments = git_arguments
return args
def main(self, folder, *git_arguments):
result = folder.run_git_command(*git_arguments)
pydoc.pager(result)
return result
Using Macros¶
Macros are special kinds of plugins that perform simple functions for transforming text you enter into fields into something else when submitting them to Jira.
Existing Macros¶
- For including programmatically-generated images in your Jira issues without
ever leaving your editor:
- jirafs-graphviz:
Embed Graphviz (e.g.
dot
orneato
) graphs using Graphviz’s ubiquitous graph description language. - jirafs-matplotlib: Embed graphs generated with the common Python charting library Matplotlib by writing simple python scripts.
- jirafs-plantuml: Embed UML (e.g. timing, sequence, or activity) diagrams generated via PlantUML’s easy-to-use text format.
- jirafs-mermaid: Embed beautiful diagrams (e.g. pie, gantt, or class) using Mermaid’s markdown-ish diagram description language.
- jirafs-graphviz:
Embed Graphviz (e.g.
- For making tables more easily:
- jirafs-csv-table: Include tables in Jira by generating them from local CSV files.
- jirafs-list-table: Create tables in Jira by using a simple list-based syntax.
Writing your own Macros¶
Macros are really just special kinds of plugins; you can find more information about writing your own plugins in Macro Plugins.
Interesting Details¶
Ignore File Format¶
The files .jirafs_local
, .jirafs_ignore
and
.jirafs_remote_ignore
use a subset
of the globbing functionality supported by git
’s gitignore
file
syntax. Specifically, you can have comments, blank lines, and
globbing patterns of files that you would not like to upload.
For example, if you’d like to ignore files having a .diff
extension,
and would like to add a comment indicating why those are ignored, you
could enter the following into any *_ignore
file:
# Hide diffs I've generated for posting to reviewboard
*.diff
Directory Structure¶
Each issue folder includes a hidden folder named .jirafs
that
stores metadata used by Jirafs for this issue. There may be
many things in this folder, but two highlights include the following
files/folders:
git
: The issue folder is tracked by a git repository to enable future features, provide for a way of easily rolling-back or reviewing an issue’s previous state.operation.log
: This file logs all operations engaged in on this specific issue folder. You can review this log to see whatjirafs
has done in the past.
VIM Plugin¶
If you’re a vim user, I recommend you install my fork of the confluencewiki.vim plugin; if you do so, comment and description field files will use Jira/Confluence’s WikiMarkup for syntax highlighting.
\ Sort by:\ best rated\ newest\ oldest\
\\
Add a comment\ (markup):
\``code``
, \ code blocks:::
and an indented block after blank line