Documentation
¶
Overview ¶
This is a lightweight Redmine API client.
It doesn't do a lot of things, you might probably only be interested in the scrolling feature Scroll.
Index ¶
- Constants
- Variables
- func ApiUrl[E Entities](ac *ApiClient, page int) (string, error)
- func BuildApiUrl(base, endpoint string, v *url.Values, p int) (string, error)
- func Create[P PostData](ac *ApiClient, data P) error
- func DecodeResp[E Entities](body io.ReadCloser) (*E, error)
- func Scroll[E Entities](ac *ApiClient) (<-chan E, <-chan error)
- type ApiClient
- func (ac ApiClient) Create(url string, data io.Reader) error
- func (ac ApiClient) Get(url string) (io.ReadCloser, error)
- func (ac ApiClient) IssuesUrl(page int) (string, error)
- func (ac ApiClient) Post(url string, data io.Reader) (int, io.ReadCloser, error)
- func (ac ApiClient) ProjectsUrl(page int) (string, error)
- func (ac ApiClient) TimeEntriesUrl(page int) (string, error)
- type CreateIssuePayload
- type CreateTimeEntryPayload
- type Date
- type Entities
- type Issue
- type Issues
- type Pagination
- type PostData
- type PostDataIssue
- type PostTimeEntryParams
- type Project
- type Projects
- type TimeEntries
- type TimeEntriesFilter
- type TimeEntry
- type User
Constants ¶
const ( ProjectsApiEndpoint = "/projects.json" IssuesApiEndpoint = "/issues.json" TimeEntriesEndpoint = "/time_entries.json" )
Variables ¶
var ( JsonDecodeError = errors.New("JSON decode error") IoReadError = errors.New("io.ReadAll error") UrlJoinPathError = errors.New("url.JoinPath error") UrlParseError = errors.New("url.Parse error") ApiEndpointUrlFatalError = errors.New("cannot build API endpoint url") ApiNewRequestFatalError = errors.New("cannot create a new request with given url") HttpError = errors.New("http error") UnknownDataTypeError = errors.New("unknown or not supported data type requested") ValidationError = errors.New("Validation error") ZeroTimeDetectedError = errors.New("Zero timestamp is not allowed") ProjectAndIssuePassedError = errors.New("Only one is required: issue_id or project_id") ProjectAndIssueMissedError = errors.New("Neither issue_id or project_id was passed") EmptyProjectError = errors.New("Project ID must not be a zero") )
There are some custom error types, from low level to high level errors which are aggregates of first ones.
Typically you should be expect only these high level errors in errChan:
- JsonDecodeError: errors related to unmarshaling redmine server response
- IoReadError: errors related to read input
- HttpError: errors related to network layer
- ApiEndpointUrlFatalError: fatal errors that means that most probably the url of redmine api is malformed or bogus, please check it
- ApiNewRequestFatalError: actually will not be thrown (see the comments in code)
Functions ¶
func BuildApiUrl ¶
Add pagination query string to URL.
func DecodeResp ¶
func DecodeResp[E Entities](body io.ReadCloser) (*E, error)
Decode JSON Redmine API response to package types.
func Scroll ¶
Scroll over Redmine API paginated responses. It going through all available data, so it may generate a lot of http requests (depending on a size of data and pagination limit).
The pagination of redmine is based on offset&limit, but in URL you may use query string param ?page=, e.g. for 53 issues and limit=25 it will be three requests:
- 0 25 53 - [0, 25] /issues.json?page=1 or omitted page number: /issues.json
- 25 25 53 - [25, 50] /issues.json?page=2
- 50 25 53 - [50, 53] /issues.json?page=3
This function do this automatically and send all the data to channel, if any error occurs, it will be send to the second, errors channel.
Types ¶
type ApiClient ¶ added in v0.1.0
type ApiClient struct { Url string Token string LogEnabled bool TimeEntriesFilter }
Config of Redmine REST API client: url, token, logging and time entries filtration.
func CreateApiClient ¶ added in v0.1.0
func CreateApiClient(url, token string, logging bool, teFilter TimeEntriesFilter) *ApiClient
func (ApiClient) Get ¶ added in v0.1.0
func (ac ApiClient) Get(url string) (io.ReadCloser, error)
Get Redmine entities respecting the setted filtration (time entries) and page of pagination.
func (ApiClient) ProjectsUrl ¶ added in v0.1.0
type CreateIssuePayload ¶ added in v0.2.0
type CreateIssuePayload struct { ProjectID int `json:"project_id,omitempty"` TrackerID int `json:"tracker_id,omitempty"` StatusID int `json:"status_id,omitempty"` PriorityID int `json:"priority_id,omitempty"` CategoryID int `json:"category_id,omitempty"` ParrentID int `json:"parent_issue_id,omitempty"` FixedVerID int `json:"fixed_version_id,omitempty"` AssignedID int `json:"assigned_to_id,omitempty"` Watchers []int `json:"watcher_user_ids,omitempty"` Subject string `json:"string,omitempty"` Desc string `json:"description,omitempty"` Private bool `json:"is_private,omitempty"` Estimate float32 `json:"estimated_hours,omitempty"` }
Payload of Redmine API POST /issues
func (CreateIssuePayload) Validate ¶ added in v0.2.0
func (p CreateIssuePayload) Validate() error
Validate payload.
type CreateTimeEntryPayload ¶ added in v0.2.0
type CreateTimeEntryPayload struct { ProjectID int `json:"project_id,omitempty"` IssueID int `json:"issue_id,omitempty"` ActivityID int `json:"activity_id,omitempty"` UserID int `json:"user_id,omitempty"` SpentOn Date `json:"spent_on,omitempty"` Comments string `json:"comments,omitempty"` Hours float32 `json:"hours,omitempty"` }
Payload of Redmine API POST /time_entries.
func (CreateTimeEntryPayload) Validate ¶ added in v0.2.0
func (p CreateTimeEntryPayload) Validate() error
Validate payload.
type Date ¶
A date type is needed for proper parsing (unmarshaling) of redmine date format used in JSON.
func (Date) MarshalJSON ¶ added in v0.2.0
Marshaling time.Time object to redmine format.
func (*Date) UnmarshalJSON ¶
Unmarshaling redmine dates.
type Entities ¶
type Entities interface { Projects | Issues | TimeEntries NextPage() (n int) }
Data type constraint, a quick glance at which will let you know the supported data types for fetching from redmine server.
type Issue ¶
type Issue struct { Id int `json:"id"` Subject string `json:"subject"` Desc string `json:"description"` Project `json:"project"` }
A Redmine issue entity.
type Issues ¶ added in v0.1.0
type Issues struct { Items []Issue `json:"issues"` Pagination }
type Pagination ¶
type Pagination struct { Offset int `json:"offset"` Limit int `json:"limit"` Total int `json:"total_count"` }
func (Pagination) NextPage ¶ added in v0.1.0
func (p Pagination) NextPage() (n int)
type PostData ¶ added in v0.2.0
type PostData interface { PostTimeEntryParams | PostDataIssue Validate() error Url(base string) (string, error) }
PostData is a generic container for payloads of API endpoints.
type PostDataIssue ¶ added in v0.2.0
type PostDataIssue struct {
Payload CreateIssuePayload `json:"issue"`
}
POST /issues params
func NewPostIssueParams ¶ added in v0.2.0
func NewPostIssueParams() *PostDataIssue
func (PostDataIssue) Validate ¶ added in v0.2.0
func (i PostDataIssue) Validate() error
type PostTimeEntryParams ¶ added in v0.2.0
type PostTimeEntryParams struct {
Payload CreateTimeEntryPayload `json:"time_entry"`
}
POST /time_entries params
func NewPostTimeEntryParams ¶ added in v0.2.0
func NewPostTimeEntryParams() *PostTimeEntryParams
func (PostTimeEntryParams) Url ¶ added in v0.2.0
func (t PostTimeEntryParams) Url(base string) (string, error)
func (PostTimeEntryParams) Validate ¶ added in v0.2.0
func (t PostTimeEntryParams) Validate() error
type Project ¶
type Project struct { Id int `json:"id"` Name string `json:"name"` Ident string `json:"identifier"` Desc string `json:"description"` // TODO correct parsing date time // CreatedOn time.Time `json:"created_on"` // UpdatedOn time.Time `json:"updated_on"` IsPublic bool `json:"is_public"` }
A Redmine project entity.
type Projects ¶ added in v0.1.0
type Projects struct { Items []Project `json:"projects"` Pagination }
type TimeEntries ¶ added in v0.1.0
type TimeEntries struct { Items []TimeEntry `json:"time_entries"` Pagination }
type TimeEntriesFilter ¶
Time Entries filtration by range of dates and user id.