Skip to content

Commit 8164512

Browse files
authored
Add scm support (#105)
* fix: various makefile target Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> * feat: add scm information to the api Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> * feat: add dryrun option for api access Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> * feat: all to filter pipelines reports by scm Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> * chore: updatecli open one pullrequest per dependency Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> * fix: remove deprecated goreleaser param Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> * fix: remove useless test file Signed-off-by: Olivier Vernin <olivier.vernin@suse.com> --------- Signed-off-by: Olivier Vernin <olivier.vernin@suse.com>
1 parent 9f6457d commit 8164512

14 files changed

Lines changed: 294 additions & 22 deletions

.goreleaser.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
version: 2
23
archives:
34
- name_template: >-
45
{{ .ProjectName }}_
@@ -38,7 +39,7 @@ builds:
3839

3940
changelog:
4041
## Delegate Changelog to release-drafter
41-
skip: true
42+
disable: true
4243

4344
dockers:
4445
- image_templates:

Makefile

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,25 @@ build: ## Build updatecli as a "dirty snapshot" (no tag, no release, but all OS/
2020

2121
.PHONY: build.all
2222
build.all: ## Build updatecli for "release" (tag or release and all OS/arch combinations)
23-
goreleaser --clean --skip-publish
23+
goreleaser --clean --skip=publish,sign
2424

2525
clean: ## Clean go test cache
2626
go clean -testcache
2727

2828
.PHONY: release ## Create a new updatecli release including packages
2929
release: ## release.snapshot generate a snapshot release but do not published it (no tag, but all OS/arch combinations)
30-
goreleaser --clean
30+
goreleaser --clean --timeout=2h
3131

3232
.PHONY: release.snapshot ## Create a new snapshot release without publishing assets
3333
release.snapshot: ## release.snapshot generate a snapshot release but do not published it (no tag, but all OS/arch combinations)
34-
goreleaser --snapshot --clean --skip-publish
34+
goreleaser --snapshot --clean --skip=publish,sign
3535

3636
.PHONY: db
3737
db.reset: db.delete db.start ## Reset development database
3838

3939
.PHONY: db.connect
4040
db.connect: ## Connect to development database
41-
docker exec -i -t udash-db-1 psql --username=udash --password udash
41+
docker exec -i -t --env "PGPASSWORD=password" udash-db-1 psql --username=udash udash
4242

4343
.PHONY: db.start
4444
db.start: ## Start development database
@@ -61,5 +61,3 @@ lint: ## Execute the Golang's linters on updatecli's source code
6161
test: ## Execute the Golang's tests for updatecli
6262
go test ./... -race -coverprofile=coverage.txt -covermode=atomic
6363

64-
post:
65-
curl -H "Content-Type: application/json" --data @data.json http://localhost:8080/api/pipelines

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ require (
1212
github.com/sirupsen/logrus v1.9.3
1313
github.com/spf13/cobra v1.8.0
1414
github.com/spf13/viper v1.18.2
15+
github.com/stretchr/testify v1.9.0
1516
github.com/updatecli/updatecli v0.74.0
1617
)
1718

1819
require (
1920
github.com/bytedance/sonic v1.9.1 // indirect
2021
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
22+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2123
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
2224
github.com/gin-contrib/sse v0.1.0 // indirect
2325
github.com/go-playground/locales v0.14.1 // indirect
@@ -41,6 +43,7 @@ require (
4143
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4244
github.com/modern-go/reflect2 v1.0.2 // indirect
4345
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
46+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
4447
github.com/rogpeppe/go-internal v1.10.0 // indirect
4548
github.com/sagikazarmark/locafero v0.4.0 // indirect
4649
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE IF EXISTS scms;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
BEGIN;
2+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
3+
CREATE TABLE IF NOT EXISTS scms(
4+
id uuid DEFAULT uuid_generate_v4 (),
5+
branch VARCHAR NOT NULL,
6+
url VARCHAR NOT NULL,
7+
created_at TIMESTAMP,
8+
updated_at TIMESTAMP
9+
);
10+
ALTER TABLE scms ALTER COLUMN created_at SET DEFAULT now();
11+
ALTER TABLE scms ALTER COLUMN updated_at SET DEFAULT now();
12+
COMMIT;

pkg/server/main.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,24 @@ func (s *Server) Run() {
5050

5151
switch strings.ToLower(s.Options.Auth.Mode) {
5252
case "oauth":
53+
r.GET("/api/pipeline/scms", checkJWT(), FindTargetSCM)
5354
r.GET("/api/pipeline/reports", checkJWT(), FindAllPipelineReports)
5455
r.GET("/api/pipeline/reports/:id", checkJWT(), FindPipelineReportByID)
55-
r.POST("/api/pipeline/reports", checkJWT(), CreatePipelineReport)
56-
r.PUT("/api/pipeline/reports/:id", checkJWT(), UpdatePipelineReport)
57-
r.DELETE("/api/pipeline/reports/:id", checkJWT(), DeletePipelineReport)
56+
if !s.Options.DryRun {
57+
r.POST("/api/pipeline/reports", checkJWT(), CreatePipelineReport)
58+
r.PUT("/api/pipeline/reports/:id", checkJWT(), UpdatePipelineReport)
59+
r.DELETE("/api/pipeline/reports/:id", checkJWT(), DeletePipelineReport)
60+
}
5861

5962
case "", "none":
63+
r.GET("/api/pipeline/scms", FindTargetSCM)
6064
r.GET("/api/pipeline/reports", FindAllPipelineReports)
6165
r.GET("/api/pipeline/reports/:id", FindPipelineReportByID)
62-
r.POST("/api/pipeline/reports", CreatePipelineReport)
63-
r.PUT("/api/pipeline/reports/:id", UpdatePipelineReport)
64-
r.DELETE("/api/pipeline/reports/:id", DeletePipelineReport)
66+
if !s.Options.DryRun {
67+
r.POST("/api/pipeline/reports", CreatePipelineReport)
68+
r.PUT("/api/pipeline/reports/:id", UpdatePipelineReport)
69+
r.DELETE("/api/pipeline/reports/:id", DeletePipelineReport)
70+
}
6571

6672
default:
6773
logrus.Errorf("Authentication mode %q not supported", s.Options.Auth.Mode)

pkg/server/option.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ package server
22

33
// Options holds the server options
44
type Options struct {
5-
Auth AuthOptions
5+
Auth AuthOptions
6+
DryRun bool
67
}
78

89
func (o *Options) Init() {

pkg/server/reportDBQuery.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ func dbDeleteReport(id string) error {
3636
return nil
3737
}
3838

39-
func dbSearchReport(id string) (*PipelineRow, error) {
40-
report := PipelineRow{}
39+
func dbSearchReport(id string) (*PipelineReportRow, error) {
40+
report := PipelineReportRow{}
4141

4242
err := database.DB.QueryRow(context.Background(), "select * from pipelineReports where id=$1", id).Scan(
4343
&report.ID,
@@ -69,8 +69,8 @@ func dbSearchNumberOfReportsByID(id string) (int, error) {
6969
return result, nil
7070
}
7171

72-
func dbSearchLatestReportByID(id string) (*PipelineRow, error) {
73-
report := PipelineRow{}
72+
func dbSearchLatestReportByID(id string) (*PipelineReportRow, error) {
73+
report := PipelineReportRow{}
7474

7575
err := database.DB.QueryRow(context.Background(), "select * from pipelineReports where data ->> 'ID'=$1 ORDER BY updated_at DESC FETCH FIRST 1 ROWS ONLY", id).Scan(
7676
&report.ID,
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import (
77
"github.com/updatecli/updatecli/pkg/core/reports"
88
)
99

10-
type PipelineRow struct {
10+
// PipelineReportRow represents a specific pipeline report from the database.
11+
type PipelineReportRow struct {
1112
ID uuid.UUID
1213
Pipeline reports.Report
1314
Created_at time.Time

pkg/server/reportHandler.go

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package server
22

33
import (
44
"context"
5+
"fmt"
56
"log"
67
"net/http"
78

@@ -24,9 +25,29 @@ func CreatePipelineReport(c *gin.Context) {
2425
return
2526
}
2627

28+
// Init scms table if needed
29+
for i := range p.Targets {
30+
branch := p.Targets[i].Scm.Branch.Target
31+
url := p.Targets[i].Scm.URL
32+
33+
got, err := dbGetScm("", url, branch)
34+
if err != nil {
35+
logrus.Errorf("get scm data: %s", err)
36+
continue
37+
}
38+
39+
if len(got) == 0 && url != "" && branch != "" {
40+
_, err := dbInsertSCM(url, branch)
41+
if err != nil {
42+
logrus.Errorf("insert scm data: %s", err)
43+
continue
44+
}
45+
}
46+
}
47+
2748
newReportID, err := dbInsertReport(p)
2849
if err != nil {
29-
logrus.Errorf("query failed: %s", err)
50+
logrus.Errorf("insert reports: %s", err)
3051
c.JSON(http.StatusInternalServerError, gin.H{"message": err})
3152
return
3253
}
@@ -63,7 +84,58 @@ func FindAllPipelineReports(c *gin.Context) {
6384
UpdatedAt string
6485
}
6586

66-
query := "SELECT * FROM pipelineReports ORDER BY updated_at DESC FETCH FIRST 1000 ROWS ONLY"
87+
queryParams := c.Request.URL.Query()
88+
89+
scmid := queryParams.Get("scmid")
90+
query := ""
91+
92+
switch scmid {
93+
case "":
94+
query = `
95+
SELECT id, data, created_at, updated_at
96+
FROM pipelineReports
97+
ORDER BY updated_at DESC FETCH FIRST 1000 ROWS ONLY`
98+
99+
case "none", "null", "nil":
100+
query = `
101+
SELECT DISTINCT ON (s.data ->> 'Name') s.id, s.data, s.created_at, s.updated_at
102+
FROM (
103+
SELECT *
104+
FROM pipelinereports
105+
WHERE NOT jsonb_path_exists(data::jsonb, '$.Targets[*].* ? (@.Scm.URL != "" && @.Scm.Branch.Target != "")')
106+
ORDER BY updated_at DESC
107+
) s
108+
ORDER BY s.data ->> 'Name', s.updated_at DESC FETCH FIRST 1000 ROWS ONLY;`
109+
110+
default:
111+
scm, err := dbGetScm(scmid, "", "")
112+
if err != nil {
113+
logrus.Errorf("get scm data: %s", err)
114+
return
115+
}
116+
117+
switch len(scm) {
118+
case 0:
119+
logrus.Errorf("scm data not found")
120+
121+
case 1:
122+
query = `
123+
SELECT DISTINCT ON (s.data ->> 'Name') s.id, s.data, s.created_at, s.updated_at
124+
FROM (
125+
SELECT *
126+
FROM pipelinereports
127+
WHERE jsonb_path_exists(data::jsonb, '$.Targets[*].* ? (@.Scm.URL == "%s" && @.Scm.Branch.Target == "%s")')
128+
ORDER BY updated_at DESC
129+
) s
130+
ORDER BY s.data ->> 'Name', s.updated_at DESC FETCH FIRST 1000 ROWS ONLY;
131+
`
132+
133+
query = fmt.Sprintf(query, scm[0].URL, scm[0].Branch)
134+
135+
default:
136+
logrus.Errorf("multiple scms found")
137+
}
138+
}
67139

68140
rows, err := database.DB.Query(context.Background(), query)
69141
if err != nil {
@@ -77,7 +149,7 @@ func FindAllPipelineReports(c *gin.Context) {
77149
dataset := []data{}
78150

79151
for rows.Next() {
80-
p := PipelineRow{}
152+
p := PipelineReportRow{}
81153

82154
err = rows.Scan(&p.ID, &p.Pipeline, &p.Created_at, &p.Updated_at)
83155
if err != nil {

0 commit comments

Comments
 (0)