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

opendefensecloud / artifact-conduit / 30286238725

27 Jul 2026 04:46PM UTC coverage: 84.322% (-0.4%) from 84.746%
30286238725

push

github

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

This PR contains the following updates:

| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| amazon/aws-cli |  | minor | `2.35.15` → `2.36.7` | `2.36.8` |
|
[cert-manager/cert-manager](https://redirect.github.com/cert-manager/cert-manager)
| | minor | `v1.20.3` → `v1.21.0` | |
|
[github/codeql-action](https://redirect.github.com/github/codeql-action)
| action | minor | `v4.36.3` → `v4.37.3` | |
|
[hairyhenderson/gomplate](https://redirect.github.com/hairyhenderson/gomplate)
| | minor | `v5.1.0-alpine` → `v5.2.0-alpine` | |
|
[open-component-model/ocm](https://redirect.github.com/open-component-model/ocm)
| | minor | `0.45.0` → `0.46.0` | |

---

### Release Notes

<details>
<summary>cert-manager/cert-manager (cert-manager/cert-manager)</summary>

###
[`v1.21.0`](https://redirect.github.com/cert-manager/cert-manager/releases/tag/v1.21.0)

[Compare
Source](https://redirect.github.com/cert-manager/cert-manager/compare/v1.20.3...v1.21.0)

cert-manager is the easiest way to automatically manage certificates in
Kubernetes and OpenShift clusters.

cert-manager 1.21 brings ACME Renewal Information (ARI) support, AWS IAM
authentication for the Vault issuer, several security hardening changes,
and continued improvements to Gateway API integration and cainjector.
There are three breaking changes related to Helm chart RBAC and metrics
values — review them carefully before upgrading.

#### Known Issues

- **Log spam for non-cert-manager-labelled Secret events**: the typed
predicates refactoring
([#&#8203;8407](https://redirect.github.com/cert-manager/cert-manager/issues/8407))
causes `filteredEventHandler` type assertion failures (`"OnAdd missing
Object"`, `"OnUpdate missing ObjectOld"`, `"OnDelete missing Object"`)
for every non-cert-manager-labelled Secret event, multiplied by 7
certificate sub-controllers. **This is cosmetic only** — the affected
controllers only need events from cert-manager-l... (continued)

796 of 944 relevant lines covered (84.32%)

1150.72 hits per line

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

83.26
/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,956✔
35
        return &SingleWorkflowHandler{r, log, aw}
2,956✔
36
}
2,956✔
37

38
func (h *SingleWorkflowHandler) DeleteArgoResources(ctx context.Context) error {
8✔
39
        wf := wfv1alpha1.Workflow{
8✔
40
                ObjectMeta: metav1.ObjectMeta{
8✔
41
                        Namespace: h.aw.Namespace,
8✔
42
                        Name:      h.aw.Name,
8✔
43
                },
8✔
44
        }
8✔
45
        if err := h.Delete(ctx, &wf); client.IgnoreNotFound(err) != nil {
8✔
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))
8✔
50

8✔
51
        return nil
8✔
52
}
53

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

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

1,568✔
62
        if err := controllerutil.SetControllerReference(h.aw, wf, h.Scheme); err != nil {
1,568✔
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,791✔
67
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "CreationFailed", "Create", fmt.Sprintf("Failed to create workflow '%s': %v", wf.GetName(), err))
223✔
68
                return errLogAndWrap(h.log, err, "failed to create argo workflow")
223✔
69
        }
223✔
70
        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Created", "Create", fmt.Sprintf("Created workflow '%s'", wf.GetName()))
1,345✔
71

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

77
        return nil
1,341✔
78
}
79

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

86
        updated := h.setStatusFromWorkflow(ctx, h.log, h.aw, &wf)
1,345✔
87

1,345✔
88
        if wf.Status.Phase == wfv1alpha1.WorkflowSucceeded && h.aw.Status.Succeeded != 1 {
1,349✔
89
                h.aw.Status.Succeeded = 1
4✔
90
                updated = true
4✔
91
        }
4✔
92

93
        failed := wf.Status.Phase == wfv1alpha1.WorkflowError ||
1,345✔
94
                wf.Status.Phase == wfv1alpha1.WorkflowFailed
1,345✔
95

1,345✔
96
        if failed && h.aw.Status.Failed != 1 {
1,348✔
97
                h.aw.Status.Failed = 1
3✔
98
                updated = true
3✔
99
        }
3✔
100

101
        if !updated {
1,348✔
102
                return nil
3✔
103
        }
3✔
104

105
        if err := h.Status().Update(ctx, h.aw); err != nil {
1,345✔
106
                return errLogAndWrap(h.log, err, "failed to update status")
3✔
107
        }
3✔
108

109
        return nil
1,339✔
110
}
111

112
var _ WorkflowHandler = &CronWorkflowHandler{}
113

114
type CronWorkflowHandler struct {
115
        *ArtifactWorkflowReconciler
116
        log logr.Logger
117
        aw  *arcv1alpha1.ArtifactWorkflow
118
}
119

120
func NewCronWorkflowHandler(r *ArtifactWorkflowReconciler, log logr.Logger, aw *arcv1alpha1.ArtifactWorkflow) *CronWorkflowHandler {
23✔
121
        return &CronWorkflowHandler{r, log, aw}
23✔
122
}
23✔
123

124
func (h *CronWorkflowHandler) DeleteArgoResources(ctx context.Context) error {
×
125
        cwf := wfv1alpha1.CronWorkflow{
×
126
                ObjectMeta: metav1.ObjectMeta{
×
127
                        Namespace: h.aw.Namespace,
×
128
                        Name:      h.aw.Name,
×
129
                },
×
130
        }
×
131
        if err := h.Delete(ctx, &cwf); client.IgnoreNotFound(err) != nil {
×
132
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "DeletionFailed", "Delete", fmt.Sprintf("Failed to delete associated cron workflow '%s': %v", h.aw.Name, err))
×
133
                return errLogAndWrap(h.log, err, "cron workflow deletion failed")
×
134
        }
×
135
        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Deleted", "Delete", fmt.Sprintf("Deleted cron workflow '%s'", h.aw.Name))
×
136

×
137
        return nil
×
138
}
139

140
func (h *CronWorkflowHandler) CreateArgoResources(ctx context.Context) error {
2✔
141
        srcSecret, dstSecret, err := h.retrieveSecrets(ctx, h.aw)
2✔
142
        if err != nil {
2✔
143
                return errLogAndWrap(h.log, err, "failed to fetch secrets for artifact workflow")
×
144
        }
×
145

146
        cwf := hydrateArgoCronWorkflow(h.aw, srcSecret, dstSecret)
2✔
147

2✔
148
        if err := controllerutil.SetControllerReference(h.aw, cwf, h.Scheme); err != nil {
2✔
149
                return errLogAndWrap(h.log, err, "failed to set controller reference")
×
150
        }
×
151

152
        if err := h.Create(ctx, cwf); err != nil {
2✔
153
                if client.IgnoreAlreadyExists(err) != nil {
×
154
                        h.Recorder.Eventf(h.aw, nil, corev1.EventTypeWarning, "CreationFailed", "Create", fmt.Sprintf("Failed to create cron workflow '%s': %v", cwf.GetName(), err))
×
155
                        return errLogAndWrap(h.log, err, "failed to create argo cron workflow")
×
156
                }
×
157
        } else {
2✔
158
                h.Recorder.Eventf(h.aw, nil, corev1.EventTypeNormal, "Created", "Create", fmt.Sprintf("Created cron workflow '%s'", cwf.GetName()))
2✔
159
        }
2✔
160

161
        h.aw.Status.Phase = arcv1alpha1.WorkflowPending
2✔
162
        if err := h.Status().Update(ctx, h.aw); err != nil {
2✔
163
                return errLogAndWrap(h.log, err, "failed to update status")
×
164
        }
×
165

166
        return nil
2✔
167
}
168

169
func (h *CronWorkflowHandler) CheckArgoResources(ctx context.Context) error {
19✔
170
        cwf := wfv1alpha1.CronWorkflow{}
19✔
171
        if err := h.Get(ctx, namespacedName(h.aw.Namespace, h.aw.Name), &cwf); err != nil {
19✔
172
                return errLogAndWrap(h.log, err, "failed to get cron workflow")
×
173
        }
×
174

175
        updated := false
19✔
176

19✔
177
        if !h.aw.Status.LastScheduled.Equal(cwf.Status.LastScheduledTime) {
21✔
178
                h.aw.Status.LastScheduled = cwf.Status.LastScheduledTime
2✔
179
                updated = true
2✔
180
        }
2✔
181
        if h.aw.Status.Failed != cwf.Status.Failed {
20✔
182
                h.aw.Status.Failed = cwf.Status.Failed
1✔
183
                updated = true
1✔
184
        }
1✔
185
        if h.aw.Status.Succeeded != cwf.Status.Succeeded {
20✔
186
                h.aw.Status.Succeeded = cwf.Status.Succeeded
1✔
187
                updated = true
1✔
188
        }
1✔
189

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

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

10✔
198
                        // Get the active workflow
10✔
199
                        wf := wfv1alpha1.Workflow{}
10✔
200
                        if err := h.Get(ctx, namespacedName(h.aw.Namespace, ref.Name), &wf); err != nil {
11✔
201
                                return errLogAndWrap(h.log, err, "failed to fetch active workflow")
1✔
202
                        }
1✔
203

204
                        h.aw.Status.ActiveWorkflowRef = corev1.LocalObjectReference{
9✔
205
                                Name: wf.Name,
9✔
206
                        }
9✔
207
                        h.aw.Status.Message = ""
9✔
208
                        h.aw.Status.Phase = arcv1alpha1.WorkflowActive
9✔
209

9✔
210
                        updated = updated || h.setStatusFromWorkflow(ctx, h.log, h.aw, &wf)
9✔
211
                }
212
        }
213

214
        // If there is an active workflow, check its status
215
        if h.aw.Status.ActiveWorkflowRef.Name != "" {
33✔
216
                wf := wfv1alpha1.Workflow{}
15✔
217
                if err := h.Get(ctx, namespacedName(h.aw.Namespace, h.aw.Status.ActiveWorkflowRef.Name), &wf); err != nil {
15✔
218
                        return errLogAndWrap(h.log, err, "failed to fetch active workflow")
×
219
                }
×
220

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

15✔
223
                if wf.Status.Phase.Completed() {
24✔
224
                        h.aw.Status.ActiveWorkflowRef.Name = ""
9✔
225
                        updated = true
9✔
226
                }
9✔
227
        }
228

229
        if !updated {
23✔
230
                return nil
5✔
231
        }
5✔
232

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

13✔
235
        if err := h.Status().Update(ctx, h.aw); err != nil {
13✔
236
                return errLogAndWrap(h.log, err, "failed to update status")
×
237
        }
×
238

239
        return nil
13✔
240
}
241

