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

enhance(repo): add repo topics to repo object + build environment #285

Merged
merged 2 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions constants/limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ const (

// FavoritesMaxSize defines the maximum size in characters for user favorites.
FavoritesMaxSize = 5000

// TopicsMaxSize defines the maximum size in characters for repo topics. Ex: GitHub has a 20-topic, 50-char limit.
TopicsMaxSize = 1020
)
22 changes: 22 additions & 0 deletions database/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"encoding/base64"
"errors"

"github.com/go-vela/types/constants"
"github.com/go-vela/types/library"
"github.com/lib/pq"
)

var (
Expand All @@ -36,6 +38,10 @@ var (
// ErrEmptyRepoVisibility defines the error type when a
// Repo type has an empty Visibility field provided.
ErrEmptyRepoVisibility = errors.New("empty repo visibility provided")

// ErrExceededTopicsLimit defines the error type when a
// User type has Topics field provided that exceeds the database limit.
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
ErrExceededTopicsLimit = errors.New("exceeded topics limit")
)

// Repo is the database representation of a repo.
Expand All @@ -49,6 +55,7 @@ type Repo struct {
Link sql.NullString `sql:"link"`
Clone sql.NullString `sql:"clone"`
Branch sql.NullString `sql:"branch"`
Topics pq.StringArray `sql:"topics" gorm:"type:varchar(1020)"`
BuildLimit sql.NullInt64 `sql:"build_limit"`
Timeout sql.NullInt64 `sql:"timeout"`
Counter sql.NullInt32 `sql:"counter"`
Expand Down Expand Up @@ -210,6 +217,7 @@ func (r *Repo) ToLibrary() *library.Repo {
repo.SetLink(r.Link.String)
repo.SetClone(r.Clone.String)
repo.SetBranch(r.Branch.String)
repo.SetTopics(r.Topics)
repo.SetBuildLimit(r.BuildLimit.Int64)
repo.SetTimeout(r.Timeout.Int64)
repo.SetCounter(int(r.Counter.Int32))
Expand Down Expand Up @@ -261,6 +269,19 @@ func (r *Repo) Validate() error {
return ErrEmptyRepoVisibility
}

// calculate total size of favorites while sanitizing entries
total := 0

for i, t := range r.Topics {
r.Topics[i] = sanitize(t)
total += len(t)
}

// verify the Favorites field is within the database constraints
if total > constants.TopicsMaxSize {
return ErrExceededTopicsLimit
}

// ensure that all Repo string fields
// that can be returned as JSON are sanitized
// to avoid unsafe HTML content
Expand Down Expand Up @@ -289,6 +310,7 @@ func RepoFromLibrary(r *library.Repo) *Repo {
Link: sql.NullString{String: r.GetLink(), Valid: true},
Clone: sql.NullString{String: r.GetClone(), Valid: true},
Branch: sql.NullString{String: r.GetBranch(), Valid: true},
Topics: pq.StringArray(r.GetTopics()),
BuildLimit: sql.NullInt64{Int64: r.GetBuildLimit(), Valid: true},
Timeout: sql.NullInt64{Int64: r.GetTimeout(), Valid: true},
Counter: sql.NullInt32{Int32: int32(r.GetCounter()), Valid: true},
Expand Down
23 changes: 23 additions & 0 deletions database/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ func TestDatabase_Repo_ToLibrary(t *testing.T) {
want.SetLink("https://github.com/github/octocat")
want.SetClone("https://github.com/github/octocat.git")
want.SetBranch("master")
want.SetTopics([]string{"cloud", "security"})
want.SetBuildLimit(10)
want.SetTimeout(30)
want.SetCounter(0)
Expand All @@ -188,6 +189,14 @@ func TestDatabase_Repo_ToLibrary(t *testing.T) {
}

func TestDatabase_Repo_Validate(t *testing.T) {
// setup types
topics := []string{}
longTopic := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

for len(topics) < 21 {
topics = append(topics, longTopic)
}

// setup tests
tests := []struct {
failure bool
Expand Down Expand Up @@ -263,6 +272,18 @@ func TestDatabase_Repo_Validate(t *testing.T) {
FullName: sql.NullString{String: "github/octocat", Valid: true},
},
},
{ // topics exceed max size
failure: true,
repo: &Repo{
ID: sql.NullInt64{Int64: 1, Valid: true},
UserID: sql.NullInt64{Int64: 1, Valid: true},
Hash: sql.NullString{String: "superSecretHash", Valid: true},
Org: sql.NullString{String: "github", Valid: true},
Name: sql.NullString{String: "octocat", Valid: true},
FullName: sql.NullString{String: "github/octocat", Valid: true},
Topics: topics,
},
},
}

// run tests
Expand Down Expand Up @@ -296,6 +317,7 @@ func TestDatabase_RepoFromLibrary(t *testing.T) {
r.SetLink("https://github.com/github/octocat")
r.SetClone("https://github.com/github/octocat.git")
r.SetBranch("master")
r.SetTopics([]string{"cloud", "security"})
r.SetBuildLimit(10)
r.SetTimeout(30)
r.SetCounter(0)
Expand Down Expand Up @@ -334,6 +356,7 @@ func testRepo() *Repo {
Link: sql.NullString{String: "https://github.com/github/octocat", Valid: true},
Clone: sql.NullString{String: "https://github.com/github/octocat.git", Valid: true},
Branch: sql.NullString{String: "master", Valid: true},
Topics: []string{"cloud", "security"},
BuildLimit: sql.NullInt64{Int64: 10, Valid: true},
Timeout: sql.NullInt64{Int64: 30, Valid: true},
Counter: sql.NullInt32{Int32: 0, Valid: true},
Expand Down
77 changes: 54 additions & 23 deletions library/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,37 @@ package library

import (
"fmt"
"strings"
)

// Repo is the library representation of a repo.
//
// swagger:model Repo
type Repo struct {
ID *int64 `json:"id,omitempty"`
UserID *int64 `json:"user_id,omitempty"`
Hash *string `json:"-"`
Org *string `json:"org,omitempty"`
Name *string `json:"name,omitempty"`
FullName *string `json:"full_name,omitempty"`
Link *string `json:"link,omitempty"`
Clone *string `json:"clone,omitempty"`
Branch *string `json:"branch,omitempty"`
BuildLimit *int64 `json:"build_limit,omitempty"`
Timeout *int64 `json:"timeout,omitempty"`
Counter *int `json:"counter,omitempty"`
Visibility *string `json:"visibility,omitempty"`
Private *bool `json:"private,omitempty"`
Trusted *bool `json:"trusted,omitempty"`
Active *bool `json:"active,omitempty"`
AllowPull *bool `json:"allow_pull,omitempty"`
AllowPush *bool `json:"allow_push,omitempty"`
AllowDeploy *bool `json:"allow_deploy,omitempty"`
AllowTag *bool `json:"allow_tag,omitempty"`
AllowComment *bool `json:"allow_comment,omitempty"`
PipelineType *string `json:"pipeline_type,omitempty"`
PreviousName *string `json:"previous_name,omitempty"`
ID *int64 `json:"id,omitempty"`
UserID *int64 `json:"user_id,omitempty"`
Hash *string `json:"-"`
Org *string `json:"org,omitempty"`
Name *string `json:"name,omitempty"`
FullName *string `json:"full_name,omitempty"`
Link *string `json:"link,omitempty"`
Clone *string `json:"clone,omitempty"`
Branch *string `json:"branch,omitempty"`
Topics *[]string `json:"topics,omitempty"`
BuildLimit *int64 `json:"build_limit,omitempty"`
Timeout *int64 `json:"timeout,omitempty"`
Counter *int `json:"counter,omitempty"`
Visibility *string `json:"visibility,omitempty"`
Private *bool `json:"private,omitempty"`
Trusted *bool `json:"trusted,omitempty"`
Active *bool `json:"active,omitempty"`
AllowPull *bool `json:"allow_pull,omitempty"`
AllowPush *bool `json:"allow_push,omitempty"`
AllowDeploy *bool `json:"allow_deploy,omitempty"`
AllowTag *bool `json:"allow_tag,omitempty"`
AllowComment *bool `json:"allow_comment,omitempty"`
PipelineType *string `json:"pipeline_type,omitempty"`
PreviousName *string `json:"previous_name,omitempty"`
}

// Environment returns a list of environment variables
Expand All @@ -48,6 +50,7 @@ func (r *Repo) Environment() map[string]string {
"VELA_REPO_ALLOW_PUSH": ToString(r.GetAllowPush()),
"VELA_REPO_ALLOW_TAG": ToString(r.GetAllowTag()),
"VELA_REPO_BRANCH": ToString(r.GetBranch()),
"VELA_REPO_TOPICS": strings.Join(r.GetTopics()[:], ","),
"VELA_REPO_BUILD_LIMIT": ToString(r.GetBuildLimit()),
"VELA_REPO_CLONE": ToString(r.GetClone()),
"VELA_REPO_FULL_NAME": ToString(r.GetFullName()),
Expand Down Expand Up @@ -197,6 +200,19 @@ func (r *Repo) GetBranch() string {
return *r.Branch
}

// GetTopics returns the Topics field.
//
// When the provided Repo type is nil, or the field within
// the type is nil, it returns the zero value for the field.
func (r *Repo) GetTopics() []string {
// return zero value if Repo type or Topics field is nil
if r == nil || r.Topics == nil {
return []string{}
}

return *r.Topics
}

// GetBuildLimit returns the BuildLimit field.
//
// When the provided Repo type is nil, or the field within
Expand Down Expand Up @@ -496,6 +512,19 @@ func (r *Repo) SetBranch(v string) {
r.Branch = &v
}

// SetTopics sets the Topics field.
//
// When the provided Repo type is nil, it
// will set nothing and immediately return.
func (r *Repo) SetTopics(v []string) {
// return if Repo type is nil
if r == nil {
return
}

r.Topics = &v
}

// SetBuildLimit sets the BuildLimit field.
//
// When the provided Repo type is nil, it
Expand Down Expand Up @@ -700,6 +729,7 @@ func (r *Repo) String() string {
PreviousName: %s,
Private: %t,
Timeout: %d,
Topics: %s,
Trusted: %t,
UserID: %d
Visibility: %s,
Expand All @@ -723,6 +753,7 @@ func (r *Repo) String() string {
r.GetPreviousName(),
r.GetPrivate(),
r.GetTimeout(),
r.GetTopics(),
r.GetTrusted(),
r.GetUserID(),
r.GetVisibility(),
Expand Down
13 changes: 13 additions & 0 deletions library/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestLibrary_Repo_Environment(t *testing.T) {
"VELA_REPO_ALLOW_PUSH": "true",
"VELA_REPO_ALLOW_TAG": "false",
"VELA_REPO_BRANCH": "master",
"VELA_REPO_TOPICS": "cloud,security",
"VELA_REPO_BUILD_LIMIT": "10",
"VELA_REPO_CLONE": "https://github.com/github/octocat.git",
"VELA_REPO_FULL_NAME": "github/octocat",
Expand Down Expand Up @@ -111,6 +112,10 @@ func TestLibrary_Repo_Getters(t *testing.T) {
t.Errorf("GetBranch is %v, want %v", test.repo.GetBranch(), test.want.GetBranch())
}

if !reflect.DeepEqual(test.repo.GetTopics(), test.want.GetTopics()) {
t.Errorf("GetTopics is %v, want %v", test.repo.GetTopics(), test.want.GetTopics())
}

if test.repo.GetBuildLimit() != test.want.GetBuildLimit() {
t.Errorf("GetBuildLimit is %v, want %v", test.repo.GetBuildLimit(), test.want.GetBuildLimit())
}
Expand Down Expand Up @@ -195,6 +200,7 @@ func TestLibrary_Repo_Setters(t *testing.T) {
test.repo.SetLink(test.want.GetLink())
test.repo.SetClone(test.want.GetClone())
test.repo.SetBranch(test.want.GetBranch())
test.repo.SetTopics(test.want.GetTopics())
test.repo.SetBuildLimit(test.want.GetBuildLimit())
test.repo.SetTimeout(test.want.GetTimeout())
test.repo.SetCounter(test.want.GetCounter())
Expand Down Expand Up @@ -246,6 +252,10 @@ func TestLibrary_Repo_Setters(t *testing.T) {
t.Errorf("SetBranch is %v, want %v", test.repo.GetBranch(), test.want.GetBranch())
}

if !reflect.DeepEqual(test.repo.GetTopics(), test.want.GetTopics()) {
t.Errorf("SetTopics is %v, want %v", test.repo.GetTopics(), test.want.GetTopics())
}

if test.repo.GetBuildLimit() != test.want.GetBuildLimit() {
t.Errorf("SetBuildLimit is %v, want %v", test.repo.GetBuildLimit(), test.want.GetBuildLimit())
}
Expand Down Expand Up @@ -324,6 +334,7 @@ func TestLibrary_Repo_String(t *testing.T) {
PreviousName: %s,
Private: %t,
Timeout: %d,
Topics: %s,
Trusted: %t,
UserID: %d
Visibility: %s,
Expand All @@ -347,6 +358,7 @@ func TestLibrary_Repo_String(t *testing.T) {
r.GetPreviousName(),
r.GetPrivate(),
r.GetTimeout(),
r.GetTopics(),
r.GetTrusted(),
r.GetUserID(),
r.GetVisibility(),
Expand All @@ -372,6 +384,7 @@ func testRepo() *Repo {
r.SetLink("https://github.com/github/octocat")
r.SetClone("https://github.com/github/octocat.git")
r.SetBranch("master")
r.SetTopics([]string{"cloud", "security"})
r.SetBuildLimit(10)
r.SetTimeout(30)
r.SetCounter(0)
Expand Down