Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Azure DevOps通过给定现有YAML的REST API创建构建定义_Azure_Azure Devops_Azure Pipelines - Fatal编程技术网

Azure DevOps通过给定现有YAML的REST API创建构建定义

Azure DevOps通过给定现有YAML的REST API创建构建定义,azure,azure-devops,azure-pipelines,Azure,Azure Devops,Azure Pipelines,我在现有Git repo中有100多个YAML文件,每个文件都定义了自己的构建管道。我正在尝试创建一个PowerShell脚本来创建这些生成定义,这样我就不必花费数小时使用web UI手动添加新的生成定义并指向它们各自的YAML文件 我也遇到过类似的问题和资源,但无法让这个脚本正常工作 我知道它支持克隆,但它是否支持创建链接到Git repo中YAML文件的构建定义 $organization=“我的公司” $project=“MyProject” $projUrl=”https://

我在现有Git repo中有100多个YAML文件,每个文件都定义了自己的构建管道。我正在尝试创建一个PowerShell脚本来创建这些生成定义,这样我就不必花费数小时使用web UI手动添加新的生成定义并指向它们各自的YAML文件

我也遇到过类似的问题和资源,但无法让这个脚本正常工作

我知道它支持克隆,但它是否支持创建链接到Git repo中YAML文件的构建定义