242
func hydrateArgoWorkflowSpec(aw *arcv1alpha1.ArtifactWorkflow, srcSecret *corev1.Secret, dstSecret *corev1.Secret) wfv1alpha1.WorkflowSpec {
1,570✔
243
        srcVolume := corev1.Volume{
1,570✔
244
                Name: "src-secret-vol",
1,570✔
245
                VolumeSource: corev1.VolumeSource{
1,570✔
246
                        EmptyDir: &corev1.EmptyDirVolumeSource{},
1,570✔
247
                },
1,570✔
248
        }
1,570✔
249
        if srcSecret.Name != "" {
2,570✔
250
                srcVolume.VolumeSource = corev1.VolumeSource{
1,000✔
251
                        Secret: &corev1.SecretVolumeSource{
1,000✔
252
                                SecretName: srcSecret.Name,
1,000✔
253
                        },
1,000✔
254
                }
1,000✔
255
        }
1,000✔
256

257
        dstVolume := corev1.Volume{
1,570✔
258
                Name: "dst-secret-vol",
1,570✔
259
                VolumeSource: corev1.VolumeSource{
1,570✔
260
                        EmptyDir: &corev1.EmptyDirVolumeSource{},
1,570✔
261
                },
1,570✔
262
        }
1,570✔
263
        if dstSecret.Name != "" {
2,570✔
264
                dstVolume.VolumeSource = corev1.VolumeSource{
1,000✔
265
                        Secret: &corev1.SecretVolumeSource{
1,000✔
266
                                SecretName: dstSecret.Name,
1,000✔
267
                        },
1,000✔
268
                }
1,000✔
269
        }
1,000✔
270

271
        parameters := []wfv1alpha1.Parameter{}
1,570✔
272
        for _, p := range aw.Spec.Parameters {
10,457✔
273
                parameters = append(parameters, wfv1alpha1.Parameter{
8,887✔
274
                        Name:  p.Name,
8,887✔
275
                        Value: (*wfv1alpha1.AnyString)(&p.Value),
8,887✔
276
                })
8,887✔
277
        }
8,887✔
278

279
        return wfv1alpha1.WorkflowSpec{
1,570✔
280
                WorkflowTemplateRef: &wfv1alpha1.WorkflowTemplateRef{
1,570✔
281
                        Name:         aw.Spec.WorkflowTemplateRef.Name,
1,570✔
282
                        ClusterScope: aw.Spec.WorkflowTemplateRef.ClusterScope,
1,570✔
283
                },
1,570✔
284
                Volumes: []corev1.Volume{
1,570✔
285
                        srcVolume,
1,570✔
286
                        dstVolume,
1,570✔
287
                },
1,570✔
288
                Arguments: wfv1alpha1.Arguments{
1,570✔
289
                        Parameters: parameters,
1,570✔
290
                },
1,570✔
291
        }
1,570✔
292
}
293

