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

mindersec / minder / 14315603253

07 Apr 2025 05:28PM UTC coverage: 56.758% (-0.01%) from 56.772%
14315603253

push

github

web-flow
build(deps): bump golangci/golangci-lint-action from 6.5.2 to 7.0.0 (#5548)

* build(deps): bump golangci/golangci-lint-action from 6.5.2 to 7.0.0

Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.5.2 to 7.0.0.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/55c2c1448...148140484)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Migrate to golangci-lint version 2

* Fix newly-detected golangci-lint issues

* Fix remaining lint issues from new golangci-lint

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Anderson <evan@stacklok.com>

53 of 164 new or added lines in 78 files covered. (32.32%)

2 existing lines in 1 file now uncovered.

18301 of 32244 relevant lines covered (56.76%)

36.9 hits per line

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

60.38
/internal/engine/actions/remediate/pull_request/pull_request.go
1
// SPDX-FileCopyrightText: Copyright 2023 The Minder Authors
2
// SPDX-License-Identifier: Apache-2.0
3

4
// Package pull_request provides the pull request remediation engine
5
package pull_request
6

7
import (
8
        "bytes"
9
        "context"
10
        "encoding/json"
11
        "errors"
12
        "fmt"
13
        "os"
14
        "strings"
15
        "text/template"
16
        "time"
17

18
        "github.com/go-git/go-git/v5"
19
        "github.com/go-git/go-git/v5/config"
20
        "github.com/go-git/go-git/v5/plumbing"
21
        "github.com/go-git/go-git/v5/plumbing/object"
22
        "github.com/google/go-github/v63/github"
23
        "github.com/rs/zerolog"
24
        "google.golang.org/protobuf/reflect/protoreflect"
25

26
        "github.com/mindersec/minder/internal/db"
27
        enginerr "github.com/mindersec/minder/internal/engine/errors"
28
        "github.com/mindersec/minder/internal/engine/interfaces"
29
        "github.com/mindersec/minder/internal/util"
30
        pb "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
31
        engifv1 "github.com/mindersec/minder/pkg/engine/v1/interfaces"
32
        "github.com/mindersec/minder/pkg/profiles/models"
33
        provifv1 "github.com/mindersec/minder/pkg/providers/v1"
34
)
35

36
const (
37
        // RemediateType is the type of the REST remediation engine
38
        RemediateType = "pull_request"
39
)
40

41
const (
42
        // if no Mode is specified, create a regular file with 0644 UNIX permissions
43
        ghModeNonExecFile = "100644"
44
        dflBranchBaseName = "minder"
45
        dflBranchTo       = "main"
46
)
47

48
const (
49
        prTemplateName = "prBody"
50
        prBodyTmplStr  = "{{.PrText}}"
51
)
52

53
const (
54
        // TitleMaxLength is the maximum number of bytes for the title
55
        TitleMaxLength = 256
56

57
        // BodyMaxLength is the maximum number of bytes for the body
58
        BodyMaxLength = 5120
59
)
60

61
type pullRequestMetadata struct {
62
        Number int `json:"pr_number,omitempty"`
63
}
64

65
// Remediator is the remediation engine for the Pull Request remediation type
66
type Remediator struct {
67
        ghCli      provifv1.GitHub
68
        actionType interfaces.ActionType
69
        setting    models.ActionOpt
70

71
        prCfg                *pb.RuleType_Definition_Remediate_PullRequestRemediation
72
        modificationRegistry modificationRegistry
73

74
        titleTemplate *util.SafeTemplate
75
        bodyTemplate  *util.SafeTemplate
76
}
77

78
type paramsPR struct {
79
        ingested   *engifv1.Result
80
        repo       *pb.Repository
81
        title      string
82
        modifier   fsModifier
83
        body       string
84
        metadata   *pullRequestMetadata
85
        prevStatus *db.ListRuleEvaluationsByProfileIdRow
86
}
87

