Cake use NuGet package to push the Artifacts AzureDevops

Foreword

Hello everyone, I recently automated packaging NuGet thinking about how to submit code to the time and then publish AzureDevOpsin Artifacts, stepped on a lot of pits in the process, but also take a lot of detours, so this article is to explore the results of my and I some of the problems encountered in finishing to others.

My last article on CI/CDthe article "Using Gitlab CI / CD automate publishing site to IIS" is using scripts implemented in the form, then there is garden Friends in the following comments can be used Cake (C # Make) the tools to achieve which function, so this would not have a script. Cake will have time to use it to transform.

the whole idea:

  1. Under first introduced Cake, AzureDevops Pipelines/Artifactshow to use

  2. Then configure AzureDevops Pipelines

  3. Creating AzureDevops Artifacts (NuGet server)

  4. AzureDevops configuration PAT (Personal Access Tokens) and the desired Pipelines Variables (variable)

  5. Cake packing increases, pushing NuGet package code.

  6. View the final run results

Use the tools and version:

dotnet core 2.2

cake 0.33.0

PowerShell, NuGet, CredentialProvider

AzureDevops Pipelines 和 AzureDevops Artifacts

Introduction

  • Cake stands C# Make, it is an automated cross-platform build system, based on C # DSL, so you can use familiar C # language to replace in our previous use of scripts built. We can use it very easily compiled code, copy files and folders, and of course you can also run the unit tests in order to make sure that our code is no problem, we have this time to release NuGet Artifacts it accounts for a very important position.

  • AzureDevops, formerly known as VSTS, it provides Repos, Pipelines, Boards, Test Plans, Artifacts:
    • Repos provide Git repository for source code control code, you can introduce your storage directly on GitHub.
    • Pipelines provide build and publish services to support the application of continuous integration and delivery (CI / CD)
    • Boards Agile provides a set of tools that support the use of Kanban and Scrum approach to planning and tracking, code defect management, etc., there is a similar tool Tencent TAPD , Ali cloud effect , Huawei cloud DevCloud and so on.
    • Test Plans provides tools for a variety of test applications, including manual / exploratory testing and continuous testing
    • Artifacts allow teams from public and private sources to share Maven, npm and NuGet package.
      Collaboration tools, including team dashboards and customizable widget configurable to share information, progress and trends; wiki built for sharing information; configurable notification.
  • CredentialProvider is Credential Provider, when we NuGet Push requires authentication, simply put it down to NuGet program.

Cake installation and use

The case I have posted on the GitHub: https://github.com/WuMortal/CakePushNuGet.Example

Installation: Here I am using dotnet core presentation, cake also supports the .NET Framework, Mono. First we need to install the cake, dotnet tool by means of this command.

dotnet tool install --global cake.tool --version 0.33.0

Successful installation will appear the following prompt:

cake installation

The cake is very simple to use, but also C # syntax believe it should be very easy to understand.

Here first we define a target variable, which saved it is the name of Task (task) we are going to perform. Then you can see in the definition of a number of Task code block, the "mission" there is a specific need to be performed, the first task is dependent reduction projects, in fact, the core code line DotNetCoreRestore(solution);, the second task is to build the project, you need to Note that the third task is actually to integrate the first two tasks together. You can also the second mission .IsDependentOn ("Restore")first task calls, of course, var target = Argument ("target", "Demo");need to be changed var target = Argument ("target", "Build");, and this depends on personal preference.

cake installation

var rootPath = "../";   //根目录
var srcPath = rootPath + "src/";    
var solution = srcPath + "Wigor.CakePushNuGet.Example.sln";   //解决方案文件
//需要执行的目标任务
var target = Argument ("target", "Demo");

Task ("Restore")
  .Description ("还原项目依赖")
  .Does (() => {
    //Restore
    Information ("开始执行还原项目依赖任务");
    DotNetCoreRestore (solution);
  });

Task ("Build")
  .Description ("编译项目")
  .Does (() => {
    Information ("开始执行编译生成项目任务");
    //Build
    DotNetCoreBuild (solution, new DotNetCoreBuildSettings {
        NoRestore = true,   //不执行还原,上一步已经还原过了
        Configuration = "Release"
    });
  });

// 执行的任务
Task ("Demo")
  .IsDependentOn ("Restore")    //1. 执行上面的 Restore 任务
  .IsDependentOn ("Build")      //2. 需要执行 上面的 Build 任务
  .Does (() => {
    Information ("所有任务完成");
  });

//运行目标任务 Demo
RunTarget (target);

After writing a good cake we can try to run it, here is my cake path build / build.cake we can change depending on the circumstances, the command is as follows:

dotnet cake build/build.cake -verbosity=diagnostic

cake run

Here you can see the cake has run successfully, and the results and information which we will run each task is displayed on the console.

cake run

Here I believe we are doing a little bit of cake to understand it, about it with multi-use ways to access the official website: https://cakebuild.net/

AzureDevops Pipelines 使用

首先你需要一个 Microsoft 账号或者 GitHub 账号,登录地址为:https://dev.azure.com,登录之后你需要创建一个项目,这里我已经创建好一个项目了,首先我们点击 Pipelines 选择 Builds,之后会出现如下界面,点击 New Pipeline。然后跟着我下面图片的步骤一步一步来就行。

AzureDevops Pipelines 使用

如果你的仓储就在 AzureDevops上那么直接选 Azure Repos Git 就行。

AzureDevops Pipelines 使用

这里你的账号是 GitHub 授权登录的话会先跳转到授权界面可能会跳转多次,同意即可。

AzureDevops Pipelines 使用
AzureDevops Pipelines 使用

删除我选中的代码,因为我不打算用 AzureDevops Pipelines 的脚本来执行本次操作,它做的只是提供我们 cake 运行的环境。

AzureDevops Pipelines 使用

更换为如下脚本,PowerShell.exe -file ./cake.ps1 是指使用 PowerShell 运行我们的 cake.ps1 文件,关于 cake.ps1 文件后面会介绍,这里我们先这样写,接着点击 Save and run

AzureDevops Pipelines 使用

trigger:
- master

pool:
  vmImage: 'windows-latest'

steps:
- script: PowerShell.exe -file ./cake.ps1
  displayName: 'Push NuGet Package'

可以看到问们管道的运行出现了错误,那是因为我们上面在运行了 cake.ps1 这个脚本,但是我们现在还没有创建这个脚本。

AzureDevops Pipelines 使用

回到我们的项目中,将 AzureDevops Pipelines 创建的 azure-pipelines.yml 文件 pull 到我们本地。

AzureDevops Pipelines 使用

接着我们编写我们下面缺少的 cake.ps1 文件,它做的事情就是将我们之前手动在 cmd 中运行的命令放入了一个 PowerShell 脚本文件中,Linux 平台的话就编写一个 shell 脚本。

AzureDevops Pipelines 使用

# Install cake.tool
dotnet tool install --global cake.tool --version 0.33.0

# 输出将要执行的命命令
Write-Host "dotnet cake build\build.cake -verbosity=diagnostic" -ForegroundColor GREEN

dotnet cake build\build.cake -verbosity=diagnostic

尝试项目根目录下运行这个脚本,在 cmd 中执行 powershell .\cake.ps1,下面报了一个错。
AzureDevops Pipelines 使用

我们只需要以管理员身份运行 PowerShell 然后执行 set-ExecutionPolicy RemoteSigned 即可

AzureDevops Pipelines 使用

AzureDevops Pipelines 使用

然后再次运行 powershell .\cake.ps1 或者命令,可以看到正确的输出了

AzureDevops Pipelines 使用

OK,这次我们推送(git push)下代码,在到 AzureDevops Pipelines 看看我们执行结果。
AzureDevops Pipelines 使用

点进去可以看到整个执行的过程,如果报错了也可以从这里看到出错的信息

AzureDevops Pipelines 使用

如果是 powershell 报错 AzureDevops Pipelines 是不会显示执行失败的,如果没得到你想要的结果你就需要点开认真的分析你的脚本了。

AzureDevops Artifacts 使用

前面已经讲过了如果使用 cake 和 在 AzureDevops Pipelines 下执行 cake。下面我们需要创建一个 NuGet Repository,这里我使用 AzureDevops 提供的 Artifacts。

AzureDevops Artifacts Use
AzureDevops Artifacts Use
AzureDevops Artifacts Use

这里面会用的就是 package source URL 和下面命令中的 -ApiKey 中的 AzureDevOps,还有这里我们需要将 NuGet + Credentials Provider 下载到我们的本地,如果你的运行环境是 Linux 或其他可以在 microsoft/artifacts-credprovider 的 GitHub 上获取对应平台的这两个包, 点击查看 GitHub 地址

创建 PAT (Personal Access Tokens)

上面说过了我们推送 NuGet 包到 Artifacts 时候是需要为两个参数提供指的的 -UserName 和 -Password,这里的 UserName 我们可以随意填,但是 Password 填的的是我们创建的 PAT。

APersonal Access Tokens use
Personal Access Tokens use

这是选择我们 PAT 所拥有的权限,需要点击 Show all scopes 找到 Packaging 勾选 Red,wirte,& manage

Personal Access Tokens use

我们可以看到我们的 PAT ,需要注意的是这个 token 只会出现一次,你需要将它保存好,如果忘记了,那么可以点击 Regenerate 重新获取 token。

Personal Access Tokens use

AzureDevops Pipelines 添加变量

上一篇文章 中我说过了为什么需要变量,这里就不重复了,有兴趣的可以看看。下面开始添加我们需要的变量。

Adding variables
A Adding variables

我们需要添加的变量有四个,分别是 NUGET_REPOSITORY_API_URLNUGET_REPOSITORY_API_KEYUSERNAMEPASSWORD

  • NUGET_REPOSITORY_API_URL:就是我们在创建 AzureDevops Artifacts 后出现的 package source URL

  • NUGET_REPOSITORY_API_KEY:就是那个 -ApiKey 参数的值 AzureDevOps

  • USERNAME:这个上面说过了可以随便填。

  • PASSWORD:这个就是之前创建的 PAT。

点击保存(Save & queue)或者 Ctrl + s 保存。

Adding variables

添加 NuGet.Tool.cake 和 NuGet.exe、Credentials Provider

这里为已经封装过了的工具类包含了打包和推送方法,地址:NuGet.Tool.cake

using System;
using System.Collections.Generic;
using System.Linq;
using Cake.Common.Tools.DotNetCore;
using Cake.Common.Tools.DotNetCore.Pack;
using Cake.Common.Tools.NuGet;
using Cake.Common.Tools.NuGet.List;
using Cake.Core;
using NuGet.Packaging;

public class NuGetTool {
    public ICakeContext CakeContext { get; }

    public string RepositoryApiUrl { get; }

    public string RepositoryApiKey { get; }

    public string UserName { get; set; }

    public string Password { get; set; }

    private NuGetListSettings ListSettings => new NuGetListSettings {
        AllVersions = true,
        Source = new string[] { this.RepositoryApiUrl }
    };

    private DotNetCorePackSettings BuildPackSettings (string packOutputDirectory) => new DotNetCorePackSettings {
        Configuration = "Release",
        OutputDirectory = packOutputDirectory,
        IncludeSource = true,
        IncludeSymbols = true,
        NoBuild = false
    };

    private NuGetTool (ICakeContext cakeContext) {
        CakeContext = cakeContext;
        RepositoryApiUrl = cakeContext.Environment.GetEnvironmentVariable ("NUGET_REPOSITORY_API_URL");
        RepositoryApiKey = cakeContext.Environment.GetEnvironmentVariable ("NUGET_REPOSITORY_API_KEY");
        UserName = cakeContext.Environment.GetEnvironmentVariable ("USERNAME");
        Password = cakeContext.Environment.GetEnvironmentVariable ("PASSWORD");
        CakeContext.Information ($"获取所需参数成功:{RepositoryApiUrl}");
    }

    public static NuGetTool FromCakeContext (ICakeContext cakeContext) {
        return new NuGetTool (cakeContext);
    }

    public void Pack (List<string> projectFilePaths, string packOutputDirectory) {
        projectFilePaths.ForEach (_ => CakeContext.DotNetCorePack (_, BuildPackSettings (packOutputDirectory)));
    }

    public void Push (List<string> packageFilePaths) {

        foreach (var packageFilePath in packageFilePaths) {
            CakeContext.NuGetAddSource (
                "wigor",
                this.RepositoryApiUrl,
                new NuGetSourcesSettings {
                    UserName = this.UserName,
                    Password = this.Password
                });

            CakeContext.NuGetPush (packageFilePath, new NuGetPushSettings {
                Source = "wigor",
                ApiKey = this.RepositoryApiKey
            });

        }

    }
}

在项目的 build/ 下创建 nuget.tool.cake 文件(build/nuget.tool.cake) 拷贝上面的代码。

这里参考了最开始提到的园友的项目,非常感谢它的贡献,GitHub 地址如下:cake.example

在创建 AzureDevops Artifacts 的时候那不是提供了 NuGet + Credentials Provider 的下载地址嘛,现在把它解压到我们项目的 build\tool\ 下。再次说明这里我是 Windows 环境,如果你的运行环境是 Linux 或其他可以在 microsoft/artifacts-credprovider 的 GitHub 上获取对应平台的这两个包, 点击查看 GitHub 地址

NuGet.exe、Credentials Provider

修改 cake.ps1 和 build.cake 文件

修改 cake.ps1,只是增加了 NuGet.exe 的环境变量,因为不加到时候 cake 会找不到 NuGet.exe,或许还有其他办法这里就先这么干,如果各位还有更方便的方法可以在下面留言,感谢!

# 执行的文件
[string]$SCRIPT = 'build/build.cake'

[string]$CAKE_VERSION = '0.33.0'

# 配置 NuGet 环境变量
$NUGET_EXE = "build/tool/NuGet.exe"
$NUGET_DIRECTORY = Get-ChildItem -Path $NUGET_EXE
$NUGET_DIRECTORY_NAME=$NUGET_DIRECTORY.DirectoryName
$ENV:Path += ";$NUGET_DIRECTORY_NAME"

# Install cake.tool
dotnet tool install --global cake.tool --version $CAKE_VERSION

# 参数:显需要执行cake 执行信息
[string]$CAKE_ARGS = "-verbosity=diagnostic"

# 输出将要执行的命命令
Write-Host "dotnet cake $SCRIPT $CAKE_ARGS $ARGS" -ForegroundColor GREEN

dotnet cake $SCRIPT $CAKE_ARGS $ARGS

修改 build.cake 文件,看着是多了很多东西其实就多了两个 Task (任务) 分别是: pack(打包)push(推送包),这里需要大家需要修改的就是 solutionproject 两个变量,将其修改为自己的解决方案名称和需要打包的项目名称。

#reference "NuGet.Packaging"

#load nuget.tool.cake

var target = Argument ("target", "PushPack");

var rootPath = "../";
var srcPath = rootPath + "src/";
var solution = srcPath + "Wigor.CakePushNuGet.Example.sln";
var project = GetFiles (srcPath + "Wigor.CakePushNuGet.HelloWorld/*.csproj");
var nugetPakcageDirectory = $"{srcPath}nugetPackage/";

var nugetTool = NuGetTool.FromCakeContext (Context);

Task ("Restore")
  .Description ("还原项目依赖")
  .Does (() => {
    //Restore
    Information ("开始执行还原项目依赖任务");
    DotNetCoreRestore (solution);
  });

Task ("Build")
  .Description ("编译项目")
  .Does (() => {
    Information ("开始执行编译生成项目任务");
    //Build
    DotNetCoreBuild (solution, new DotNetCoreBuildSettings {
        NoRestore = true,
        Configuration = "Release"
    });
  });

Task ("UnitTest")
  .Description ("单元测试")
  .Does (() => {
    Information ("开始执行单元测试任务");
    
    DotNetCoreTest(solution);
  });

Task ("Pack")
  .Description ("Nuget 打包")
  .Does (() => {
    Information ("开始执行打包任务");

    // 确保目录存在
    EnsureDirectoryExists (nugetPakcageDirectory);

    var packageFilePaths = project.Select (_ => _.FullPath).ToList ();

    nugetTool.Pack (packageFilePaths, nugetPakcageDirectory);
  });

Task ("Push")
  .Description ("Nuget 发布")
  .Does (() => {
    Information ("开始执行 Nuget 包发布任务");
    var packageFilePaths = GetFiles ($"{nugetPakcageDirectory}*.symbols.nupkg").Select (_ => _.FullPath).ToList ();

    nugetTool.Push(packageFilePaths);
  });

Task ("PushPack")
  .Description ("发布 Nuget 包")
  .IsDependentOn ("Restore")
  .IsDependentOn ("Build")
  .IsDependentOn ("Pack")
  .IsDependentOn ("Push")
  .Does (() => {
    Information ("所有任务完成");
  });

RunTarget (target);

最后我们推送修改后的代码,查看执行结果看看 NuGet 包是否发布到 AzureDevops Artifacts 上。

result

至此已经实现了 使用 Cake 推送 NuGet 包到 AzureDevops 的 Artifacts 上,你如果不熟悉 AzureDevops Pipelines 你也可以用其他的 CI/CD 工具来执行。

补充

在整个尝试过程中肯定会出现一些问题,不要着急认真分析,看看 AzureDevops Pipelines 上给出的提示,也可以现在本机跑一下看看是否正常。出现问题第一步查看错误信息,看看有没有错误信息(基本都有),然后根据错误信息去分析是我们的那个地方出错了,顺序是 cake.ps1 --> build.cake --> nuget.tool.cake,然后是所需的 PAT 的权限是否勾选,AzureDevops Pipelines 变量是否配置并且是 URL、Key 什么的都是正确,再然后就是 百度、Google。最后你可以在评论区留言(分享你碰到的问题以及解决方法)。

相关文献

在这里感谢各位的贡献!

《[Cake] 0. C#Make自动化构建-简介》

《2. dotnet 全局工具 cake》

《基于cake-build的dotnet自动化发布》

《Pushing Packages From Azure Pipelines To Azure Artifacts Using Cake》

AzureDevops Pipelines variables related documents

"Meet Azure DevOps"
reference project: CakePushNuGet.Example

Reference projects: cake.example

Guess you like

Origin www.cnblogs.com/AMortal/p/11100669.html