NAME

Git::Hooks::CheckJira - Git::Hooks plugin which requires citation of Jira issues in commit messages

VERSION

version 4.0.0

SYNOPSIS

As a Git::Hooks plugin you don't use this Perl module directly. Instead, you may configure it in a Git configuration file like this:

[githooks]

  # Enable the plugin
  plugin = CheckJira

  # These users are exempt from all checks
  admin = joe molly

[githooks "checkjira"]

  # Configure the URL and the admin credentials to interact with the Jira
  # server.
  jiraurl = https://jira.example.net
  jirauser = jiradmin
  jirapass = my-secret

  # Look for Jira keys at the beginning of the commit messages title, enclosed
  # in brackets.
  matchlog = (?s)^\\[([^]]+)\\]

  # Impose restrictions on valid Jira issues
  jql = project IN (ABC, UTF, GIT) AND \
        issuetype IN (Bug, Story) AND \
        status IN ("In progress", "In testing")

  # Require that all cited Jira issues be assigned to the user pushing the
  # commits.
  by-assignee = true

  # Commits pushed to master must cite Jiras associated with the fixVersion
  # 'future'
  fixversion = refs/heads/master             future

  # Commits pushed to release branches must cite Jiras associated with the
  # fixVersion named after the same major.minor version number.
  fixversion = ^refs/heads/(\\d+\\.\\d+)\\.  ^$+

DESCRIPTION

