GithubHelp home page GithubHelp logo

gabor-boros / minutes Goto Github PK

View Code? Open in Web Editor NEW
26.0 2.0 1.0 1008 KB

Sync worklogs between multiple time trackers, invoicing, and bookkeeping software.

Home Page: https://gabor-boros.github.io/minutes/

License: MIT License

Makefile 1.24% Go 98.69% CSS 0.07%
tempo clockify toggl golang harvest timewarrior time-sync worklog cli go

minutes's Introduction

Contributors Forks Stargazers Issues MIT License Maintainability Coverage


Minutes

Sync worklogs between multiple time trackers, invoicing, and bookkeeping software.
Explore the docs

Bug report · Feature request

About The Project

minutes

Minutes is a CLI tool for synchronizing work logs between multiple time trackers, invoicing, and bookkeeping software to make entrepreneurs' daily work easier. Every source and destination comes with their specific flags. Before using any flags, check the related documentation.

Minutes come with absolutely NO WARRANTY; before and after synchronizing any logs, please ensure you got the expected result.

Getting Started

Prerequisites

Based on the nature of the project, prerequisites depending on what tools you are using. In case you are using Clockify as a time tracker and Tempo as your sync target, you should have an account at Clockify and Jira.

Installation

Using brew

$ brew tap gabor-boros/brew
$ brew install minutes

Manual install

To install minutes, use one of the release artifacts. If you have go installed, you can build from source as well.

Configuration

minutes has numerous flags and there will be more when other sources or targets are added. Therefore, minutes comes with a config file, that can be placed to the user's home directory or the config directory.

To read more about the config file, please refer to the Documentation

Usage

Below you can find more information about how to use minutes.

Usage:
  minutes [flags]

Flags:
      --clockify-api-key string                set the API key
      --clockify-url string                    set the base URL (default "https://api.clockify.me")
      --clockify-workspace string              set the workspace ID
      --config string                          config file (default is $HOME/.minutes.yaml)
      --date-format string                     set start and end date format (in Go style) (default "2006-01-02 15:04:05")
      --dry-run                                fetch entries, but do not sync them
      --end string                             set the end date (defaults to now)
      --filter-client string                   filter for client name after fetching
      --filter-project string                  filter for project name after fetching
      --force-billed-duration                  treat every second spent as billed
      --harvest-account int                    set the Account ID
      --harvest-api-key string                 set the API key
  -h, --help                                   help for minutes
      --round-to-closest-minute                round time to closest minute
  -s, --source string                          set the source of the sync [clockify harvest tempo timewarrior toggl]
      --source-user string                     set the source user ID
      --start string                           set the start date (defaults to 00:00:00)
      --table-hide-column strings              hide table column [summary project client start end]
      --table-sort-by strings                  sort table by column [task summary project client start end billable unbillable] (default [start,project,task,summary])
      --tags-as-tasks-regex string             regex of the task pattern
  -t, --target string                          set the target of the sync [tempo]
      --target-user string                     set the source user ID
      --tempo-password string                  set the login password
      --tempo-url string                       set the base URL
      --tempo-username string                  set the login user ID
      --timewarrior-arguments strings          set additional arguments
      --timewarrior-client-tag-regex string    regex of client tag pattern
      --timewarrior-command string             set the executable name (default "timew")
      --timewarrior-project-tag-regex string   regex of project tag pattern
      --timewarrior-unbillable-tag string      set the unbillable tag (default "unbillable")
      --toggl-api-key string                   set the API key
      --toggl-workspace int                    set the workspace ID
      --version                                show command version

Usage examples

Depending on the config file, the number of flags can change.

Simplest command

# No arguments, no flags, just running the command
$ minutes

Set specific date and time

# Set the date and time to fetch entries in the given time frame
$ minutes --start "2021-10-07 00:00:00" --end "2021-10-07 23:59:59"
# Specify the start and end date format
$ minutes --date-format "2006-01-02" --start "2021-10-07" --end "2021-10-08"

Use tags for tasks

# Specify how a tag should look like to be considered as a task
$ minutes --tags-as-tasks-regex '[A-Z]{2,7}-\d{1,6}'

Minute based rounding

# Set the billed and unbilled time separately
# to round to the closest minute (even if it is zero)
$ minutes --round-to-closest-minute

Sample config file

# Source config
source = "clockify"
source-user = "<clockify user ID>"

clockify-url = "https://api.clockify.me"
clockify-api-key = "<clockify API token>"
clockify-workspace = "<clockify workspace ID>"

