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
}