• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mindersec / minder / 12253366916

10 Dec 2024 09:40AM UTC coverage: 55.353% (-0.006%) from 55.359%
12253366916

Pull #5170

github

web-flow
Merge c245322aa into 4e29d370e
Pull Request #5170: Allow `git` ingester to work on Pull Requests as well

2 of 4 new or added lines in 1 file covered. (50.0%)

2 existing lines in 1 file now uncovered.

16678 of 30130 relevant lines covered (55.35%)

38.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.46
/internal/engine/ingester/git/git.go
1
// SPDX-FileCopyrightText: Copyright 2023 The Minder Authors
2
// SPDX-License-Identifier: Apache-2.0
3

4
// Package git provides the git rule data ingest engine
5
package git
6

7
import (
8
        "context"
9
        "errors"
10
        "fmt"
11

12
        "github.com/go-viper/mapstructure/v2"
13
        "google.golang.org/protobuf/reflect/protoreflect"
14

15
        engerrors "github.com/mindersec/minder/internal/engine/errors"
16
        pbinternal "github.com/mindersec/minder/internal/proto"
17
        pb "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
18
        "github.com/mindersec/minder/pkg/engine/v1/interfaces"
19
        "github.com/mindersec/minder/pkg/entities/v1/checkpoints"
20
        provifv1 "github.com/mindersec/minder/pkg/providers/v1"
21
)
22

23
const (
24
        // GitRuleDataIngestType is the type of the git rule data ingest engine
25
        GitRuleDataIngestType = "git"
26
        defaultBranch         = "main"
27
)
28

29
// Git is the engine for a rule type that uses git data ingest
30
type Git struct {
31
        cfg     *pb.GitType
32
        gitprov provifv1.Git
33
}
34

35
// NewGitIngester creates a new git rule data ingest engine
36
func NewGitIngester(cfg *pb.GitType, gitprov provifv1.Git) (*Git, error) {
14✔
37
        if gitprov == nil {
14✔
38
                return nil, fmt.Errorf("provider is nil")
×
39
        }
×
40

41
        if cfg == nil {
15✔
42
                cfg = &pb.GitType{}
1✔
43
        }
1✔
44

45
        return &Git{
14✔
46
                cfg:     cfg,
14✔
47
                gitprov: gitprov,
14✔
48
        }, nil
14✔
49
}
50

51
// GetType returns the type of the git rule data ingest engine
52
func (*Git) GetType() string {
3✔
53
        return GitRuleDataIngestType
3✔
54
}
3✔
55

56
// GetConfig returns the config for the git rule data ingest engine
57
func (gi *Git) GetConfig() protoreflect.ProtoMessage {
6✔
58
        return gi.cfg
6✔
59
}
6✔
60

61
// Ingest does the actual data ingestion for a rule type by cloning a git repo
62
func (gi *Git) Ingest(ctx context.Context, ent protoreflect.ProtoMessage, params map[string]any) (*interfaces.Result, error) {
9✔
63
        userCfg := &IngesterConfig{}
9✔
64
        if err := mapstructure.Decode(params, userCfg); err != nil {
9✔
65
                return nil, fmt.Errorf("failed to read git ingester configuration from params: %w", err)
×
66
        }
×
67

68
        url := getCloneUrl(ent, userCfg)
9✔
69
        if url == "" {
9✔
70
                return nil, fmt.Errorf("could not get clone url")
×
71
        }
×
72

73
        branch := gi.getBranch(ent, userCfg)
9✔
74

9✔
75
        // We clone to the memfs go-billy filesystem driver, which doesn't
9✔
76
        // allow for direct access to the underlying filesystem. This is
9✔
77
        // because we want to be able to run this in a sandboxed environment
9✔
78
        // where we don't have access to the underlying filesystem.
9✔
79
        r, err := gi.gitprov.Clone(ctx, url, branch)
9✔
80
        if err != nil {
14✔
81
                if errors.Is(err, provifv1.ErrProviderGitBranchNotFound) {
6✔
82
                        return nil, fmt.Errorf("%w: %s: branch %s", engerrors.ErrEvaluationFailed,
1✔
83
                                provifv1.ErrProviderGitBranchNotFound, branch)
1✔
84
                } else if errors.Is(err, provifv1.ErrRepositoryEmpty) {
5✔
85
                        return nil, fmt.Errorf("%w: %s", engerrors.ErrEvaluationSkipped, provifv1.ErrRepositoryEmpty)
×
86
                }
×
87
                return nil, err
4✔
88
        }
89

90
        wt, err := r.Worktree()
4✔
91
        if err != nil {
4✔
92
                return nil, fmt.Errorf("could not get worktree: %w", err)
×
93
        }
×
94

95
        head, err := r.Head()
4✔
96
        if err != nil {
4✔
97
                return nil, fmt.Errorf("could not get head: %w", err)
×
98
        }
×
99

100
        hsh := head.Hash()
4✔
101

4✔
102
        chkpoint := checkpoints.NewCheckpointV1Now().
4✔
103
                WithBranch(branch).
4✔
104
                WithCommitHash(hsh.String())
4✔
105

4✔
106
        return &interfaces.Result{
4✔
107
                Object:     nil,
4✔
108
                Fs:         wt.Filesystem,
4✔
109
                Storer:     r.Storer,
4✔
110
                Checkpoint: chkpoint,
4✔
111
        }, nil
4✔
112
}
113

114
func (gi *Git) getBranch(ent protoreflect.ProtoMessage, userCfg *IngesterConfig) string {
9✔
115
        // If the user has specified a branch, use that
9✔
116
        if userCfg.Branch != "" {
11✔
117
                return userCfg.Branch
2✔
118
        }
2✔
119

120
        // If the branch is provided in the rule-type
121
        // configuration, use that
122
        if gi.cfg.Branch != "" {
12✔
123
                return gi.cfg.Branch
5✔
124
        }
5✔
125

126
        if repo, ok := ent.(*pb.Repository); ok {
3✔
127
                if repo.GetDefaultBranch() != "" {
2✔
128
                        return repo.GetDefaultBranch()
1✔
129
                }
1✔
130
        } else if pr, ok := ent.(*pbinternal.PullRequest); ok {
1✔
NEW
131
                return pr.GetTargetRef()
×
UNCOV
132
        }
×
133

134
        // If the branch is not provided in the rule-type
135
        // configuration, use the default branch
136
        return defaultBranch
1✔
137
}
138

139
func getCloneUrl(ent protoreflect.ProtoMessage, cfg *IngesterConfig) string {
9✔
140
        if cfg.CloneURL != "" {
17✔
141
                return cfg.CloneURL
8✔
142
        }
8✔
143

144
        if repo, ok := ent.(*pb.Repository); ok {
2✔
145
                return repo.GetCloneUrl()
1✔
146
        } else if pr, ok := ent.(*pbinternal.PullRequest); ok {
1✔
NEW
147
                return pr.GetTargetCloneUrl()
×
UNCOV
148
        }
×
149

150
        return ""
×
151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc