@spinnaker/docker 2025.0.6 → 2025.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,3 +40,36 @@ export class DockerImageReader {
40
40
  .catch((): string[] => []);
41
41
  }
42
42
  }
43
+
44
+ export class DockerChartImageReader {
45
+ public static getImage(imageName: string, region: string, credentials: string): PromiseLike<IDockerImage> {
46
+ return REST('/charts')
47
+ .path(credentials, region, imageName)
48
+ .query({ provider: 'docker' })
49
+ .get()
50
+ .then((results: IDockerImage[]) => (results && results.length ? results[0] : null))
51
+ .catch((): IDockerImage => null);
52
+ }
53
+
54
+ public static findImages(params: IFindImageParams): PromiseLike<IDockerImage[]> {
55
+ return RetryService.buildRetrySequence<IDockerImage[]>(
56
+ () => REST('/charts/find').query(params).get(),
57
+ (results: IDockerImage[]) => results.length > 0,
58
+ 10,
59
+ 1000,
60
+ )
61
+ .then((results: IDockerImage[]) => results)
62
+ .catch((): IDockerImage[] => []);
63
+ }
64
+
65
+ public static findTags(params: IFindTagsParams): PromiseLike<string[]> {
66
+ return RetryService.buildRetrySequence<string[]>(
67
+ () => REST('/charts/tags').query(params).get(),
68
+ (results: string[]) => results.length > 0,
69
+ 10,
70
+ 1000,
71
+ )
72
+ .then((results: string[]) => results)
73
+ .catch((): string[] => []);
74
+ }
75
+ }
@@ -0,0 +1,39 @@
1
+ import type { FormikProps } from 'formik';
2
+ import React from 'react';
3
+
4
+ import type { IDockerTrigger } from '@spinnaker/core';
5
+ import type { IDockerChartAndTagChanges } from '../../image/DockerChartAndTagSelector';
6
+ import { DockerChartAndTagSelector } from '../../image/DockerChartAndTagSelector';
7
+
8
+ export interface IDockerTriggerConfigProps {
9
+ formik: FormikProps<IDockerTrigger>;
10
+ triggerUpdated: (trigger: IDockerTrigger) => void;
11
+ }
12
+
13
+ export function DockerHelmOciTriggerConfig(props: IDockerTriggerConfigProps) {
14
+ const { formik } = props;
15
+ const trigger = formik.values;
16
+
17
+ const dockerChanged = (changes: IDockerChartAndTagChanges) => {
18
+ // Trigger doesn't use imageId.
19
+ const { imageId, ...rest } = changes;
20
+ props.triggerUpdated(rest as IDockerTrigger);
21
+ };
22
+
23
+ return (
24
+ <div className="form-horizontal">
25
+ <DockerChartAndTagSelector
26
+ allowManualDefinition={false}
27
+ specifyTagByRegex={true}
28
+ account={trigger.account}
29
+ organization={trigger.organization}
30
+ registry={trigger.registry}
31
+ repository={trigger.repository}
32
+ tag={trigger.tag}
33
+ showRegistry={true}
34
+ onChange={dockerChanged}
35
+ showDigest={false}
36
+ />
37
+ </div>
38
+ );
39
+ }
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  import type { IDockerTrigger, IExecutionTriggerStatusComponentProps } from '@spinnaker/core';
4
4
  import { Registry } from '@spinnaker/core';
5
5
 
6
+ import { DockerHelmOciTriggerConfig } from './DockerHelmOciTriggerConfig';
6
7
  import { DockerTriggerConfig } from './DockerTriggerConfig';
7
8
  import { DockerTriggerTemplate } from './DockerTriggerTemplate';
8
9
 
@@ -42,3 +43,31 @@ Registry.pipeline.registerTrigger({
42
43
  },
43
44
  ],
44
45
  });
46
+
47
+ Registry.pipeline.registerTrigger({
48
+ label: 'Helm Docker Registry',
49
+ description: 'Executes the pipeline on an helm/image update',
50
+ key: 'helm/oci',
51
+ component: DockerHelmOciTriggerConfig,
52
+ manualExecutionComponent: DockerTriggerTemplate,
53
+ executionStatusComponent: DockerTriggerExecutionStatus,
54
+ executionTriggerLabel: () => 'Helm Docker Registry',
55
+ validators: [
56
+ {
57
+ type: 'requiredField',
58
+ fieldName: 'account',
59
+ message: '<strong>Registry</strong> is a required field for Docker Registry triggers.',
60
+ },
61
+ {
62
+ type: 'requiredField',
63
+ fieldName: 'repository',
64
+ message: '<strong>Image</strong> is a required field for Docker Registry triggers.',
65
+ },
66
+ {
67
+ type: 'serviceAccountAccess',
68
+ preventSave: true,
69
+ message: `You do not have access to the service account configured in this pipeline's Docker Registry trigger.
70
+ You will not be able to save your edits to this pipeline.`,
71
+ },
72
+ ],
73
+ });
@@ -10,6 +10,7 @@ import type { IDockerTrigger, IPipelineCommand, ITriggerTemplateComponentProps }
10
10
  import { HelpField, Spinner, TetheredSelect } from '@spinnaker/core';
11
11
 
12
12
  import type { IDockerLookupType } from '../../image';
13
+ import { DockerChartImageReader } from '../../image';
13
14
  import { DockerImageReader } from '../../image';
14
15
 
15
16
  const lookupTypeOptions = [
@@ -51,13 +52,23 @@ export class DockerTriggerTemplate extends React.Component<
51
52
 
52
53
  private handleQuery = () => {
53
54
  const trigger = this.props.command.trigger as IDockerTrigger;
54
- return observableFrom(
55
- DockerImageReader.findTags({
56
- provider: 'dockerRegistry',
57
- account: trigger.account,
58
- repository: trigger.repository,
59
- }),
60
- );
55
+ if (trigger.type === 'helm/oci') {
56
+ return observableFrom(
57
+ DockerChartImageReader.findTags({
58
+ provider: 'dockerRegistry', // Use helmOci provider for Helm OCI triggers
59
+ account: trigger.account,
60
+ repository: trigger.repository,
61
+ }),
62
+ );
63
+ } else {
64
+ return observableFrom(
65
+ DockerImageReader.findTags({
66
+ provider: 'dockerRegistry',
67
+ account: trigger.account,
68
+ repository: trigger.repository,
69
+ }),
70
+ );
71
+ }
61
72
  };
62
73
 
63
74
  private lookupTypeChanged = (o: Option<IDockerLookupType>) => {
@@ -82,10 +93,12 @@ export class DockerTriggerTemplate extends React.Component<
82
93
  } else {
83
94
  imageReference = `${imageName}:${tagOrDigest}`;
84
95
  }
96
+ // Use 'helm/image' artifact type for helm/oci triggers, otherwise use 'docker/image'
97
+ const artifactType = trigger.type === 'docker' ? 'docker/image' : 'helm/image';
85
98
 
86
99
  this.props.updateCommand('extraFields.artifacts', [
87
100
  {
88
- type: 'docker/image',
101
+ type: artifactType,
89
102
  name: imageName,
90
103
  version: tagOrDigest,
91
104
  reference: imageReference,
@@ -142,7 +155,7 @@ export class DockerTriggerTemplate extends React.Component<
142
155
  }
143
156
 
144
157
  // cancel search stream if trigger has changed to some other type
145
- if (command.trigger.type !== 'docker') {
158
+ if (command.trigger.type !== 'docker' && command.trigger.type !== 'helm/oci') {
146
159
  return;
147
160
  }
148
161