targetprocess

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 7, 2020 License: Apache-2.0 Imports: 12 Imported by: 0

README

PkgGoDevGitHub release (latest SemVer) GitHub go.mod Go version CircleCI Code Coverage Go Report Card Apache 2.0 license

Go-Targetprocess

Package targetprocess is a go library to make using the Targetprocess API easier. Some public types are included to ease in json -> struct unmarshaling. A lot of inspiration for this package comes from https://github.com/adlio/trello

Want to learn more? Reach out on the Slack channel (request invite), send an email to opensource@fairwinds.com, or join us for office hours on Zoom

Usage

package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/sirupsen/logrus"

	tp "github.com/FairwindsOps/go-targetprocess"
)

func main() {
	logger := logrus.New()
	tpClient, err := tp.NewClient("exampleCompany", "superSecretToken")
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	tpClient.Logger = logger

	userStories, err := tpClient.GetUserStories(
		// we set paging to false so we only get the first page of results
		false,
		// The Where() filter function takes in any queries the targetprocess API accepts
		// Read about those here: https://dev.targetprocess.com/docs/sorting-and-filters
		tp.Where("EntityState.Name != 'Done'"),
		tp.Where("EntityState.Name != 'Backlog'"),
                // Simlar to Where(), the Include() function will limit the
                // response to a given list of fields
		tp.Include("Team", "Name", "ModifyDate"),
	)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	jsonBytes, _ := json.Marshal(userStories)
	fmt.Print(string(jsonBytes))
}

Custom structs for queries

go-targetprocess includes some built-in structs that can be used for Users, Projects, Teams, and UserStories. You don't have to use those though and can use the generic Get() method with a custom struct as the output for a response to be JSON decoded into. Filtering functions (Where(), Include(), etc.) can be used in Get() just like they can in any of the helper functions.

Ex:

func main() {
	out := struct {
		Next  string
		Prev  string
		Items []interface{}
	}{}
	tpClient, err := tp.NewClient("exampleCompany", "superSecretToken")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
	err := tpClient.Get(&out, "Users", nil)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	jsonBytes, _ := json.Marshal(out)
	fmt.Print(string(jsonBytes))
}

Debug Logging

This idea was taken directly from the https://github.com/adlio/trello package. To add a debug logger, do the following:

logger := logrus.New()
// Also supports logrus.InfoLevel but that is default if you leave out the SetLevel method
logger.SetLevel(logrus.DebugLevel)
client, err := targetprocess.NewClient(accountName, token)
if err != nil {
    fmt.Println(err)
    os.Exit(1)
}
client.Logger = logger

Contributing

PRs welcome! Check out the Contributing Guidelines and Code of Conduct for more information.

Documentation

Overview

Package targetprocess is a go library to make using the Targetprocess API easier. Some public types are included to ease in json -> struct unmarshaling. A lot of inspiration for this package comes from https://github.com/adlio/trello

Example Usage:

 func main() {
   logger := logrus.New()
   tpClient, err := tp.NewClient("exampleCompany", "superSecretToken")
	  if err != nil {
   	fmt.Println(err)
     os.Exit(1)
   }
   tpClient.Logger = logger
   userStories, err := tpClient.GetUserStories(
   	// The Where() filter function takes in any queries the targetprocess API accepts
   	// Read about those here: https://dev.targetprocess.com/docs/sorting-and-filters
   	tp.Where("EntityState.Name != 'Done'"),
   	tp.Where("EntityState.Name != 'Backlog'"),
   	// Simlar to Where(), the Include() function will limit the
   	// response to a given list of fields
   	tp.Include("Team", "Name", "ModifyDate"),
   )
   if err != nil {
   	fmt.Println(err)
   	os.Exit(1)
   }
   jsonBytes, _ := json.Marshal(userStories)
   fmt.Print(string(jsonBytes))
 }

go-targetprocess includes some built-in structs that can be used for Users, Projects, Teams, and UserStories. You don't have to use those though and can use the generic `Get()` method with a custom struct as the output for a response to be JSON decoded into. Filtering functions (`Where()`, `Include()`, etc.) can be used in `Get()` just like they can in any of the helper functions.

Example:

 func main() {
   out := struct {
   	Next  string
   	Prev  string
   	Items []interface{}
   }{}
   tpClient, err := tp.NewClient("exampleCompany", "superSecretToken")
	  if err != nil {
   	fmt.Println(err)
     os.Exit(1)
   }
   err := tpClient.Get(&out, "Users", nil)
   if err != nil {
   	fmt.Println(err)
   	os.Exit(1)
   }
   jsonBytes, _ := json.Marshal(out)
   fmt.Print(string(jsonBytes))
 }