294
func hydrateArgoWorkflow(aw *arcv1alpha1.ArtifactWorkflow, srcSecret *corev1.Secret, dstSecret *corev1.Secret) *wfv1alpha1.Workflow {
1,568✔
295
        return &wfv1alpha1.Workflow{
1,568✔
296
                ObjectMeta: workflowObjectMeta(aw),
1,568✔
297
                Spec:       hydrateArgoWorkflowSpec(aw, srcSecret, dstSecret),
1,568✔
298
        }
1,568✔
299
}
1,568✔
300

301
func hydrateArgoCronWorkflow(aw *arcv1alpha1.ArtifactWorkflow, srcSecret *corev1.Secret, dstSecret *corev1.Secret) *wfv1alpha1.CronWorkflow {
2✔
302
        om := workflowObjectMeta(aw)
2✔
303
        wf := &wfv1alpha1.CronWorkflow{
2✔
304
                ObjectMeta: om,
2✔
305
                Spec: wfv1alpha1.CronWorkflowSpec{
2✔
306
                        WorkflowSpec:               hydrateArgoWorkflowSpec(aw, srcSecret, dstSecret),
2✔
307
                        Schedules:                  aw.Spec.Cron.Schedules,
2✔
308
                        ConcurrencyPolicy:          wfv1alpha1.ReplaceConcurrent,
2✔
309
                        StartingDeadlineSeconds:    aw.Spec.Cron.StartingDeadlineSeconds,
2✔
310
                        Timezone:                   aw.Spec.Cron.Timezone,
2✔
311
                        When:                       aw.Spec.Cron.When,
2✔
312
                        SuccessfulJobsHistoryLimit: new(int32(1)),
2✔
313
                        FailedJobsHistoryLimit:     new(int32(1)),
2✔
314
                        WorkflowMetadata:           &om,
2✔
315
                },
2✔
316
        }
2✔
317

2✔
318
        return wf
2✔
319
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc