Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
go-version-file: 'go.mod'
- name: lint
run: |
go install honnef.co/go/tools/cmd/staticcheck@v0.8.0-rc.1
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck ./...
- name: vet
run: |
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.27 AS builder
FROM golang:1.25 AS builder

WORKDIR /go/src/github.com/whywaita/myshoes

Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/whywaita/myshoes

go 1.27
go 1.25

require (
github.com/bradleyfalzon/ghinstallation/v2 v2.17.0
Expand All @@ -16,6 +16,7 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/prometheus/client_golang v1.23.2
github.com/r3labs/diff/v2 v2.15.1
github.com/satori/go.uuid v1.2.0
goji.io v2.0.2+incompatible
golang.org/x/oauth2 v0.32.0
golang.org/x/sync v0.18.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ github.com/r3labs/diff/v2 v2.15.1 h1:EOrVqPUzi+njlumoqJwiS/TgGgmZo83619FNDB9xQUg
github.com/r3labs/diff/v2 v2.15.1/go.mod h1:I8noH9Fc2fjSaMxqF3G2lhDdC0b+JXCfyx85tWFM9kc=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
2 changes: 1 addition & 1 deletion pkg/datastore/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"strings"
"time"

"uuid"
uuid "github.com/satori/go.uuid"

"github.com/whywaita/myshoes/pkg/gh"
"github.com/whywaita/myshoes/pkg/logger"
Expand Down
4 changes: 2 additions & 2 deletions pkg/datastore/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"sync"
"time"

"uuid"
uuid "github.com/satori/go.uuid"

"github.com/whywaita/myshoes/pkg/datastore"
)
Expand Down Expand Up @@ -214,7 +214,7 @@ func (m *Memory) ListRunnersByTargetID(ctx context.Context, targetID uuid.UUID)