Debug Logging: This idea was taken directly from the https://github.com/adlio/trello package. To add a debug logger, do the following:

 logger := logrus.New()
 // Also supports logrus.InfoLevel but that is default if you leave out the SetLevel method
 logger.SetLevel(logrus.DebugLevel)
 client, err := targetprocess.NewClient(accountName, token)
	  if err != nil {
   	fmt.Println(err)
     os.Exit(1)
   }
 client.Logger = logger

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsNotFound

func IsNotFound(err error) bool

IsNotFound takes an error and returns true if the error is exactly a not-found error.

func IsPermissionDenied

func IsPermissionDenied(err error) bool

IsPermissionDenied takes an error and returns true if the error is exactly a permission-denied error.

Types

type AssignedUser added in v0.3.0

type AssignedUser struct {
	Items []UserAssignment
}

AssignedUser is used in UserStories and potentially other places. Returns a list of user assignments.

type Client

type Client struct {

	// Client is the HTTP client to use for communication.
	Client *http.Client

	// Logger is an optional logging interface for debugging
	Logger logger

	// Token is the user access token to authenticate to the Targetprocess instance
	Token string

	// Timeout is the timeout used in any request made
	Timeout time.Duration

	// UserAgent is the user agent to send with API requests
	UserAgent string
	// contains filtered or unexported fields
}

Client is the API client for Targetprocess. Create this using NewClient. This can also be constructed manually but it isn't recommended.

func NewClient

func NewClient(account, token string) (*Client, error)

NewClient will create a new Targetprocess client

account is the name of your Targetprocess account and will be the first part of your Targetprocess url. ex:

https://exampleaccount.tpondemand.com

token is your user access token taken from your account settings see here: https://dev.targetprocess.com/docs/authentication#token-authentication

func (*Client) Get

func (c *Client) Get(out interface{}, entityType string, values url.Values, filters ...QueryFilter) error

Get is a generic HTTP GET call to the targetprocess api passing in the type of entity and any query filters

Example

Example of client.Get() for godoc

tpClient, err := NewClient("exampleaccount", "superSecretToken")
if err != nil {
	fmt.Println("Failed to create tp client:", err)
	os.Exit(1)
}
var response = UserResponse{}
err = tpClient.Get(response,
	"User",
	nil)
if err != nil {
	fmt.Println("Failed to get users:", err)
	os.Exit(1)
}
jsonBytes, _ := json.Marshal(response)
fmt.Print(string(jsonBytes))
Output:

func (*Client) GetCustomField

func (c *Client) GetCustomField(name string) (CustomField, error)

GetCustomField will return a CustomField object from a name. Returns an error if not found.

func (*Client) GetEntityStates

func (c *Client) GetEntityStates(filters ...QueryFilter) ([]EntityState, error)

GetEntityStates will return all EntityStates

func (*Client) GetFeature

func (c *Client) GetFeature(name string) (Feature, error)

GetFeature will return a single feature based on its name. If somehow there are features with the same name, this will only return the first one.

func (*Client) GetFeatures

func (c *Client) GetFeatures(filters ...QueryFilter) ([]Feature, error)

GetFeatures will return all features

func (*Client) GetNext

func (c *Client) GetNext(out interface{}, nextURL string) error

GetNext is a helper method to get the next page of results from a query.

func (*Client) GetProcesses

func (c *Client) GetProcesses(filters ...QueryFilter) ([]Process, error)

GetProcesses will return all Processs

func (*Client) GetProject

func (c *Client) GetProject(name string) (Project, error)

GetProject will return a single project based on its name. If somehow there are projects with the same name, this will only return the first one.

func (*Client) GetProjects

func (c *Client) GetProjects(filters ...QueryFilter) ([]Project, error)

GetProjects will return all projects

func (*Client) GetTeam

func (c *Client) GetTeam(name string) (Team, error)

GetTeam will return a single team based on its name. If somehow there are teams with the same name, this will only return the first one.

func (*Client) GetUserStories

func (c *Client) GetUserStories(page bool, filters ...QueryFilter) ([]UserStory, error)

GetUserStories will return all user stories

Use with caution if you have a lot and are not setting the MaxPerPage to a high number as it could cause a lot of requests to the API and may take a long time. If you know you have a lot you may want to include the QueryFilter MaxPerPage

func (*Client) GetUsers

func (c *Client) GetUsers(filters ...QueryFilter) ([]User, error)

GetUsers will return all users

func (*Client) GetWorkflows

func (c *Client) GetWorkflows(filters ...QueryFilter) ([]Workflow, error)

