Inedo Community Forums Forums
    • Recent
    • Tags
    • Popular
    • Login

    Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

    If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

    Buildmaster SDK - ReleaseNumber

    Scheduled Pinned Locked Moved Support
    buildmastersdkwindows-sdk
    9 Posts 2 Posters 39 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ? This user is from outside of this forum
      Guest
      last edited by

      Hey,

      Just trying to upgrade the Inedo.Buildmaster.SDK to v6.0.0. Running into an issue where:

      public override Task ExecuteAsync(IOperationExecutionContext context)
      {
           return Task.Run(async () => {
               var releaseNumber = $"{context.ReleaseNumber}.{context.BuildNumber}";
           });
      }
      

      is now invalid because context doesn't contain ReleaseNumber or BuildNumber.

      How can I get the current release and build numbers in the new SDK version?

      Thanks!
      Chris

      Product: BuildMaster
      Version: 6.0.6

      1 Reply Last reply Reply Quote 0
      • ? This user is from outside of this forum
        Guest
        last edited by

        Hi Chris,

        That appears to have been an oversight in the Inedo SDK. However, you should be able to just cast context to Inedo.BuildMaster.Extensibility.IGenericBuildMasterContext, which does have a ReleaseNumber and BuildNumber property.

        This is safe to do; it's how we have the $ReleaseNumber function implemented internally.

        Hope this helps!

        1 Reply Last reply Reply Quote 0
        • ? This user is from outside of this forum
          Guest
          last edited by

          Thanks Dean, worked like a charm.

          1 Reply Last reply Reply Quote 0
          • ? This user is from outside of this forum
            Guest
            last edited by

            Hi Dean,

            Turns out that built it, but when I cast the IExecutionContext to an IGenericBuildmasterContext it just returns null when run inside Buildmaster.

            Any ideas?

            Cheers,
            Chris

            1 Reply Last reply Reply Quote 0
            • T Offline
              thoven
              last edited by

              Are you able to post the full code, or submit the code as a support ticket if you don't want it public? There must be something else happening because that should definitely work.

              1 Reply Last reply Reply Quote 0
              • ? This user is from outside of this forum
                Guest
                last edited by

                No worries Todd - here's the code:

                Line 62 logs "Package Context is null? True".

                Line 133 is where the exception gets thrown: NullReferenceException

                Inedo SDK is v1.0.5 (which at the time of writing is the latest stable version)

                using Inedo;
                using Inedo.BuildMaster.Data;
                using Inedo.BuildMaster.Extensibility;
                using Inedo.Diagnostics;
                using Inedo.Documentation;
                using Inedo.ExecutionEngine.Executer;
                using Inedo.Extensibility;
                using Inedo.Extensibility.Operations;
                using LibGit2Sharp;
                using Custom.BuildMaster.Interfaces;
                using System;
                using System.ComponentModel;
                using System.IO;
                using System.Threading.Tasks;
                
                namespace Custom.BuildMaster.Actions.Git
                {
                    [DisplayName("Git-Clone")]
                    [Description("Clone's a repository")]
                    [ScriptAlias("Git-Clone")]
                    [ScriptNamespace("CUSTOM")]
                    [Serializable]
                    public class GitClone : GitOperation
                    {
                        [Required]
                        [ScriptAlias("Branch")]
                        [DisplayName("Branch to Clone")]
                        [PlaceholderText("e.g. master")]
                        public string Branch { get; set; }
                
                        [ScriptAlias("Commit")]
                        [DisplayName("Commit Hash")]
                        [PlaceholderText("e.g. 3917402e798a42fbdde99a66b8cac5d61a720b8f or leave blank for latest")]
                        public string Commit { get; set; }
                
                        [Required]
                        [ScriptAlias("CloneTo")]
                        [DisplayName("Clone to")]
                        [PlaceholderText("e.g. $WorkingDirectory")]
                        public string CloneTo { get; set; }
                
                        [ScriptAlias("SaveToVariable")]
                        [DisplayName("Save Commit Hash to Variable")]
                        [PlaceholderText("VariableName (optional)")]
                        public string VariableName { get; set; }
                
                        protected override ExtendedRichDescription GetDescription(IOperationConfiguration config)
                        {
                            return new ExtendedRichDescription(
                                new RichDescription(
                                    $"Clone {config[nameof(this.RepositoryName)]} to {config[nameof(this.CloneTo)]}"
                                )
                            );
                        }
                
                        public override Task ExecuteAsync(IOperationExecutionContext context)
                        {
                            return Task.Run(async () =>
                            {
                                // Turn this into the buildmaster context to get package variables out
                                var packageContext = context as IGenericBuildMasterContext;                
                                Log(new SimpleLogMessage(MessageLevel.Debug, $"Package Context is null? {packageContext == null}", "Git", "", context));  // THIS LINE LOGS "Package Context is null? True"
                
                                // Clone Repo to directory
                                CloneOptions co = new CloneOptions();
                
                                co.CredentialsProvider = (_url, _user, _cred) => new LibGit2Sharp.SecureUsernamePasswordCredentials { Username = Username, Password = Password };
                
                                var path = context.ResolvePath(CloneTo);
                
                                path = Repository.Clone(Path.Combine(BaseUrl, RepositoryName), path, co);
                
                                // Get Commit hash
                                var repo = new Repository(path);
                                var commitHash = repo.Head.Tip.Sha;
                
                                // Get local + remote branch names
                                var localBranchName = "refs/heads/" + Branch;
                                var remoteBranchName = "refs/remotes/origin/" + Branch;
                
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Local Branch set to {localBranchName}", "Git", "", context));
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Remote Branch set to {remoteBranchName}", "Git", "", context));
                
                                // Check the remote branch exists
                                var trackingBranch = repo.Branches[remoteBranchName];
                                if (trackingBranch == null)
                                {
                                    Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Error, $"Branch {Branch} does not exist on the remote.", "Git", "", context));
                                    throw new Exception($"Branch {Branch} does not exist on remote");
                                }
                
                                // Checkout branch
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Creating Branch {Branch} Locally", "Git", "", context));
                                Branch localBranch;
                                try
                                {
                                    localBranch = repo.CreateBranch(Branch, trackingBranch.Tip);
                                }catch
                                {
                                    // Branch already exists - set it up
                                    localBranch = repo.Branches[localBranchName];
                                }
                
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, "Tracking remote branch", "Git", "", context));
                                repo.Branches.Update(localBranch, b => b.TrackedBranch = trackingBranch.CanonicalName);
                
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, "Checking out branch", "Git", "", context));
                                Commands.Checkout(repo, Branch);
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Cloned branch {Branch} Successfully", "Git", "", context));
                
                                // If hash is specified, checkout that
                                if (!string.IsNullOrWhiteSpace(Commit))
                                {
                                    Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Commit Hash set. Attempting to checkout commit hash {Commit}", "Git", "", context));
                                    repo.Reset(ResetMode.Hard, Commit);                    
                                }
                
                                // Make sure the commit hash is set correctly
                                commitHash = repo.Head.Tip.Sha;
                
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Information, $"Cloned Successfully: Hash is {commitHash}", "Git", "", context));
                
                                // Set commit hash 
                                if (String.IsNullOrWhiteSpace(VariableName))
                                {
                                    Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Information, "No Commit Hash Variable Specified. Not setting.", "Git", "", context));
                                }
                                else
                                {
                
                                    using (var db = new DB.Context())
                                    {
                                        var build = await db.Builds_GetBuildAsync(packageContext.ApplicationId, packageContext.ReleaseNumber, packageContext.BuildNumber); // THIS LINE FAILS with NullReferenceException
                                        if (build == null)
                                            throw new ExecutionFailureException($"Package {packageContext.BuildNumber} was not found for release {packageContext.ReleaseNumber}.");
                
                                        db.Variables_CreateOrUpdatePackageVariable(
                                            Build_Id: build.Build_Id,
                                            Variable_Name: VariableName,
                                            ValueType_Code: Domains.VariableValueType.Scalar,
                                            Variable_Value: InedoLib.UTF8Encoding.GetBytes(commitHash),
                                            Sensitive_Indicator: false,
                                            EvaluateVariables_Indicator: false
                                        );
                
                                        Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Information, $"Assigned commit hash {commitHash} to variable {VariableName}", "Git", "", context));
                                    }
                                }
                
                                //Delete the .git Directory
                                repo.Dispose();
                                Helpers.DirectoryHelper.DeleteReadOnlyDirectory(path);
                                Helpers.DirectoryHelper.DeleteReadOnlyFile(context.ResolvePath(".gitignore"));
                                Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, "Removed .git directory and .gitignore", "Git", "", context));
                
                                // Write hash
                                return new object();
                            }); 
                        }
                    }
                }
                
                1 Reply Last reply Reply Quote 0
                • T Offline
                  thoven
                  last edited by

                  Try the following code; it removes the need for IGenericBuildMasterContext altogether and uses an async method to replace the Task.Run call:


                      public override async Task ExecuteAsync(IOperationExecutionContext context)
                      {
                          // Clone Repo to directory
                          CloneOptions co = new CloneOptions();
                  
                          co.CredentialsProvider = (_url, _user, _cred) => new LibGit2Sharp.SecureUsernamePasswordCredentials { Username = Username, Password = Password };
                  
                          var path = context.ResolvePath(CloneTo);
                  
                          path = Repository.Clone(Path.Combine(BaseUrl, RepositoryName), path, co);
                  
                          // Get Commit hash
                          var repo = new Repository(path);
                          var commitHash = repo.Head.Tip.Sha;
                  
                          // Get local + remote branch names
                          var localBranchName = "refs/heads/" + Branch;
                          var remoteBranchName = "refs/remotes/origin/" + Branch;
                  
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Local Branch set to {localBranchName}", "Git", "", context));
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Remote Branch set to {remoteBranchName}", "Git", "", context));
                  
                          // Check the remote branch exists
                          var trackingBranch = repo.Branches[remoteBranchName];
                          if (trackingBranch == null)
                          {
                              Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Error, $"Branch {Branch} does not exist on the remote.", "Git", "", context));
                              throw new Exception($"Branch {Branch} does not exist on remote");
                          }
                  
                          // Checkout branch
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Creating Branch {Branch} Locally", "Git", "", context));
                          Branch localBranch;
                          try
                          {
                              localBranch = repo.CreateBranch(Branch, trackingBranch.Tip);
                          }
                          catch
                          {
                              // Branch already exists - set it up
                              localBranch = repo.Branches[localBranchName];
                          }
                  
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, "Tracking remote branch", "Git", "", context));
                          repo.Branches.Update(localBranch, b => b.TrackedBranch = trackingBranch.CanonicalName);
                  
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, "Checking out branch", "Git", "", context));
                          Commands.Checkout(repo, Branch);
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Cloned branch {Branch} Successfully", "Git", "", context));
                  
                          // If hash is specified, checkout that
                          if (!string.IsNullOrWhiteSpace(Commit))
                          {
                              Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, $"Commit Hash set. Attempting to checkout commit hash {Commit}", "Git", "", context));
                              repo.Reset(ResetMode.Hard, Commit);
                          }
                  
                          // Make sure the commit hash is set correctly
                          commitHash = repo.Head.Tip.Sha;
                  
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Information, $"Cloned Successfully: Hash is {commitHash}", "Git", "", context));
                  
                          // Set commit hash 
                          if (String.IsNullOrWhiteSpace(VariableName))
                          {
                              Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Information, "No Commit Hash Variable Specified. Not setting.", "Git", "", context));
                          }
                          else
                          {
                              using (var db = new DB.Context())
                              {
                                  var exec = await db.Builds_GetExecutionAsync(context.ExecutionId);
                  
                                  await db.Variables_CreateOrUpdatePackageVariableAsync(
                                      Build_Id: exec.Build_Id,
                                      Variable_Name: VariableName,
                                      ValueType_Code: Domains.VariableValueType.Scalar,
                                      Variable_Value: InedoLib.UTF8Encoding.GetBytes(commitHash),
                                      Sensitive_Indicator: false,
                                      EvaluateVariables_Indicator: false
                                  );
                  
                                  Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Information, $"Assigned commit hash {commitHash} to variable {VariableName}", "Git", "", context));
                              }
                          }
                  
                          //Delete the .git Directory
                          repo.Dispose();
                          Helpers.DirectoryHelper.DeleteReadOnlyDirectory(path);
                          Helpers.DirectoryHelper.DeleteReadOnlyFile(context.ResolvePath(".gitignore"));
                          Log(new SimpleLogMessage(Inedo.Diagnostics.MessageLevel.Debug, "Removed .git directory and .gitignore", "Git", "", context));              
                      }
                  

                  However, I'm guessing this was written a while ago before the built-in Git operations handled this? We use the Git operations to perform this same functionality by combining two operations:

                  # Gets source from the BuildMaster repository and creates a release package variable named GitCommit
                  Git::Git-GetSource
                  (
                      Credentials: GitLab,
                      RepositoryUrl: https://gitlab.com/inedo/BuildMaster.git,
                      DiskPath: ~\Src,
                      RecurseSubmodules: true,
                      Branch: $Branch,
                      CommitHash => $commit
                  );
                  
                  Set-ReleaseVariable GitCommit
                  (
                      Value: $commit,
                      Package: $PackageNumber
                  );
                  
                  1 Reply Last reply Reply Quote 0
                  • ? This user is from outside of this forum
                    Guest
                    last edited by

                    Hi Todd,

                    Thanks for the such quick replies. I've implemented that in the code, but will need to wait for a bit to actually test it.

                    Is there a way of cloning a particular commit using the built-in extension (as above) or can you only clone branches? I think that's where this extension initially arose.

                    1 Reply Last reply Reply Quote 0
                    • T Offline
                      thoven
                      last edited by

                      You can actually put a full commit ID in the Tag field (which actually supports any refname)... I'll have someone put a note in to change that in the operation.

                      1 Reply Last reply Reply Quote 0

                      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                      With your input, this post could be even better 💗

                      Register Login
                      • 1 / 1
                      • First post
                        Last post
                      Inedo Website Home • Support Home • Code of Conduct • Forums Guide • Documentation