Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce DDD directory structure #2

Merged
merged 14 commits into from
Feb 23, 2023
10 changes: 8 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ linters:
- durationcheck
- errorlint
- exhaustive
- exhaustivestruct
#- exhaustivestruct
- exportloopref
- forcetypeassert
- funlen
# - funlen
- gci
- gochecknoglobals
- gochecknoinits
Expand All @@ -55,3 +55,9 @@ linters:
- unparam
- wastedassign
- whitespace
linters-settings:
tagliatelle:
case:
use-field-name: true
rules:
json: snake
Empty file added cmd/.gitkeep
Empty file.
Empty file added config/.gitkeep
Empty file.
25 changes: 25 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Package config get setting from environment variable or configuration file.
package config

// Config represents configuration information for the leadtime CLI command.
// For example, include GitHub API access information.
type Config struct {
// GitHubAccessToken is access token for GitHub API.
GitHubAccessToken string
}

// Argument represents the argument for leadtime CLI startup.
type Argument struct {
// GitHubOwner is GitHun owner name(e.g. nao1215)
GitHubOwner string
// GitHubRepository is GitHub repository name(e.g. leadtime)
GitHubRepository string
}

// NewArgument initialize Argument struct.
func NewArgument(owner, repo string) *Argument {
return &Argument{
GitHubOwner: owner,
GitHubRepository: repo,
}
}
25 changes: 25 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Package config get setting from environment variable or configuration file.
package config

import (
"testing"

"github.com/google/go-cmp/cmp"
)

func TestNewArgument(t *testing.T) {
t.Parallel()
t.Run("new argument", func(t *testing.T) {
t.Parallel()

want := &Argument{
GitHubOwner: "nao1215",
GitHubRepository: "leadtime",
}

got := NewArgument(want.GitHubOwner, want.GitHubRepository)
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
22 changes: 22 additions & 0 deletions domain/model/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Package model is domain model and business logic.
package model

// Repository represents GitHub repository information
type Repository struct {
// ID is repository id
ID *int64 `json:"id,omitempty"`
// Owner is repository owner
Owner *User `json:"owner,omitempty"`
// Name is repository name
Name *string `json:"name,omitempty"`
// FullName is repository full name
FullName *string `json:"full_name,omitempty"`
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
// Description is repository description
Description *string `json:"description,omitempty"`
}

// User represents a GitHub user.
type User struct {
// Name is user name.
Name *string `json:"name,omitempty"`
}
Empty file added domain/repository/.gitkeep
Empty file.
Empty file added domain/service/.gitkeep
Empty file.
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
module github.com/nao1215/leadtime

go 1.20

require (
github.com/google/go-cmp v0.5.9
github.com/google/go-github/v50 v50.0.0
golang.org/x/oauth2 v0.5.0
)

require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/net v0.6.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
31 changes: 31 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v50 v50.0.0 h1:gdO1AeuSZZK4iYWwVbjni7zg8PIQhp7QfmPunr016Jk=
github.com/google/go-github/v50 v50.0.0/go.mod h1:Ev4Tre8QoKiolvbpOSG3FIi4Mlon3S2Nt9W5JYqKiwA=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
16 changes: 16 additions & 0 deletions infrastructure/github/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package github

import "fmt"

// APIError is error for GitHub API.
type APIError struct {
// StatusCode is HTTP status code from GitHub.
StatusCode int
// Message is error message
Message string
}

// Error return string that represents a GitHub API error
func (e *APIError) Error() string {
return fmt.Sprintf("GitHub API error: status code %d, message: %s", e.StatusCode, e.Message)
}
43 changes: 43 additions & 0 deletions infrastructure/github/error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package github

import (
"net/http"
"testing"
)

func TestAPIError_Error(t *testing.T) {
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()

type fields struct {
StatusCode int
Message string
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "Get 401 error",
fields: fields{
StatusCode: http.StatusUnauthorized,
Message: "unauthorized",
},
want: "GitHub API error: status code 401, message: unauthorized",
},
}
for _, tt := range tests {
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

e := &APIError{
StatusCode: tt.fields.StatusCode,
Message: tt.fields.Message,
}
if got := e.Error(); got != tt.want {
t.Errorf("APIError.Error() = %v, want %v", got, tt.want)
}
})
}
}
52 changes: 52 additions & 0 deletions infrastructure/github/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Package github is http client for GitHub API.
// This package is wrapper for google/go-github package.
package github

import (
"context"

"github.com/google/go-github/v50/github"
"github.com/nao1215/leadtime/domain/model"
"golang.org/x/oauth2"
)

// Client is http client for GitHub API.
type Client struct {
// client is http client
client *github.Client
}

// NewClient return http client for GitHub API.
func NewClient(token string) *Client {
tokenSource := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
)
client := oauth2.NewClient(context.Background(), tokenSource)

return &Client{client: github.NewClient(client)}
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
}

// ListRepositories return List the repositories for a user.
func (c *Client) ListRepositories(ctx context.Context) ([]*model.Repository, error) {
repos, resp, err := c.client.Repositories.List(ctx, "", nil)
if resp != nil {
defer resp.Body.Close()
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
}
if err != nil {
return nil, &APIError{StatusCode: resp.StatusCode, Message: "failed to gey repository list"}
}

repoList := make([]*model.Repository, 0)
for _, v := range repos {
repo := &model.Repository{
ID: v.ID,
Owner: &model.User{Name: v.Owner.Name},
Name: v.Name,
FullName: v.FullName,
Description: v.Description,
}
repoList = append(repoList, repo)
}

return repoList, nil
nao1215 marked this conversation as resolved.
Show resolved Hide resolved
}
Loading