GetWorkflows will return all Workflows

func (*Client) NewUserStoryList

func (c *Client) NewUserStoryList(list []UserStory) *UserStoryList

NewUserStoryList returns a UserStoryList from a list of user stories. Used for batch POSTing of UserStories

func (*Client) Post

func (c *Client) Post(out interface{}, entityType string, values url.Values, body []byte) error

Post is for both creating and updating objects in TargetProcess

func (*Client) WithContext

func (c *Client) WithContext(ctx context.Context)

WithContext takes a context.Context, sets it as context on the client and returns a Client pointer.

type CustomField

type CustomField struct {
	ID    int32       `json:"Id,omitempty"`
	Type  string      `json:",omitempty"`
	Name  string      `json:",omitempty"`
	Value interface{} `json:",omitempty"`
	// contains filtered or unexported fields
}

CustomField are user defined in TargetProcess and are arbitrarily set for many different resource types

type CustomFieldResponse

type CustomFieldResponse struct {
	Items []CustomField
	Next  string
	Prev  string
}

CustomFieldResponse is a representation of the http response for a group of CustomField

type DateTime

type DateTime string

DateTime currently does nothing special but will represent the TP DateTime objects

type EntityState

type EntityState struct {
	ID                int32        `json:"Id,omitempty"`
	Name              string       `json:",omitempty"`
	NumericPriority   float64      `json:",omitempty"`
	ParentEntityState *EntityState `json:",omitempty"`
	Process           *Process     `json:",omitempty"`
	IsInital          bool         `json:",omitempty"`
	IsFinal           bool         `json:",omitempty"`
	IsPlanned         bool         `json:",omitempty"`
	IsCommentRequired bool         `json:",omitempty"`
}

EntityState contains metadata for the state of an Entity. Collection of EntityStates form Workflow for Entity. For example, Bug has four EntityStates by default: Open, Fixed, Invalid and Done

type EntityStateResponse

type EntityStateResponse struct {
	Items []EntityState
	Next  string
	Prev  string
}

EntityStateResponse is a representation of the http response for a group of EntityStates

type Feature

type Feature struct {
	ID               int32         `json:"Id,omitempty"`
	Name             string        `json:",omitempty"`
	Effort           float32       `json:",omitempty"`
	UserStoriesCount int64         `json:"UserStories-Count,omitempty"`
	Project          *Project      `json:",omitempty"`
	Description      string        `json:",omitempty"`
	NumericPriority  float32       `json:",omitempty"`
	CustomFields     []CustomField `json:",omitempty"`
	// contains filtered or unexported fields
}

Feature matches up with a targetprocess Feature

func (Feature) NewUserStory

func (f Feature) NewUserStory(name, description, project string) (UserStory, error)

NewUserStory will make a UserStory with the Feature that this method is built off of

type FeatureResponse

type FeatureResponse struct {
	Items []Feature
	Next  string
	Prev  string
}

FeatureResponse is a representation of the http response for a group of Features

type Process

type Process struct {
	ID          int32  `json:"Id,omitempty"`
	Name        string `json:",omitempty"`
	Description string `json:",omitempty"`
}

Process contains metadata for the state of a Process. Collection of Processes form Process for Entity. For example, Bug has four Processs by default: Open, Fixed, Invalid and Done

type ProcessResponse

type ProcessResponse struct {
	Items []Process
	Next  string
	Prev  string
}

ProcessResponse is a representation of the http response for a group of Processs

type Project

type Project struct {
	ID              int32         `json:"Id,omitempty"`
	Name            string        `json:",omitempty"`
	Description     string        `json:",omitempty"`
	StartDate       DateTime      `json:",omitempty"`
	EndDate         DateTime      `json:",omitempty"`
	CreateDate      DateTime      `json:",omitempty"`
	ModifyDate      DateTime      `json:",omitempty"`
	NumericPriority float64       `json:",omitempty"`
	CustomFields    []CustomField `json:",omitempty"`
	Effort          float32       `json:",omitempty"`
	EffortCompleted float32       `json:",omitempty"`
	EffortToDo      float32       `json:",omitempty"`
	IsActive        bool          `json:",omitempty"`
	Abbreviation    string        `json:",omitempty"`
	Color           string        `json:",omitempty"`
	Process         *Process      `json:",omitempty"`
	// contains filtered or unexported fields
}

Project matches up with a targetprocess Project

func (Project) GetProcess

func (p Project) GetProcess() (*Process, error)

GetProcess returns the process associated with a project

func (Project) NewUserStory

func (p Project) NewUserStory(name, description, team string) (UserStory, error)

