protected override async Task PerformActionAsync()

in src/Amazon.Lambda.Tools/Commands/PackageCommand.cs [148:266]


        protected override async Task<bool> PerformActionAsync()
        {
            EnsureInProjectDirectory();

            // Disable interactive since this command is intended to be run as part of a pipeline.
            this.DisableInteractive = true;

            string projectLocation = Utilities.DetermineProjectLocation(this.WorkingDirectory, this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false));

            Lambda.PackageType packageType = LambdaUtilities.DeterminePackageType(this.GetStringValueOrDefault(this.PackageType, LambdaDefinedCommandOptions.ARGUMENT_PACKAGE_TYPE, false));
            if(packageType == Lambda.PackageType.Image)
            {
                var pushResults = await PushLambdaImageAsync();

                if (!pushResults.Success)
                {
                    if (pushResults.LastException != null)
                        throw pushResults.LastException;

                    throw new LambdaToolsException("Failed to push container image to ECR.", LambdaToolsException.LambdaErrorCode.FailedToPushImage);
                }
            }
            else
            {
                var layerVersionArns = this.GetStringValuesOrDefault(this.LayerVersionArns, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_LAYERS, false);
                LayerPackageInfo layerPackageInfo = null;
                if (layerVersionArns != null)
                {
                    if (!this.DisableRegionAndCredentialsCheck)
                    {
                        // Region and credentials are only required if using layers. This is new behavior so do a preemptive check when there are layers to
                        // see if region and credentials are set. If they are not set give a specific error message about region and credentials required
                        // when using layers.
                        try
                        {
                            base.DetermineAWSRegion();
                        }
                        catch (Exception)
                        {
                            throw new ToolsException("Region is required for the package command when layers are specified. The layers must be inspected to see how they affect packaging.", ToolsException.CommonErrorCode.RegionNotConfigured);
                        }
                        try
                        {
                            base.DetermineAWSCredentials();
                        }
                        catch (Exception)
                        {
                            throw new ToolsException("AWS credentials are required for the package command when layers are specified. The layers must be inspected to see how they affect packaging.", ToolsException.CommonErrorCode.InvalidCredentialConfiguration);
                        }
                    }

                    layerPackageInfo = await LambdaUtilities.LoadLayerPackageInfos(this.Logger, this.LambdaClient, this.S3Client, layerVersionArns);
                }
                else
                {
                    layerPackageInfo = new LayerPackageInfo();
                }

                // Release will be the default configuration if nothing set.
                var configuration = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false);

                var msbuildParameters = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false);
                var targetFramework = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false);
                if (string.IsNullOrEmpty(targetFramework))
                {
                    targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(projectLocation, msbuildParameters);

                    // If we still don't know what the target framework is ask the user what targetframework to use.
                    // This is common when a project is using multi targeting.
                    if (string.IsNullOrEmpty(targetFramework))
                    {
                        targetFramework = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                    }
                }

                bool isNativeAot = Utilities.LookPublishAotFlag(projectLocation, msbuildParameters);

                var architecture = this.GetStringValueOrDefault(this.Architecture, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_ARCHITECTURE, false);
                var disableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault();

                var zipArchivePath = GetStringValueOrDefault(this.OutputPackageFileName, LambdaDefinedCommandOptions.ARGUMENT_OUTPUT_PACKAGE, false);

                string publishLocation;
                var success = LambdaPackager.CreateApplicationBundle(defaults: this.DefaultConfig,
                                                                     logger: this.Logger,
                                                                     workingDirectory: this.WorkingDirectory,
                                                                     projectLocation: projectLocation,
                                                                     configuration: configuration,
                                                                     targetFramework: targetFramework,
                                                                     msbuildParameters: msbuildParameters,
                                                                     architecture: architecture,
                                                                     disableVersionCheck: disableVersionCheck,
                                                                     layerPackageInfo: layerPackageInfo,
                                                                     isNativeAot: isNativeAot,
                                                                     useContainerForBuild: GetBoolValueOrDefault(this.UseContainerForBuild, LambdaDefinedCommandOptions.ARGUMENT_USE_CONTAINER_FOR_BUILD, false),
                                                                     containerImageForBuild: GetStringValueOrDefault(this.ContainerImageForBuild, LambdaDefinedCommandOptions.ARGUMENT_CONTAINER_IMAGE_FOR_BUILD, false),
                                                                     codeMountDirectory: GetStringValueOrDefault(this.CodeMountDirectory, LambdaDefinedCommandOptions.ARGUMENT_CODE_MOUNT_DIRECTORY, false),
                                                                     publishLocation: out publishLocation, 
                                                                     zipArchivePath: ref zipArchivePath);
                if (!success)
                {
                    throw new LambdaToolsException("Failed to create Lambda deployment bundle.", ToolsException.CommonErrorCode.DotnetPublishFailed);
                }


                this.Logger.WriteLine("Lambda project successfully packaged: " + zipArchivePath);
                var dotnetSharedStoreValue = layerPackageInfo.GenerateDotnetSharedStoreValue();
                if (!string.IsNullOrEmpty(dotnetSharedStoreValue))
                {
                    this.NewDotnetSharedStoreValue = dotnetSharedStoreValue;

                    this.Logger.WriteLine($"\nWarning: You must set the {LambdaConstants.ENV_DOTNET_SHARED_STORE} environment variable when deploying the package. " +
                                          "If not set the layers specified will not be located by the .NET Core runtime. The trailing '/' is required.");
                    this.Logger.WriteLine($"{LambdaConstants.ENV_DOTNET_SHARED_STORE}: {dotnetSharedStoreValue}");
                }
            }

            return true;
        }