88
// NewPullRequestRemediate creates a new PR remediation engine
89
func NewPullRequestRemediate(
90
        actionType interfaces.ActionType,
91
        prCfg *pb.RuleType_Definition_Remediate_PullRequestRemediation,
92
        ghCli provifv1.GitHub,
93
        setting models.ActionOpt,
94
) (*Remediator, error) {
8✔
95
        err := prCfg.Validate()
8✔
96
        if err != nil {
8✔
97
                return nil, fmt.Errorf("pull request remediation config is invalid: %w", err)
×
98
        }
×
99

100
        titleTmpl, err := util.NewSafeHTMLTemplate(&prCfg.Title, "title")
8✔
101
        if err != nil {
8✔
102
                return nil, fmt.Errorf("cannot parse title template: %w", err)
×
103
        }
×
104

105
        bodyTmpl, err := util.NewSafeHTMLTemplate(&prCfg.Body, "body")
8✔
106
        if err != nil {
8✔
107
                return nil, fmt.Errorf("cannot parse body template: %w", err)
×
108
        }
×
109

110
        modRegistry := newModificationRegistry()
8✔
111
        modRegistry.registerBuiltIn()
8✔
112

8✔
113
        return &Remediator{
8✔
114
                ghCli:                ghCli,
8✔
115
                prCfg:                prCfg,
8✔
116
                actionType:           actionType,
8✔
117
                modificationRegistry: modRegistry,
8✔
118
                setting:              setting,
8✔
119

8✔
120
                titleTemplate: titleTmpl,
8✔
121
                bodyTemplate:  bodyTmpl,
8✔
122
        }, nil
8✔
123
}
124

125
// PrTemplateParams is the parameters for the PR templates
126
type PrTemplateParams struct {
127
        // Entity is the entity to be evaluated
128
        Entity any
129
        // Profile are the parameters to be used in the template
130
        Profile map[string]any
131
        // Params are the rule instance parameters
132
        Params map[string]any
133
}
134

135
// Class returns the action type of the remediation engine
136
func (r *Remediator) Class() interfaces.ActionType {
×
137
        return r.actionType
×
138
}
×
139

140
// Type returns the action subtype of the remediation engine
NEW
141
func (*Remediator) Type() string {
×
142
        return RemediateType
×
143
}
×
144

145
// GetOnOffState returns the alert action state read from the profile
146
func (r *Remediator) GetOnOffState() models.ActionOpt {
×
147
        return models.ActionOptOrDefault(r.setting, models.ActionOptOff)
×
148
}
×
149

150
// Do perform the remediation
151
func (r *Remediator) Do(
152
        ctx context.Context,
153
        cmd interfaces.ActionCmd,
154
        ent protoreflect.ProtoMessage,
155
        params interfaces.ActionsParams,
156
        metadata *json.RawMessage,
157
) (json.RawMessage, error) {
8✔
158
        p, err := r.getParamsForPRRemediation(ctx, ent, params, metadata)
8✔
159
        if err != nil {
8✔
160
                return nil, fmt.Errorf("cannot get PR remediation params: %w", err)
×
161
        }
×
162
        var remErr error
8✔
163
        switch r.setting {
8✔
164
        case models.ActionOptOn:
8✔
165
                return r.run(ctx, cmd, p)
8✔
166
        case models.ActionOptDryRun:
×
167
                return r.dryRun(ctx, cmd, p)
×
168
        case models.ActionOptOff, models.ActionOptUnknown:
×
169
                remErr = errors.New("unexpected action")
×
170
        }
171
        return nil, remErr
×
172
}
173