NewUserStory will make a UserStory for assigned to the Project that this method is built off of and for the given Team

type ProjectResponse

type ProjectResponse struct {
	Items []Project
	Next  string
	Prev  string
}

ProjectResponse is a representation of the http response for a group of Projects

type QueryFilter

type QueryFilter func(r url.Values) (url.Values, error)

QueryFilter accepts a query and returns a query, modifying it in some way before sending

func First

func First() QueryFilter

First is a QueryFilter that will only return a single Entity. It returns the first one encountered.

**WARNING** if using this with a helper function that supports automatic paging, ensure to set page to false (e.g. client.GetUserStories())

Example
tpClient, err := NewClient("accountName", "superSecretToken")
if err != nil {
	fmt.Println("Error creating tp client:", err)
	os.Exit(1)
}
userStories, err := tpClient.GetUserStories(
	false,
	First(),
)
if err != nil {
	fmt.Println("Error getting UserStories:", err)
	os.Exit(1)
}
fmt.Printf("%+v\n", userStories)
Output:

func MaxPerPage

func MaxPerPage(count int) QueryFilter

MaxPerPage is how many results we will allow to return per page. Default enforced by the API is 25. If a negative number is passed in it will be converted to a positive number. In the TP API, a negative number has the same return as a positive, but we convert any negative to positive anyway.

Example
tpClient, err := NewClient("accountName", "superSecretToken")
if err != nil {
	fmt.Println("Error creating tp client:", err)
	os.Exit(1)
}
userStories, err := tpClient.GetUserStories(
	false,
	MaxPerPage(200),
)
if err != nil {
	fmt.Println("Error getting UserStories:", err)
	os.Exit(1)
}
fmt.Printf("%+v\n", userStories)
Output:

func Result added in v0.3.0

func Result(query string) QueryFilter

Result is a QueryFilter that represents the `result` parameter in a url query. It is used to do custom calculations over the entire result set, such as getting the average Effort value across multiple items.

It is important to note that this changes the output json and therefore you will need to adjust your receiving struct

Example
tpClient, err := NewClient("accountName", "superSecretToken")
if err != nil {
	fmt.Println("Error creating tp client:", err)
	os.Exit(1)
}
response := struct {
	EffortSum float64 `json:",omitempty"`
}{}
err = tpClient.Get(&response,
	"UserStories",
	nil,
	Result("effortSum:sum(effort)"),
)
if err != nil {
	fmt.Println("Error getting UserStories:", err)
	os.Exit(1)
}
fmt.Printf("%+v\n", response)
Output:

func Select added in v0.3.0

func Select(query string) QueryFilter

Select is a QueryFilter that represents the `select` parameter in a url query. It is used to determine what fields are returned. It is important that the struct you are casting your results into accept the fields you specify.

Example
tpClient, err := NewClient("accountName", "superSecretToken")
if err != nil {
	fmt.Println("Error creating tp client:", err)
	os.Exit(1)
}
userStories, err := tpClient.GetUserStories(
	false,
	Select("name,id"),
)
if err != nil {
	fmt.Println("Error getting UserStories:", err)
	os.Exit(1)
}
fmt.Printf("%+v\n", userStories)
Output:

func Where

func Where(queries ...string) QueryFilter

Where is a QueryFilter that represents the `where` parameter in a url query.

Example
tpClient, err := NewClient("accountName", "superSecretToken")
if err != nil {
	fmt.Println("Error creating tp client:", err)
	os.Exit(1)
}
userStories, err := tpClient.GetUserStories(
	false,
	Where("EntityState.Name == 'Done'"),
	Where("Team.Name == 'Team-1'"),
)
if err != nil {
	fmt.Println("Error getting UserStories:", err)
	os.Exit(1)
}
fmt.Printf("%+v\n", userStories)
Output:

type Team

type Team struct {
	ID              int32         `json:"Id,omitempty"`
	Name            string        `json:",omitempty"`
	Description     string        `json:",omitempty"`
	StartDate       DateTime      `json:",omitempty"`
	EndDate         DateTime      `json:",omitempty"`
	CreateDate      DateTime      `json:",omitempty"`
	ModifyDate      DateTime      `json:",omitempty"`
	NumericPriority float64       `json:",omitempty"`
	CustomFields    []CustomField `json:",omitempty"`
	Abbreviation    string        `json:",omitempty"`
	// contains filtered or unexported fields
}

Team matches up with a targetprocess Team

func (Team) NewUserStory

func (t Team) NewUserStory(name, description, project string) (UserStory, error)

NewUserStory will make a UserStory assigned to the Team that this method is built off of

type TeamAssignment