$organization=“我的公司”
$project=“MyProject”
$projUrl=”https://dev.azure.com/$($组织)/$($项目)/”
$patToken=“”
$token=[System.Convert]::TOBASE64字符串([System.Text.Encoding]::ASCII.GetBytes(“:$($patToken)”)
$header=@{authorization=“Basic$token”}
$Url=“$($projUrl)\u api/build/definitions?api版本=5.1”
$json=@{
project=“$($project)”;
name=“My.New.Definition.Linked.To.Existing.YAML.File”;
存储库=@{
url=“”;
};
#脚本仍无法定义。进程不能为null。
#过程=0;
path=“\A新文件夹”;
type=“构建”
}
$body=($json |转换为json-深度3)
调用RestMethod-Uri$Url-Headers$header-Body$Body-Method-Post-ContentType application/json;
我在上面的脚本中遇到以下错误:

Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Value cannot be null.\r\nParameter name:
definition.Process","typeName":"System.ArgumentNullException, mscorlib","typeKey":"ArgumentNullException","errorCode":0,"eventId":0}
At create_pipelines.ps1:22 char:1
+ Invoke-RestMethod -Uri $Url -Headers $header -Body $body -Method Post ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
是否可以创建一个新的构建定义,而不克隆一个必须通过web UI手动创建的现有构建定义

我有100多个YAML文件位于Git repo中的/azure pipeline YAML/文件夹中。我怀疑我需要以某种方式将其包含在通过RESTAPI发送的JSON中,但是在哪里/如何?我被这个定义难住了。进程错误

更新 多亏了@danielmann,我最终需要获得一些额外的信息(即
repository.Id
和更改
repository.Type
)。我在脚本中添加了以下内容,以获取基于现有YAML文件创建的临时定义的示例

$Url=“$($projUrl)\u api/build/definitions/13?api版本=5.1”
调用RestMethod$Url-Headers$header-Method Get-ContentType应用程序/json;
工作脚本最终是:

$organization=“我的公司”
$project=“MyProject”
$projUrl=”https://dev.azure.com/$($组织)/$($项目)/”
$patToken=“”
$token=[System.Convert]::TOBASE64字符串([System.Text.Encoding]::ASCII.GetBytes(“:$($patToken)”)
$header=@{authorization=“Basic$token”}
$Url=“$($projUrl)\u api/build/definitions?api版本=5.1”
$json=@{
project=“$($project)”;
name=“My.New.Definition.Linked.To.Existing.YAML.File”;
存储库=@{
url=“”;
defaultBranch=“refs/heads/feature/my new feature branch”;
id=“”;
type=“TfsGit”;
};
进程=@{
yamlFilename=“azure管道YAML/my pipeline.yml”;
类型=2;
};
path=“\A新文件夹”;
type=“build”;
}
$body=($json |转换为json-深度3)
调用RestMethod-Uri$Url-Headers$header-Body$Body-Method-Post-ContentType application/json;

指定
process=0时失败,因为
process
不应该是数字数据类型。进程需要指定一个YAML文件和一个“type”参数

  "process": {
    "yamlFilename": "build.yaml",
    "type": 2
  }
我真的忘了什么类型的“2”和类型的“1”和类型的“90072972”,但我过去用过

解决这类问题的最简单方法是创建一个YAML构建,并使用RESTAPI提取JSON定义。我就是这样想出来的。

公共类常量
     public class Constants
    {
     public class DevOps
        {
            public class Build
            {
                public const string QUEUE_STATUS = "enabled";
                public const string YAML_FILE_PATH = "Data/azure-pipelines.yml";
                public const string AGENT_POOL_NAME = "Hosted Ubuntu 1604";
                public const string JOB_AUTHORIZATION_SCOPE = "projectCollection";
                public const string REPOSITORY_TYPE = "TfsGit";
                public const string CREATE_BUILD_DEF_URI = "https://dev.azure.com/{0}/{1}/_apis/build/definitions?api-version=5.0";
            }
    }
}
public class Repository
{
          public string id { get; set; }
        public string name { get; set; }
        public string url { get; set; }
        public DevOpsProject project { get; set; }
        public int size { get; set; }
        public string remoteUrl { get; set; }
        public string sshUrl { get; set; }
        public bool isFork { get; set; }
        public _Links _links { get; set; }
        public string defaultBranch { get; set; }

        public string type { get; set; }


}

   private void CreateIntegrationPipelineWithForkRepository(string orgnizationName, string sourceProjectName, string sourceProjectId, Repository forkRepository)
    {
        System.Action action = delegate
        {
            //********************************* Create Build with CICD ******************///
            var continuousIntegration = new List<BuildTrigger>() { new BuildTrigger() };
            var referenceYamlPath = new
            {
                yamlFilename = Constants.DevOps.Build.YAML_FILE_PATH,// = "Data/azure-pipelines.yml",
                type = 2
            };
            var queueWithAgentPool = new
            {
                name = Constants.DevOps.Build.AGENT_POOL_NAME,
                pool = new
                {
                    name = Constants.DevOps.Build.AGENT_POOL_NAME,
                    isHosted = true
                }
            };

            //Set repository type to: 'TfsGit'
            forkRepository.type = Constants.DevOps.Build.REPOSITORY_TYPE;// = "TfsGit";
            var requestBuild = new
            {
                triggers = continuousIntegration,
                jobAuthorizationScope = Constants.DevOps.Build.JOB_AUTHORIZATION_SCOPE,
                jobTimeoutInMinutes = 60,
                jobCancelTimeoutInMinutes = 5,
                process = referenceYamlPath,
                repository = forkRepository, // new repository
                quality = "definition",
                queue = queueWithAgentPool,
                name = string.Format("{0}-{1}", forkRepository.name, "ci"),
                path = "\\",
                type = "build",
                queueStatus = Constants.DevOps.Build.QUEUE_STATUS,//= "enabled",
                revision = 1,
                project = new { id = sourceProjectId } // source project id
            };

            //********************************* Create Build with CICD ******************///
            var uri = string.Format(Constants.DevOps.Build.CREATE_BUILD_DEF_URI, orgnizationName,sourceProjectName);

            this.Post(uri, HttpMethod.Post, requestBuild);
        };

        _exceptionHandlingPolicy.Execute(action);

    }
    
    private string Post<T>(uri, HttpMethod.Post, T request)
    {
    if (request != null)
                {
                    data = JsonConvert.SerializeObject(request);
                }
                var personalaccesstoken = "azure-devOps-PAT-token";

                var authorization = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalaccesstoken)));

                var result = _httpClient.Send(uri, method, data, authorization);
    }
{ 公共类DevOps { 公共类构建 { public const string QUEUE_STATUS=“enabled”; public const string YAML_FILE_PATH=“Data/azure pipelines.yml”; public const string AGENT_POOL_NAME=“Hosted Ubuntu 1604”; public const string JOB\u AUTHORIZATION\u SCOPE=“projectCollection”; 公共常量字符串存储库\u TYPE=“TfsGit”; public const string CREATE_BUILD_DEF_URI=”https://dev.azure.com/{0}/{1}/_api/build/definitions?api版本=5.0”; } } } 公共类存储库 { 公共字符串id{get;set;} 公共字符串名称{get;set;} 公共字符串url{get;set;} 公共DevPSProject项目{get;set;} 公共整数大小{get;set;} 公共字符串remoteUrl{get;set;} 公共字符串sshull{get;set;} 公共bool isFork{get;set;} 公共链接{get;set;} 公共字符串defaultBranch{get;set;} 公共字符串类型{get;set;} } private void CreateIntegrationPipelineWithForkRepository(字符串组织名称、字符串sourceProjectName、字符串sourceProjectId、存储库forkRepository) { System.Action动作=委托 { //*********************************使用CICD创建构建******************/// var continuousIntegration=new List(){new BuildTrigger()}; var referenceYamlPath=new { yamlFilename=Constants.DevOps.Build.YAML\u文件路径,//=“Data/azure pipelines.yml”, 类型=2 }; var queueWithAgentPool=new { name=Constants.DevOps.Build.AGENT\u POOL\u name, 池=新 { name=Constants.DevOps.Build.AGENT\u POOL\u name, isHosted=true } }; //将存储库类型设置为:“TfsGit” forksrepository.type=Constants.DevOps.Build.REPOSITORY_type;//=“TfsGit”; var requestBuild=new { 触发器=持续集成, jobAuthorizationScope=Const
$DevOpsPat = "PersonalAccessTokenHere"
$Organization = "OrgNameHere"
$Project = "ProjNameHere"
$RepoName = "RepoNameHere"
$PipelineName = "PipelineNameHere"
$PipelinePath = "\PathHere"
$PipelineTriggerBranch = "master"
$YamlPath = "/azure-pipelines.yml"

$AuthHeader = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($DevOpsPat)"))

$QueuesSplat = @{
    Uri = "https://dev.azure.com/$Organization/$Project/_apis/distributedtask/queues?api-version=6.1-preview.1"
    Method = "GET"
    ContentType = "application/json"
    Headers = @{
        Authorization = $AuthHeader
    }
}
$Queues = Invoke-RestMethod @QueuesSplat
$APQueueID = ($Queues.value | Where-Object {$_.name -eq "Azure Pipelines"}).id

$ReposSplat = @{
    Uri = "https://dev.azure.com/$Organization/$Project/_apis/git/repositories?api-version=6.1-preview.1"
    Method = "GET"
    ContentType = "application/json"
    Headers = @{
        Authorization = $AuthHeader
    }
}
$Repos = Invoke-RestMethod @ReposSplat
$Repo = $Repos.value | Where-Object {$_.name -eq $RepoName}

$PipelineSplat = @{
    Uri = "https://dev.azure.com/$Organization/$Project/_apis/build/definitions?api-version=5.1"
    Method = "POST"
    ContentType = "application/json" 
    Body = ConvertTo-Json @{
        project = "$Project"
        name = $PipelineName
        repository = @{
            url = $Repo.webUrl
            defaultBranch = $PipelineTriggerBranch
            id = $Repo.id
            type = "TfsGit"
        }
        process = @{
            yamlFilename = $YamlPath
            type = 2
        }
        path = $PipelinePath
        type = "build"
        triggers = @(
            @{
                settingsSourceType = 2
                triggerType = "continuousIntegration"
            }
        )
        queue  = @{
            id = $APQueueID
        }
    }
    Headers = @{
        Authorization = $AuthHeader
    }    
}
Invoke-RestMethod @PipelineSplat