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

opendefensecloud / artifact-conduit / 28542006243

01 Jul 2026 07:20PM UTC coverage: 83.728% (-0.6%) from 84.375%
28542006243

push

github

web-flow
chore(deps): update dependencies (minor) (#414)

> ℹ️ **Note**
> 
> This PR body was truncated due to platform limits.

This PR contains the following updates:

| Package | Type | Update | Change | Pending |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|---|
| amazon/aws-cli | | minor | `2.34.63` → `2.35.11` | `2.35.13` (+1) |
![age](https://developer.mend.io/api/mc/badges/age/docker/amazon%2faws-cli/2.35.11?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/amazon%2faws-cli/2.34.63/2.35.11?slim=true)
|
| [aquasec/trivy](https://www.aquasec.com/products/trivy/)
([source](https://redirect.github.com/aquasecurity/trivy)) | | minor |
`0.70.0` → `0.71.2` | `0.72.0` |
![age](https://developer.mend.io/api/mc/badges/age/docker/aquasec%2ftrivy/0.71.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/aquasec%2ftrivy/0.70.0/0.71.2?slim=true)
|
|
[cert-manager/trust-manager](https://redirect.github.com/cert-manager/trust-manager)
| | minor | `v0.22.1` → `v0.24.0` | |
![age](https://developer.mend.io/api/mc/badges/age/github-releases/cert-manager%2ftrust-manager/v0.24.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/github-releases/cert-manager%2ftrust-manager/v0.22.1/v0.24.0?slim=true)
|
| [helm](https://redirect.github.com/helm/helm) | uses-with | minor |
`v4.0.1` → `v4.2.2` | |
![age](https://developer.mend.io/api/mc/badges/age/github-releases/helm%2fhelm/v4.2.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/github-releases/helm%2fhelm/v4.0.1/v4.2.2?slim=true)
|
| [osv-scanner](https://redirect.github.com/google/osv-scanner) | |
minor | `v2.3.8` → `v2.4.0` | |
![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgoogle%2fosv-scanner%2fv2%2fcmd%2fosv-scanner/v2.4.0?slim=true)
|
![confidence](https://developer.mend.io/api/m... (continued)

777 of 928 relevant lines covered (83.73%)

1036.78 hits per line

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

82.27
/pkg/controller/workflow_handler.go
1
// Copyright 2025 BWI GmbH and Artifact Conduit contributors
2
// SPDX-License-Identifier: Apache-2.0
3

4
package controller
5

6
import (
7
        "context"
8
        "fmt"
9

10
        wfv1alpha1 "github.com/argoproj/argo-workflows/v4/pkg/apis/workflow/v1alpha1"
11
        "github.com/go-logr/logr"
12
        corev1 "k8s.io/api/core/v1"
13
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
        "sigs.k8s.io/controller-runtime/pkg/client"
15
        "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
16

17
        arcv1alpha1 "go.opendefense.cloud/arc/api/arc/v1alpha1"
18
)
19

20
type WorkflowHandler interface {
21
        DeleteArgoResources(ctx context.Context) error
22
        CreateArgoResources(ctx context.Context) error
23
        CheckArgoResources(ctx context.Context) error
24
}
25

26
var _ WorkflowHandler = &SingleWorkflowHandler{}
27

28
type SingleWorkflowHandler struct {
29
        *ArtifactWorkflowReconciler
30
        log logr.Logger
31
        aw  *arcv1alpha1.ArtifactWorkflow
32
}
33

34
func NewSingleWorkflowHandler(r *ArtifactWorkflowReconciler, log logr.Logger, aw *arcv1alpha1.ArtifactWorkflow) *SingleWorkflowHandler {
2,551✔
35
        return &SingleWorkflowHandler{r, log, aw}
2,551✔
36
}
2,551✔
37

38
func (h *SingleWorkflowHandler) DeleteArgoResources(ctx context.Context) error {
9✔
39
        wf := wfv1alpha1.Workflow{
9✔
40
                ObjectMeta: metav1.ObjectMeta{
9✔
41
                        Namespace: h.aw.Namespace,
9✔
42
                        Name:      h.aw.Name,
9✔
43
                },
9✔
44
        }
9✔
45
        if err := h.Delete(ctx, &wf); client.IgnoreNotFound(err) != nil {
9✔
46
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "DeletionFailed", "Delete", fmt.Sprintf("Failed to delete associated workflow '%s': %v", h.aw.Name, err))
×
47
                return errLogAndWrap(h.log, err, "workflow deletion failed")
×
48
        }
×
49
        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Deleted", "Delete", fmt.Sprintf("Deleted workflow '%s'", h.aw.Name))
9✔
50

9✔
51
        return nil
9✔
52
}
53

54
func (h *SingleWorkflowHandler) CreateArgoResources(ctx context.Context) error {
1,366✔
55
        srcSecret, dstSecret, err := h.retrieveSecrets(ctx, h.aw)
1,366✔
56
        if err != nil {
1,366✔
57
                return errLogAndWrap(h.log, err, "failed to fetch secrets for artifact workflow")
×
58
        }
×
59

60
        wf := hydrateArgoWorkflow(h.aw, srcSecret, dstSecret)
1,366✔
61

1,366✔
62
        if err := controllerutil.SetControllerReference(h.aw, wf, h.Scheme); err != nil {
1,366✔
63
                return errLogAndWrap(h.log, err, "failed to set controller reference")
×
64
        }
×
65

66
        if err := h.Create(ctx, wf); client.IgnoreAlreadyExists(err) != nil {
1,590✔
67
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "CreationFailed", "Create", fmt.Sprintf("Failed to create workflow '%s': %v", wf.GetName(), err))
224✔
68
                return errLogAndWrap(h.log, err, "failed to create argo workflow")
224✔
69
        }
224✔
70
        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Created", "Create", fmt.Sprintf("Created workflow '%s'", wf.GetName()))
1,142✔
71

1,142✔
72
        h.aw.Status.Phase = arcv1alpha1.WorkflowPending
1,142✔
73
        if err := h.Status().Update(ctx, h.aw); err != nil {
1,146✔
74
                return errLogAndWrap(h.log, err, "failed to update status")
4✔
75
        }
4✔
76

77
        return nil
1,138✔
78
}
79

80
func (h *SingleWorkflowHandler) CheckArgoResources(ctx context.Context) error {
1,141✔
81
        wf := wfv1alpha1.Workflow{}
1,141✔
82
        if err := h.Get(ctx, namespacedName(h.aw.Namespace, h.aw.Name), &wf); err != nil {
1,141✔
83
                return errLogAndWrap(h.log, err, "failed to get workflow")
×
84
        }
×
85

86
        if updated := h.setStatusFromWorkflow(ctx, h.log, h.aw, &wf); !updated {
1,144✔
87
                return nil // nothing updated
3✔
88
        }
3✔
89

90
        if err := h.Status().Update(ctx, h.aw); err != nil {
1,139✔
91
                return errLogAndWrap(h.log, err, "failed to update status")
1✔
92
        }
1✔
93

94
        return nil
1,137✔
95
}
96

97
var _ WorkflowHandler = &CronWorkflowHandler{}
98

99
type CronWorkflowHandler struct {
100
        *ArtifactWorkflowReconciler
101
        log logr.Logger
102
        aw  *arcv1alpha1.ArtifactWorkflow
103
}
104

105
func NewCronWorkflowHandler(r *ArtifactWorkflowReconciler, log logr.Logger, aw *arcv1alpha1.ArtifactWorkflow) *CronWorkflowHandler {
23✔
106
        return &CronWorkflowHandler{r, log, aw}
23✔
107
}
23✔
108

109
func (h *CronWorkflowHandler) DeleteArgoResources(ctx context.Context) error {
×
110
        cwf := wfv1alpha1.CronWorkflow{
×
111
                ObjectMeta: metav1.ObjectMeta{
×
112
                        Namespace: h.aw.Namespace,
×
113
                        Name:      h.aw.Name,
×
114
                },
×
115
        }
×
116
        if err := h.Delete(ctx, &cwf); client.IgnoreNotFound(err) != nil {
×
117
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "DeletionFailed", "Delete", fmt.Sprintf("Failed to delete associated cron workflow '%s': %v", h.aw.Name, err))
×
118
                return errLogAndWrap(h.log, err, "cron workflow deletion failed")
×
119
        }
×
120
        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Deleted", "Delete", fmt.Sprintf("Deleted cron workflow '%s'", h.aw.Name))
×
121

×
122
        return nil
×
123
}
124

125
func (h *CronWorkflowHandler) CreateArgoResources(ctx context.Context) error {
2✔
126
        srcSecret, dstSecret, err := h.retrieveSecrets(ctx, h.aw)
2✔
127
        if err != nil {
2✔
128
                return errLogAndWrap(h.log, err, "failed to fetch secrets for artifact workflow")
×
129
        }
×
130

131
        cwf := hydrateArgoCronWorkflow(h.aw, srcSecret, dstSecret)
2✔
132

2✔
133
        if err := controllerutil.SetControllerReference(h.aw, cwf, h.Scheme); err != nil {
2✔
134
                return errLogAndWrap(h.log, err, "failed to set controller reference")
×
135
        }
×
136

137
        if err := h.Create(ctx, cwf); err != nil {
2✔
138
                if client.IgnoreAlreadyExists(err) != nil {
×
139
                        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "CreationFailed", "Create", fmt.Sprintf("Failed to create cron workflow '%s': %v", cwf.GetName(), err))
×
140
                        return errLogAndWrap(h.log, err, "failed to create argo cron workflow")
×
141
                }
×
142
        } else {
2✔
143
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Created", "Create", fmt.Sprintf("Created cron workflow '%s'", cwf.GetName()))
2✔
144
        }
2✔
145

146
        h.aw.Status.Phase = arcv1alpha1.WorkflowPending
2✔
147
        if err := h.Status().Update(ctx, h.aw); err != nil {
2✔
148
                return errLogAndWrap(h.log, err, "failed to update status")
×
149
        }
×
150

151
        return nil
2✔
152
}
153

154
func (h *CronWorkflowHandler) CheckArgoResources(ctx context.Context) error {
19✔
155
        cwf := wfv1alpha1.CronWorkflow{}
19✔
156
        if err := h.Get(ctx, namespacedName(h.aw.Namespace, h.aw.Name), &cwf); err != nil {
19✔
157
                return errLogAndWrap(h.log, err, "failed to get cron workflow")
×
158
        }
×
159

160
        updated := false
19✔
161

19✔
162
        if !h.aw.Status.LastScheduled.Equal(cwf.Status.LastScheduledTime) {
21✔
163
                h.aw.Status.LastScheduled = cwf.Status.LastScheduledTime
2✔
164
                updated = true
2✔
165
        }
2✔
166
        if h.aw.Status.Failed != cwf.Status.Failed {
20✔
167
                h.aw.Status.Failed = cwf.Status.Failed
1✔
168
                updated = true
1✔
169
        }
1✔
170
        if h.aw.Status.Succeeded != cwf.Status.Succeeded {
20✔
171
                h.aw.Status.Succeeded = cwf.Status.Succeeded
1✔
172
                updated = true
1✔
173
        }
1✔
174

175
        // If the active workflow is not the same as the current one, update the reference
176
        if len(cwf.Status.Active) > 0 {
35✔
177
                // Should only contain a single element at most (expected to be in the same namespace!)
16✔
178
                ref := cwf.Status.Active[len(cwf.Status.Active)-1]
16✔
179

16✔
180
                if h.aw.Status.ActiveWorkflowRef.Name != ref.Name {
26✔
181
                        h.log.V(1).Info("Updating reference for cron workflow", "cronWorkflow", cwf.Name, "activeWorkflow", ref.Name)
10✔
182

10✔
183
                        // Get the active workflow
10✔
184
                        wf := wfv1alpha1.Workflow{}
10✔
185
                        if err := h.Get(ctx, namespacedName(h.aw.Namespace, ref.Name), &wf); err != nil {
11✔
186
                                return errLogAndWrap(h.log, err, "failed to fetch active workflow")
1✔
187
                        }
1✔
188

189
                        h.aw.Status.ActiveWorkflowRef = corev1.LocalObjectReference{
9✔
190
                                Name: wf.Name,
9✔
191
                        }
9✔
192
                        h.aw.Status.Message = ""
9✔
193
                        h.aw.Status.Phase = arcv1alpha1.WorkflowActive
9✔
194

9✔
195
                        updated = updated || h.setStatusFromWorkflow(ctx, h.log, h.aw, &wf)
9✔
196
                }
197
        }
198

199
        // If there is an active workflow, check its status
200
        if h.aw.Status.ActiveWorkflowRef.Name != "" {
33✔
201
                wf := wfv1alpha1.Workflow{}
15✔
202
                if err := h.Get(ctx, namespacedName(h.aw.Namespace, h.aw.Status.ActiveWorkflowRef.Name), &wf); err != nil {
15✔
203
                        return errLogAndWrap(h.log, err, "failed to fetch active workflow")
×
204
                }
×
205

206
                updated = updated || h.setStatusFromWorkflow(ctx, h.log, h.aw, &wf)
15✔
207

15✔
208
                if wf.Status.Phase.Completed() {
24✔
209
                        h.aw.Status.ActiveWorkflowRef.Name = ""
9✔
210
                        updated = true
9✔
211
                }
9✔
212
        }
213

214
        if !updated {
23✔
215
                return nil
5✔
216
        }
5✔
217

218
        h.log.V(1).Info("Updating status from active workflow", "cronWorkflow", cwf.Name)
13✔
219

13✔
220
        if err := h.Status().Update(ctx, h.aw); err != nil {
13✔
221
                return errLogAndWrap(h.log, err, "failed to update status")
×
222
        }
×
223

224
        return nil
13✔
225
}
226

227
func hydrateArgoWorkflowSpec(aw *arcv1alpha1.ArtifactWorkflow, srcSecret *corev1.Secret, dstSecret *corev1.Secret) wfv1alpha1.WorkflowSpec {
1,368✔
228
        srcVolume := corev1.Volume{
1,368✔
229
                Name: "src-secret-vol",
1,368✔
230
                VolumeSource: corev1.VolumeSource{
1,368✔
231
                        EmptyDir: &corev1.EmptyDirVolumeSource{},
1,368✔
232
                },
1,368✔
233
        }
1,368✔
234
        if srcSecret.Name != "" {
2,328✔
235
                srcVolume.VolumeSource = corev1.VolumeSource{
960✔
236
                        Secret: &corev1.SecretVolumeSource{
960✔
237
                                SecretName: srcSecret.Name,
960✔
238
                        },
960✔
239
                }
960✔
240
        }
960✔
241

242
        dstVolume := corev1.Volume{
1,368✔
243
                Name: "dst-secret-vol",
1,368✔
244
                VolumeSource: corev1.VolumeSource{
1,368✔
245
                        EmptyDir: &corev1.EmptyDirVolumeSource{},
1,368✔
246
                },
1,368✔
247
        }
1,368✔
248
        if dstSecret.Name != "" {
2,328✔
249
                dstVolume.VolumeSource = corev1.VolumeSource{
960✔
250
                        Secret: &corev1.SecretVolumeSource{
960✔
251
                                SecretName: dstSecret.Name,
960✔
252
                        },
960✔
253
                }
960✔
254
        }
960✔
255

256
        parameters := []wfv1alpha1.Parameter{}
1,368✔
257
        for _, p := range aw.Spec.Parameters {
9,463✔
258
                parameters = append(parameters, wfv1alpha1.Parameter{
8,095✔
259
                        Name:  p.Name,
8,095✔
260
                        Value: (*wfv1alpha1.AnyString)(&p.Value),
8,095✔
261
                })
8,095✔
262
        }
8,095✔
263

264
        return wfv1alpha1.WorkflowSpec{
1,368✔
265
                WorkflowTemplateRef: &wfv1alpha1.WorkflowTemplateRef{
1,368✔
266
                        Name:         aw.Spec.WorkflowTemplateRef.Name,
1,368✔
267
                        ClusterScope: aw.Spec.WorkflowTemplateRef.ClusterScope,
1,368✔
268
                },
1,368✔
269
                Volumes: []corev1.Volume{
1,368✔
270
                        srcVolume,
1,368✔
271
                        dstVolume,
1,368✔
272
                },
1,368✔
273
                Arguments: wfv1alpha1.Arguments{
1,368✔
274
                        Parameters: parameters,
1,368✔
275
                },
1,368✔
276
        }
1,368✔
277
}
278

279
func hydrateArgoWorkflow(aw *arcv1alpha1.ArtifactWorkflow, srcSecret *corev1.Secret, dstSecret *corev1.Secret) *wfv1alpha1.Workflow {
1,366✔
280
        return &wfv1alpha1.Workflow{
1,366✔
281
                ObjectMeta: workflowObjectMeta(aw),
1,366✔
282
                Spec:       hydrateArgoWorkflowSpec(aw, srcSecret, dstSecret),
1,366✔
283
        }
1,366✔
284
}
1,366✔
285

286
func hydrateArgoCronWorkflow(aw *arcv1alpha1.ArtifactWorkflow, srcSecret *corev1.Secret, dstSecret *corev1.Secret) *wfv1alpha1.CronWorkflow {
2✔
287
        om := workflowObjectMeta(aw)
2✔
288
        wf := &wfv1alpha1.CronWorkflow{
2✔
289
                ObjectMeta: om,
2✔
290
                Spec: wfv1alpha1.CronWorkflowSpec{
2✔
291
                        WorkflowSpec:               hydrateArgoWorkflowSpec(aw, srcSecret, dstSecret),
2✔
292
                        Schedules:                  aw.Spec.Cron.Schedules,
2✔
293
                        ConcurrencyPolicy:          wfv1alpha1.ReplaceConcurrent,
2✔
294
                        StartingDeadlineSeconds:    aw.Spec.Cron.StartingDeadlineSeconds,
2✔
295
                        Timezone:                   aw.Spec.Cron.Timezone,
2✔
296
                        When:                       aw.Spec.Cron.When,
2✔
297
                        SuccessfulJobsHistoryLimit: new(int32(1)),
2✔
298
                        FailedJobsHistoryLimit:     new(int32(1)),
2✔
299
                        WorkflowMetadata:           &om,
2✔
300
                },
2✔
301
        }
2✔
302

2✔
303
        return wf
2✔
304
}
2✔
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