diff --git a/.gcloudignore b/.gcloudignore index e69de29bb2d..56e791512dd 100644 --- a/.gcloudignore +++ b/.gcloudignore @@ -0,0 +1,6 @@ +# By default, the .git directory (along with .gitignore and everything listed +# inside of it) does not get uploaded to Google Cloud Build. But the container +# builds fail if the git directory is missing. Adding this file overrides that +# behavior, but we'll still go ahead and exclude a few large cache directories. +.gradle +node_modules diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85128546282..b7f64fe14e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,12 +8,13 @@ on: - release-* env: - NODE_VERSION: 10.15.1 + NODE_VERSION: 12.16.0 jobs: ci: + # Meta-job that depends on the other job statuses. Branch protection then checks this job status. name: Deck CI - needs: [test, build, packages] + needs: [test, build, functional-tests, packages] runs-on: ubuntu-latest steps: - run: echo test, build, packages successful diff --git a/.github/workflows/publish_amazon.yml b/.github/workflows/publish_amazon.yml index 31262678691..09e1579538b 100644 --- a/.github/workflows/publish_amazon.yml +++ b/.github/workflows/publish_amazon.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish amazon run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_appengine.yml b/.github/workflows/publish_appengine.yml index 56d5d9d3f9c..0a167b30bef 100644 --- a/.github/workflows/publish_appengine.yml +++ b/.github/workflows/publish_appengine.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish appengine run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_azure.yml b/.github/workflows/publish_azure.yml index 4190f8b430b..6f3caebd4cf 100644 --- a/.github/workflows/publish_azure.yml +++ b/.github/workflows/publish_azure.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish azure run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_cloudfoundry.yml b/.github/workflows/publish_cloudfoundry.yml index d6aa8d1b94f..ae358793cd8 100644 --- a/.github/workflows/publish_cloudfoundry.yml +++ b/.github/workflows/publish_cloudfoundry.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish cloudfoundry run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_core.yml b/.github/workflows/publish_core.yml index 0e105c9216b..b795fcdcede 100644 --- a/.github/workflows/publish_core.yml +++ b/.github/workflows/publish_core.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish core run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_docker.yml b/.github/workflows/publish_docker.yml index 51304d1e18b..d19f78cccd7 100644 --- a/.github/workflows/publish_docker.yml +++ b/.github/workflows/publish_docker.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish docker run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_ecs.yml b/.github/workflows/publish_ecs.yml index 28cc7d9c173..52df97b72ae 100644 --- a/.github/workflows/publish_ecs.yml +++ b/.github/workflows/publish_ecs.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish ecs run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_google.yml b/.github/workflows/publish_google.yml index c5e6895a231..3d69f54ba60 100644 --- a/.github/workflows/publish_google.yml +++ b/.github/workflows/publish_google.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish google run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_huaweicloud.yml b/.github/workflows/publish_huaweicloud.yml index 829bea7266c..8d92aed60a9 100644 --- a/.github/workflows/publish_huaweicloud.yml +++ b/.github/workflows/publish_huaweicloud.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish huaweicloud run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_kubernetes.yml b/.github/workflows/publish_kubernetes.yml index 8b5246be85e..6cd59dcaa28 100644 --- a/.github/workflows/publish_kubernetes.yml +++ b/.github/workflows/publish_kubernetes.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish kubernetes run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_oracle.yml b/.github/workflows/publish_oracle.yml index 68f6d537bd8..b390f2d4ce7 100644 --- a/.github/workflows/publish_oracle.yml +++ b/.github/workflows/publish_oracle.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish oracle run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/.github/workflows/publish_titus.yml b/.github/workflows/publish_titus.yml index 530807c7635..ff968926ef6 100644 --- a/.github/workflows/publish_titus.yml +++ b/.github/workflows/publish_titus.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Use Node.js 10.15.1 + - name: Use Node.js 12.16.0 uses: actions/setup-node@v1 with: - node-version: 10.15.1 + node-version: 12.16.0 - name: publish titus run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN diff --git a/app/scripts/modules/amazon/package.json b/app/scripts/modules/amazon/package.json index bb658976e4c..c1d90bf0c7c 100644 --- a/app/scripts/modules/amazon/package.json +++ b/app/scripts/modules/amazon/package.json @@ -1,6 +1,6 @@ { "name": "@spinnaker/amazon", - "version": "0.0.238", + "version": "0.0.239", "main": "lib/lib.js", "typings": "lib/index.d.ts", "scripts": { diff --git a/app/scripts/modules/core/package.json b/app/scripts/modules/core/package.json index b946a0ab76e..bc45498e176 100644 --- a/app/scripts/modules/core/package.json +++ b/app/scripts/modules/core/package.json @@ -1,6 +1,6 @@ { "name": "@spinnaker/core", - "version": "0.0.448", + "version": "0.0.450", "main": "lib/lib.js", "typings": "lib/index.d.ts", "scripts": { diff --git a/app/scripts/modules/core/src/application/applicationSearchResultType.tsx b/app/scripts/modules/core/src/application/applicationSearchResultType.tsx index c9051df0b70..d06f4c4f749 100644 --- a/app/scripts/modules/core/src/application/applicationSearchResultType.tsx +++ b/app/scripts/modules/core/src/application/applicationSearchResultType.tsx @@ -8,9 +8,9 @@ import { ISearchResult, DefaultSearchResultTab, HeaderCell, - TableBody, - TableHeader, - TableRow, + SearchTableBody, + SearchTableHeader, + SearchTableRow, ISearchColumn, ISearchResultSet, SearchResultType, @@ -49,11 +49,11 @@ class ApplicationSearchResultType extends SearchResultType ( - + - + ); public DataComponent = ({ resultSet }: { resultSet: ISearchResultSet }) => { @@ -63,15 +63,15 @@ class ApplicationSearchResultType extends SearchResultType + {results.map(item => ( - + - + ))} - + ); }; diff --git a/app/scripts/modules/core/src/ci/igor.service.ts b/app/scripts/modules/core/src/ci/igor.service.ts index b36af2cce06..f7b123ee9da 100644 --- a/app/scripts/modules/core/src/ci/igor.service.ts +++ b/app/scripts/modules/core/src/ci/igor.service.ts @@ -76,4 +76,11 @@ export class IgorService { .one('accounts') .get(); } + + public static getCodeBuildProjects(account: string): IPromise { + return API.one('codebuild') + .one('projects') + .one(account) + .get(); + } } diff --git a/app/scripts/modules/core/src/cluster/clusterSearchResultType.tsx b/app/scripts/modules/core/src/cluster/clusterSearchResultType.tsx index abbdc6c8739..5e96bb1cc90 100644 --- a/app/scripts/modules/core/src/cluster/clusterSearchResultType.tsx +++ b/app/scripts/modules/core/src/cluster/clusterSearchResultType.tsx @@ -15,9 +15,9 @@ import { DefaultSearchResultTab, SearchStatus, HeaderCell, - TableBody, - TableHeader, - TableRow, + SearchTableBody, + SearchTableHeader, + SearchTableRow, ISearchResult, SearchResultType, ISearchResultSet, @@ -45,10 +45,10 @@ class ClustersSearchResultType extends SearchResultType { public TabComponent = DefaultSearchResultTab; public HeaderComponent = () => ( - + - + ); public DataComponent = ({ resultSet }: { resultSet: ISearchResultSet }) => { @@ -57,14 +57,14 @@ class ClustersSearchResultType extends SearchResultType { const results = resultSet.results.slice().sort(itemSortFn); return ( - + {results.map(item => ( - + - + ))} - + ); }; diff --git a/app/scripts/modules/core/src/core.module.ts b/app/scripts/modules/core/src/core.module.ts index 4aea0dc4b73..3f3a34ed415 100644 --- a/app/scripts/modules/core/src/core.module.ts +++ b/app/scripts/modules/core/src/core.module.ts @@ -46,7 +46,7 @@ import { INSIGHT_MODULE } from './insight/insight.module'; import { INTERCEPTOR_MODULE } from './interceptor/interceptor.module'; import { LOAD_BALANCER_MODULE } from './loadBalancer/loadBalancer.module'; import { MANAGED_RESOURCE_CONFIG } from './application/config/managedResources/ManagedResourceConfig'; -import { MANAGED_RESOURCES_DATA_SOURCE } from './managed'; +import { MANAGED_RESOURCES_DATA_SOURCE, CORE_MANAGED_MANAGED_MODULE } from './managed'; import { FUNCTION_MODULE } from './function/function.module'; import { NETWORK_INTERCEPTOR } from './api/network.interceptor'; @@ -137,6 +137,7 @@ module(CORE_MODULE, [ FUNCTION_MODULE, MANAGED_RESOURCE_CONFIG, MANAGED_RESOURCES_DATA_SOURCE, + CORE_MANAGED_MANAGED_MODULE, CORE_MODAL_MODAL_MODULE, NETWORK_INTERCEPTOR, diff --git a/app/scripts/modules/core/src/domain/IPipeline.ts b/app/scripts/modules/core/src/domain/IPipeline.ts index c91ff78d205..d204ed3916b 100644 --- a/app/scripts/modules/core/src/domain/IPipeline.ts +++ b/app/scripts/modules/core/src/domain/IPipeline.ts @@ -33,6 +33,7 @@ export interface IPipeline { }; type?: string; updateTs?: number; + spelEvaluator?: string; } export interface IPipelineManualStartAlert { diff --git a/app/scripts/modules/core/src/instance/instanceSearchResultType.tsx b/app/scripts/modules/core/src/instance/instanceSearchResultType.tsx index 2c3780b1250..c49ef6ac20e 100644 --- a/app/scripts/modules/core/src/instance/instanceSearchResultType.tsx +++ b/app/scripts/modules/core/src/instance/instanceSearchResultType.tsx @@ -8,9 +8,9 @@ import { DefaultSearchResultTab, ISearchResult, HeaderCell, - TableBody, - TableHeader, - TableRow, + SearchTableBody, + SearchTableHeader, + SearchTableRow, ISearchColumn, SearchResultType, ISearchResultSet, @@ -45,12 +45,12 @@ class InstancesSearchResultType extends SearchResultType public TabComponent = DefaultSearchResultTab; public HeaderComponent = () => ( - + - + ); public DataComponent = ({ resultSet }: { resultSet: ISearchResultSet }) => { @@ -60,19 +60,19 @@ class InstancesSearchResultType extends SearchResultType const results = resultSet.results.slice().sort(itemSortFn); return ( - + {results .slice() .sort(itemSortFn) .map(item => ( - + - + ))} - + ); }; diff --git a/app/scripts/modules/core/src/loadBalancer/loadBalancerSearchResultType.tsx b/app/scripts/modules/core/src/loadBalancer/loadBalancerSearchResultType.tsx index 8ddeda08c60..7c920c4a627 100644 --- a/app/scripts/modules/core/src/loadBalancer/loadBalancerSearchResultType.tsx +++ b/app/scripts/modules/core/src/loadBalancer/loadBalancerSearchResultType.tsx @@ -9,9 +9,9 @@ import { DefaultSearchResultTab, ISearchResult, HeaderCell, - TableBody, - TableHeader, - TableRow, + SearchTableBody, + SearchTableHeader, + SearchTableRow, SearchResultType, ISearchResultSet, } from 'core/search'; @@ -48,12 +48,12 @@ class LoadBalancersSearchResultType extends SearchResultType ( - + - + ); public DataComponent = ({ resultSet }: { resultSet: ISearchResultSet }) => { @@ -66,19 +66,19 @@ class LoadBalancersSearchResultType extends SearchResultType + {results .slice() .sort(itemSortFn) .map(item => ( - + - + ))} - + ); }; diff --git a/app/scripts/modules/core/src/managed/Environments.tsx b/app/scripts/modules/core/src/managed/Environments.tsx new file mode 100644 index 00000000000..aa5ac682a3f --- /dev/null +++ b/app/scripts/modules/core/src/managed/Environments.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Environments() { + return
For there shall be no greater pursuit than that towards desired state.
; +} diff --git a/app/scripts/modules/core/src/managed/index.ts b/app/scripts/modules/core/src/managed/index.ts index be87e515a08..d0e33c94901 100644 --- a/app/scripts/modules/core/src/managed/index.ts +++ b/app/scripts/modules/core/src/managed/index.ts @@ -4,6 +4,7 @@ export * from './ManagedWriter'; export * from './ManagedResourceDetailsIndicator'; export * from './managedResourceDetailsIndicator.component'; export * from './ManagedResourceStatusIndicator'; +export * from './managed.module'; export * from './managed.dataSource'; export * from './managedResourceDecorators'; export * from './ManagedMenuItem'; diff --git a/app/scripts/modules/core/src/managed/managed.module.js b/app/scripts/modules/core/src/managed/managed.module.js new file mode 100644 index 00000000000..d2f4e79dad1 --- /dev/null +++ b/app/scripts/modules/core/src/managed/managed.module.js @@ -0,0 +1,8 @@ +'use strict'; + +import { module } from 'angular'; + +import { MANAGED_STATES } from './managed.states'; + +export const CORE_MANAGED_MANAGED_MODULE = 'spinnaker.managed'; +module(CORE_MANAGED_MANAGED_MODULE, [MANAGED_STATES]); diff --git a/app/scripts/modules/core/src/managed/managed.states.ts b/app/scripts/modules/core/src/managed/managed.states.ts new file mode 100644 index 00000000000..f910edec2e6 --- /dev/null +++ b/app/scripts/modules/core/src/managed/managed.states.ts @@ -0,0 +1,29 @@ +import { module } from 'angular'; + +import { INestedState } from 'core/navigation/state.provider'; +import { APPLICATION_STATE_PROVIDER, ApplicationStateProvider } from 'core/application/application.state.provider'; +import { SETTINGS } from 'core/config'; +import Environments from './Environments'; + +export const MANAGED_STATES = 'spinnaker.core.managed.states'; +module(MANAGED_STATES, [APPLICATION_STATE_PROVIDER]).config([ + 'applicationStateProvider', + (applicationStateProvider: ApplicationStateProvider) => { + if (SETTINGS.feature.managedDelivery) { + const environments: INestedState = { + name: 'environments', + url: '/environments', + views: { + insight: { component: Environments, $type: 'react' }, + }, + data: { + pageTitleSection: { + title: 'Environments', + }, + }, + children: [], + }; + applicationStateProvider.addChildState(environments); + } + }, +]); diff --git a/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildSourceList.tsx b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildSourceList.tsx new file mode 100644 index 00000000000..fa194a97b98 --- /dev/null +++ b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildSourceList.tsx @@ -0,0 +1,109 @@ +import React from 'react'; +import { Subject } from 'rxjs'; +import classNames from 'classnames'; + +import { EditAwsCodeBuildSourceModal } from './EditAwsCodeBuildSourceModal'; +import { IAwsCodeBuildSource } from './IAwsCodeBuildSource'; +import { IPipeline, IStage } from 'core/domain'; +import { ArtifactIcon } from 'core/artifact'; + +export interface IAwsCodeBuildSourceListProps { + stage: IStage; + pipeline: IPipeline; + sources: IAwsCodeBuildSource[]; + updateSources: (notifications: IAwsCodeBuildSource[]) => void; +} + +export class AwsCodeBuildSourceList extends React.Component { + private destroy$ = new Subject(); + + constructor(props: IAwsCodeBuildSourceListProps) { + super(props); + } + + public componentWillUnmount() { + this.destroy$.next(); + } + + private addSource = () => { + this.editSource(); + }; + + private editSource = (source?: IAwsCodeBuildSource, index?: number) => { + const { sources, updateSources, stage, pipeline } = this.props; + EditAwsCodeBuildSourceModal.show({ + source: source || {}, + stage, + pipeline, + }) + .then(newSource => { + const sourceCopy = sources || []; + if (!source) { + updateSources(sourceCopy.concat(newSource)); + } else { + const update = [...sourceCopy]; + update[index] = newSource; + updateSources(update); + } + }) + .catch(() => {}); + }; + + private removeSource = (index: number) => { + const sources = [...this.props.sources]; + sources.splice(index, 1); + this.props.updateSources(sources); + }; + + public render() { + const { sources } = this.props; + return ( +
+
+ + + + + + + + + + + {sources && + sources.map((source, i) => { + return ( + + + + + + + ); + })} + + + + + + +
ArtifactTypeSource VersionActions
+ + {source.sourceArtifact.artifactDisplayName} + {source.type}{source.sourceVersion} + + +
+ +
+
+
+ ); + } +} diff --git a/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildStageForm.tsx b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildStageForm.tsx index 51a6a2e0dd8..7787d8b7597 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildStageForm.tsx +++ b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/AwsCodeBuildStageForm.tsx @@ -2,8 +2,6 @@ import React from 'react'; import { get } from 'lodash'; import { - ArtifactTypePatterns, - excludeAllTypesExcept, FormikFormField, IArtifact, IExpectedArtifact, @@ -19,18 +17,13 @@ import { YamlEditor, } from 'core'; import { CheckboxInput } from 'core/presentation'; +import { EXCLUDED_ARTIFACT_TYPES, SOURCE_TYPES, IAwsCodeBuildSource } from './IAwsCodeBuildSource'; +import { AwsCodeBuildSourceList } from './AwsCodeBuildSourceList'; interface IAwsCodeBuildStageFormProps { updatePipeline: (pipeline: IPipeline) => void; } -const EXCLUDED_ARTIFACT_TYPES: RegExp[] = excludeAllTypesExcept( - ArtifactTypePatterns.S3_OBJECT, - ArtifactTypePatterns.GIT_REPO, -); - -const SOURCE_TYPES: string[] = ['BITBUCKET', 'CODECOMMIT', 'GITHUB', 'GITHUB_ENTERPRISE', 'S3']; - export function AwsCodeBuildStageForm(props: IAwsCodeBuildStageFormProps & IFormikStageConfigInjectedProps) { const stage = props.formik.values; @@ -40,18 +33,14 @@ export function AwsCodeBuildStageForm(props: IAwsCodeBuildStageFormProps & IForm [], ); - const onYamlChange = (buildspec: string, _: any): void => { - props.formik.setFieldValue('buildspec', buildspec); - }; - - const setArtifactId = (artifactId: string): void => { - props.formik.setFieldValue('source.artifactId', artifactId); - props.formik.setFieldValue('source.artifact', null); - }; + const { result: fetchProjectsResult, status: fetchProjectsStatus } = useData( + () => IgorService.getCodeBuildProjects(stage.account), + [], + [stage.account], + ); - const setArtifact = (artifact: IArtifact): void => { - props.formik.setFieldValue('source.artifact', artifact); - props.formik.setFieldValue('source.artifactId', null); + const onFieldChange = (fieldName: string, fieldValue: any): void => { + props.formik.setFieldValue(fieldName, fieldValue); }; return ( @@ -70,23 +59,29 @@ export function AwsCodeBuildStageForm(props: IAwsCodeBuildStageFormProps & IForm /> )} /> - {/* TODO: Select project from a drop-down list. Behind the scene, gate calls igor to fetch projects list */} } + input={(inputProps: IFormInputProps) => ( + + )} />

Source Configuration

( )} /> - {stage.sourceOverride === true && ( + {get(stage, 'source.sourceOverride') === true && ( )} - {stage.sourceOverride === true && ( + {get(stage, 'source.sourceOverride') === true && ( ( setArtifactId(artifact.id)} + expectedArtifactId={get(stage, 'source.sourceArtifact.artifactId')} + onArtifactEdited={(artifact: IArtifact) => { + onFieldChange('source.sourceArtifact.artifact', artifact); + onFieldChange('source.sourceArtifact.artifactId', null); + }} + onExpectedArtifactSelected={(artifact: IExpectedArtifact) => { + onFieldChange('source.sourceArtifact.artifact', null); + onFieldChange('source.sourceArtifact.artifactId', artifact.id); + }} pipeline={props.pipeline} stage={stage} /> @@ -118,15 +119,33 @@ export function AwsCodeBuildStageForm(props: IAwsCodeBuildStageFormProps & IForm } /> ( - + onFieldChange('source.buildspec', buildspec)} + /> + )} + /> + ( + onFieldChange('secondarySources', sources)} + stage={stage} + pipeline={props.pipeline} + /> )} />

Environment Configuration

diff --git a/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/EditAwsCodeBuildSourceModal.tsx b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/EditAwsCodeBuildSourceModal.tsx new file mode 100644 index 00000000000..3d5e5cf2df0 --- /dev/null +++ b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/EditAwsCodeBuildSourceModal.tsx @@ -0,0 +1,129 @@ +import React from 'react'; +import { get } from 'lodash'; + +import { Formik, FormikProps, Form } from 'formik'; +import { Modal } from 'react-bootstrap'; +import { + FormikFormField, + FormValidator, + IArtifact, + IExpectedArtifact, + IFormInputProps, + IPipeline, + IStage, + IModalComponentProps, + ReactModal, + ReactSelectInput, + SpinFormik, + StageArtifactSelector, + TextInput, +} from 'core'; +import { SubmitButton, ModalClose } from 'core/modal'; +import { EXCLUDED_ARTIFACT_TYPES, IAwsCodeBuildSource, SOURCE_TYPES } from './IAwsCodeBuildSource'; + +export interface IEditAwsCodeBuildSourceModalProps extends IModalComponentProps { + source: IAwsCodeBuildSource; + stage: IStage; + pipeline: IPipeline; +} + +export class EditAwsCodeBuildSourceModal extends React.Component { + private formikRef = React.createRef>(); + + private submit = (values: IAwsCodeBuildSource): void => { + this.props.closeModal(values); + }; + + public static show(props: any): Promise { + const modalProps = { dialogClassName: 'modal-md' }; + return ReactModal.show(EditAwsCodeBuildSourceModal, props, modalProps); + } + + private onExpectedArtifactSelected = ( + formik: FormikProps, + artifact: IExpectedArtifact, + ): void => { + formik.setFieldValue('sourceArtifact.artifactId', artifact.id); + formik.setFieldValue('sourceArtifact.artifactDisplayName', artifact.displayName); + formik.setFieldValue( + 'sourceArtifact.artifactType', + (artifact.matchArtifact && artifact.matchArtifact.type) || + (artifact.defaultArtifact && artifact.defaultArtifact.type), + ); + formik.setFieldValue('sourceArtifact.artifact', null); + }; + + private onArtifactEdited = (formik: FormikProps, artifact: IArtifact): void => { + formik.setFieldValue('sourceArtifact.artifact', artifact); + formik.setFieldValue('sourceArtifact.artifactDisplayName', artifact.reference); + formik.setFieldValue('sourceArtifact.artifactType', artifact.type); + formik.setFieldValue('sourceArtifact.artifactId', null); + }; + + private validate = (values: IAwsCodeBuildSource): any => { + const formValidator = new FormValidator(values); + formValidator + .field('sourceArtifact', 'Source Artifact') // display name should exist no matter if it's artifact or id + .required() + .withValidators((value: any[]) => !value && 'Artifact is required'); + return formValidator.validateForm(); + }; + + public render(): React.ReactElement { + const { dismissModal, source, stage, pipeline } = this.props; + return ( + + ref={this.formikRef} + initialValues={source} + onSubmit={this.submit} + validate={this.validate} + render={formik => ( +
+ + + Edit Source + + +
+
Source Artifact
+
+ this.onArtifactEdited(formik, artifact)} + onExpectedArtifactSelected={(artifact: IExpectedArtifact) => + this.onExpectedArtifactSelected(formik, artifact) + } + pipeline={pipeline} + stage={stage} + /> +
+
+ ( + + )} + /> + } + /> +
+ + + + + + )} + /> + ); + } +} diff --git a/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/IAwsCodeBuildSource.tsx b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/IAwsCodeBuildSource.tsx new file mode 100644 index 00000000000..7d5fa19ee89 --- /dev/null +++ b/app/scripts/modules/core/src/pipeline/config/stages/awsCodeBuild/IAwsCodeBuildSource.tsx @@ -0,0 +1,21 @@ +import { ArtifactTypePatterns, excludeAllTypesExcept, IArtifact } from 'core'; + +export interface IAwsCodeBuildSource { + type?: string; + sourceArtifact: IAwsCodeBuildSourceArtifact; + sourceVersion?: string; +} + +interface IAwsCodeBuildSourceArtifact { + artifactId?: string; + artifactDisplayName?: string; + artifactType?: string; + artifact?: IArtifact; +} + +export const SOURCE_TYPES: string[] = ['BITBUCKET', 'CODECOMMIT', 'GITHUB', 'GITHUB_ENTERPRISE', 'S3']; + +export const EXCLUDED_ARTIFACT_TYPES: RegExp[] = excludeAllTypesExcept( + ArtifactTypePatterns.S3_OBJECT, + ArtifactTypePatterns.GIT_REPO, +); diff --git a/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/BakeManifestStageForm.tsx b/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/BakeManifestStageForm.tsx index a14d1157ed9..8c367a2f7e5 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/BakeManifestStageForm.tsx +++ b/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/BakeManifestStageForm.tsx @@ -14,11 +14,11 @@ interface IBakeManifestStageFormProps { export class BakeManifestStageForm extends React.Component< IBakeManifestStageFormProps & IFormikStageConfigInjectedProps > { - public HELM_RENDERER = 'HELM2'; + public HELM_RENDERERS = new Set(['HELM2', 'HELM3']); public KUSTOMIZE_RENDERER = 'KUSTOMIZE'; private templateRenderers = (): string[] => { - const renderers = [this.HELM_RENDERER]; + const renderers = [...this.HELM_RENDERERS]; if (SETTINGS.feature.kustomizeEnabled) { renderers.push(this.KUSTOMIZE_RENDERER); } @@ -27,7 +27,7 @@ export class BakeManifestStageForm extends React.Component< private shouldRenderHelm(): boolean { const stage = this.props.formik.values; - return stage.templateRenderer === this.HELM_RENDERER; + return this.HELM_RENDERERS.has(stage.templateRenderer); } public render() { diff --git a/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/ManualExecutionBakeManifest.tsx b/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/ManualExecutionBakeManifest.tsx index 67c1c3faa43..2f715e9c804 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/ManualExecutionBakeManifest.tsx +++ b/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/ManualExecutionBakeManifest.tsx @@ -31,7 +31,10 @@ export function ManualExecutionBakeManifest(props: ITriggerTemplateComponentProp Bake (Manifest) stage and exactly one artifact of type `helm/chart`. */ const bakeManifestStages = props.command.pipeline.stages.filter(stage => stage.type === BAKE_MANIFEST_STAGE_KEY); - if (bakeManifestStages.length !== 1 || bakeManifestStages[0].templateRenderer !== 'HELM2') { + if ( + bakeManifestStages.length !== 1 || + (bakeManifestStages[0].templateRenderer !== 'HELM2' && bakeManifestStages[0].templateRenderer !== 'HELM3') + ) { return null; } const expectedArtifacts = props.command.pipeline.expectedArtifacts || []; diff --git a/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/bakeManifestStage.ts b/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/bakeManifestStage.ts index 2b838582391..747d51bdac7 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/bakeManifestStage.ts +++ b/app/scripts/modules/core/src/pipeline/config/stages/bakeManifest/bakeManifestStage.ts @@ -20,7 +20,7 @@ if (SETTINGS.feature.versionedProviders) { _validator: IValidatorConfig, _config: IStageOrTriggerTypeConfig, ): string => { - if (stage.templateRenderer !== 'HELM2') { + if (stage.templateRenderer !== 'HELM2' && stage.templateRenderer !== 'HELM3') { return ''; } diff --git a/app/scripts/modules/core/src/pipeline/config/stages/managed/ImportDeliveryConfigExecutionDetails.tsx b/app/scripts/modules/core/src/pipeline/config/stages/managed/ImportDeliveryConfigExecutionDetails.tsx index 111a2117bc2..ab555f60f0a 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/managed/ImportDeliveryConfigExecutionDetails.tsx +++ b/app/scripts/modules/core/src/pipeline/config/stages/managed/ImportDeliveryConfigExecutionDetails.tsx @@ -4,10 +4,11 @@ import { ExecutionDetailsSection, IExecutionDetailsSectionProps, StageFailureMes import { IGitTrigger } from 'core/domain'; import { SETTINGS } from 'core/config'; +const NOT_FOUND = 'Not found'; + export function ImportDeliveryConfigExecutionDetails(props: IExecutionDetailsSectionProps) { const { stage } = props; const trigger = props.execution.trigger as IGitTrigger; - const errorDetailsAvailable = stage.isFailed && !stage.failureMessage && stage.context.error; const manifestPath = SETTINGS.managedDelivery?.manifestBasePath + '/' + @@ -19,31 +20,22 @@ export function ImportDeliveryConfigExecutionDetails(props: IExecutionDetailsSec
SCM
-
{trigger.source}
+
{trigger.source ?? NOT_FOUND}
Project
-
{trigger.project}
+
{trigger.project ?? NOT_FOUND}
Repository
-
{trigger.slug}
+
{trigger.slug ?? NOT_FOUND}
Manifest Path
-
{manifestPath}
+
{manifestPath ?? NOT_FOUND}
Branch
-
{trigger.branch}
+
{trigger.branch ?? NOT_FOUND}
Commit
-
{trigger.hash.substring(0, 7)}
+
{trigger.hash?.substring(0, 7) ?? NOT_FOUND}
- {errorDetailsAvailable && ( -
-
- Something went wrong during import: -
{stage.context.error}
-
-
- )} - - + ); } diff --git a/app/scripts/modules/core/src/pipeline/config/stages/pipeline/pipelineStage.js b/app/scripts/modules/core/src/pipeline/config/stages/pipeline/pipelineStage.js index ee04aa95fb9..70c3fde4bf0 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/pipeline/pipelineStage.js +++ b/app/scripts/modules/core/src/pipeline/config/stages/pipeline/pipelineStage.js @@ -155,7 +155,7 @@ module(CORE_PIPELINE_CONFIG_STAGES_PIPELINE_PIPELINESTAGE, []) delete $scope.userSuppliedParameters[parameter]; delete $scope.stage.pipelineParameters[parameter]; } else if ($scope.userSuppliedParameters[parameter]) { - $scope.stage.pipelineParameters[parameter] = $scope.userSuppliedParameters[parameter]; + $scope.stage.pipelineParameters[parameter] = $scope.userSuppliedParameters[parameter] || ''; } }; diff --git a/app/scripts/modules/core/src/pipeline/create/CreatePipelineModal.tsx b/app/scripts/modules/core/src/pipeline/create/CreatePipelineModal.tsx index c5647b1ce74..16cfe33ebad 100644 --- a/app/scripts/modules/core/src/pipeline/create/CreatePipelineModal.tsx +++ b/app/scripts/modules/core/src/pipeline/create/CreatePipelineModal.tsx @@ -89,6 +89,7 @@ export class CreatePipelineModal extends React.Component