174
func (r *Remediator) getParamsForPRRemediation(
175
        ctx context.Context,
176
        ent protoreflect.ProtoMessage,
177
        params interfaces.ActionsParams,
178
        metadata *json.RawMessage,
179
) (*paramsPR, error) {
8✔
180
        logger := zerolog.Ctx(ctx)
8✔
181

8✔
182
        repo, ok := ent.(*pb.Repository)
8✔
183
        if !ok {
8✔
184
                return nil, fmt.Errorf("expected repository, got %T", ent)
×
185
        }
×
186

187
        tmplParams := &PrTemplateParams{
8✔
188
                Entity:  ent,
8✔
189
                Profile: params.GetRule().Def,
8✔
190
                Params:  params.GetRule().Params,
8✔
191
        }
8✔
192

8✔
193
        ingested := params.GetIngestResult()
8✔
194
        if ingested == nil || ingested.Fs == nil || ingested.Storer == nil {
8✔
195
                return nil, errors.New("ingested filesystem is nil or no git repo was ingested")
×
196
        }
×
197

198
        title, err := r.titleTemplate.Render(ctx, tmplParams, TitleMaxLength)
8✔
199
        if err != nil {
8✔
200
                return nil, fmt.Errorf("cannot execute title template: %w", err)
×
201
        }
×
202

203
        modification, err := r.modificationRegistry.getModification(getMethod(r.prCfg), &modificationConstructorParams{
8✔
204
                prCfg: r.prCfg,
8✔
205
                ghCli: r.ghCli,
8✔
206
                bfs:   ingested.Fs,
8✔
207
                def:   params.GetRule().Def,
8✔
208
        })
8✔
209
        if err != nil {
8✔
210
                return nil, fmt.Errorf("cannot get modification: %w", err)
×
211
        }
×
212

213
        err = modification.createFsModEntries(ctx, params)
8✔
214
        if err != nil {
8✔
215
                return nil, fmt.Errorf("cannot create PR entries: %w", err)
×
216
        }
×
217

218
        prFullBodyText, err := r.getPrBodyText(ctx, tmplParams)
8✔
219
        if err != nil {
8✔
220
                return nil, fmt.Errorf("cannot create PR full body text: %w", err)
×
221
        }
×
222

223
        // Unmarshal the existing remediation metadata, if any
224
        meta := &pullRequestMetadata{}
8✔
225
        if metadata != nil {
8✔
226
                err := json.Unmarshal(*metadata, meta)
×
227
                if err != nil {
×
228
                        // There's nothing saved apparently, so no need to fail here, but do log the error
×
229
                        logger.Debug().Msgf("error unmarshalling remediation metadata: %v", err)
×
230
                }
×
231
        }
232
        return &paramsPR{
8✔
233
                ingested:   ingested,
8✔
234
                repo:       repo,
8✔
235
                title:      title,
8✔
236
                modifier:   modification,
8✔
237
                body:       prFullBodyText,
8✔
238
                metadata:   meta,
8✔
239
                prevStatus: params.GetEvalStatusFromDb(),
8✔
240
        }, nil
8✔
241
}
242

