Skip to content

Commit a06580c

Browse files
committed
feat: initial github support
1 parent d71528c commit a06580c

30 files changed

+1414
-234
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ jobs:
4646
- name: Ensure scm-engine binary work
4747
run: ./scm-engine -h
4848

49-
- name: Test scm-engine against test GitLab project
49+
- name: Test scm-engine against a GitLab project
5050
run: ./scm-engine evaluate all
5151
env:
5252
SCM_ENGINE_TOKEN: "${{ secrets.GITLAB_INTEGRATION_TEST_API_TOKEN }}"
53-
SCM_ENGINE_CONFIG_FILE: ".scm-engine.example.yml"
53+
SCM_ENGINE_CONFIG_FILE: ".scm-engine.gitlab.example.yml"
5454
GITLAB_PROJECT: "jippi/scm-engine-schema-test"
5555
GITLAB_BASEURL: https://gitlab.com/
5656

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
/scm-engine
1818
/scm-engine.exe
1919
/docs/gitlab/script-attributes.md
20+
/docs/github/script-attributes.md
File renamed without changes.

cmd/cmd_evaluate.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,26 @@ import (
55

66
"github.com/jippi/scm-engine/pkg/config"
77
"github.com/jippi/scm-engine/pkg/scm"
8-
"github.com/jippi/scm-engine/pkg/scm/gitlab"
98
"github.com/jippi/scm-engine/pkg/state"
109
"github.com/urfave/cli/v2"
1110
)
1211

1312
func Evaluate(cCtx *cli.Context) error {
1413
ctx := state.WithProjectID(cCtx.Context, cCtx.String(FlagSCMProject))
14+
ctx = state.WithBaseURL(ctx, cCtx.String(FlagSCMBaseURL))
1515
ctx = state.WithCommitSHA(ctx, cCtx.String(FlagCommitSHA))
1616
ctx = state.WithDryRun(ctx, cCtx.Bool(FlagDryRun))
17+
ctx = state.WithProvider(ctx, cCtx.String(FlagProvider))
18+
ctx = state.WithToken(ctx, cCtx.String(FlagAPIToken))
19+
ctx = state.WithToken(ctx, cCtx.String(FlagAPIToken))
1720
ctx = state.WithUpdatePipeline(ctx, cCtx.Bool(FlagUpdatePipeline))
1821

1922
cfg, err := config.LoadFile(cCtx.String(FlagConfigFile))
2023
if err != nil {
2124
return err
2225
}
2326

24-
client, err := gitlab.NewClient(cCtx.String(FlagAPIToken), cCtx.String(FlagSCMBaseURL))
27+
client, err := getClient(ctx)
2528
if err != nil {
2629
return err
2730
}

cmd/cmd_server.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"time"
1515

1616
"github.com/jippi/scm-engine/pkg/config"
17-
"github.com/jippi/scm-engine/pkg/scm/gitlab"
1817
"github.com/jippi/scm-engine/pkg/state"
1918
"github.com/urfave/cli/v2"
2019
slogctx "github.com/veqryn/slog-context"
@@ -55,15 +54,22 @@ func errHandler(ctx context.Context, w http.ResponseWriter, code int, err error)
5554
return
5655
}
5756

