func()

in internal/pkg/cli/svc_deploy.go [210:347]


func (o *deploySvcOpts) Execute() error {
	if !o.clientConfigured {
		if err := o.configureClients(); err != nil {
			return err
		}
	}
	if !o.allowWkldDowngrade {
		if err := validateWkldVersion(o.svcVersionGetter, o.name, o.templateVersion); err != nil {
			return err
		}
	}
	mft, interpolated, err := workloadManifest(&workloadManifestInput{
		name:         o.name,
		appName:      o.appName,
		envName:      o.envName,
		ws:           o.ws,
		interpolator: o.newInterpolator(o.appName, o.envName),
		unmarshal:    o.unmarshal,
		sess:         o.envSess,
	})
	if err != nil {
		return err
	}
	o.rawMft = interpolated
	o.appliedDynamicMft = mft
	if o.forceNewUpdate && o.svcType == manifestinfo.StaticSiteType {
		return fmt.Errorf("--%s is not supported for service type %q", forceFlag, manifestinfo.StaticSiteType)
	}
	if err := validateWorkloadManifestCompatibilityWithEnv(o.ws, o.envFeaturesDescriber, mft, o.envName); err != nil {
		return err
	}
	deployer, err := o.newSvcDeployer()
	if err != nil {
		return err
	}
	serviceInRegion, err := deployer.IsServiceAvailableInRegion(o.targetEnv.Region)
	if err != nil {
		return fmt.Errorf("check if %s is available in region %s: %w", o.svcType, o.targetEnv.Region, err)
	}
	if !serviceInRegion {
		log.Warningf(`%s might not be available in region %s; proceed with caution.
`, o.svcType, o.targetEnv.Region)
	}
	uploadOut, err := deployer.UploadArtifacts()
	if err != nil {
		return fmt.Errorf("upload deploy resources for service %s: %w", o.name, err)
	}
	targetApp, err := o.getTargetApp()
	if err != nil {
		return err
	}
	if o.showDiff {
		output, err := deployer.GenerateCloudFormationTemplate(&clideploy.GenerateCloudFormationTemplateInput{
			StackRuntimeConfiguration: clideploy.StackRuntimeConfiguration{
				RootUserARN:               o.rootUserARN,
				Tags:                      targetApp.Tags,
				EnvFileARNs:               uploadOut.EnvFileARNs,
				ImageDigests:              uploadOut.ImageDigests,
				AddonsURL:                 uploadOut.AddonsURL,
				CustomResourceURLs:        uploadOut.CustomResourceURLs,
				StaticSiteAssetMappingURL: uploadOut.StaticSiteAssetMappingLocation,
				Version:                   o.templateVersion,
			},
		})
		if err != nil {
			return fmt.Errorf("generate the template for workload %q against environment %q: %w", o.name, o.envName, err)
		}
		if err := diff(deployer, output.Template, o.diffWriter); err != nil {
			var errHasDiff *errHasDiff
			if !errors.As(err, &errHasDiff) {
				return err
			}
		}
		contd, err := o.skipDiffPrompt, nil
		if !o.skipDiffPrompt {
			contd, err = o.prompt.Confirm(continueDeploymentPrompt, "")
		}
		if err != nil {
			return fmt.Errorf("ask whether to continue with the deployment: %w", err)
		}
		if !contd {
			o.noDeploy = true
			return nil
		}
	}
	deployRecs, err := deployer.DeployWorkload(&clideploy.DeployWorkloadInput{
		StackRuntimeConfiguration: clideploy.StackRuntimeConfiguration{
			ImageDigests:              uploadOut.ImageDigests,
			EnvFileARNs:               uploadOut.EnvFileARNs,
			AddonsURL:                 uploadOut.AddonsURL,
			RootUserARN:               o.rootUserARN,
			Tags:                      tags.Merge(targetApp.Tags, o.resourceTags),
			CustomResourceURLs:        uploadOut.CustomResourceURLs,
			StaticSiteAssetMappingURL: uploadOut.StaticSiteAssetMappingLocation,
			Version:                   o.templateVersion,
		},
		Options: clideploy.Options{
			ForceNewUpdate:  o.forceNewUpdate,
			DisableRollback: o.disableRollback,
			Detach:          o.detach,
		},
	})
	if err != nil {
		var errStackDeletedOnInterrupt *deploycfn.ErrStackDeletedOnInterrupt
		var errStackUpdateCanceledOnInterrupt *deploycfn.ErrStackUpdateCanceledOnInterrupt
		var errEmptyChangeSet *awscfn.ErrChangeSetEmpty
		if errors.As(err, &errStackDeletedOnInterrupt) {
			o.noDeploy = true
			return nil
		}
		if errors.As(err, &errStackUpdateCanceledOnInterrupt) {
			log.Successf("Successfully rolled back service %s to the previous configuration.\n", color.HighlightUserInput(o.name))
			o.noDeploy = true
			return nil
		}
		if o.disableRollback {
			stackName := stack.NameForWorkload(o.targetApp.Name, o.targetEnv.Name, o.name)
			rollbackCmd := fmt.Sprintf("aws cloudformation rollback-stack --stack-name %s --role-arn %s", stackName, o.targetEnv.ExecutionRoleARN)
			log.Infof(`It seems like you have disabled automatic stack rollback for this deployment. To debug, you can:
* Run %s to inspect the service log.
* Visit the AWS console to inspect the errors.
After fixing the deployment, you can:
1. Run %s to rollback the deployment.
2. Run %s to make a new deployment.
`, color.HighlightCode("copilot svc logs"), color.HighlightCode(rollbackCmd), color.HighlightCode("copilot svc deploy"))
		}
		if errors.As(err, &errEmptyChangeSet) {
			return &errNoInfrastructureChanges{parentErr: err}
		}
		return fmt.Errorf("deploy service %s to environment %s: %w", o.name, o.envName, err)
	}
	if o.detach {
		return nil
	}
	log.Successf("Deployed service %s.\n", color.HighlightUserInput(o.name))
	o.deployRecs = deployRecs
	return nil
}