243
func (r *Remediator) dryRun(
244
        ctx context.Context,
245
        cmd interfaces.ActionCmd,
246
        p *paramsPR,
247
) (json.RawMessage, error) {
×
248
        logger := zerolog.Ctx(ctx).Info().Str("repo", p.repo.String())
×
249
        // Process the command
×
250
        switch cmd {
×
251
        case interfaces.ActionCmdOn:
×
252
                // TODO: jsonize too
×
253
                logger.Msgf("title:\n%s\n", p.title)
×
254
                logger.Msgf("body:\n%s\n", p.body)
×
255

×
256
                err := p.modifier.writeSummary(os.Stdout)
×
257
                if err != nil {
×
258
                        logger.Msgf("cannot write summary: %s\n", err)
×
259
                }
×
260
                return nil, nil
×
261
        case interfaces.ActionCmdOff:
×
262
                if p.metadata == nil || p.metadata.Number == 0 {
×
263
                        // We cannot do anything without a PR number, so we assume that closing this is a success
×
264
                        return nil, fmt.Errorf("no pull request number provided: %w", enginerr.ErrActionSkipped)
×
265
                }
×
266
                endpoint := fmt.Sprintf("repos/%v/%v/pulls/%d", p.repo.GetOwner(), p.repo.GetName(), p.metadata.Number)
×
267
                body := "{\"state\": \"closed\"}"
×
268
                curlCmd, err := util.GenerateCurlCommand(ctx, "PATCH", r.ghCli.GetBaseURL(), endpoint, body)
×
269
                if err != nil {
×
270
                        return nil, fmt.Errorf("cannot generate curl command to close a pull request: %w", err)
×
271
                }
×
272
                logger.Msgf("run the following curl command: \n%s\n", curlCmd)
×
273
                return nil, nil
×
274
        case interfaces.ActionCmdDoNothing:
×
275
                return r.runDoNothing(ctx, p)
×
276
        }
277
        return nil, nil
×
278
}
279
func (r *Remediator) runOn(
280
        ctx context.Context,
281
        p *paramsPR,
282
) (json.RawMessage, error) {
8✔
283
        logger := zerolog.Ctx(ctx).With().Str("repo", p.repo.String()).Logger()
8✔
284
        repo, err := git.Open(p.ingested.Storer, p.ingested.Fs)
8✔
285
        if err != nil {
8✔
286
                return nil, fmt.Errorf("cannot open git repo: %w", err)
×
287
        }
×
288

289
        wt, err := repo.Worktree()
8✔
290
        if err != nil {
8✔
291
                return nil, fmt.Errorf("cannot get worktree: %w", err)
×
292
        }
×
293

294
        logger.Debug().Msg("Getting authenticated user details")
8✔
295
        email, err := r.ghCli.GetPrimaryEmail(ctx)
8✔
296
        if err != nil {
8✔
297
                return nil, fmt.Errorf("cannot get primary email: %w", err)
×
298
        }
×
299

300
        currentHeadReference, err := repo.Head()
8✔
301
        if err != nil {
8✔
302
                return nil, fmt.Errorf("cannot get current HEAD: %w", err)
×
303
        }
×
304
        currHeadName := currentHeadReference.Name()
8✔
305

8✔
306
        // This resets the worktree so we don't corrupt the ingest cache (at least the main/originally-fetched branch).
8✔
307
        // This also makes sure, all new remediations check out from main branch rather than prev remediation branch.
8✔
308
        defer checkoutToOriginallyFetchedBranch(&logger, wt, currHeadName)
8✔
309

8✔
310
        logger.Debug().Str("branch", branchBaseName(p.title)).Msg("Checking out branch")
8✔
311
        err = wt.Checkout(&git.CheckoutOptions{
8✔
312
                Branch: plumbing.NewBranchReferenceName(branchBaseName(p.title)),
8✔
313
                Create: true,
8✔
314
        })
8✔
315
        if err != nil {
8✔
316
                return nil, fmt.Errorf("cannot checkout branch: %w", err)
×
317
        }
×
318

319
        logger.Debug().Msg("Creating file entries")
8✔
320
        changeEntries, err := p.modifier.modifyFs()
8✔
321
        if err != nil {
8✔
322
                return nil, fmt.Errorf("cannot modifyFs: %w", err)
×
323
        }
×
324

325
        logger.Debug().Msg("Staging changes")
8✔
326
        for _, entry := range changeEntries {
20✔
327
                if _, err := wt.Add(entry.Path); err != nil {
12✔
328
                        return nil, fmt.Errorf("cannot add file %s: %w", entry.Path, err)
×
329
                }
×
330
        }
331

332
        logger.Debug().Msg("Committing changes")
8✔
333
        _, err = wt.Commit(p.title, &git.CommitOptions{
8✔
334
                Author: &object.Signature{
8✔
335
                        Name:  userNameForCommit(ctx, r.ghCli),
8✔
336
                        Email: email,
8✔
337
                        When:  time.Now(),
8✔
338
                },
8✔
339
        })
8✔
340
        if err != nil {
8✔
341
                return nil, fmt.Errorf("cannot commit: %w", err)
×
342
        }
×
343

344
        refspec := refFromBranch(branchBaseName(p.title))
8✔
345

8✔
346
        l := logger.With().Str("branchBaseName", branchBaseName(p.title)).Logger()
8✔
347

8✔
348
        // Check if a PR already exists for this branch
8✔
349
        prNumber := getPRNumberFromBranch(ctx, r.ghCli, p.repo, branchBaseName(p.title))
8✔
350

8✔
351
        // If no PR exists, push the branch and create a PR
8✔
352
        if prNumber == 0 {
15✔
353
                err = pushBranch(ctx, repo, refspec, r.ghCli)
7✔
354
                if err != nil {
7✔
355
                        return nil, fmt.Errorf("cannot push branch: %w", err)
×
356
                }
×
357

358
                pr, err := r.ghCli.CreatePullRequest(
7✔
359
                        ctx, p.repo.GetOwner(), p.repo.GetName(),
7✔
360
                        p.title, p.body,
7✔
361
                        refspec,
7✔
362
                        dflBranchTo,
7✔
363
                )
7✔
364
                if err != nil {
8✔
365
                        return nil, fmt.Errorf("cannot create pull request: %w, %w", err, enginerr.ErrActionFailed)
1✔
366
                }
1✔
367
                // Return the new PR number
368
                prNumber = pr.GetNumber()
6✔
369
                l = l.With().Str("pr_origin", "newly_created").Logger()
6✔
370
        } else {
1✔
371
                l = l.With().Str("pr_origin", "already_existed").Logger()
1✔
372
        }
1✔
373

374
        newMeta, err := json.Marshal(pullRequestMetadata{Number: prNumber})
7✔
375
        if err != nil {
7✔
376
                return nil, fmt.Errorf("error marshalling pull request remediation metadata json: %w", err)
×
377
        }
×
378
        // Success - return the new metadata for storing the pull request number
379
        l.Info().Int("pr_number", prNumber).Msg("pull request remediation completed")
7✔
380
        return newMeta, enginerr.ErrActionPending
7✔
381
}
382