58-
func Server(cCtx *cli.Context) error { //nolint:unparam
59-
slogctx.Info(cCtx.Context, "Starting HTTP server", slog.String("listen", cCtx.String(FlagServerListen)))
57+
func Server(cCtx *cli.Context) error {
58+
// Initialize context
59+
ctx := state.WithDryRun(cCtx.Context, cCtx.Bool(FlagDryRun))
60+
ctx = state.WithBaseURL(ctx, cCtx.String(FlagSCMBaseURL))
61+
ctx = state.WithToken(ctx, cCtx.String(FlagAPIToken))
62+
ctx = state.WithProvider(ctx, cCtx.String(FlagProvider))
63+
ctx = state.WithUpdatePipeline(ctx, cCtx.Bool(FlagUpdatePipeline))
64+
65+
slogctx.Info(ctx, "Starting HTTP server", slog.String("listen", cCtx.String(FlagServerListen)))
6066

6167
mux := http.NewServeMux()
6268

6369
ourSecret := cCtx.String(FlagWebhookSecret)
6470

65-
// Initialize GitLab client
66-
client, err := gitlab.NewClient(cCtx.String(FlagAPIToken), cCtx.String(FlagSCMBaseURL))
71+
// Initialize client
72+
client, err := getClient(cCtx.Context)
6773
if err != nil {
6874
return err
6975
}
@@ -179,9 +185,6 @@ func Server(cCtx *cli.Context) error { //nolint:unparam
179185
ReadTimeout: 5 * time.Second,
180186
WriteTimeout: 5 * time.Second,
181187
BaseContext: func(l net.Listener) context.Context {
182-
ctx := state.WithDryRun(cCtx.Context, cCtx.Bool(FlagDryRun))
183-
ctx = state.WithUpdatePipeline(ctx, cCtx.Bool(FlagUpdatePipeline))
184-
185188
return ctx
186189
},
187190
}

cmd/conventions.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ package cmd
22

33
const (
44
FlagAPIToken = "api-token"
5+
FlagCommitSHA = "commit"
56
FlagConfigFile = "config"
67
FlagDryRun = "dry-run"
78
FlagMergeRequestID = "id"
8-
FlagUpdatePipeline = "update-pipeline"
9-
FlagCommitSHA = "commit"
9+
FlagProvider = "provider"
1010
FlagSCMBaseURL = "base-url"
1111
FlagSCMProject = "project"
1212
FlagServerListen = "listen"
13+
FlagUpdatePipeline = "update-pipeline"
1314
FlagWebhookSecret = "webhook-secret"
1415
)

cmd/shared.go

+18-3
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,29 @@ import (
88

99
"github.com/jippi/scm-engine/pkg/config"
1010
"github.com/jippi/scm-engine/pkg/scm"
11+
"github.com/jippi/scm-engine/pkg/scm/github"
12+
"github.com/jippi/scm-engine/pkg/scm/gitlab"
1113
"github.com/jippi/scm-engine/pkg/state"
1214
slogctx "github.com/veqryn/slog-context"
1315
)
1416

17+
func getClient(ctx context.Context) (scm.Client, error) {
18+
switch state.Provider(ctx) {
19+
case "github":
20+
return github.NewClient(ctx), nil
21+
22+
case "gitlab":
23+
return gitlab.NewClient(ctx)
24+
25+
default:
26+
return nil, fmt.Errorf("unknown provider %q - we only support 'github' and 'gitlab'", state.Provider(ctx))
27+
}
28+
}
29+
1530
func ProcessMR(ctx context.Context, client scm.Client, cfg *config.Config, event any) (err error) {
1631
// Stop the pipeline when we leave this func
1732
defer func() {
18-
if stopErr := client.Stop(ctx, err); err != nil {
33+
if stopErr := client.Stop(ctx, err); stopErr != nil {
1934
slogctx.Error(ctx, "Failed to update pipeline", slog.Any("error", stopErr))
2035
}
2136
}()
@@ -157,12 +172,12 @@ func syncLabels(ctx context.Context, client scm.Client, remote []*scm.Label, req
157172

158173
// Update
159174
for _, label := range required {
160-
e, ok := remoteLabels[label.Name]
175+
remote, ok := remoteLabels[label.Name]
161176
if !ok {
162177
continue
163178
}
164179

165-
if label.IsEqual(e) {
180+
if label.IsEqual(ctx, remote) {
166181
continue
167182
}
168183

docs/github/setup.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Setup
2+
3+
TODO

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/expr-lang/expr v1.16.7
1010
github.com/fatih/structtag v1.2.0
1111
github.com/golang-cz/devslog v0.0.8
12+
github.com/google/go-github/v62 v62.0.0
1213
github.com/guregu/null/v5 v5.0.0
1314
github.com/hasura/go-graphql-client v0.12.1
1415
github.com/iancoleman/strcase v0.3.0

go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4
2626
github.com/golang-cz/devslog v0.0.8 h1:53ipA2rC5JzWBWr9qB8EfenvXppenNiF/8DwgtNT5Q4=
2727
github.com/golang-cz/devslog v0.0.8/go.mod h1:bSe5bm0A7Nyfqtijf1OMNgVJHlWEuVSXnkuASiE1vV8=
2828
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
29-
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
30-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
29+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
30+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
31+
github.com/google/go-github/v62 v62.0.0 h1:/6mGCaRywZz9MuHyw9gD1CwsbmBX8GWsbFkwMmHdhl4=
32+
github.com/google/go-github/v62 v62.0.0/go.mod h1:EMxeUqGJq2xRu9DYBMwel/mr7kZrzUOfQmmpYrZn2a4=
3133
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
3234
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
3335
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=

main.go

+8
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ func main() {
5252
"SCM_ENGINE_CONFIG_FILE",
5353
},
5454
},
55+
&cli.StringFlag{
56+
Name: cmd.FlagProvider,
57+
Usage: "Provider to use - can be 'github' or 'gitlab'",
58+
Value: "gitlab",
59+
EnvVars: []string{
60+
"SCM_ENGINE_PROVIDER",
61+
},
62+
},
5563
&cli.StringFlag{
5664
Name: cmd.FlagAPIToken,
5765
Usage: "GitHub/GitLab API token",

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ nav:
1313
- install.md
1414
- ... | configuration/*.md
1515
- ... | commands/*.md
16+
- ... | github/*.md
1617
- ... | gitlab/*.md
1718

1819
plugins:

pkg/scm/github/client.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package github
2+
3+
import (
4+
"context"
5+
6+
go_github "github.com/google/go-github/v62/github"
7+
"github.com/jippi/scm-engine/pkg/scm"
8+
"github.com/jippi/scm-engine/pkg/state"
9+
)
10+
11+
// Ensure the GitLab client implements the [scm.Client]
12+
var _ scm.Client = (*Client)(nil)
13+
14+
// Client is a wrapper around the GitLab specific implementation of [scm.Client] interface
15+
type Client struct {
16+
wrapped *go_github.Client
17+
18+
labels *LabelClient
19+
mergeRequests *MergeRequestClient
20+
}
21+
22+
// NewClient creates a new GitLab client
23+
func NewClient(ctx context.Context) *Client {
24+
client := go_github.NewClient(nil).WithAuthToken(state.Token(ctx))
25+
26+
return &Client{wrapped: client}
27+
}
28+
29+
// Labels returns a client target at managing labels/tags
30+
func (client *Client) Labels() scm.LabelClient {
31+
if client.labels == nil {
32+
client.labels = NewLabelClient(client)
33+
}
34+
35+
return client.labels
36+
}
37+
38+
// MergeRequests returns a client target at managing merge/pull requests
39+
func (client *Client) MergeRequests() scm.MergeRequestClient {
40+
if client.mergeRequests == nil {
41+
client.mergeRequests = NewMergeRequestClient(client)
42+
}
43+
44+
return client.mergeRequests
45+
}
46+
47+
// EvalContext creates a new evaluation context for GitLab specific usage
48+
func (client *Client) EvalContext(ctx context.Context) (scm.EvalContext, error) {
49+
res, err := NewContext(ctx, "https://api.github.com/", state.Token(ctx))
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
return res, nil
55+
}
56+
57+
// Start pipeline
58+
func (client *Client) Start(ctx context.Context) error {
59+
return nil
60+
}
61+
62+
// Stop pipeline
63+
func (client *Client) Stop(ctx context.Context, err error) error {
64+
return nil
65+
}

0 commit comments

Comments
 (0)