# Target config
target = "tempo"
target-user = "<jira username>"

tempo-url = "https://<org>.atlassian.net"
tempo-username = "<jira username>"
tempo-password = "<jira password>"

# General config
tags-as-tasks-regex = '[A-Z]{2,7}-\d{1,6}'
round-to-closest-minute = true
force-billed-duration = true

table-sort-by = [
    "start",
    "project",
    "task",
    "summary",
]

table-hide-column = [
    "end"
]

[table-column-truncates]
summary = 40
project = 10
client = 10

# Column Config
[table-column-config.summary]
widthmax = 40

Supported tools

Tool Use as source Use as target
Clockify yes upon request
Everhour upon request upon request
FreshBooks upon request planned
Harvest yes upon request
QuickBooks upon request upon request
Tempo yes yes
Time Doctor upon request upon request
TimeCamp upon request upon request
Timewarrior yes upon request
Toggl Track yes upon request
Zoho Books upon request planned

See the open issues for a full list of proposed features, tools and known issues.

Unsupported features

The following list of features are not supported at the moment:

  • Cost rate sync
  • Hourly rate sync
  • Estimate sync
  • Multiple source and target user support

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this tool better, please fork the repo and create a pull request. You can also simply open an issue. Don't forget to give the project a star!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b github-username/amazing-feature)
  3. Commit your Changes (git commit -m 'feat(new tool): add my favorite tool as a source)
  4. Push to the Branch (git push origin github-username/amazing-feature)
  5. Open a Pull Request

minutes's People

Contributors

gabor-boros avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

othrayte

minutes's Issues

[BUG] Missing tag produces missing title

Describe the bug

Using Clockify and the settings below, both Task and Summary columns' values are missing if no tag is set.

To Reproduce

Steps to reproduce the behavior:

  1. set the specified config
  2. create a new entry in Clockify with a title set, but no task or tags are assigned
  3. run minutes

Expected behavior

The Summary field should have value, regardless of the missing Task.

Screenshots

N/A

System information:

  • OS name: All OS
  • OS version: Any version
  • Version (output of minutes --version): minutes version 0.2.3, commit 31e9656 (2021-11-08T07:00:12Z)

List of flags used:

N/A

Additional context

# Source config
source = "clockify"
source-user = "<hidden>"

clockify-url = "https://api.clockify.me"
clockify-api-key = "<hidden>"
clockify-workspace = "<hidden>"

# Target config
target = "tempo"
target-user = "gabor-boros"

tempo-url = "<hidden>"
tempo-username = "gabor-boros"
tempo-password = "<hidden>"

# General config
tags-as-tasks = true
tags-as-tasks-regex = '[A-Z]{2,7}-\d{1,6}'

round-to-closest-minute = true
force-billed-duration = true

date-format = "2006-01-02"

table-column-config = {
    summary = {
        widthmax = 40
    },
    end = {
        hidden = true
    },
    project = {
        hidden = true
    }
}

[REQUEST] Implement Toggl Track as as source

Is your feature request related to a problem? Please describe.

Toggl Track support would be needed for v0.1.0, but it is not supported yet.

Describe the solution you'd like

Add Toggl Track support (using their updated API domains) as a source. Also, Toggl Track's paid plans support Tasks, so that should be considered too.

Describe alternatives you've considered

N/A

Additional context

[REQUEST] Upload completion message

Is your feature request related to a problem? Please describe.

The upload completion is indicated by an exit code 0, but nothing else.

Describe the solution you'd like

Add at least a message after the upload is completed to indicate successful upload.

Describe alternatives you've considered

N/A

Additional context

N/A

[REQUEST] Parse tags from summary

Is your feature request related to a problem? Please describe.

There are some sources that have no support for tags. In the case of these sources, like Harvest, the tags-as-tasks flag is not considered.

Describe the solution you'd like

Create a new flag and config option to parse tags from the Summary field of entries. Therefore, combining tags-as-tasks and the new flag would provide a similar user experience compared to sources that are supporting tags natively.

The new flag should have a pair as well, which would stand for the regex used for parsing.

An example call:

minutes \
    --tags-in-summary \
    --tags-in-summary-regex '\[(\w+|\s+)+\]' \
    --tags-as-tasks \
    --tags-as-tasks-regex '[A-Z]{2,7}-\d{1,6}'

Describe alternatives you've considered

As an alternative tags-in-summary could replace tags-as-tasks. During the implementation it should be evaluated.

Additional context

N/A

[REQUEST] Usage telemetry

Is your feature request related to a problem? Please describe.

It is not visible how many users using what version of the app.

Describe the solution you'd like

Implement sending telemetry reports when the app starts. The telemetry should be optional and turned on by default. Also, the first start should warn the user about how to turn it off.

Describe alternatives you've considered

N/A

Additional context

N/A

[BUG] Do not upload entries parallelly for the same task

Describe the bug

Some tools (like Tempo / older version of Tempo) may get confused when multiple entries are uploaded for the same task. The reason, in the case of Tempo, is that tries to calculate the remaining estimate for the task automatically, hence the calculation can go wrong and the remaining estimate will be set to a higher number than it should be.

Example:

Task TSK-123 has 3 entries with 1, 2, and 3 hours logged on them. When the entries are uploaded by the corresponding goroutines, Tempo will try to calculate the remaining time for TSK-123 at upload. If the calculation is done simultaneously for 2 out of the 3 entries, the remaining estimate on TSK-123 will not match the reality.

To Reproduce

  1. Upload ~3-5 entries for the same task at "once"
  2. Check the remaining estimates in Tempo

Expected behavior

Entries for the same task are uploaded after each other, therefore not causing any race conditions on the server-side. A possible solution could be using linked lists for tasks and during upload, one goroutine would be responsible for one chain.

Screenshots

N/A

System information:

  • OS name: ALL
  • OS version: ALL
  • Version (output of minutes --version): master

List of flags used:

Not relevant

Additional context

N/A

[REQUEST] Update notifier

Is your feature request related to a problem? Please describe.

The fact of a new release is not shown when the app starts, hence it is harder to be informed about newer versions.

Describe the solution you'd like

Have a built-in mechanism for checking for newer versions at command start. The check should be optional and turned on by default.

Describe alternatives you've considered

N/A

Additional context

N/A

[REQUEST] Let minutes log time

Is your feature request related to a problem? Please describe.

minutes is capable of syncing time between tools, but it cannot act as a source.

Describe the solution you'd like

Implement basic time tracking features and add minutes as a source plugin.

Describe alternatives you've considered

Additional context

[REQUEST] Implement Zoho Books as a target

Is your feature request related to a problem? Please describe.

Zoho Books support would be needed for v0.1.0, but it is not supported yet.

Describe the solution you'd like

Implement Zoho Books as a sync target based on their documentation.

Describe alternatives you've considered

N/A

Additional context

[BUG] If no config file set an error raised

Describe the bug

When no config file present, an error raised that the config file cannot be located.
Setting the exact config file results in Error: Config File "/tmp/minutes.toml" Not Found in "[]"

To Reproduce

Steps to reproduce the behavior:

  1. remove the existing .minutes.toml config file
  2. run minutes --version

Expected behavior

Minutes should work without a config file and with specific config locations.

Screenshots

N/A

System information:

  • OS name: ALL
  • OS version: ALL
  • Version (output of minutes --version): minutes version 0.2.1, commit d343fe3 (2021-11-04T08:43:07)

List of flags used:

N/A

Additional context

N/A

[REQUEST] Refactor sources and targets as plugins

Is your feature request related to a problem? Please describe.

Adding (and maintaining) more sources and targets would be harder over time and "pollutes" the core logic in some way.

Describe the solution you'd like

To have a more flexible and well separated structure, extract the sources and targets into plugins. This way the core logic would be somewhat simpler and sources/targets would be self-contained.

Describe alternatives you've considered

Additional context

[REQUEST] Upload data overrides

Is your feature request related to a problem? Please describe.

When uploading to a target, there is no way to override Client and Project parameters.

Describe the solution you'd like

In many cases, the target will have different Client and Project names compared to the source. For example, in the source (like Tempo) the Client is called "MC" (as per the AccountKey is "MC"), though in the target tool it is called "My Company", hence it will be printed on the invoice. In the case of Project names, the situation is similar.

To eliminate this issue, create an override configuration, that can be configured per target. Why not source? Because sources have nothing to do with upload overrides.

Describe alternatives you've considered

N/A

Additional context

N/A

[REQUEST] Support filtering for sources

Is your feature request related to a problem? Please describe.

At the moment, filtering for workspaces, projects, and clients is not supported, though it would require low effort to support.

Describe the solution you'd like

When fetching entries from source, allow users to filter for a given users, project, and/or client.

Describe alternatives you've considered

N/A

Additional context

This will probably introduce some assumptions for some sources such as for Tempo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.