383
func getPRNumberFromBranch(
384
        ctx context.Context,
385
        cli provifv1.GitHub,
386
        repo *pb.Repository,
387
        branchName string,
388
) int {
8✔
389
        opts := &github.PullRequestListOptions{
8✔
390
                // TODO: This is not working as expected, need to fix this
8✔
391
                // Head: fmt.Sprintf("%s:%s", repo.GetOwner(), branchName),
8✔
392
                State: "open",
8✔
393
        }
8✔
394
        openPrs, err := cli.ListPullRequests(ctx, repo.GetOwner(), repo.GetName(), opts)
8✔
395
        if err != nil {
8✔
396
                return 0
×
397
        }
×
398
        for _, pr := range openPrs {
9✔
399
                if pr.GetHead().GetRef() == branchName {
2✔
400
                        return pr.GetNumber()
1✔
401
                }
1✔
402
        }
403
        return 0
7✔
404
}
405

406
func (r *Remediator) runOff(
407
        ctx context.Context,
408
        p *paramsPR,
409
) (json.RawMessage, error) {
×
410
        logger := zerolog.Ctx(ctx).With().Str("repo", p.repo.String()).Logger()
×
411

×
412
        if p.metadata == nil || p.metadata.Number == 0 {
×
413
                // We cannot do anything without a PR number, so we assume that closing this is a success
×
414
                return nil, fmt.Errorf("no pull request number provided: %w", enginerr.ErrActionSkipped)
×
415
        }
×
416

417
        pr, err := r.ghCli.ClosePullRequest(ctx, p.repo.GetOwner(), p.repo.GetName(), p.metadata.Number)
×
418
        if err != nil {
×
419
                return nil, fmt.Errorf("error closing pull request %d: %w, %w", p.metadata.Number, err, enginerr.ErrActionFailed)
×
420
        }
×
421
        logger.Info().Int("pr_number", pr.GetNumber()).Msg("pull request closed")
×
422
        return nil, enginerr.ErrActionSkipped
×
423
}
424

425
func (r *Remediator) run(
426
        ctx context.Context,
427
        cmd interfaces.ActionCmd,
428
        p *paramsPR,
429
) (json.RawMessage, error) {
8✔
430
        // Process the command
8✔
431
        switch cmd {
8✔
432
        case interfaces.ActionCmdOn:
8✔
433
                return r.runOn(ctx, p)
8✔
434
        case interfaces.ActionCmdOff:
×
435
                return r.runOff(ctx, p)
×
436
        case interfaces.ActionCmdDoNothing:
×
437
                return r.runDoNothing(ctx, p)
×
438
        }
439
        return nil, enginerr.ErrActionSkipped
×
440
}
441

442
func pushBranch(ctx context.Context, repo *git.Repository, refspec string, gh provifv1.GitHub) error {
7✔
443
        var b bytes.Buffer
7✔
444
        pushOptions := &git.PushOptions{
7✔
445
                RemoteName: guessRemote(repo),
7✔
446
                Force:      true,
7✔
447
                RefSpecs: []config.RefSpec{
7✔
448
                        config.RefSpec(
7✔
449
                                fmt.Sprintf("+%s:%s", refspec, refspec),
7✔
450
                        ),
7✔
451
                },
7✔
452
                Progress: &b,
7✔
453
        }
7✔
454
        err := gh.AddAuthToPushOptions(ctx, pushOptions)
7✔
455
        if err != nil {
7✔
456
                return fmt.Errorf("cannot add auth to push options: %w", err)
×
457
        }
×
458

459
        err = repo.PushContext(ctx, pushOptions)
7✔
460
        if err != nil {
7✔
461
                return fmt.Errorf("cannot push: %w", err)
×
462
        }
×
463
        zerolog.Ctx(ctx).Debug().Msgf("Push output: %s", b.String())
7✔
464
        return nil
7✔
465
}
466

467
func guessRemote(gitRepo *git.Repository) string {
7✔
468
        remotes, err := gitRepo.Remotes()
7✔
469
        if err != nil {
7✔
470
                return ""
×
471
        }
×
472

473
        if len(remotes) == 0 {
7✔
474
                return ""
×
475
        }
×
476

477
        for _, remote := range remotes {
14✔
478
                if remote.Config().Name == "origin" {
14✔
479
                        return remote.Config().Name
7✔
480
                }
7✔
481
        }
482

483
        return remotes[0].Config().Name
×
484
}
485