type TeamAssignment struct {
	ID        int32    `json:"Id,omitempty"`
	StartDate DateTime `json:",omitempty"`
	EndDate   DateTime `json:",omitempty"`
	Team      *Team    `json:",omitempty"`
}

TeamAssignment has it's own unique Id and also includes a reference to the team, which also has an Id

type TeamResponse

type TeamResponse struct {
	Items []Team
	Next  string
	Prev  string
}

TeamResponse is a representation of the http response for a group of Teams

type User

type User struct {
	CustomFields    []CustomField `json:",omitempty"`
	CreateDate      DateTime      `json:",omitempty"`
	ModifyDate      DateTime      `json:",omitempty"`
	DeleteDate      DateTime      `json:",omitempty"`
	Email           string        `json:",omitempty"`
	FirstName       string        `json:",omitempty"`
	GlobalID        string        `json:",omitempty"`
	ID              int32         `json:"Id"`
	IsActive        bool          `json:",omitempty"`
	IsAdministrator bool          `json:",omitempty"`
	LastName        string        `json:",omitempty"`
	Locale          string        `json:",omitempty"`
	Login           string        `json:",omitempty"`
}

User matches up with a targetprocess User

type UserAssignment added in v0.3.0

type UserAssignment struct {
	User
}

UserAssignment has its own unique Id and also includes a reference to a user, which also has an Id

type UserResponse

type UserResponse struct {
	Items []User
	Next  string
	Prev  string
}

UserResponse is a representation of the http response for a group of Users

type UserStory

type UserStory struct {
	ID                  int32           `json:"Id,omitempty"`
	Name                string          `json:",omitempty"`
	Description         string          `json:",omitempty"`
	StartDate           DateTime        `json:",omitempty"`
	EndDate             DateTime        `json:",omitempty"`
	CreateDate          DateTime        `json:",omitempty"`
	ModifyDate          DateTime        `json:",omitempty"`
	NumericPriority     float64         `json:",omitempty"`
	CustomFields        []CustomField   `json:",omitempty"`
	Effort              float32         `json:",omitempty"`
	EffortCompleted     float32         `json:",omitempty"`
	EffortToDo          float32         `json:",omitempty"`
	Project             *Project        `json:",omitempty"`
	Progress            float32         `json:",omitempty"`
	TimeSpent           float32         `json:",omitempty"`
	TimeRemain          float32         `json:",omitempty"`
	LastStateChangeDate DateTime        `json:",omitempty"`
	InitialEstimate     float32         `json:",omitempty"`
	ResponsibleTeam     *TeamAssignment `json:",omitempty"`
	Team                *Team           `json:",omitempty"`
	EntityState         *EntityState    `json:",omitempty"`
	AssignedUser        *AssignedUser   `json:",omitempty"`
	Feature             *Feature        `json:",omitempty"`
	// contains filtered or unexported fields
}

UserStory matches up with a targetprocess UserStory

func NewUserStory

func NewUserStory(c *Client, name, description, project string) (UserStory, error)

NewUserStory creates a new UserStory with the required fields of name, description, and project. If more fields are required, use the Add<Field> method of UserStory to add them

func (UserStory) Create

func (us UserStory) Create() (int32, error)

Create takes a UserStory struct and crafts a POST to make it so in TP it returns the ID of the UserStory created

func (*UserStory) SetFeature

func (us *UserStory) SetFeature(feature string) error

SetFeature sets the Feature field for a user story

func (*UserStory) SetProject

func (us *UserStory) SetProject(project string) error

SetProject sets the Project field for a user story

func (*UserStory) SetTeam

func (us *UserStory) SetTeam(team string) error

SetTeam sets the Team field for a user story

type UserStoryList

type UserStoryList struct {
	Stories []UserStory `json:"Stories"`
	// contains filtered or unexported fields
}

UserStoryList is a list of user stories. Can be used to create multiple stories at once

func (UserStoryList) Create

func (usl UserStoryList) Create() ([]int32, error)

Create posts a list of user stories to create them

type UserStoryResponse

type UserStoryResponse struct {
	Items []UserStory
	Next  string
	Prev  string
}

UserStoryResponse is a representation of the http response for a group of UserStories

type Workflow

type Workflow struct {
	ID      int32    `json:"Id,omitempty"`
	Name    string   `json:",omitempty"`
	Process *Process `json:",omitempty"`
}

Workflow contains metadata for the state of a Workflow.

type WorkflowResponse

type WorkflowResponse struct {
	Items []Workflow
	Next  string
	Prev  string
}

WorkflowResponse is a representation of the http response for a group of Workflows

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL