Skip to content

Commit 99f2243

Browse files
committed
feat(codeaction): extend remy to IaC, SCA, Code findings [IDE-2052]
Remy remediation is now offered for Snyk Code (HasAIFix), Snyk Open Source (upgradable), and Snyk IaC findings. Secrets are excluded because automated secret remediation requires credential rotation outside remy's scope. IaC bypasses the IsFixable guard (which always returns false for IaC) so remy can be offered. Code and OSS retain the IsFixable check to ensure a fixability signal exists before invoking the agent. Add tests for Secrets (excluded), ProductUnknown (excluded), and IaC (offered) product filter branches.
1 parent 58ce900 commit 99f2243

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

application/codeaction/codeaction.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/snyk/snyk-ls/domain/snyk/remediation"
3535
"github.com/snyk/snyk-ls/infrastructure/featureflag"
3636
noti "github.com/snyk/snyk-ls/internal/notification"
37+
"github.com/snyk/snyk-ls/internal/product"
3738
"github.com/snyk/snyk-ls/internal/types"
3839
"github.com/snyk/snyk-ls/internal/uri"
3940
)
@@ -144,14 +145,17 @@ func (c *CodeActionsService) remediationCodeActions(issues []types.Issue, path t
144145
if findingId == "" {
145146
continue
146147
}
148+
issueProduct := issue.GetProduct()
149+
if issueProduct == product.ProductSecrets || issueProduct == product.ProductUnknown {
150+
continue
151+
}
147152
additionalData := issue.GetAdditionalData()
148-
if additionalData == nil || !additionalData.IsFixable() {
153+
if issueProduct != product.ProductInfrastructureAsCode && (additionalData == nil || !additionalData.IsFixable()) {
149154
continue
150155
}
151156
// Capture loop variables for the closure.
152157
issueFindingId := findingId
153158
issueRange := r
154-
issueProduct := issue.GetProduct()
155159
provider := c.remediationProvider
156160
deferredEdit := func() *types.WorkspaceEdit {
157161
edit, err := provider.Remediate(context.Background(), remediation.RemediationRequest{

application/codeaction/remediation_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/snyk/snyk-ls/domain/snyk/remediation"
3434
"github.com/snyk/snyk-ls/infrastructure/featureflag"
3535
"github.com/snyk/snyk-ls/internal/notification"
36+
"github.com/snyk/snyk-ls/internal/product"
3637
"github.com/snyk/snyk-ls/internal/testutil"
3738
"github.com/snyk/snyk-ls/internal/testutil/workspaceutil"
3839
"github.com/snyk/snyk-ls/internal/types"
@@ -53,6 +54,7 @@ func (f *fakeRemediationProvider) Remediate(_ context.Context, _ remediation.Rem
5354
func buildFixableIssue(findingId string) *snyk.Issue {
5455
return &snyk.Issue{
5556
FindingId: findingId,
57+
Product: product.ProductCode,
5658
AdditionalData: snyk.CodeIssueData{
5759
HasAIFix: true,
5860
},
@@ -211,3 +213,60 @@ func TestGetCodeActions_RemediationAgent_DoesNotMutateIssueCodeActions(t *testin
211213
}
212214
assert.True(t, found, "expected RemediationAgentQuickFix in returned actions")
213215
}
216+
217+
func TestGetCodeActions_RemediationAgent_SecretsIssue_NoAction(t *testing.T) {
218+
fake := &fakeRemediationProvider{edit: &types.WorkspaceEdit{}}
219+
issue := &snyk.Issue{
220+
FindingId: "finding-secret",
221+
Product: product.ProductSecrets,
222+
AdditionalData: snyk.SecretsIssueData{},
223+
}
224+
225+
service, params := setupWithIssueAndProvider(t, issue, fake)
226+
227+
actions := service.GetCodeActions(params)
228+
229+
for _, a := range actions {
230+
assert.NotEqual(t, types.RemediationAgentQuickFix, a.Kind,
231+
"Secrets product must not produce RemediationAgentQuickFix actions")
232+
}
233+
}
234+
235+
func TestGetCodeActions_RemediationAgent_UnknownProduct_NoAction(t *testing.T) {
236+
fake := &fakeRemediationProvider{edit: &types.WorkspaceEdit{}}
237+
issue := &snyk.Issue{
238+
FindingId: "finding-unknown",
239+
Product: product.ProductUnknown,
240+
AdditionalData: snyk.CodeIssueData{HasAIFix: true},
241+
}
242+
243+
service, params := setupWithIssueAndProvider(t, issue, fake)
244+
245+
actions := service.GetCodeActions(params)
246+
247+
for _, a := range actions {
248+
assert.NotEqual(t, types.RemediationAgentQuickFix, a.Kind,
249+
"unknown product must not produce RemediationAgentQuickFix actions")
250+
}
251+
}
252+
253+
func TestGetCodeActions_RemediationAgent_IaCIssue_WithFindingId_OfferedAction(t *testing.T) {
254+
fake := &fakeRemediationProvider{edit: &types.WorkspaceEdit{}}
255+
issue := &snyk.Issue{
256+
FindingId: "finding-iac",
257+
Product: product.ProductInfrastructureAsCode,
258+
AdditionalData: snyk.IaCIssueData{},
259+
}
260+
261+
service, params := setupWithIssueAndProvider(t, issue, fake)
262+
263+
actions := service.GetCodeActions(params)
264+
265+
found := false
266+
for _, a := range actions {
267+
if a.Kind == types.RemediationAgentQuickFix {
268+
found = true
269+
}
270+
}
271+
assert.True(t, found, "IaC issue with FindingId must produce RemediationAgentQuickFix action")
272+
}

0 commit comments

Comments
 (0)