static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            //get environment configuration
            EnvironmentConfiguration environmentConfigDef;

            try
            {
                environmentConfigDef = PopulateArguments(args);
            }
            catch (MissingFieldException mfe)
            {
                Log.ToFile($"A failure occured during the read of execution parameters: {mfe.Message}");
                return;
            }

            //builds the VSTS Url based on the default values or passed in parameters
            string _uri = string.Format("https://{0}/{1}/{2}/_apis/release/", VSTSDomain, VSTSCollection, VSTSTeamProject);

            Log.ToFile(string.Format("Derived URL: {0}", _uri));
            ReleaseManagementApi RM_api = new ReleaseManagementApi(ApiVersion, _uri, IsTest);


            //Gets the Release Definition from VSTS
            ReleaseManagementModels.ReleaseDraft responseGet = RM_api.GetReleaseDefinition(ReleaseId.Value);

            int?highestRank       = null;
            int?targetEnvironment = null;

            //Determine the first environment you will need to deploy to
            foreach (ReleaseManagementModels.ReleaseEnvironment selectedEnv in responseGet.environments)
            {
                if (!highestRank.HasValue || highestRank.Value < selectedEnv.id)
                {
                    highestRank       = selectedEnv.rank;
                    targetEnvironment = selectedEnv.id;
                }
            }

            Log.ToFile(JsonConvert.SerializeObject(responseGet));

            Log.ToFile("\n\nCreating new Release Draft");
            //construct the draft release model
            ReleaseManagementModels.CreateDraftRelease draft = new ReleaseManagementModels.CreateDraftRelease()
            {
                definitionId        = ReleaseId.Value,
                isDraft             = true,
                targetEnvironmentId = targetEnvironment.Value
            };

            //Post the Draft release to the RM API.
            ReleaseManagementModels.ReleaseDraft responsePost = RM_api.CreateDraftRelease(draft);


            //update the different release environments with the proper environment variables
            foreach (ReleaseManagementModels.ReleaseEnvironment selectedEnv in responsePost.environments)
            {
                Log.ToFile("Updating Environment Variables: " + selectedEnv.name);
                try
                {
                    ReleaseManagementModels.ReleaseEnvironment tempEnv = responseGet.environments.Where(x => x.id == selectedEnv.definitionEnvironmentId).FirstOrDefault();
                    selectedEnv.preApprovalsSnapshot  = tempEnv?.preDeployApprovals;
                    selectedEnv.postApprovalsSnapshot = tempEnv?.postDeployApprovals;
                    // The environment is a JSON Dictionary of environment specific variables for when deploying web/app configs.
                    // QA and DEV will have different connection strings and cerdentials that are stored in the Release Environment Variables
                    dynamic resultingVariables = GetUpdatedEnvironmentVariables(environmentConfigDef, selectedEnv.name);
                    selectedEnv.variables = resultingVariables;
                }
                catch (MissingMemberException mme)
                {
                    Log.ToFile($"No environment defined in config:{mme.Message}");
                }
            }

            //set release level variables
            Dictionary <string, Common.Value> releaseVariables = new Dictionary <string, Common.Value>();

            releaseVariables.Add("eRestVersion", new Common.Value()
            {
                value = BuildVersion
            });
            responsePost.variables = releaseVariables;


            //Update the draft with all the new Environment and Release variables
            Log.ToFile("Updating ReleaseDraft variables (Environment and Release)");
            RM_api.PostRelease(responsePost, responsePost.id);
            Log.ToFile("Updated ReleaseDraft variables");

            Log.ToFile($"Starting Release {responsePost.name} ....");
            //start Release
            StartRelease(responsePost, draft.isDraft, targetEnvironment.Value, RM_api);
            Log.ToFile($"Started Release {responsePost.name}");
        }
        public static dynamic StartRelease(ReleaseManagementModels.ReleaseDraft draft, bool _isDraft, int targetEnv, ReleaseManagementApi api)
        {
            //Get the latest draft
            Log.ToFile($"Getting latest release with id: {draft.id}");
            ReleaseManagementModels.ReleaseDraft currentRelease = api.GetRelease(draft.id);


            //first get list of artifacts...
            Log.ToFile($"Getting list of artifact versions");
            ArtifactVersionList versions = api.GetArtifactVersions(currentRelease.artifacts);

            Log.ToFile($"Got artifact versions \n\n" + JsonConvert.SerializeObject(versions));

            //determine the highest version of all the artifacts and use that.
            Dictionary <int, BuildArtifactSourceData> artifactSources = new Dictionary <int, BuildArtifactSourceData>();

            foreach (ArtifactVersion av in versions.artifactVersions)
            {
                var highestVersion = av.versions.First();

                BuildArtifactSourceData sd = new BuildArtifactSourceData()
                {
                    value        = highestVersion.id,
                    displayValue = highestVersion.name,
                    data         = new Common.BranchLocation()
                    {
                        branch = highestVersion.sourceBranch
                    }
                };

                artifactSources.Add(av.artifactSourceId, sd);
            }

            //update the current release to put it in a building state
            currentRelease.status = "1";
            currentRelease.reason = "1";

            //set environment statuses and approvals
            foreach (ReleaseManagementModels.ReleaseEnvironment env in currentRelease.environments)
            {
                env.status = "0";
                env.originalPostDeployApprovals = null;
                env.originalPreDeployApprovals  = null;
            }

            //set artifact versions
            foreach (Artifact art in currentRelease.artifacts)
            {
                BuildArtifactSourceData versionData = artifactSources[art.id];
                Log.ToFile($"Latest vesrion of artifact {art.id}, \nlatest version: {versionData.value} - {versionData.displayValue} \nBranch: {versionData.data.branch}");
                art.definitionReference.version = new Common.ValueIdentifier()
                {
                    id = versionData.value, name = versionData.displayValue
                };
                art.definitionReference.branch = new Common.ValueIdentifier()
                {
                    id = versionData.data.branch, name = versionData.data.branch
                };
            }


            Log.ToFile("Queueing Release");
            dynamic response = api.PostRelease(currentRelease, currentRelease.id);

            //sets the release status to be in progress
            Log.ToFile("Release to be started...");
            dynamic patchResponse = new ExpandoObject();

            patchResponse = new
            {
                status = 3, //I beleive this maps to inProgress
            };

            response = api.StartRelease(patchResponse, currentRelease.id);

            return(response);
        }