-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Add support for cloud installations #24
Conversation
Thanks for your contribution! :) |
Hi. Thanks again for the change. Sry, took a while to get to it. I tried it out locally, and it works great. I have a few minor/cosmetic tweaks to your change that I think make sense to be merged alongside this PR. Do you mind if I push directly to your branch? Here's the patch if it helps. expanddiff --git a/cmd/config.go b/cmd/config.go
index 10e12d5..6046753 100644
--- a/cmd/config.go
+++ b/cmd/config.go
@@ -1,30 +1,33 @@
package cmd
import (
"github.com/BurntSushi/toml"
)
+const (
+ jiraInstallationTypeOnPremise = "onpremise"
+ jiraInstallationTypeCloud = "cloud"
+)
+
type JiraConfig struct {
+ InstallationType string `toml:"installation_type"`
JiraURL *string `toml:"jira_url"`
Jql *string
JiraTimeDeltaMins int `toml:"jira_time_delta_mins"`
JiraToken *string `toml:"jira_token"`
- JiraCloudToken *string `toml:"jira_cloud_token"`
- JiraCloudUsername *string `toml:"jira_cloud_username"`
+ JiraUsername *string `toml:"jira_username"`
}
type POConfig struct {
Jira JiraConfig
}
func readConfig(filePath string) (POConfig, error) {
-
var config POConfig
_, err := toml.DecodeFile(expandTilde(filePath), &config)
if err != nil {
return config, err
}
return config, nil
-
}
diff --git a/cmd/root.go b/cmd/root.go
index 16f2bd1..daf3fe1 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -12,32 +12,31 @@ import (
jiraOnPremise "github.com/andygrunwald/go-jira/v2/onpremise"
"github.com/dhth/punchout/internal/ui"
)
func die(msg string, args ...any) {
fmt.Fprintf(os.Stderr, msg+"\n", args...)
os.Exit(1)
}
var (
+ jiraInstallationType = flag.String("jira-installation-type", "", "JIRA installation type; allowed values: [cloud, onpremise]")
jiraURL = flag.String("jira-url", "", "URL of the JIRA server")
jiraToken = flag.String("jira-token", "", "personal access token for the JIRA server")
- jiraCloudToken = flag.String("jira-cloud-token", "", "API token for the JIRA cloud")
- jiraCloudUsername = flag.String("jira-cloud-username", "", "username for the JIRA cloud")
+ jiraUsername = flag.String("jira-username", "", "username for the JIRA cloud")
jql = flag.String("jql", "", "JQL to use to query issues at startup")
jiraTimeDeltaMinsStr = flag.String("jira-time-delta-mins", "", "Time delta (in minutes) between your timezone and the timezone of the server; can be +/-")
listConfig = flag.Bool("list-config", false, "Whether to only print out the config that punchout will use or not")
)
func Execute() {
currentUser, err := user.Current()
-
if err != nil {
die("Error getting your home directory, explicitly specify the path for the config file using -config-file-path")
}
defaultConfigFP := fmt.Sprintf("%s/.config/punchout/punchout.toml", currentUser.HomeDir)
configFilePath := flag.String("config-file-path", defaultConfigFP, "location of the punchout config file")
defaultDBPath := fmt.Sprintf("%s/punchout.v%s.db", currentUser.HomeDir, PUNCHOUT_DB_VERSION)
dbPath := flag.String("db-path", defaultDBPath, "location where punchout should create its DB file")
@@ -59,109 +58,109 @@ func Execute() {
dbPathFull := expandTilde(*dbPath)
var jiraTimeDeltaMins int
if *jiraTimeDeltaMinsStr != "" {
jiraTimeDeltaMins, err = strconv.Atoi(*jiraTimeDeltaMinsStr)
if err != nil {
die("couldn't convert jira-time-delta-mins to a number")
}
}
- poCfg, err := readConfig(*configFilePath)
+ cfg, err := readConfig(*configFilePath)
if err != nil {
- fmt.Fprintf(os.Stderr, "error reading config at %s: %s.\n"+
- "continue with command line args only\n", *configFilePath, err.Error())
+ die("error reading config: %s.\n", err.Error())
+ }
+
+ if *jiraInstallationType != "" {
+ cfg.Jira.InstallationType = *jiraInstallationType
}
if *jiraURL != "" {
- poCfg.Jira.JiraURL = jiraURL
+ cfg.Jira.JiraURL = jiraURL
}
if *jiraToken != "" {
- poCfg.Jira.JiraToken = jiraToken
+ cfg.Jira.JiraToken = jiraToken
}
- if *jiraCloudToken != "" {
- poCfg.Jira.JiraCloudToken = jiraCloudToken
- }
-
- if *jiraCloudUsername != "" {
- poCfg.Jira.JiraCloudUsername = jiraCloudUsername
+ if *jiraUsername != "" {
+ cfg.Jira.JiraUsername = jiraUsername
}
if *jql != "" {
- poCfg.Jira.Jql = jql
+ cfg.Jira.Jql = jql
}
+
if *jiraTimeDeltaMinsStr != "" {
- poCfg.Jira.JiraTimeDeltaMins = jiraTimeDeltaMins
+ cfg.Jira.JiraTimeDeltaMins = jiraTimeDeltaMins
}
// validations
- if poCfg.Jira.JiraURL == nil || *poCfg.Jira.JiraURL == "" {
+ var installationType ui.JiraInstallationType
+ switch cfg.Jira.InstallationType {
+ case "", jiraInstallationTypeOnPremise: // "" to maintain backwards compatibility
+ installationType = ui.OnPremiseInstallation
+ case jiraInstallationTypeCloud:
+ installationType = ui.CloudInstallation
+ default:
+ die("invalid value for jira installation type (allowed values: [%s, %s]): %q", jiraInstallationTypeOnPremise, jiraInstallationTypeCloud, cfg.Jira.InstallationType)
+ }
+
+ if cfg.Jira.JiraURL == nil || *cfg.Jira.JiraURL == "" {
die("jira-url cannot be empty")
}
- if poCfg.Jira.Jql == nil || *poCfg.Jira.Jql == "" {
+ if cfg.Jira.Jql == nil || *cfg.Jira.Jql == "" {
die("jql cannot be empty")
}
- if (poCfg.Jira.JiraToken == nil) == (poCfg.Jira.JiraCloudToken == nil) {
- die("only one of on-premise or cloud auth method must be provided")
+ if cfg.Jira.JiraToken != nil && *cfg.Jira.JiraToken == "" {
+ die("jira-token cannot be empty")
}
- if poCfg.Jira.JiraToken != nil && *poCfg.Jira.JiraToken == "" {
- die("jira-token cannot be empty for on premise auth")
- }
-
- if poCfg.Jira.JiraCloudToken != nil && *poCfg.Jira.JiraCloudToken == "" {
- die("jira-token cannot be empty for cloud auth")
- }
-
- if poCfg.Jira.JiraCloudToken != nil && (poCfg.Jira.JiraCloudUsername == nil || *poCfg.Jira.JiraCloudUsername == "") {
- die("jira-username cannot be empty for cloud auth")
+ if installationType == ui.CloudInstallation && (cfg.Jira.JiraUsername == nil || *cfg.Jira.JiraUsername == "") {
+ die("jira-username cannot be empty for installation type \"cloud\"")
}
configKeyMaxLen := 40
if *listConfig {
fmt.Fprint(os.Stdout, "Config:\n\n")
fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("Config File Path", configKeyMaxLen), *configFilePath)
fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("DB File Path", configKeyMaxLen), dbPathFull)
- fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA URL", configKeyMaxLen), *poCfg.Jira.JiraURL)
- if poCfg.Jira.JiraToken != nil {
- fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA Token", configKeyMaxLen), *poCfg.Jira.JiraToken)
+ fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA Installation Type", configKeyMaxLen), cfg.Jira.InstallationType)
+ fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA URL", configKeyMaxLen), *cfg.Jira.JiraURL)
+ fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA Token", configKeyMaxLen), *cfg.Jira.JiraToken)
+ if installationType == ui.CloudInstallation {
+ fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA Username", configKeyMaxLen), *cfg.Jira.JiraUsername)
}
- if poCfg.Jira.JiraCloudToken != nil {
- fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA API Token", configKeyMaxLen), *poCfg.Jira.JiraCloudToken)
- fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JIRA Username", configKeyMaxLen), *poCfg.Jira.JiraCloudUsername)
- }
- fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JQL", configKeyMaxLen), *poCfg.Jira.Jql)
- fmt.Fprintf(os.Stdout, "%s%d\n", ui.RightPadTrim("JIRA Time Delta Mins", configKeyMaxLen), poCfg.Jira.JiraTimeDeltaMins)
+ fmt.Fprintf(os.Stdout, "%s%s\n", ui.RightPadTrim("JQL", configKeyMaxLen), *cfg.Jira.Jql)
+ fmt.Fprintf(os.Stdout, "%s%d\n", ui.RightPadTrim("JIRA Time Delta Mins", configKeyMaxLen), cfg.Jira.JiraTimeDeltaMins)
os.Exit(0)
}
db, err := setupDB(dbPathFull)
if err != nil {
die("couldn't set up punchout database. This is a fatal error\n")
}
- // setup jira client with one of available auth methods
- var client *http.Client
- if poCfg.Jira.JiraToken != nil {
+ var httpClient *http.Client
+ switch installationType {
+ case ui.OnPremiseInstallation:
tp := jiraOnPremise.BearerAuthTransport{
- Token: *poCfg.Jira.JiraToken,
+ Token: *cfg.Jira.JiraToken,
}
- client = tp.Client()
- } else {
+ httpClient = tp.Client()
+ case ui.CloudInstallation:
tp := jiraCloud.BasicAuthTransport{
- Username: *poCfg.Jira.JiraCloudUsername,
- APIToken: *poCfg.Jira.JiraCloudToken,
+ Username: *cfg.Jira.JiraUsername,
+ APIToken: *cfg.Jira.JiraToken,
}
- client = tp.Client()
+ httpClient = tp.Client()
}
- cl, err := jiraOnPremise.NewClient(*poCfg.Jira.JiraURL, client)
+ cl, err := jiraOnPremise.NewClient(*cfg.Jira.JiraURL, httpClient)
if err != nil {
- panic(err)
+ die("couldn't create JIRA client: %s", err)
}
- ui.RenderUI(db, cl, *poCfg.Jira.Jql, poCfg.Jira.JiraTimeDeltaMins)
+ ui.RenderUI(db, cl, installationType, *cfg.Jira.Jql, cfg.Jira.JiraTimeDeltaMins)
}
diff --git a/internal/ui/cmds.go b/internal/ui/cmds.go
index e6a75b5..9e2e861 100644
--- a/internal/ui/cmds.go
+++ b/internal/ui/cmds.go
@@ -159,48 +159,52 @@ func updateSyncStatusForEntry(db *sql.DB, entry worklogEntry, index int) tea.Cmd
return logEntrySyncUpdated{
entry: entry,
index: index,
err: err,
}
}
}
func fetchJIRAIssues(cl *jira.Client, jql string) tea.Cmd {
return func() tea.Msg {
- jIssues, err := getIssues(cl, jql)
+ jIssues, statusCode, err := getIssues(cl, jql)
var issues []Issue
+ if err != nil {
+ return issuesFetchedFromJIRAMsg{issues, statusCode, err}
+ }
+
for _, issue := range jIssues {
var assignee string
var totalSecsSpent int
var status string
if issue.Fields != nil {
if issue.Fields.Assignee != nil {
- assignee = issue.Fields.Assignee.Name
+ assignee = issue.Fields.Assignee.DisplayName
}
totalSecsSpent = issue.Fields.AggregateTimeSpent
if issue.Fields.Status != nil {
status = issue.Fields.Status.Name
}
}
issues = append(issues, Issue{
issueKey: issue.Key,
issueType: issue.Fields.Type.Name,
summary: issue.Fields.Summary,
assignee: assignee,
status: status,
aggSecondsSpent: totalSecsSpent,
trackingActive: false,
})
}
- return issuesFetchedFromJIRAMsg{issues, err}
+ return issuesFetchedFromJIRAMsg{issues, statusCode, nil}
}
}
func syncWorklogWithJIRA(cl *jira.Client, entry worklogEntry, index int, timeDeltaMins int) tea.Cmd {
return func() tea.Msg {
err := addWLtoJira(cl, entry, timeDeltaMins)
return wlAddedOnJIRA{index, entry, err}
}
}
diff --git a/internal/ui/initial.go b/internal/ui/initial.go
index 49c0fb7..36f573b 100644
--- a/internal/ui/initial.go
+++ b/internal/ui/initial.go
@@ -2,21 +2,21 @@ package ui
import (
"database/sql"
jira "github.com/andygrunwald/go-jira/v2/onpremise"
"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/textinput"
"github.com/charmbracelet/lipgloss"
)
-func InitialModel(db *sql.DB, jiraClient *jira.Client, jql string, jiraTimeDeltaMins int, debug bool) model {
+func InitialModel(db *sql.DB, jiraClient *jira.Client, installationType JiraInstallationType, jql string, jiraTimeDeltaMins int, debug bool) model {
var stackItems []list.Item
var worklogListItems []list.Item
var syncedWorklogListItems []list.Item
trackingInputs := make([]textinput.Model, 3)
trackingInputs[entryBeginTS] = textinput.New()
trackingInputs[entryBeginTS].Placeholder = "09:30"
trackingInputs[entryBeginTS].Focus()
trackingInputs[entryBeginTS].CharLimit = len(string(timeFormat))
trackingInputs[entryBeginTS].Width = 30
@@ -29,20 +29,21 @@ func InitialModel(db *sql.DB, jiraClient *jira.Client, jql string, jiraTimeDelta
trackingInputs[entryComment] = textinput.New()
trackingInputs[entryComment].Placeholder = "Your comment goes here"
trackingInputs[entryComment].Focus()
trackingInputs[entryComment].CharLimit = 255
trackingInputs[entryComment].Width = 60
m := model{
db: db,
jiraClient: jiraClient,
+ installationType: installationType,
jql: jql,
issueList: list.New(stackItems, newItemDelegate(lipgloss.Color(issueListColor)), listWidth, 0),
issueMap: make(map[string]*Issue),
issueIndexMap: make(map[string]int),
worklogList: list.New(worklogListItems, newItemDelegate(lipgloss.Color(worklogListColor)), listWidth, 0),
syncedWorklogList: list.New(syncedWorklogListItems, newItemDelegate(syncedWorklogListColor), listWidth, 0),
jiraTimeDeltaMins: jiraTimeDeltaMins,
showHelpIndicator: true,
trackingInputs: trackingInputs,
debug: debug,
diff --git a/internal/ui/jira.go b/internal/ui/jira.go
index c0cc823..e083715 100644
--- a/internal/ui/jira.go
+++ b/internal/ui/jira.go
@@ -1,27 +1,25 @@
package ui
import (
"context"
"errors"
"time"
jira "github.com/andygrunwald/go-jira/v2/onpremise"
)
-var (
- jiraRepliedWithEmptyWorklogErr = errors.New("JIRA replied with an empty worklog; something is probably wrong")
-)
+var jiraRepliedWithEmptyWorklogErr = errors.New("JIRA replied with an empty worklog; something is probably wrong")
-func getIssues(cl *jira.Client, jql string) ([]jira.Issue, error) {
- issues, _, err := cl.Issue.Search(context.Background(), jql, nil)
- return issues, err
+func getIssues(cl *jira.Client, jql string) ([]jira.Issue, int, error) {
+ issues, resp, err := cl.Issue.Search(context.Background(), jql, nil)
+ return issues, resp.StatusCode, err
}
func addWLtoJira(cl *jira.Client, entry worklogEntry, timeDeltaMins int) error {
start := entry.BeginTS
if timeDeltaMins != 0 {
start = start.Add(time.Minute * time.Duration(timeDeltaMins))
}
timeSpentSecs := int(entry.EndTS.Sub(entry.BeginTS).Seconds())
diff --git a/internal/ui/model.go b/internal/ui/model.go
index caf66a7..a17847f 100644
--- a/internal/ui/model.go
+++ b/internal/ui/model.go
@@ -4,20 +4,27 @@ import (
"database/sql"
"time"
jira "github.com/andygrunwald/go-jira/v2/onpremise"
"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/textinput"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
)
+type JiraInstallationType uint
+
+const (
+ OnPremiseInstallation JiraInstallationType = iota
+ CloudInstallation
+)
+
type trackingStatus uint
const (
trackingInactive trackingStatus = iota
trackingActive
)
type dBChange uint
const (
@@ -56,20 +63,21 @@ const (
dayAndTimeFormat = "Mon, 15:04"
dateFormat = "2006/01/02"
timeOnlyFormat = "15:04"
)
type model struct {
activeView stateView
lastView stateView
db *sql.DB
jiraClient *jira.Client
+ installationType JiraInstallationType
jql string
issueList list.Model
issueMap map[string]*Issue
issueIndexMap map[string]int
issuesFetched bool
worklogList list.Model
unsyncedWLCount uint
unsyncedWLSecsSpent int
syncedWorklogList list.Model
activeIssueBeginTS time.Time
diff --git a/internal/ui/msgs.go b/internal/ui/msgs.go
index 55ad2bb..323fee4 100644
--- a/internal/ui/msgs.go
+++ b/internal/ui/msgs.go
@@ -45,22 +45,23 @@ type logEntriesDeletedMsg struct {
err error
}
type logEntrySyncUpdated struct {
entry worklogEntry
index int
err error
}
type issuesFetchedFromJIRAMsg struct {
- issues []Issue
- err error
+ issues []Issue
+ responseStatusCode int
+ err error
}
type wlAddedOnJIRA struct {
index int
entry worklogEntry
err error
}
type urlOpenedinBrowserMsg struct {
url string
diff --git a/internal/ui/render_helpers.go b/internal/ui/render_helpers.go
index 0c43774..3a1f2c4 100644
--- a/internal/ui/render_helpers.go
+++ b/internal/ui/render_helpers.go
@@ -4,21 +4,21 @@ import "fmt"
func (issue *Issue) setDesc() {
// TODO: The padding here is a bit of a mess; make it more readable
var assignee string
var status string
var totalSecsSpent string
issueType := getIssueTypeStyle(issue.issueType).Render(issue.issueType)
if issue.assignee != "" {
- assignee = assigneeStyle(issue.assignee).Render(RightPadTrim("@"+issue.assignee, int(listWidth/4)))
+ assignee = assigneeStyle(issue.assignee).Render(RightPadTrim(issue.assignee, int(listWidth/4)))
} else {
assignee = assigneeStyle(issue.assignee).Render(RightPadTrim("", int(listWidth/4)))
}
status = issueStatusStyle.Render(RightPadTrim(issue.status, int(listWidth/4)))
if issue.aggSecondsSpent > 0 {
totalSecsSpent = aggTimeSpentStyle.Render(humanizeDuration(issue.aggSecondsSpent))
}
diff --git a/internal/ui/styles.go b/internal/ui/styles.go
index 901421d..c054bcf 100644
--- a/internal/ui/styles.go
+++ b/internal/ui/styles.go
@@ -1,20 +1,22 @@
package ui
import (
- "github.com/charmbracelet/lipgloss"
"hash/fnv"
+
+ "github.com/charmbracelet/lipgloss"
)
const (
defaultBackgroundColor = "#282828"
issueListUnfetchedColor = "#928374"
+ failureColor = "#fb4934"
issueListColor = "#fe8019"
worklogListColor = "#fabd2f"
syncedWorklogListColor = "#b8bb26"
trackingColor = "#fe8019"
unsyncedCountColor = "#fabd2f"
activeIssueKeyColor = "#d3869b"
activeIssueSummaryColor = "#8ec07c"
trackingBeganColor = "#fabd2f"
issueStatusColor = "#665c54"
toolNameColor = "#b8bb26"
diff --git a/internal/ui/ui.go b/internal/ui/ui.go
index 85bfab9..67a85f4 100644
--- a/internal/ui/ui.go
+++ b/internal/ui/ui.go
@@ -2,27 +2,27 @@ package ui
import (
"database/sql"
"fmt"
"os"
jira "github.com/andygrunwald/go-jira/v2/onpremise"
tea "github.com/charmbracelet/bubbletea"
)
-func RenderUI(db *sql.DB, jiraClient *jira.Client, jql string, jiraTimeDeltaMins int) {
+func RenderUI(db *sql.DB, jiraClient *jira.Client, installationType JiraInstallationType, jql string, jiraTimeDeltaMins int) {
if len(os.Getenv("DEBUG_LOG")) > 0 {
f, err := tea.LogToFile("debug.log", "debug")
if err != nil {
fmt.Println("fatal:", err)
os.Exit(1)
}
defer f.Close()
}
debug := os.Getenv("DEBUG") == "true"
- p := tea.NewProgram(InitialModel(db, jiraClient, jql, jiraTimeDeltaMins, debug), tea.WithAltScreen())
+ p := tea.NewProgram(InitialModel(db, jiraClient, installationType, jql, jiraTimeDeltaMins, debug), tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there has been an error: %v", err)
os.Exit(1)
}
}
diff --git a/internal/ui/update.go b/internal/ui/update.go
index 5b9c177..3f43604 100644
--- a/internal/ui/update.go
+++ b/internal/ui/update.go
@@ -432,23 +432,35 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.helpVP.HighPerformanceRendering = useHighPerformanceRenderer
m.helpVP.SetContent(helpText)
m.helpVPReady = true
} else {
m.helpVP.Height = m.terminalHeight - 7
m.helpVP.Width = w - 5
}
case issuesFetchedFromJIRAMsg:
if msg.err != nil {
- message := "error fetching issues from JIRA: " + msg.err.Error()
- m.message = message
- m.messages = append(m.messages, message)
+ var remoteServerName string
+ if msg.responseStatusCode >= 400 && msg.responseStatusCode < 500 {
+ switch m.installationType {
+ case OnPremiseInstallation:
+ remoteServerName = "Your on-premise installation"
+ case CloudInstallation:
+ remoteServerName = "Atlassian Cloud"
+ }
+ m.message = fmt.Sprintf("%s returned a %d status codel, check if your configuration is correct", remoteServerName, msg.responseStatusCode)
+ } else {
+ m.message = fmt.Sprintf("error fetching issues from JIRA: %s", msg.err.Error())
+ }
+ m.messages = append(m.messages, m.message)
+ m.issueList.Title = "Failure"
+ m.issueList.Styles.Title = m.issueList.Styles.Title.Background(lipgloss.Color(failureColor))
} else {
issues := make([]list.Item, 0, len(msg.issues))
for i, issue := range msg.issues {
issue.setDesc()
issues = append(issues, &issue)
m.issueMap[issue.issueKey] = &issue
m.issueIndexMap[issue.issueKey] = i
}
m.issueList.SetItems(issues)
m.issueList.Title = "Issues" |
Hi. No worries, I understand that sometimes it's hard to find a moment, especially around New Year's Eve. [jira]
jira_url = "https://jira.company.com"
# allowed values: [cloud, onpremise]
# default "onpremise"
# installation_type = "onpremise"
# for on-premise installations
# you can use a JIRA PAT token here
# or if you use cloud instance
# use your API token:
jira_token = "XXX"
# required when you use cloud instance
# jira_username = "example@example.com"
# put whatever JQL you want to query for
jql = "assignee = currentUser() AND updatedDate >= -14d ORDER BY updatedDate DESC"
# I don't know how many people will find use for this.
# I need this, since the JIRA server I use runs 5 hours behind
# the actual time, for whatever reason 🤷
# jira_time_delta_mins = 300 and punchout \
[ -db-path='/path/to/punchout/db/file.db' ] \
[ -jira-url='https://jira.company.com' ] \
[ -jira-token='XXX' ] \
[ -jira-username='example@example.com' ] \
[ -jql='assignee = currentUser() AND updatedDate >= -14d ORDER BY updatedDate DESC' ] \
[ -jira-time-delta-mins='300' ] \
[ -config-file-path='/path/to/punchout/config/file.toml' ] \
[ -list-config ] Go ahead, feel free to push directly to my branch👌 |
Done, thanks for the effort! Hope the tool saves you time :) |
* origin/main: feat: add support for cloud installations (#24)
Hello,
I found this repo by accident and wanted to give it a try since I'm building something similar for myself. To test it I also needed support for cloud installations and since this is an open issue #16 and go-jira already supports it I managed to add it. During my work, I also found few things to improve.
So what changed:
to
I hope it's up to your standard.