An open API service indexing awesome lists of open source software.

https://github.com/smlx/jiratime

Submit timesheets to Jira from the command line
https://github.com/smlx/jiratime

go hacktoberfest jira

Last synced: 11 months ago
JSON representation

Submit timesheets to Jira from the command line

Awesome Lists containing this project

README

          

# JiraTime

![Tag and Release](https://github.com/smlx/jiratime/workflows/Tag%20and%20Release/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/smlx/jiratime/badge.svg?branch=main)](https://coveralls.io/github/smlx/jiratime?branch=main)
[![Go Report Card](https://goreportcard.com/badge/github.com/smlx/jiratime)](https://goreportcard.com/report/github.com/smlx/jiratime)

`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.


## Get it

Download the latest [release](https://github.com/smlx/jiratime/releases) on github, or:

```
go install github.com/smlx/jiratime/cmd/jiratime@latest
```

## How it works

### Configuration

`jiratime` reads configuration from [`$XDG_CONFIG_HOME`](https://github.com/adrg/xdg#xdg-base-directory)`/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$
```

### Timesheet format

The timesheet format is minimal and opinionated.

#### Sample timesheet

```
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?
```

#### Features

* 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.

#### Timesheet entry processing examples

Each row in this table shows:

1. a single timesheet entry
2. configuration involved in processing the entry
3. 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? |
```

### Design Philosophy

`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.

## Authorization Setup

`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).

### OAuth2

#### Configure jiratime app in Jira cloud

1. Visit Atlassian's [developer console](https://developer.atlassian.com/console/myapps/), and log in.
2. Create a new "OAuth 2.0 integration".
3. Name the app `jiratime`, and agree to Atlassian's T&Cs.

##### Scopes

1. Select "Permissions", then "Add", and "Configure" the "Jira platform REST API".
2. Ensure these scopes are selected:
* `read:jira-work`
* `write:jira-work`

##### Authorization callback URL

1. Select "Authorization", then "Configure" the "OAuth 2.0 (3LO)" authorization type.
2. Set the callback URL to `http://localhost:8080/oauth/redirect`

##### Gather app Credentials

1. Select "Settings".
2. In "Authentication details", copy the "Client ID" and "Secret" values.

#### Complete OAuth2 authorization flow

Create `$XDG_CONFIG_HOME/jiratime/auth.yml` and add your app credentials:

```yaml
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.

### Basic Auth

1. Visit Atlassian's [developer console](https://developer.atlassian.com/console/myapps/), and log in.
2. Create a new API Key.
3. Add the credentials to `$XDG_CONFIG_HOME/jiratime/basicauth.yml`.

Example:

```yaml
user: my.name@example.com
apiKey: SZ8411BnS9dKw2FDArWAe9eYiToNTx6ugtCzR2UTtaSFmXnw16bYcBuiLFYuqSffnFEzdXti8HcVRWPaLjPxFaOx7KVlckD2amFoxiiwK2hTBlfYU62CrJJ3VfZprwf3
```

## Usage

### Timesheet submission

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:

![animation demonstrating visual selection](visual-selection.gif)

```
:'<,'>!jiratime
```

`vim` line selection:

![animation demonstrating line selection](line-selection.gif)

```
:130,135!jiratime
```

## FAQ

### Why does Tempo not show all the entries submitted by 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.

### Why do the entries have a weird time offset?

`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.

### How do I submit timesheets for yesterday?

```
jiratime submit --day-offset="-1" < timesheet
```

## Options

Run `jiratime --help` to discover the command line options and contextual help.