diff --git a/app/scripts/modules/core/src/domain/IArtifact.ts b/app/scripts/modules/core/src/domain/IArtifact.ts
index 006f9c04c6e..dc4d4531f8d 100644
--- a/app/scripts/modules/core/src/domain/IArtifact.ts
+++ b/app/scripts/modules/core/src/domain/IArtifact.ts
@@ -1,4 +1,5 @@
export interface IArtifact {
+ kind: string; // json model only
type: string;
name: string;
version: string;
diff --git a/app/scripts/modules/core/src/domain/IArtifactKindConfig.ts b/app/scripts/modules/core/src/domain/IArtifactKindConfig.ts
new file mode 100644
index 00000000000..fb6149c7912
--- /dev/null
+++ b/app/scripts/modules/core/src/domain/IArtifactKindConfig.ts
@@ -0,0 +1,8 @@
+export interface IArtifactKindConfig {
+ label: string;
+ description: string;
+ key: string;
+ template: string;
+ controller: string;
+ controllerAs?: string;
+}
diff --git a/app/scripts/modules/core/src/domain/index.ts b/app/scripts/modules/core/src/domain/index.ts
index 08d2da79b47..7a03aabc314 100644
--- a/app/scripts/modules/core/src/domain/index.ts
+++ b/app/scripts/modules/core/src/domain/index.ts
@@ -1,6 +1,7 @@
export * from '../search/searchResult/model/IApplicationSearchResult';
export * from './IArtifact'
+export * from './IArtifactKindConfig'
export * from './IBuild';
export * from './IBuildDiffInfo';
diff --git a/app/scripts/modules/core/src/help/help.contents.ts b/app/scripts/modules/core/src/help/help.contents.ts
index ed499ae73ec..d48eb6fad33 100644
--- a/app/scripts/modules/core/src/help/help.contents.ts
+++ b/app/scripts/modules/core/src/help/help.contents.ts
@@ -85,10 +85,11 @@ module(HELP_CONTENTS, [])
the configuration based on the newest server group in the cluster.
If you want to start from scratch, select "None".
You can always edit the cluster configuration after you've created it.
`,
- 'pipeline.config.expectedArtifact.custom.matchArtifact': `
+ 'pipeline.config.expectedArtifact.matchArtifact': `
This specifies which fields in your incoming artifact to match against. Every field that you supply will be used to match against all incoming artifacts. If all fields specified match, the incoming artifact is bound to your pipeline context.
- For example, if you want to match against any GCS object, only supply type =gcs/object . If you also want to restrict the matches by other fields, include those as well.
`,
- 'pipeline.config.expectedArtifact.custom.ifMissing': `
+ For example, if you want to match against any GCS object, only supply type = gcs/object. If you also want to restrict the matches by other fields, include those as well.
+ Regex is accepted, so you could for example match on a filepath like so name = .*\\.yaml to match all incoming YAML files.
`,
+ 'pipeline.config.expectedArtifact.ifMissing': `
If no artifact was supplied by your trigger to match against this expected artifact, you have a few options:
1. Attempt to match against an artifact in the prior pipeline execution's context. This ensures that you will always be using the most recently supplied artifact to this pipeline, and is generally a safe choice.
@@ -96,6 +97,10 @@ module(HELP_CONTENTS, [])
3. Fail the pipeline if options 1 or 2 fail or aren't selected.
`,
+ 'pipeline.config.expectedArtifact.defaultArtifact': `
+ If your artifact either wasn't supplied from a trigger, or it wasn't found in a prior execution, the artifact specified below will end up in your pipeline's execution context.
`,
+ 'pipeline.config.expectedArtifact.gcs.name': `
+ The GCS object name, in the form 'gs://bucket/path/to/file.yml.'
`,
'loadBalancer.advancedSettings.healthTimeout': 'Configures the timeout, in seconds, for reaching the healthCheck target. Must be less than the interval.
Default: 5
',
'loadBalancer.advancedSettings.healthInterval': 'Configures the interval, in seconds, between ELB health checks. Must be greater than the timeout.
Default: 10
',
'loadBalancer.advancedSettings.healthyThreshold': 'Configures the number of healthy observations before reinstituting an instance into the ELB’s traffic rotation.
Default: 10
',
diff --git a/app/scripts/modules/core/src/pipeline/config/pipelineConfigProvider.ts b/app/scripts/modules/core/src/pipeline/config/pipelineConfigProvider.ts
index b611c09fe36..68cda4c8b22 100644
--- a/app/scripts/modules/core/src/pipeline/config/pipelineConfigProvider.ts
+++ b/app/scripts/modules/core/src/pipeline/config/pipelineConfigProvider.ts
@@ -3,9 +3,8 @@ import { cloneDeep, intersection, memoize } from 'lodash';
import { $log } from 'ngimport';
import { Application } from 'core/application/application.model';
-import { IExecution, IStage, ITriggerTypeConfig, IStageTypeConfig } from 'core/domain';
+import { IExecution, IStage, ITriggerTypeConfig, IStageTypeConfig, IArtifactKindConfig, IStageOrTriggerTypeConfig } from 'core/domain';
import { SETTINGS } from 'core/config/settings';
-import { IStageOrTriggerTypeConfig } from '@spinnaker/core';
export interface ITransformer {
transform: (application: Application, execution: IExecution) => void;
@@ -17,6 +16,7 @@ export class PipelineConfigProvider implements IServiceProvider {
private triggerTypes: ITriggerTypeConfig[] = [];
private stageTypes: IStageTypeConfig[] = [];
private transformers: ITransformer[] = [];
+ private artifactKinds: IArtifactKindConfig[] = [];
constructor() {
this.getStageConfig = memoize(this.getStageConfig.bind(this),
@@ -58,6 +58,10 @@ export class PipelineConfigProvider implements IServiceProvider {
this.normalizeStageTypes();
}
+ public registerArtifactKind(artifactKindConfig: IArtifactKindConfig): void {
+ this.artifactKinds.push(artifactKindConfig);
+ }
+
public getExecutionTransformers(): ITransformer[] {
return this.transformers;
}
@@ -70,6 +74,10 @@ export class PipelineConfigProvider implements IServiceProvider {
return cloneDeep(this.stageTypes);
}
+ public getArtifactKinds(): IArtifactKindConfig[] {
+ return cloneDeep(this.artifactKinds);
+ }
+
private getCloudProvidersForStage(type: IStageTypeConfig, allStageTypes: IStageTypeConfig[], providers: string[]): string[] {
let cloudProviders: string[] = [];
if (type.providesFor) {
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.component.ts b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.component.ts
index 337c9af2f2e..651d792d2d1 100644
--- a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.component.ts
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.component.ts
@@ -1,20 +1,88 @@
-import { IComponentController, IComponentOptions, module } from 'angular';
+import {
+ ICompileService,
+ IComponentOptions,
+ IController,
+ IControllerService,
+ IRootElementService,
+ IRootScopeService,
+ module
+} from 'angular';
+import { IArtifact, IArtifactKindConfig } from 'core/domain';
+import { PipelineConfigProvider } from 'core/pipeline';
-import { PIPELINE_CONFIG_PROVIDER } from 'core/pipeline/config/pipelineConfigProvider';
-import { IArtifact } from 'core/domain/IArtifact';
-
-class ArtifactController implements IComponentController {
+class ArtifactCtrl implements IController {
public artifact: IArtifact;
+ public options: IArtifactKindConfig[];
+ public description: string;
+
+ constructor(private pipelineConfig: PipelineConfigProvider,
+ private $controller: IControllerService,
+ private $compile: ICompileService,
+ private $element: IRootElementService,
+ private $rootScope: IRootScopeService) {
+ 'ngInject';
+ this.options = this.pipelineConfig.getArtifactKinds();
+ this.loadArtifactKind();
+ }
+
+ public loadArtifactKind(): void {
+ const kind = this.artifact.kind;
+ if (!kind) {
+ return;
+ }
+ const artifactKindConfig = this.options.filter(function(config) {
+ return config.key === kind;
+ });
+
+ if (artifactKindConfig.length) {
+ const config = artifactKindConfig[0];
+ const template: Element = config.template as any;
+ this.description = config.description;
+
+ const ctrl = config.controller;
+ const controller = this.$controller(ctrl, {artifact: this.artifact});
+ const scope = this.$rootScope.$new();
+ const controllerAs = config.controllerAs;
+ if (controllerAs) {
+ scope[config.controllerAs] = controller;
+ } else {
+ scope['ctrl'] = controller;
+ }
+
+ const templateBody = this.$compile(template)(scope) as any;
+ this.$element.find('.artifact-body').html(templateBody);
+ }
+ }
}
class ArtifactComponent implements IComponentOptions {
- public bindings = { artifact: '=' };
- public templateUrl = require('./artifact.html');
- public controller = ArtifactController;
+ public bindings: any = {artifact: '='};
+ public controller: any = ArtifactCtrl;
public controllerAs = 'ctrl';
+ public template = `
+
+
+
+`;
}
-export const ARTIFACT = 'spinnaker.core.pipeline.trigger.artifact';
-module(ARTIFACT, [
- PIPELINE_CONFIG_PROVIDER,
-]).component('artifact', new ArtifactComponent());
+export const ARTIFACT = 'spinnaker.core.pipeline.config.trigger.artifacts.artifact';
+module(ARTIFACT, [])
+ .component('artifact', new ArtifactComponent());
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.module.ts b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.module.ts
new file mode 100644
index 00000000000..e8f68488d5e
--- /dev/null
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.module.ts
@@ -0,0 +1,15 @@
+import { module } from 'angular';
+
+import { EXPECTED_ARTIFACT } from './expectedArtifact.component';
+import { CUSTOM_ARTIFACT } from './custom/custom.artifact';
+import { GCS_ARTIFACT } from './gcs/gcs.artifact';
+import { ARTIFACT } from './artifact.component';
+
+export const ARTIFACT_MODULE = 'spinnaker.core.pipeline.config.trigger.artifacts';
+
+module(ARTIFACT_MODULE, [
+ EXPECTED_ARTIFACT,
+ CUSTOM_ARTIFACT,
+ GCS_ARTIFACT,
+ ARTIFACT,
+]);
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.html b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/custom/custom.artifact.ts
similarity index 59%
rename from app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.html
rename to app/scripts/modules/core/src/pipeline/config/triggers/artifacts/custom/custom.artifact.ts
index d058393b6c2..0b728b706dc 100644
--- a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/artifact.html
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/custom/custom.artifact.ts
@@ -1,3 +1,26 @@
+import { IController, module } from 'angular';
+
+import { PIPELINE_CONFIG_PROVIDER } from 'core/pipeline/config/pipelineConfigProvider';
+import { IArtifact } from 'core/domain/IArtifact';
+import { PipelineConfigProvider } from 'core/pipeline';
+
+class CustomArtifactController implements IController {
+ constructor(public artifact: IArtifact) {
+ 'ngInject';
+ }
+}
+
+export const CUSTOM_ARTIFACT = 'spinnaker.core.pipeline.trigger.custom.artifact';
+module(CUSTOM_ARTIFACT, [
+ PIPELINE_CONFIG_PROVIDER,
+]).config((pipelineConfigProvider: PipelineConfigProvider) => {
+ pipelineConfigProvider.registerArtifactKind({
+ label: 'Custom',
+ description: 'A custom-defined artifact.',
+ key: 'custom',
+ controller: 'customArtifactCtrl',
+ controllerAs: 'ctrl',
+ template: `
@@ -44,4 +67,8 @@
class="form-control input-sm"
ng-model="ctrl.artifact.reference"/>
+
+`
+ });
+}).controller('customArtifactCtrl', CustomArtifactController);
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.component.ts b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.component.ts
index 90c7d2c7fdf..561a85f6eb0 100644
--- a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.component.ts
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.component.ts
@@ -1,8 +1,7 @@
import { equals, IComponentController, IComponentOptions, module } from 'angular';
import { PIPELINE_CONFIG_PROVIDER } from 'core/pipeline/config/pipelineConfigProvider';
-import { IExpectedArtifact } from 'core/domain/IExpectedArtifact';
-import { IPipeline } from 'core/domain/IPipeline';
+import { IExpectedArtifact, IPipeline } from 'core/domain';
class ExpectedArtifactController implements IComponentController {
public expectedArtifact: IExpectedArtifact;
@@ -25,12 +24,57 @@ class ExpectedArtifactController implements IComponentController {
class ExpectedArtifactComponent implements IComponentOptions {
public bindings = { expectedArtifact: '=', pipeline: '=' };
- public templateUrl = require('./expectedArtifact.html');
public controller = ExpectedArtifactController;
public controllerAs = 'ctrl';
+ public template = `
+
+`
}
-export const EXPECTED_ARTIFACT = 'spinnaker.core.pipeline.trigger.expected.artifact';
+export const EXPECTED_ARTIFACT = 'spinnaker.core.pipeline.trigger.artifacts.expected';
module(EXPECTED_ARTIFACT, [
PIPELINE_CONFIG_PROVIDER,
]).component('expectedArtifact', new ExpectedArtifactComponent());
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.html b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.html
deleted file mode 100644
index a1704020210..00000000000
--- a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/expectedArtifact.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/gcs/gcs.artifact.ts b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/gcs/gcs.artifact.ts
new file mode 100644
index 00000000000..922cda2520b
--- /dev/null
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/artifacts/gcs/gcs.artifact.ts
@@ -0,0 +1,42 @@
+import { IController, module } from 'angular';
+
+import { PIPELINE_CONFIG_PROVIDER } from 'core/pipeline/config/pipelineConfigProvider';
+import { IArtifact } from 'core/domain/IArtifact';
+import { PipelineConfigProvider } from 'core/pipeline';
+
+class GcsArtifactController implements IController {
+ constructor(public artifact: IArtifact) {
+ 'ngInject';
+ this.artifact.type = 'gcs/object';
+ }
+}
+
+export const GCS_ARTIFACT = 'spinnaker.core.pipeline.trigger.gcs.artifact';
+module(GCS_ARTIFACT, [
+ PIPELINE_CONFIG_PROVIDER,
+]).config((pipelineConfigProvider: PipelineConfigProvider) => {
+ pipelineConfigProvider.registerArtifactKind({
+ label: 'GCS',
+ description: 'A GCS object.',
+ key: 'gcs',
+ controller: 'gcsArtifactCtrl',
+ controllerAs: 'ctrl',
+ template: `
+
+`,
+ });
+}).controller('gcsArtifactCtrl', GcsArtifactController);
+
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/trigger.module.js b/app/scripts/modules/core/src/pipeline/config/triggers/trigger.module.js
index 2da6b1e2993..683bc92bd4b 100644
--- a/app/scripts/modules/core/src/pipeline/config/triggers/trigger.module.js
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/trigger.module.js
@@ -6,10 +6,10 @@ import { RUN_AS_USER_SELECTOR_COMPONENT } from './runAsUserSelector.component';
import { TRAVIS_TRIGGER } from './travis/travisTrigger.module';
import { GIT_TRIGGER } from './git/git.trigger';
import { PUBSUB_TRIGGER } from './pubsub/pubsub.trigger';
-import { EXPECTED_ARTIFACT } from './artifacts/expectedArtifact.component';
-import { ARTIFACT } from './artifacts/artifact.component';
+import { ARTIFACT_MODULE } from './artifacts/artifact.module';
module.exports = angular.module('spinnaker.core.pipeline.config.trigger', [
+ ARTIFACT_MODULE,
require('../stages/stage.module.js').name,
require('./cron/cronTrigger.module.js').name,
GIT_TRIGGER,
@@ -17,8 +17,6 @@ module.exports = angular.module('spinnaker.core.pipeline.config.trigger', [
TRAVIS_TRIGGER,
require('./pipeline/pipelineTrigger.module.js').name,
PUBSUB_TRIGGER,
- ARTIFACT,
- EXPECTED_ARTIFACT,
require('./trigger.directive.js').name,
require('./triggers.directive.js').name,
RUN_AS_USER_SELECTOR_COMPONENT,
diff --git a/app/scripts/modules/core/src/pipeline/config/triggers/triggers.directive.js b/app/scripts/modules/core/src/pipeline/config/triggers/triggers.directive.js
index 6cf4e848350..9dc33909a7f 100644
--- a/app/scripts/modules/core/src/pipeline/config/triggers/triggers.directive.js
+++ b/app/scripts/modules/core/src/pipeline/config/triggers/triggers.directive.js
@@ -33,8 +33,12 @@ module.exports = angular.module('spinnaker.core.pipeline.config.trigger.triggers
$scope.pipeline.triggers.push(newTrigger);
};
+ this.defaultArtifact = () => ({
+ kind: 'custom'
+ });
+
this.addArtifact = () => {
- const newArtifact = {matchArtifact: {}, usePriorExecution: false, useDefaultArtifact: false, defaultArtifact: {}};
+ const newArtifact = {matchArtifact: this.defaultArtifact(), usePriorExecution: false, useDefaultArtifact: false, defaultArtifact: this.defaultArtifact()};
if (!$scope.pipeline.expectedArtifacts) {
$scope.pipeline.expectedArtifacts = [];