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

feat(deployment): add deployment table #323

Merged
merged 18 commits into from
Dec 22, 2023
3 changes: 3 additions & 0 deletions constants/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const (
// TableBuildExecutable defines the table type for the database build_executables table.
TableBuildExecutable = "build_executables"

// TableDeployments defines the table type for the database deployments table.
claire1618 marked this conversation as resolved.
Show resolved Hide resolved
TableDeployment = "deployments"

// TableHook defines the table type for the database hooks table.
TableHook = "hooks"

Expand Down
8 changes: 8 additions & 0 deletions database/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type Build struct {
Started sql.NullInt64 `sql:"started"`
Finished sql.NullInt64 `sql:"finished"`
Deploy sql.NullString `sql:"deploy"`
DeployNumber sql.NullInt64 `sql:"deploy_number"`
DeployPayload raw.StringSliceMap `sql:"deploy_payload" gorm:"type:varchar(2000)"`
Clone sql.NullString `sql:"clone"`
Source sql.NullString `sql:"source"`
Expand Down Expand Up @@ -170,6 +171,11 @@ func (b *Build) Nullify() *Build {
b.Deploy.Valid = false
}

// check if the Deploy field should be false
claire1618 marked this conversation as resolved.
Show resolved Hide resolved
if b.DeployNumber.Int64 == 0 {
b.Deploy.Valid = false
}

// check if the Clone field should be false
if len(b.Clone.String) == 0 {
b.Clone.Valid = false
Expand Down Expand Up @@ -282,6 +288,7 @@ func (b *Build) ToLibrary() *library.Build {
build.SetStarted(b.Started.Int64)
build.SetFinished(b.Finished.Int64)
build.SetDeploy(b.Deploy.String)
build.SetDeployNumber(b.DeployNumber.Int64)
build.SetDeployPayload(b.DeployPayload)
build.SetClone(b.Clone.String)
build.SetSource(b.Source.String)
Expand Down Expand Up @@ -365,6 +372,7 @@ func BuildFromLibrary(b *library.Build) *Build {
Started: sql.NullInt64{Int64: b.GetStarted(), Valid: true},
Finished: sql.NullInt64{Int64: b.GetFinished(), Valid: true},
Deploy: sql.NullString{String: b.GetDeploy(), Valid: true},
DeployNumber: sql.NullInt64{Int64: b.GetDeployNumber(), Valid: true},
DeployPayload: b.GetDeployPayload(),
Clone: sql.NullString{String: b.GetClone(), Valid: true},
Source: sql.NullString{String: b.GetSource(), Valid: true},
Expand Down
4 changes: 4 additions & 0 deletions database/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func TestDatabase_Build_Nullify(t *testing.T) {
Started: sql.NullInt64{Int64: 0, Valid: false},
Finished: sql.NullInt64{Int64: 0, Valid: false},
Deploy: sql.NullString{String: "", Valid: false},
DeployNumber: sql.NullInt64{Int64: 0, Valid: false},
DeployPayload: nil,
Clone: sql.NullString{String: "", Valid: false},
Source: sql.NullString{String: "", Valid: false},
Expand Down Expand Up @@ -121,6 +122,7 @@ func TestDatabase_Build_ToLibrary(t *testing.T) {
want.SetStarted(1563474078)
want.SetFinished(1563474079)
want.SetDeploy("")
want.SetDeployNumber(0)
want.SetDeployPayload(nil)
want.SetClone("https://github.com/github/octocat.git")
want.SetSource("https://github.com/github/octocat/48afb5bdc41ad69bf22588491333f7cf71135163")
Expand Down Expand Up @@ -212,6 +214,7 @@ func TestDatabase_BuildFromLibrary(t *testing.T) {
b.SetStarted(1563474078)
b.SetFinished(1563474079)
b.SetDeploy("")
b.SetDeployNumber(0)
b.SetDeployPayload(nil)
b.SetClone("https://github.com/github/octocat.git")
b.SetSource("https://github.com/github/octocat/48afb5bdc41ad69bf22588491333f7cf71135163")
Expand Down Expand Up @@ -273,6 +276,7 @@ func testBuild() *Build {
Started: sql.NullInt64{Int64: 1563474078, Valid: true},
Finished: sql.NullInt64{Int64: 1563474079, Valid: true},
Deploy: sql.NullString{String: "", Valid: false},
DeployNumber: sql.NullInt64{Int64: 0, Valid: true},
DeployPayload: raw.StringSliceMap{"foo": "test1", "bar": "test2"},
Clone: sql.NullString{String: "https://github.com/github/octocat.git", Valid: true},
Source: sql.NullString{String: "https://github.com/github/octocat/48afb5bdc41ad69bf22588491333f7cf71135163", Valid: true},
Expand Down
176 changes: 176 additions & 0 deletions database/deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// SPDX-License-Identifier: Apache-2.0

package database

import (
"database/sql"
"errors"
"fmt"

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

var (
// ErrEmptyDeploymentNumber defines the error type when a
// Deployment type has an empty Number field provided.
ErrEmptyDeploymentNumber = errors.New("empty deployment number provided")

// ErrEmptyDeploymentRepoID defines the error type when a
// Deployment type has an empty RepoID field provided.
ErrEmptyDeploymentRepoID = errors.New("empty deployment repo_id provided")
)

// Deployment is the database representation of a deployment for a repo.
type Deployment struct {
ID sql.NullInt64 `sql:"id"`
Number sql.NullInt64 `sql:"number"`
RepoID sql.NullInt64 `sql:"repo_id"`
URL sql.NullString `sql:"url"`
User sql.NullString `sql:"user"`
Commit sql.NullString `sql:"commit"`
Ref sql.NullString `sql:"ref"`
Task sql.NullString `sql:"task"`
Target sql.NullString `sql:"target"`
Description sql.NullString `sql:"description"`
Payload raw.StringSliceMap `sql:"payload"`
Builds pq.StringArray `sql:"builds" gorm:"type:varchar(50)"`
}
claire1618 marked this conversation as resolved.
Show resolved Hide resolved

// Nullify ensures the valid flag for
// the sql.Null types are properly set.
//
// When a field within the Deployment type is the zero
// value for the field, the valid flag is set to
// false causing it to be NULL in the database.
func (d *Deployment) Nullify() *Deployment {
if d == nil {
return nil
}

// check if the ID field should be false
if d.ID.Int64 == 0 {
d.ID.Valid = false
}

// check if the Number field should be false
if d.Number.Int64 == 0 {
d.Number.Valid = false
}

// check if the RepoID field should be false
if d.RepoID.Int64 == 0 {
d.RepoID.Valid = false
}

// check if the URL field should be false
if len(d.URL.String) == 0 {
d.URL.Valid = false
}

// check if the User field should be false
if len(d.User.String) == 0 {
d.User.Valid = false
}

// check if the Commit field should be false
if len(d.Commit.String) == 0 {
d.Commit.Valid = false
}

// check if the Ref field should be false
if len(d.Ref.String) == 0 {
d.Ref.Valid = false
}

// check if the Task field should be false
if len(d.Task.String) == 0 {
d.Task.Valid = false
}

// check if the Target field should be false
if len(d.Target.String) == 0 {
d.Target.Valid = false
}

// check if the Description field should be false
if len(d.Description.String) == 0 {
d.Description.Valid = false
}

return d
}

// ToLibrary converts the Deployment type
// to a library Deployment type.
func (d *Deployment) ToLibrary(builds *[]library.Build) *library.Deployment {
deployment := new(library.Deployment)

deployment.SetID(d.ID.Int64)
deployment.SetNumber(d.Number.Int64)
deployment.SetRepoID(d.RepoID.Int64)
deployment.SetURL(d.URL.String)
deployment.SetUser(d.User.String)
deployment.SetCommit(d.Commit.String)
deployment.SetRef(d.Ref.String)
deployment.SetTask(d.Task.String)
deployment.SetTarget(d.Target.String)
deployment.SetDescription(d.Description.String)
deployment.SetPayload(d.Payload)
deployment.SetBuilds(builds)

return deployment
}

// Validate verifies the necessary fields for
// the Deployment type are populated correctly.
func (d *Deployment) Validate() error {
// verify the RepoID field is populated
if d.RepoID.Int64 <= 0 {
return ErrEmptyDeploymentRepoID
}

// verify the Number field is populated
if d.Number.Int64 <= 0 {
return ErrEmptyDeploymentNumber
}

// ensure that all Deployment string fields
// that can be returned as JSON are sanitized
// to avoid unsafe HTML content
d.User = sql.NullString{String: sanitize(d.User.String), Valid: d.User.Valid}
d.Commit = sql.NullString{String: sanitize(d.Commit.String), Valid: d.Commit.Valid}
d.Ref = sql.NullString{String: sanitize(d.Ref.String), Valid: d.Ref.Valid}
d.Task = sql.NullString{String: sanitize(d.Task.String), Valid: d.Task.Valid}
d.Target = sql.NullString{String: sanitize(d.Target.String), Valid: d.Target.Valid}
d.Description = sql.NullString{String: sanitize(d.Description.String), Valid: d.Description.Valid}

return nil
}

// DeploymentFromLibrary converts the Deployment type
// to a library Deployment type.
claire1618 marked this conversation as resolved.
Show resolved Hide resolved
func DeploymentFromLibrary(d *library.Deployment) *Deployment {
buildIDs := []string{}
for _, build := range d.GetBuilds() {
buildIDs = append(buildIDs, fmt.Sprint(build.GetID()))
}

deployment := &Deployment{
ID: sql.NullInt64{Int64: d.GetID(), Valid: true},
Number: sql.NullInt64{Int64: d.GetNumber(), Valid: true},
RepoID: sql.NullInt64{Int64: d.GetRepoID(), Valid: true},
URL: sql.NullString{String: d.GetURL(), Valid: true},
User: sql.NullString{String: d.GetUser(), Valid: true},
Commit: sql.NullString{String: d.GetCommit(), Valid: true},
Ref: sql.NullString{String: d.GetRef(), Valid: true},
Task: sql.NullString{String: d.GetTask(), Valid: true},
Target: sql.NullString{String: d.GetTarget(), Valid: true},
Description: sql.NullString{String: d.GetDescription(), Valid: true},
Payload: d.GetPayload(),
Builds: buildIDs,
}

return deployment.Nullify()
}
Loading