This Git::Hooks plugin hooks itself to the hooks below to guarantee that every commit message cites at least one valid Jira issue key in its log message, so that you can be certain that every change has a proper change request (a.k.a. ticket) open.

  • commit-msg, applypatch-msg

    This hook is invoked during the commit, to check if the commit message cites valid Jira issues.

  • update

    This hook is invoked multiple times in the remote repository during git push, once per branch being updated, to check if the commit message cites valid Jira issues.

  • pre-receive

    This hook is invoked once in the remote repository during git push, to check if the commit message cites valid Jira issues.

  • post-receive

    This hook is invoked once in the remote repository after a successful git push. It's used to notify Jira of commits citing its issues via comments.

  • ref-update

    This hook is invoked when a direct push request is received by Gerrit Code Review, to check if the commit message cites valid Jira issues.

  • commit-received

    This hook is invoked when a push request is received by Gerrit Code Review to create a change for review, to check if the commit message cites valid Jira issues.

  • submit

    This hook is invoked when a change is submitted in Gerrit Code Review, to check if the commit message cites valid Jira issues.

  • patchset-created

    This hook is invoked when a push request is received by Gerrit Code Review for a virtual branch (refs/for/*), to check if the commit message cites valid Jira issues.

It requires that any Git commits affecting all or some branches must make reference to valid Jira issues in the commit log message. Jira issues are cited by their keys which, by default, consist of a sequence of uppercase letters separated by an hyphen from a sequence of digits. E.g., CDS-123, RT-1, and GIT-97.

To enable it you should add it to the githooks.plugin configuration option:

[githooks]
  plugin = CheckJira

NAME

CheckJira - Git::Hooks plugin to implement Jira checks

CONFIGURATION

The plugin is configured by the following git options under the githooks.checkjira subsection.

It can be disabled for specific references via the githooks.ref and githooks.noref options about which you can read in the Git::Hooks documentation.

jiraurl URL

This option specifies the Jira server HTTP URL, used to construct the JIRA::REST object which is used to interact with your Jira server. Please, see the JIRA::REST documentation to know about them.

jirauser USERNAME

This option specifies the Jira server username, used to construct the JIRA::REST object.

jirapass PASSWORD

This option specifies the Jira server password, used to construct the JIRA::REST object.

matchkey REGEXP

By default, Jira keys are matched with the regex /\b[A-Z][A-Z]+-\d+\b/, meaning, a sequence of two or more capital letters, followed by an hyphen, followed by a sequence of digits. If you customized your Jira project keys, you may need to customize how this hook is going to match them. Set this option to a suitable regex to match a complete Jira issue key.

matchlog REGEXP

By default, Jira keys are looked for in all of the commit message. However, this can lead to some false positives, since the default issue pattern can match other things besides Jira issue keys. You may use this option to restrict the places inside the commit message where the keys are going to be looked for. You do this by specifying a regular expression with a capture group (a pair of parenthesis) in it. The commit message is matched against the regular expression and the Jira tickets are looked for only within the part that matched the capture group.

Here are some examples:

  • \[([^]]+)\]

    Looks for Jira keys inside the first pair of brackets found in the message.

  • (?s)^\[([^]]+)\]

    Looks for Jira keys inside a pair of brackets that must be at the beginning of the message's title.

  • (?im)^Bug:(.*)

    Looks for Jira keys in a line beginning with Bug:. This is a common convention around some high caliber projects, such as OpenStack and Wikimedia.

This is a multi-valued option. You may specify it more than once. All regexes are tried and Jira keys are looked for in all of them. This allows you to more easily accommodate more than one way of specifying Jira keys if you wish.

jql JQL

By default, any cited issue must exist on the server and be unresolved. You can specify other restrictions (and even allow for resolved issues) by specifying a JQL expression which must match all cited issues. For example, you may want to:

  • Allow for resolved issues

    [githooks "checkjira"]
      jql = resolution IS EMPTY OR resolution IS NOT EMPTY
  • Require specific projects, issue-types, and statuses

    [githooks "checkjira"]
      jql = project IN (ABC, UTF, GIT) AND issuetype IN (Bug, Story) AND status IN ("In progress", "In testing")

This is a scalar option. Only the last JQL expression will be used to check the issues.

The special value 'undef' can be used to disable the option, making it possible to disable it locally.

ref-jql REF JQL

You may impose restrictions on specific branches (or, more broadly, any reference) by mentioning them before the JQL expression. REF can be specified as a complete ref name (e.g. "refs/heads/master") or by a regular expression starting with a caret (^), which is kept as part of the regexp (e.g. "^refs/heads/(master|fix)"). For instance:

[githooks "checkjira"]
  ref-jql = refs/heads/master fixVersion = future
  ref-jql = ^refs/heads/release/ fixVersion IN releasedVersions()

This is a scalar option. Only the last JQL expression will be used to check the issues.

The special value 'undef' can be used to disable the option, making it possible to disable it locally.

Note, though, that if there is a global JQL specified by the githooks.checkjira.jql option it will be checked separately and both expressions must validate the issues matching REF.

and-jql JQL

Unlike the jql option, this one is multi-valued. All JQL terms specified with this option are AND-ed together with the last jql expression and with the ref-jql expression, if they exist.

It is useful, for instance, when you want to specialize a default JQL with new terms. Suppose you have a global jql option with some general requirements that all Jira issues must fulfill, like being of particular types and in specific statuses:

[githooks "checkjira"]
  jql = issuetype IN (Bug, Story) AND status IN ("In progress", "In testing")

Moreover, you may have several repositories, each one associated with a particular Jira project. Then, you can AND more terms to the global JQL like this in a repository:

[githooks "checkjira"]
  and-jql = project = ABC

The special value 'undef' can be used to reset the option, effectively making any previous values be forgotten so that you can start anew to add terms to it.

require BOOL

By default, the log must reference at least one Jira issue. You can make the reference optional by setting this option to false.

unresolved BOOL

By default, every issue referenced must be unresolved, i.e., it must not have a resolution. You can relax this requirement by setting this option to false.

fixversion BRANCH FIXVERSION

This multi-valued option allows you to specify that commits affecting BRANCH must cite only issues that have their Fix For Version field matching FIXVERSION. This may be useful if you have release branches associated with particular Jira versions.

BRANCH can be specified as a complete ref name (e.g. "refs/heads/master") or by a regular expression starting with a caret (^), which is kept as part of the regexp (e.g. "^refs/heads/(master|fix)").

FIXVERSION can be specified as a complete Jira version name (e.g. "1.2.3") or by a regular expression starting with a caret (^), which is kept as part of the regexp (e.g. "^1\.2").

As a special feature, if BRANCH is a regular expression containing capture groups, then every occurrence of the substring $+ in FIXVERSION, if any, is replaced by the text matched by the last capture group in BRANCH. (Hint: Perl's $+ variable is defined as "The text matched by the last bracket of the last successful search pattern.") If FIXVERSION is also a regular expression, the $+ are replaced by the text properly escaped so that it matches literally.

Commits that do not affect any BRANCH are accepted by default.

So, suppose you have this configuration:

[githooks "checkjira"]
  fixversion = refs/heads/master          future
  fixversion = ^refs/heads/(\d+\.\d+)\.   ^$+

Then, commits affecting the master branch must cite issues assigned to the future version. Also, commits affecting any branch which name begins with a version number (e.g. 1.0.3) be assigned to the corresponding Jira version (e.g. 1.0).

by-assignee BOOL

By default, the committer can reference any valid Jira issue. Setting this value to true requires that the user doing the push/commit (as specified by the userenv configuration variable) be the current issue's assignee.

check-code CODESPEC

If the above checks aren't enough you can use this option to define a custom code to check your commits. The code may be specified directly as the option's value or you may specify it indirectly via the filename of a script. If the option's value starts with "file:", the remaining is treated as the script filename, which is executed by a do command. Otherwise, the option's value is executed directly by an eval. Either way, the code must end with the definition of a routine, which will be called once for each commit with the following arguments:

  • GIT

    The Git repository object used to grok information about the commit.

  • COMMITID

    The SHA-1 id of the Git commit. It is undef in the commit-msg hook, because there is no commit yet.

  • JIRA

    The JIRA::REST object used to talk to the Jira server.

    Note that up to version 0.047 of Git::Hooks::CheckJira this used to be a JIRA::Client object, which uses Jira's SOAP API which was deprecated on Jira 6.0 and won't be available anymore on Jira 7.0.

    If you have code relying on the JIRA::Client module you're advised to rewrite it using the JIRA::REST module. As a stopgap measure you can disregard the JIRA::REST object and create your own JIRA::Client object.

    The routine must return a true value to signal success. It may return a false value or throw an exception to signal failure. It's best if it uses the 'fault' method to produce error messages.

  • ISSUES...

    The remaining arguments are RemoteIssue objects representing the issues being cited by the commit's message.

The subroutine should return a Boolean value indicating success. Any errors should be produced by invoking the Git::Repository::Plugin::GitHooks::error method.

If the subroutine returns undef it's considered to have succeeded.

If it raises an exception (e.g., by invoking die) it's considered to have failed and a proper message is produced to the user.

Since the code may take much time to run, the plugin checks if the githooks.timeout option has been violated after each code runs.

check-code-ref CODESPEC

This option is an extension of the check-code option. The difference is that the routine defined by the CODESPEC will get an extra argument (REF). All the others are exactly the same:

  • GIT

  • REF

    The name of the affected branch. This is the current branch, for the commit-msg hook, and the branch to which the commit has been pushed to, for the other hooks.

  • COMMITID

  • JIRA

  • ISSUES...

comment VISIBILITY

If this option is set and the post-receive hook is enabled, for every pushed commit, every cited Jira issue receives a comment showing the result of the git show --stat COMMIT command. This is meant to notify the issue assignee of commits referring to the issue.

Note that the user with which Git::Hooks authenticates to Jira must have permission to add comments to the issues or an error will be logged. However, since this happens after the push, the result of the operation isn't affected.

You must specify the VISIBILITY of the comments in one of these ways.

  • role:NAME

    In this case, NAME must be the name of a Jira role, such as Administrators, Developers, or Users.

  • group:NAME

    In this case, NAME must be the name of a Jira group.

  • all

    In this case, the visibility isn't restricted at all.

skip-merges BOOL

By default, all commits are checked. You can exempt merge commits from being checked by setting this option to true.

SEE ALSO

REFERENCES

AUTHOR

Gustavo L. de M. Chaves <gnustavo@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2024 by CPQD <www.cpqd.com.br>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.