486
func refFromBranch(branchFrom string) string {
16✔
487
        return fmt.Sprintf("refs/heads/%s", branchFrom)
16✔
488
}
16✔
489

490
func branchBaseName(prTitle string) string {
48✔
491
        baseName := dflBranchBaseName
48✔
492
        normalizedPrTitle := strings.ReplaceAll(strings.ToLower(prTitle), " ", "_")
48✔
493
        return fmt.Sprintf("%s_%s", baseName, normalizedPrTitle)
48✔
494
}
48✔
495

496
func userNameForCommit(ctx context.Context, gh provifv1.GitHub) string {
8✔
497
        var name string
8✔
498

8✔
499
        // we ignore errors here, as we can still create a commit without a name
8✔
500
        // and errors are checked when getting the primary email
8✔
501
        name, _ = gh.GetName(ctx)
8✔
502
        if name == "" {
8✔
503
                name, _ = gh.GetLogin(ctx)
×
504
        }
×
505
        return name
8✔
506
}
507

508
func (r *Remediator) getPrBodyText(ctx context.Context, tmplParams *PrTemplateParams) (string, error) {
8✔
509
        body := new(bytes.Buffer)
8✔
510
        if err := r.bodyTemplate.Execute(ctx, body, tmplParams, BodyMaxLength); err != nil {
8✔
511
                return "", fmt.Errorf("cannot execute body template: %w", err)
×
512
        }
×
513

514
        prFullBodyText, err := createReviewBody(body.String())
8✔
515
        if err != nil {
8✔
516
                return "", fmt.Errorf("cannot create PR full body text: %w", err)
×
517
        }
×
518

519
        return prFullBodyText, nil
8✔
520
}
521

522
func getMethod(prCfg *pb.RuleType_Definition_Remediate_PullRequestRemediation) string {
8✔
523
        if prCfg.Method == "" {
8✔
524
                return minderContentModification
×
525
        }
×
526

527
        return prCfg.Method
8✔
528
}
529

530
func createReviewBody(prText string) (string, error) {
8✔
531
        tmpl, err := template.New(prTemplateName).Option("missingkey=error").Parse(prBodyTmplStr)
8✔
532
        if err != nil {
8✔
533
                return "", err
×
534
        }
×
535

536
        data := struct {
8✔
537
                PrText string
8✔
538
        }{
8✔
539
                PrText: prText,
8✔
540
        }
8✔
541

8✔
542
        // Execute the template
8✔
543
        var buf bytes.Buffer
8✔
544
        if err := tmpl.Execute(&buf, data); err != nil {
8✔
545
                return "", err
×
546
        }
×
547

548
        return buf.String(), nil
8✔
549
}
550

551
func checkoutToOriginallyFetchedBranch(
552
        logger *zerolog.Logger,
553
        wt *git.Worktree,
554
        originallyFetchedBranch plumbing.ReferenceName,
555
) {
8✔
556
        err := wt.Checkout(&git.CheckoutOptions{
8✔
557
                Branch: originallyFetchedBranch,
8✔
558
        })
8✔
559
        if err != nil {
8✔
560
                logger.Err(err).Msg(
×
561
                        "unable to checkout to the previous head, this can corrupt the ingest cache, should not happen",
×
562
                )
×
563
        } else {
8✔
564
                logger.Info().Msg(fmt.Sprintf("checked out back to %s branch", originallyFetchedBranch))
8✔
565
        }
8✔
566
}
567

568
// runDoNothing returns the previous remediation status
NEW
569
func (*Remediator) runDoNothing(ctx context.Context, p *paramsPR) (json.RawMessage, error) {
×
570
        logger := zerolog.Ctx(ctx).With().Str("repo", p.repo.String()).Logger()
×
571

×
572
        logger.Debug().Msg("Running do nothing")
×
573

×
574
        // Return the previous remediation status.
×
575
        err := enginerr.RemediationStatusAsError(p.prevStatus)
×
576
        // If there is a valid remediation metadata, return it too
×
577
        if p.prevStatus != nil {
×
578
                return p.prevStatus.RemMetadata, err
×
579
        }
×
580
        // If there is no remediation metadata, return nil as the metadata and the error
581
        return nil, err
×
582
}
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

© 2026 Coveralls, Inc