Skip to content

Commit

Permalink
initial checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
ttyfky committed Dec 29, 2020
1 parent d5114fe commit 510a97f
Show file tree
Hide file tree
Showing 14 changed files with 1,051 additions and 3 deletions.
12 changes: 10 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,13 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
# IDE
.vscode*
.history
.idea
.DS_store

# Go
*/pkg
*/bin
vendor
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.PHONY: mod
mod:
go mod download

.PHONY: vendor
vendor:
go mod vendor

.PHONY: test
test:
go test ./...
68 changes: 67 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,68 @@
# go-circleci
Go client of CircleCI API v2

[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

This is a Go client of [CircleCI API v2](https://circleci.com/docs/api/v2/).

This API is implemented by following the public docs by CircleCI.
* [API Reference](https://circleci.com/docs/2.0/api-intro/)
* [CircleCI API v2](https://circleci.com/docs/api/v2/)
* [CircleCI API Developer's Guide](https://circleci.com/docs/2.0/api-developers-guide/)

## Install

```console
$ go get github.com/ttyfky/go-circleci
```

## Use

```go
import "github.com/bold-commerce/go-shopify"
```

### Authentication
CircleCI supports two types of authentication 1. api_key_header and 2. basic_auth.

This Client currently supports api_key_header authentication.

#### Get API token
Get API token by following [instruction](https://circleci.com/docs/2.0/api-developers-guide/#authentication-and-authorization) before using this client.


### Create Client
Give API token to `NewClient` function.
```go
token := "API_TOKEN"
client := circleci.NewClient(token)
```

### API call
Use resource service in the client to call API of each resources in CircleCI.

```go
client := circleci.NewClient(token)
workflowID := "ID"
workflow, _ := client.Workflow.Get(workflowID)
```

More examples are availablein [example_test.go](./example_test.go).

# API availability

Not all of the APIs are implemented yet. It's more based on demand of the actions.
The table below shows the API's availability as of Jan 2021.

`Preview` means it's preview phase in CircleCI side.

| API | Availability |
|-------------------|--------------|
| Context (Preview) | Available |
| Insights | Not Implemented |
| User (Preview) | Not Implemented |
| Pipeline | Not Implemented |
| Job (Preview) | Available |
| Workflow | Available |
| Project | Partially Available |

Note: Environment variable handling is part of Project API, but extracted as `ProjectEnvVar` it for convenience.
143 changes: 143 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package circleci

import "time"

const (
contextBasePath = "/context"

defaultContextType = "organization"
)

// ContextService is an interface for Context in Project API.
type ContextService interface {
List(slug string) (*ContextList, error)
Create(projectSlug, name string) (*Context, error)
Delete(id string) error
Get(id string) (*Context, error)
ListEnvVar(id string) (*ContextEnvVarList, error)
UpsertEnvVar(id, envVarName, envVarValue string) (*ContextEnvVar, error)
RemoveEnvVar(id, envVarName string) error
}

// ContextOp handles communication with the project related methods in the CircleCI API v2.
type ContextOp struct {
client *Client
}

var _ ContextService = (*ContextOp)(nil)

// Context represents information about a context in CircleCI.
type Context struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
}

// ContextList represents a list of Context variables.
type ContextList struct {
NextPageToken string `json:"next_page_token,omitempty"`
Items []*Context `json:"items,omitempty"`
}

// Owner represents Owner used in ContextCreate.
type Owner struct {
Slug string `json:"slug,omitempty"`
Type string `json:"type,omitempty"`
}

// ContextCreate represents payload to create Context.
type ContextCreate struct {
Name string `json:"name,omitempty"`
*Owner `json:"owner,omitempty"`
}

// ContextEnvVar represents information about an environment variable of Context.
type ContextEnvVar struct {
Variable string `json:"variable,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
ContextID string `json:"context_id,omitempty"`
}

// ContextEnvVarList represents a list of ContextEnvVar.
type ContextEnvVarList struct {
NextPageToken string `json:"next_page_token,omitempty"`
Items []*ContextEnvVar `json:"items,omitempty"`
}

// List list contexts for an owner.
// owner-slug is expected but not owner-id.
func (ps *ContextOp) List(slug string) (*ContextList, error) {
cl := &ContextList{}
path := contextBasePath + "?owner-slug=" + slug
err := ps.client.Get(path, cl, nil)
if err != nil {
return nil, err
}
return cl, nil
}

// Create adds a new environment variable or update existing variable on the specified project.
// Returns the added env var (the value will be masked).
func (ps *ContextOp) Create(projectSlug, name string) (*Context, error) {
c := &Context{}
err := ps.client.Post(contextBasePath, &ContextCreate{Name: name, Owner: &Owner{Slug: projectSlug, Type: defaultContextType}}, c)
if err != nil {
return nil, err
}
return c, nil
}

// Delete deletes the specified environment variable from the project.
func (ps *ContextOp) Delete(id string) error {
return ps.client.Delete(contextBasePath + "/" + id)
}

// Get gets environment variable.
// Returns the env vars (the value will be masked).
func (ps *ContextOp) Get(id string) (*Context, error) {
c := &Context{}
err := ps.client.Get(contextBasePath+"/"+id, c, nil)
if err != nil {
return nil, err
}
return c, nil
}

// ListEnvVar list contexts for an owner.
// Returns the env vars (the value will be masked).
func (ps *ContextOp) ListEnvVar(id string) (*ContextEnvVarList, error) {
cel := &ContextEnvVarList{}
err := ps.client.Get(contextEnvVarPath(id), cel, nil)
if err != nil {
return nil, err
}
return cel, nil
}

// UpsertEnvVar list contexts for an owner.
// Returns the env vars (the value will be masked).
func (ps *ContextOp) UpsertEnvVar(id, envVarName, envVarValue string) (*ContextEnvVar, error) {
ce := &ContextEnvVar{}
path := contextEnvVarPath(id) + "/" + envVarName
err := ps.client.Put(path,
struct {
Value string `json:"value"`
}{
Value: envVarValue,
},
ce)
if err != nil {
return nil, err
}
return ce, nil
}

// RemoveEnvVar list contexts for an owner.
// Returns the env vars (the value will be masked).
func (ps *ContextOp) RemoveEnvVar(id, envVarName string) error {
return ps.client.Delete(contextEnvVarPath(id) + "/" + envVarName)
}

func contextEnvVarPath(id string) string {
return contextBasePath + "/" + id + "/environment-variable"
}
101 changes: 101 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package circleci_test

import (
"bytes"
"encoding/json"
"log"
"os"

"github.com/ttyfky/go-circleci"
)

func ExampleProjectServiceOp_Get() {
token := os.Getenv("CIRCLECI_TOKEN")
client := circleci.NewClient(token)

project, err := client.Project.Get(projectSlug())
if err != nil {
log.Fatal(err)
}
printPretty(project)
}

func ExampleProjectEnvVarOp_List() {
token := os.Getenv("CIRCLECI_TOKEN")
client := circleci.NewClient(token)

envVarList, err := client.EnvVar.List(projectSlug())
if err != nil {
log.Fatal(err)
}
printPretty(envVarList)
}

func ExampleWorkflowOp_Get() {
token := os.Getenv("CIRCLECI_TOKEN")
client := circleci.NewClient(token)

workflowID := "ID"
workflow, err := client.Workflow.Get(workflowID)
if err != nil {
log.Fatal(err)
}
printPretty(workflow)
}

func ExampleContextOp_Get() {
token := os.Getenv("CIRCLECI_TOKEN")
client := circleci.NewClient(token)

id := "context_id"
contextList, err := client.Context.Get(id)
if err != nil {
log.Fatal(err)
}
printPretty(contextList)
}

func ExampleContextOp_Create() {
token := os.Getenv("CIRCLECI_TOKEN")
client := circleci.NewClient(token)

id := "context_id"

envVarName := "test_key"
envVar, err := client.Context.UpsertEnvVar(id, envVarName, "test_value")
println("Created env Var")
printPretty(envVar)
contextList, err := client.Context.ListEnvVar(id)
if err != nil {
log.Fatal(err)
}
printPretty(contextList)
err = client.Context.RemoveEnvVar(id, envVarName)
if err != nil {
log.Fatal(err)
}
println("Deleted env var")
contextList, err = client.Context.ListEnvVar(id)
if err != nil {
log.Fatal(err)
}
printPretty(contextList)

}

func projectSlug() string {
projectType := "gh"
org := "ttyfky"
repo := "go-circleci"
return circleci.ProjectSlug(projectType, org, repo)
}

func printPretty(obj interface{}) {
b, err := json.Marshal(obj)
if err != nil {
log.Fatal(err)
}
var prettyJSON bytes.Buffer
_ = json.Indent(&prettyJSON, b, "", "\t")
println(prettyJSON.String())
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/ttyfky/go-circleci

go 1.15

require github.com/google/go-querystring v1.0.0
Loading

0 comments on commit 510a97f

Please sign in to comment.