jiratime
makes it easy to submit worklog records to Jira quickly from the command line.
It accepts timesheets on standard input so works well with any editor that lets you pipe chunks of text to external commands, such as (neo)vim.
jiratime
only works with Atlassian Cloud hosted Jira, and does not support the deprecated self-hosted Jira server.
Download the latest release on github, or:
go install github.com/smlx/jiratime/cmd/jiratime@latest
jiratime
reads configuration from $XDG_CONFIG_HOME
/jiratime/config.yml
.
This example config.yml
has a list of regular expressions for implicitly identifying issues, and another list for matching timesheet entries to be ignored.
jiraURL: https://example.atlassian.net/
issues:
- id: XYZ-1
defaultComment: email / slack
regexes:
- ^admin( .+)?$
- id: ABC-2
defaultComment: Primary On-call
regexes:
- ^pd$
ignore:
- ^lunch$
The timesheet format is minimal and opinionated.
0900-0945
admin - TPS report cover sheet
0945-1100
XYZ-123 - fighting fires
1100-1200
admin
1200-1300
lunch
1300-1400
ABC-987
- more meetings after...
lunch
1400-1430
ABC-988
will the meetings
ever stop?
- Each entry begins with a duration written as a 24-hour time range.
- The comment body of a timesheet entry is anything on the first line following an issue match, and any lines below before the next duration or end of the timesheet.
- Comment lines are trimmed of spaces and hyphens before being added to the comment body.
- Jira issues may be identified explicitly by putting the name of the issue at the start of the first line of the comment body.
- Jira issues may be identified implicitly by matching the first line against a configured list of regular expressions.
- Regular expressions for implicitly identifying issues may have a capture group. In that case the capture group becomes part of the comment body.
- Timesheet entries may be ignored by matching the first line against a configured list of regular expressions.
- Implicitly matched issues can have a default comment configured which will be automatically added to the Jira worklog record if no comment is defined in the timesheet.
Each row in this table shows:
- a single timesheet entry
- configuration involved in processing the entry
- the worklog record generated by the entry
| Timesheet Entry | Configuration | Jira Worklog Record |
| --- | --- | --- |
| 0900-0945 | issues: | Issue: XYZ-1 |
| admin - TPS report cover sheet | - id: XYZ-1 | Start: 0900 (local TZ) |
| | defaultComment: email / slack | Duration: 45 minutes |
| | regexes: | Comment: TPS report cover sheet |
| | - ^admin( .+)?$ | |
| --- | --- | --- |
| 0945-1100 | n/a (explicit issue) | Issue: XYZ-123 |
| XYZ-123 - fighting fires | | Start: 0945 (local TZ) |
| | | Duration: 1 hour, 15 minutes |
| | | Comment: fighting fires |
| --- | --- | --- |
| 1100-1200 | issues: | Issue: XYZ-1 |
| admin | - id: XYZ-1 | Start: 1100 (local TZ) |
| | defaultComment: email / slack | Duration: 1 hour |
| | regexes: | Comment: email / slack |
| | - ^admin( .+)?$ | |
| --- | --- | --- |
| 1200-1300 | ignore: | n/a (this entry is skipped) |
| lunch | - ^lunch$ | |
| --- | --- | --- |
| 1300-1400 | n/a (explicit issue) | Issue: ABC-987 |
| ABC-987 | | Start: 1300 (local TZ) |
| - more meetings after... | | Duration: 1 hour |
| lunch | | Comment: more meetings after... |
| | | lunch |
| --- | --- | --- |
| 1400-1430 | n/a (explicit issue) | Issue: ABC-988 |
| ABC-988 | | Start: 1400 (local TZ) |
| will the meetings | | Duration: 30 minutes |
| ever stop? | | Comment: will the meetings |
| | | ever stop? |
jiratime
tries hard to submit timesheets atomically.
That is, either all worklog records are submitted, or none are.
It does this by checking that all issues identified are valid Jira issues before submitting any worklogs.
Unfortunately there is no transactional batch API for Jira worklogs.
jiratime
exits with a return code of zero and no output on success.
On failure it will exit with a non-zero return code and a message on standard error.
jiratime
authentication requires a one-time initial setup.
jiratime
can authenticate using OAuth2 (more secure, more complex setup, the default), or using an API Key and HTTP Basic Auth (less secure, but simpler).
- Visit Atlassian's developer console, and log in.
- Create a new "OAuth 2.0 integration".
- Name the app
jiratime
, and agree to Atlassian's T&Cs.
- Select "Permissions", then "Add", and "Configure" the "Jira platform REST API".
- Ensure these scopes are selected:
read:jira-work
write:jira-work
- Select "Authorization", then "Configure" the "OAuth 2.0 (3LO)" authorization type.
- Set the callback URL to
http://localhost:8080/oauth/redirect
- Select "Settings".
- In "Authentication details", copy the "Client ID" and "Secret" values.
Create $XDG_CONFIG_HOME/jiratime/auth.yml
and add your app credentials:
oauth2:
clientID: chiYahchob7xoThahvohH5quae6Di0Ee
secret: HxHOiN3bD5l93X3qugp9bHI8EKEJ7xVV4vcj6tG3vr7GFqxtxruMrkLcgtZAOPrZ
Run jiratime authorize
and open the generated URL in your browser.
Once you click "Accept", you should see this message in your browser:
Authorization successful. You may now close this page.
$XDG_CONFIG_HOME/jiratime/auth.yml
now contains a token that jiratime
will use and automatically refresh as required.
- Visit Atlassian's developer console, and log in.
- Create a new API Key.
- Add the credentials to
$XDG_CONFIG_HOME/jiratime/basicauth.yml
.
Example:
user: my.name@example.com
apiKey: SZ8411BnS9dKw2FDArWAe9eYiToNTx6ugtCzR2UTtaSFmXnw16bYcBuiLFYuqSffnFEzdXti8HcVRWPaLjPxFaOx7KVlckD2amFoxiiwK2hTBlfYU62CrJJ3VfZprwf3
Once configured and authorized, calling jiratime
parses and submits timesheets read from standard input.
It assumes all times are from the current local day.
Command line:
$ jiratime < timesheet
vim
visual selection:
:'<,'>!jiratime
vim
line selection:
:130,135!jiratime
It seems to sometimes take a while for worklog entries submitted via API to show up in Tempo. Try refreshing after a few minutes.
jiratime
submits all times in your local timezone.
Jira has a single timezone that it uses to display worklogs regardless of localisation settings.
I can't see this timezone displayed anywhere in the UI, but you can see it via the API.
Use scripts/check-worklog.sh
to dump issue worklogs, including timezone.
jiratime submit --day-offset="-1" < timesheet
Run jiratime --help
to discover the command line options and contextual help.