var runners []datastore.Runner
for _, r := range m.runners {
if r.TargetID == targetID {
if uuid.Equal(r.TargetID, targetID) {
runners = append(runners, r)
}
}
Expand Down
58 changes: 5 additions & 53 deletions pkg/datastore/mysql/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,15 @@ import (
"database/sql"
"errors"
"fmt"
"time"

uuid "github.com/satori/go.uuid"
"github.com/whywaita/myshoes/pkg/datastore"
"uuid"
)

// rowJob mirrors datastore.Job but stores the UUID columns (uuid, target_id) as
// strings so that database/sql can scan the VARCHAR(36) columns. The standard
// library uuid.UUID is a [16]byte with no sql.Scanner.
type rowJob struct {
UUID string `db:"uuid"`
GHEDomain sql.NullString `db:"ghe_domain"`
Repository string `db:"repository"`
CheckEventJSON string `db:"check_event"`
TargetID string `db:"target_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}

func (r rowJob) job() (datastore.Job, error) {
u, err := uuid.Parse(r.UUID)
if err != nil {
return datastore.Job{}, fmt.Errorf("failed to parse job uuid %q: %w", r.UUID, err)
}

tid, err := uuid.Parse(r.TargetID)
if err != nil {
return datastore.Job{}, fmt.Errorf("failed to parse target id %q: %w", r.TargetID, err)
}

return datastore.Job{
UUID: u,
GHEDomain: r.GHEDomain,
Repository: r.Repository,
CheckEventJSON: r.CheckEventJSON,
TargetID: tid,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
}, nil
}

func jobsFromRows(rows []rowJob) ([]datastore.Job, error) {
js := make([]datastore.Job, 0, len(rows))
for _, r := range rows {
j, err := r.job()
if err != nil {
return nil, err
}
js = append(js, j)
}
return js, nil
}

// EnqueueJob add a job
func (m *MySQL) EnqueueJob(ctx context.Context, job datastore.Job) error {
query := `INSERT INTO jobs(uuid, ghe_domain, repository, check_event, target_id) VALUES (?, ?, ?, ?, ?)`
if _, err := m.Conn.ExecContext(ctx, query, job.UUID.String(), job.GHEDomain, job.Repository, job.CheckEventJSON, job.TargetID.String()); err != nil {
if _, err := m.Conn.ExecContext(ctx, query, job.UUID, job.GHEDomain, job.Repository, job.CheckEventJSON, job.TargetID.String()); err != nil {
return fmt.Errorf("failed to execute INSERT query: %w", err)
}

Expand All @@ -77,17 +29,17 @@ func (m *MySQL) EnqueueJob(ctx context.Context, job datastore.Job) error {

// ListJobs get all jobs
func (m *MySQL) ListJobs(ctx context.Context) ([]datastore.Job, error) {
var rows []rowJob
var jobs []datastore.Job
query := `SELECT uuid, ghe_domain, repository, check_event, target_id, created_at, updated_at FROM jobs`
if err := m.Conn.SelectContext(ctx, &rows, query); err != nil {
if err := m.Conn.SelectContext(ctx, &jobs, query); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, datastore.ErrNotFound
}

return nil, fmt.Errorf("failed to execute SELECT query: %w", err)
}

return jobsFromRows(rows)
return jobs, nil
}

// DeleteJob delete a job
Expand Down
40 changes: 5 additions & 35 deletions pkg/datastore/mysql/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/jmoiron/sqlx"
"uuid"
uuid "github.com/satori/go.uuid"

"github.com/whywaita/myshoes/internal/testutils"
"github.com/whywaita/myshoes/pkg/datastore"
)

var testJobID = uuid.MustParse("1b4e5b7a-e3c1-4829-9cfd-eac4183f2c95")
var testJobID = uuid.FromStringOrNil("1b4e5b7a-e3c1-4829-9cfd-eac4183f2c95")

func TestMySQL_EnqueueJob(t *testing.T) {
testDatastore, teardown := testutils.GetTestDatastore()
Expand Down Expand Up @@ -206,46 +206,16 @@ func TestMySQL_DeleteJob(t *testing.T) {
}
}

type sqlJobRow struct {
UUID string `db:"uuid"`
GHEDomain sql.NullString `db:"ghe_domain"`
Repository string `db:"repository"`
CheckEventJSON string `db:"check_event"`
TargetID string `db:"target_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}

func (r sqlJobRow) job() (*datastore.Job, error) {
u, err := uuid.Parse(r.UUID)
if err != nil {
return nil, err
}
tid, err := uuid.Parse(r.TargetID)
if err != nil {
return nil, err
}
return &datastore.Job{
UUID: u,
GHEDomain: r.GHEDomain,
Repository: r.Repository,
CheckEventJSON: r.CheckEventJSON,
TargetID: tid,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
}, nil
}

func getJobFromSQL(testDB *sqlx.DB, id uuid.UUID) (*datastore.Job, error) {
var row sqlJobRow
var j datastore.Job
query := `SELECT uuid, ghe_domain, repository, check_event, target_id FROM jobs WHERE uuid = ?`
stmt, err := testDB.Preparex(query)
if err != nil {
return nil, fmt.Errorf("failed to prepare: %w", err)
}
err = stmt.Get(&row, id.String())
err = stmt.Get(&j, id)
if err != nil {
return nil, fmt.Errorf("failed to get job: %w", err)
}
return row.job()
return &j, nil
}
85 changes: 12 additions & 73 deletions pkg/datastore/mysql/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,67 +7,10 @@ import (
"fmt"
"time"

uuid "github.com/satori/go.uuid"
"github.com/whywaita/myshoes/pkg/datastore"
"uuid"
)

// rowRunner mirrors datastore.Runner but stores the UUID columns (runner_id,
// target_id) as strings so that database/sql can scan the VARCHAR(36) columns.
// The standard library uuid.UUID is a [16]byte with no sql.Scanner.
type rowRunner struct {
UUID string `db:"runner_id"`
ShoesType string `db:"shoes_type"`
IPAddress string `db:"ip_address"`
TargetID string `db:"target_id"`
CloudID string `db:"cloud_id"`
ResourceType datastore.ResourceType `db:"resource_type"`
RunnerUser sql.NullString `db:"runner_user"`
ProviderURL sql.NullString `db:"provider_url"`
RepositoryURL string `db:"repository_url"`
RequestWebhook string `db:"request_webhook"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}

func (r rowRunner) runner() (datastore.Runner, error) {
u, err := uuid.Parse(r.UUID)
if err != nil {
return datastore.Runner{}, fmt.Errorf("failed to parse runner uuid %q: %w", r.UUID, err)
}

tid, err := uuid.Parse(r.TargetID)
if err != nil {
return datastore.Runner{}, fmt.Errorf("failed to parse target id %q: %w", r.TargetID, err)
}

return datastore.Runner{
UUID: u,
ShoesType: r.ShoesType,
IPAddress: r.IPAddress,
TargetID: tid,
CloudID: r.CloudID,
ResourceType: r.ResourceType,
RunnerUser: r.RunnerUser,
ProviderURL: r.ProviderURL,
RepositoryURL: r.RepositoryURL,
RequestWebhook: r.RequestWebhook,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
}, nil
}

func runnersFromRows(rows []rowRunner) ([]datastore.Runner, error) {
rs := make([]datastore.Runner, 0, len(rows))
for _, r := range rows {
runner, err := r.runner()
if err != nil {
return nil, err
}
rs = append(rs, runner)
}
return rs, nil
}

// CreateRunner add a runner
func (m *MySQL) CreateRunner(ctx context.Context, runner datastore.Runner) error {
tx := m.Conn.MustBegin()
Expand Down Expand Up @@ -99,10 +42,10 @@ func (m *MySQL) CreateRunner(ctx context.Context, runner datastore.Runner) error

// ListRunners get a not deleted runners
func (m *MySQL) ListRunners(ctx context.Context) ([]datastore.Runner, error) {
var rows []rowRunner
var runners []datastore.Runner
query := `SELECT runner.runner_id, detail.shoes_type, detail.ip_address, detail.target_id, detail.cloud_id, detail.created_at, detail.updated_at, detail.resource_type, detail.repository_url, detail.request_webhook, detail.runner_user, detail.provider_url
FROM runners_running AS runner JOIN runner_detail AS detail ON runner.runner_id = detail.runner_id`
err := m.Conn.SelectContext(ctx, &rows, query)
err := m.Conn.SelectContext(ctx, &runners, query)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, datastore.ErrNotFound
Expand All @@ -111,15 +54,15 @@ func (m *MySQL) ListRunners(ctx context.Context) ([]datastore.Runner, error) {
return nil, fmt.Errorf("failed to execute SELECT query: %w", err)
}

return runnersFromRows(rows)
return runners, nil
}

// ListRunnersByTargetID get a not deleted runners that has target_id
func (m *MySQL) ListRunnersByTargetID(ctx context.Context, targetID uuid.UUID) ([]datastore.Runner, error) {
var rows []rowRunner
var runners []datastore.Runner
query := `SELECT runner.runner_id, detail.shoes_type, detail.ip_address, detail.target_id, detail.cloud_id, detail.created_at, detail.updated_at, detail.resource_type, detail.repository_url, detail.request_webhook, detail.runner_user, detail.provider_url
FROM runners_running AS runner JOIN runner_detail AS detail ON runner.runner_id = detail.runner_id WHERE detail.target_id = ?`
err := m.Conn.SelectContext(ctx, &rows, query, targetID.String())
err := m.Conn.SelectContext(ctx, &runners, query, targetID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, datastore.ErrNotFound
Expand All @@ -128,15 +71,15 @@ func (m *MySQL) ListRunnersByTargetID(ctx context.Context, targetID uuid.UUID) (
return nil, fmt.Errorf("failed to execute SELECT query: %w", err)
}

return runnersFromRows(rows)
return runners, nil
}

// ListRunnersLogBySince ListRunnerLog get a runners since time
func (m *MySQL) ListRunnersLogBySince(ctx context.Context, since time.Time) ([]datastore.Runner, error) {
var rows []rowRunner
var runners []datastore.Runner

query := `SELECT runner_id, shoes_type, ip_address, target_id, cloud_id, created_at, updated_at, resource_type, repository_url, request_webhook, runner_user, provider_url FROM runner_detail WHERE created_at > ?`
err := m.Conn.SelectContext(ctx, &rows, query, since)
err := m.Conn.SelectContext(ctx, &runners, query, since)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, datastore.ErrNotFound
Expand All @@ -145,26 +88,22 @@ func (m *MySQL) ListRunnersLogBySince(ctx context.Context, since time.Time) ([]d
return nil, fmt.Errorf("failed to execute SELECT query: %w", err)
}

return runnersFromRows(rows)
return runners, nil
}

// GetRunner get a runner
func (m *MySQL) GetRunner(ctx context.Context, id uuid.UUID) (*datastore.Runner, error) {
var row rowRunner
var r datastore.Runner

query := `SELECT runner_id, shoes_type, ip_address, target_id, cloud_id, created_at, updated_at, resource_type, repository_url, request_webhook, runner_user, provider_url FROM runner_detail WHERE runner_id = ?`
if err := m.Conn.GetContext(ctx, &row, query, id.String()); err != nil {
if err := m.Conn.GetContext(ctx, &r, query, id.String()); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, datastore.ErrNotFound
}

return nil, fmt.Errorf("failed to execute SELECT query: %w", err)
}

r, err := row.runner()
if err != nil {
return nil, err
}
return &r, nil
}

Expand Down
Loading
Loading