WangShuXian6 / blog

FE-BLOG
https://wangshuxian6.github.io/blog/
MIT License
46 stars 10 forks source link

Cake(C# Make) #172

Open WangShuXian6 opened 1 year ago

WangShuXian6 commented 1 year ago

Cake(C# Make)

文档 https://cakebuild.net/docs/ Cake(C# Make)是一个跨平台的构建自动化系统,具有用于编译代码、复制文件和文件夹、运行单元测试、压缩文件和构建NuGet包等任务的C# DSL。

它既可作为.NET工具使用,也可作为库在控制台应用程序中使用,并可在Windows、Linux和macOS上运行。

它默认包含许多不同的别名,让您可以快速编排构建流程,例如MSBuild、DotNet Core CLI、NuGet和Chocolatey。此外,还有来自社区的300多个插件和模块,允许您执行其他构建任务。

还有可用于编辑器、IDE以及构建系统的扩展,可以增强在处理Cake构建时的可用性。

入门 - 快速入门的教程 基础知识 - 关于Cake的基础知识 运行构建 - 如何运行您的Cake构建的信息 编写构建 - 如何编写构建的信息 集成 - 与编辑器、IDE和构建服务器的集成 扩展Cake - 如何使用自定义功能扩展Cake的文档 团队 - 维护团队为您提供Cake的团队

这些是关于Cake的文档资源,可帮助您深入了解和使用这个构建自动化工具。

以下文档为 Cake 3.1.0 翻译自官网 2023/10/3

WangShuXian6 commented 1 year ago

入门指南

创建新的Cake .NET工具项目

这是一个使用Cake .NET工具入门并向您展示Cake工作原理的指南。

选择您的运行环境

选择适合您情况的运行环境。有关运行Cake构建的其他可能方式,请参阅运行环境。

在本教程中,我们将在.NET Core 3.1及更高版本上使用Cake .NET工具。

确保在您的存储库中有一个工具清单可用,或者使用以下命令创建一个:

dotnet new tool-manifest

使用dotnet tool命令将Cake安装为本地工具(您可以将3.1.0替换为您要使用的不同Cake版本):

dotnet tool install Cake.Tool --version 3.1.0

有关引导过程的详细信息,请参阅引导Cake .NET工具。

创建初始构建脚本

创建一个名为build.cake的文件,其内容如下:

var target = Argument("target", "Test");
var configuration = Argument("configuration", "Release");

//////////////////////////////////////////////////////////////////////
// 任务
//////////////////////////////////////////////////////////////////////

Task("Clean")
    .WithCriteria(c => HasArgument("rebuild"))
    .Does(() =>
{
    CleanDirectory($"./src/Example/bin/{configuration}");
});

Task("Build")
    .IsDependentOn("Clean")
    .Does(() =>
{
    DotNetBuild("./src/Example.sln", new DotNetBuildSettings
    {
        Configuration = configuration,
    });
});

Task("Test")
    .IsDependentOn("Build")
    .Does(() =>
{
    DotNetTest("./src/Example.sln", new DotNetTestSettings
    {
        Configuration = configuration,
        NoBuild = true,
    });
});

//////////////////////////////////////////////////////////////////////
// 执行
//////////////////////////////////////////////////////////////////////

RunTarget(target);

运行构建脚本

使用.NET CLI运行构建脚本:

dotnet cake

创建新的Cake Frosting项目

这是一个入门指南,介绍了如何开始使用Cake Frosting,并向您展示Cake Frosting的工作原理。

安装和搭建

本教程使用Cake Frosting,它允许您将构建作为标准控制台应用程序的一部分编写,作为您解决方案的一部分。有关运行Cake构建的其他可能方式,请参阅运行环境。

以下说明要求Cake Frosting 1.0.0或更新版本,在.NET Core 3.1.301或更新版本上运行。您可以在https://dotnet.microsoft.com/download上找到.NET SDK。

要创建一个新的Cake Frosting项目,您需要安装Frosting模板:

dotnet new install Cake.Frosting.Template

创建一个新的Frosting项目:

dotnet new cakefrosting

这将创建Cake Frosting项目和引导脚本。

有关Cake Frosting引导过程的详细信息,请参阅Cake Frosting的引导。

初始构建项目

Program类包含配置和运行Cake主机的代码:

public static class Program
{
    public static int Main(string[] args)
    {
        return new CakeHost()
            .UseContext<BuildContext>()
            .Run(args);
    }
}

BuildContext类可用于添加额外的自定义属性。默认模板包含一个示例属性Delay,可以通过--delay参数进行设置。您可以删除此属性并根据您的特定需求自定义属性。

public class BuildContext : FrostingContext
{
    public bool Delay { get; set; }

    public BuildContext(ICakeContext context)
        : base(context)
    {
        Delay = context.Arguments.HasArgument("delay");
    }
}

该文件还包含了三个任务的类:

[TaskName("Hello")]
public sealed class HelloTask : FrostingTask<BuildContext>
{
    public override void Run(BuildContext context)
    {
        context.Log.Information("Hello");
    }
}

[TaskName("World")]
[IsDependentOn(typeof(HelloTask))]
public sealed class WorldTask : AsyncFrostingTask<BuildContext>
{
    // 任务可以是异步的
    public override async Task RunAsync(BuildContext context)
    {
        if (context.Delay)
        {
            context.Log.Information("等待...");
            await Task.Delay(1500);
        }

        context.Log.Information("World");
    }
}

[TaskName("Default")]
[IsDependentOn(typeof(WorldTask))]
public class DefaultTask : FrostingTask
{
}

默认任务依赖于World任务,而World任务依赖于Hello任务。如果设置了Delay属性,World任务是一个异步任务,会等待1.5秒。

示例构建流程

以下示例创建一个简单的构建流程,包括清理任务、编译MsBuild解决方案的任务以及测试解决方案的任务。

以下示例期望存储库根文件夹中有一个名为src/Example.sln的Visual Studio解决方案。您需要根据您的解决方案来调整路径。

添加所需的 using 语句:

using Cake.Common;
using Cake.Common.IO;
using Cake.Common.Tools.DotNet;
using Cake.Common.Tools.DotNet.Build;
using Cake.Common.Tools.DotNet.Test;

从BuildContext类中删除Delay属性,并添加一个MsBuildConfiguration属性,用于存储应该构建的解决方案的配置:

public class BuildContext : FrostingContext
{
    public string MsBuildConfiguration { get; set; }

    public BuildContext(ICakeContext context)
        : base(context)
    {
        MsBuildConfiguration = context.Argument("configuration", "Release");
    }
}

可以删除HelloTask和WorldTask类。

为清理目录创建一个名为CleanTask的新类:

[TaskName("Clean")]
public sealed class CleanTask : FrostingTask<BuildContext>
{
    public override void Run(BuildContext context)
    {
        context.CleanDirectory($"../src/Example/bin/{context.MsBuildConfiguration}");
    }
}

为构建解决方案创建一个名为BuildTask的新类:

[TaskName("Build")]
[IsDependentOn(typeof(CleanTask))]
public sealed class BuildTask : FrostingTask<BuildContext>
{
    public override void Run(BuildContext context)
    {
        context.DotNetBuild("../src/Example.sln", new DotNetBuildSettings
        {
            Configuration = context.MsBuildConfiguration,
        });
    }
}

为测试解决方案创建一个名为TestTask的新类:

[TaskName("Test")]
[IsDependentOn(typeof(BuildTask))]
public sealed class TestTask : FrostingTask<BuildContext>
{
    public override void Run(BuildContext context)
    {
        context.DotNetTest("../src/Example.sln", new DotNetTestSettings
        {
            Configuration = context.MsBuildConfiguration,
            NoBuild = true,
        });
    }
}

更新DefaultTask类以调用新任务:

[IsDependentOn(typeof(TestTask))]
public sealed class Default : FrostingTask
{
}

运行构建脚本

Windows

./build.ps1

Linux


build.sh

>MacOS

build.sh


>有关如何运行Cake Frosting构建的详细信息,请参阅Cake Frosting https://cakebuild.net/docs/running-builds/runners/cake-frosting

***

## 常见问题
>如何锁定正在使用的Cake版本?
>请查看锁定Cake版本。[Pinning Cake Version](https://cakebuild.net/docs/writing-builds/reproducible-builds/pinning-cake-version).

>如何锁定正在使用的插件(Addin)版本?
>请查看锁定插件版本。 [Pinning Addin Version](https://cakebuild.net/docs/writing-builds/reproducible-builds/pinning-addin-version).

>如何锁定正在使用的工具(Tool)版本?
>请查看锁定工具版本。 [Pinning Tool Version](https://cakebuild.net/docs/writing-builds/reproducible-builds/pinning-tool-version).

>如何锁定正在使用的模块(Module)版本?
>请查看锁定模块版本。 [Pinning Module Version](https://cakebuild.net/docs/writing-builds/reproducible-builds/pinning-module-version).

>如何在Cake中启用不同的日志详细程度?
>这个问题已经在Stack Overflow的一个问题中得到了回答。[Stack Overflow question](https://stackoverflow.com/questions/38658660).

***

## 支持生命周期
### 版本管理
>Cake使用语义化版本控制(Semantic Versioning)。这意味着1.0.1版本只包含与1.0版本相比的错误修复,而1.1版本只包含向后兼容的新功能。2.0版本将包含与1.0版本相比的破坏性变更。

### 支持生命周期
>我们支持当前主要版本,提供最新版本的bug修复支持。

>主要版本将在下一个主要版本发布之前得到支持。一旦发布了更新的主要版本,对先前版本的支持就结束了。这意味着一旦2.0版本发布,我们将不再发布任何1.x版本的修复。

>Cake支持生命周期

![image](https://github.com/WangShuXian6/blog/assets/30850497/7626d5d7-0634-43f4-aa36-d568399e7016)

***

## 升级说明
>要更新Cake,请按照以下说明进行操作:

>Cake .NET工具
>使用.NET工具作为本地工具时:
```bash
dotnet tool install --local Cake.Tool

使用.NET工具作为全局工具时:

dotnet tool install --global Cake.Tool

Cake Frosting 更新Cake.Frosting NuGet包的版本。

.NET Framework的Cake运行时 更新tools\packages.config文件中Cake包的版本。

.NET Core的Cake运行时 更新tools\packages.config文件中的Cake.CoreCLR包版本。

从Cake 2.x升级到Cake 3.0

Cake 3.0是一个包含破坏性变更的主要版本。

所需的.NET版本

Cake将不再在.NET Core 3.1或.NET 5上运行,但Cake将继续支持构建.NET Framework项目以及针对.NET 5.0或更早版本的项目。

Cake 3.0.0的支持平台矩阵如下:

运行时 .NET 7 .NET 6
Cake .NET工具 支持 支持
Cake Frosting 支持 支持

DotNet别名

已删除DotNetCore*别名,并替换为DotNet*别名。

Frosting生命周期

现在,Cake Frosting生命周期还需要一个ISetupContext实例。

FrostingLifetime实现从

public class BuildLifetime : FrostingLifetime<BuildContext>
{
    public override void Setup(BuildContext context)
    {}
}

更改为

public class BuildLifetime : FrostingLifetime<BuildContext>
{
    public override void Setup(BuildContext context, ISetupContext info)
    {}
}

从Cake 1.x升级到Cake 2.0

Cake 2.0是一个包含破坏性变更的主要版本。

支持的运行时和所需的.NET版本

为了使Cake能够利用现代平台功能、为扩展作者简化工作并简化用户的决策过程,我们决定停止在2.0中发布.NET Framework的Cake运行时以及已经弃用的.NET Core的Cake运行时。此外,我们还取消了对Cake.NET工具和Cake Frosting中运行.NET Core 2.1和.NET Core 3.0的支持。

这意味着,从Cake 2.0开始,您需要在构建机器上安装.NET SDK,至少需要.NET Core 3.1,但建议使用.NET 6,以便运行Cake。换句话说,Cake本身将不再在.NET Framework、Mono和.NET Core 3.0或更早版本上运行。Cake将继续支持构建.NET Framework项目以及针对.NET Core 3.0或更早版本的项目。

Cake 2.0的支持平台矩阵如下:

运行时 .NET 6 .NET 5 .NET Core 3.1
Cake .NET工具 支持 支持 支持
Cake Frosting 支持 支持 支持

由于不再发布Cake运行.NET Framework的版本,我们还将停止发布Cake.Portable Chocolatey包和Homebrew Cake公式。

自Cake.NET工具的1.0版本起,已弃用Cake运行.NET Core,并建议使用Cake.NET工具作为替代。对于使用Cake运行.NET Framework的用户,建议切换到Cake.NET工具,并在.NET Core 3.1或更新版本上运行构建。对于依赖于扩展或其他依赖项,需要.NET Framework或.NET Core 3.0或更早版本的用户,建议保持在Cake 1.x上。

有关详细信息,请参阅Cake 2.0中.NET Framework和.NET Core运行时的淘汰。

Cake Frosting

已删除的ReverseDependencyAttribute和DependencyAttribute。ReverseDependencyAttribute可以替换为IsDependeeOfAttribute,DependencyAttribute可以替换为IsDependentOnAttribute。

有关详细信息,请参见#3003和#3577。

Azure Pipelines构建提供程序更新

IsRunningOnAzurePipelines和IsRunningOnAzurePipelinesHosted属性 使用Cake 1.x时,IAzurePipelinesProvider.IsRunningOnAzurePipelines如果在自托管代理上运行构建,则返回true。要检查构建是否在Azure Pipelines上运行,无论使用哪种类型的代理,需要检查两个属性:

var isRunningOnAzurePipelines =
    BuildSystem.AzurePipelines.IsRunningOnAzurePipelines || BuildSystem.AzurePipelines.IsRunningOnAzurePipelinesHosted;

使用Cake 2.0后,IAzurePipelinesProvider.IsRunningOnAzurePipelines和BuildSystem.IsRunningOnAzurePipelines属性的含义已更改,仅用于检查构建是否在Azure Pipelines上运行。

要检查构建是否在Microsoft托管的或自托管的代理上运行,可以使用IsHosted属性:

var isMicrosoftHostedAgent =
    BuildSystem.AzurePipelines.Environment.Agent.IsHosted;

已删除IAzurePipelinesProvider.IsRunningOnAzurePipelinesHosted和BuildSystem.IsRunningOnAzurePipelinesHosted属性,需要用上述代码替换它们。此外,已删除了BuildProvider.AzurePipelinesHosted枚举值。

有关详细信息,请参见#3654。

AzurePipelinesBuildInfo属性数据类型

AzurePipelinesBuildInfo.ArtifactStagingDirectory、AzurePipelinesBuildInfo.BinariesDirectory、>AzurePipelinesBuildInfo.SourcesDirectory、AzurePipelinesBuildInfo.StagingDirectory和>AzurePipelinesBuildInfo.TestResultsDirectory的数据类型已从FilePath更改为DirectoryPath。

有关详细信息,请参见#3590。

删除的TFBuildProvider

已弃用的TFBuildProvider已删除。它可以替换为AzurePipelinesProvider。

有关详细信息,请参见#3610。

MsBuild和dotnet支持

新的dotnet别名

已弃用现有的DotNetCore别名,并应替换为新的DotNet别名。

有关详细信息,请参见#3341。

Xamarin.iOS平台目标支持

已向MSBuildSettings.PlatformTarget添加了PlatformTarget.ARMv6、PlatformTarget.ARMv7和PlatformTarget.ARMv7s,以支持Xamarin.iOS。

有关详细信息,请参见#3222。

工具支持

GitVersion

GitVersionVerbosity已更新,以与当前版本的GitVersion中的详细程度匹配。

有关详细信息,请参见#3282。

OpenCover

在Cake 1.x中,OpenCoverSettings具有类型为string的Register属性,可以为空以进行管理员模式、用户模式或DLL的路径:

OpenCover(x => {
    x.NUnit3(tests);
},
    coverageFile,
    new OpenCoverSettings{
        Register = "some-path-to-dll"
    }
);

在Cake 2.0中,OpenCoverSettings.Register已更改为OpenCoverRegisterOption类型。还有额外的OpenCoverSettings扩展方法:

OpenCover(x => {
    x.NUnit3(tests);
},
    coverageFile,
    new OpenCoverSettings()
        .WithoutRegister() //省略注册设置
        .WithRegisterAdmin() // -register
        .WithRegisterUser() // -register:user <--这是默认值
        .WithRegisterDll(someFilePath) // -register:path-to-dll
);

有关详细信息,请参见#2788。

从Cake 1.0.0升级到Cake 1.1.0

Cake.DotNetTool.Module

从这个版本开始,Cake.DotNetTool.Module将始终与Cake一起发布,并且只与当前版本兼容。

如果您已经在构建中使用了Cake.DotNetTool.Module,请从构建脚本中删除Cake.DotNetTool.Module,因为它不再需要。

从Cake 0.38.x升级到Cake 1.0.0

Cake 1.0是一个包含破坏性变更的主要版本。

替换已弃用的成员

在先前版本中标记为已弃用的成员已在Cake 1.0中删除。请更新为已弃用消息中建议的成员。

Cake Frosting

删除了CakeHostBuilder 已删除CakeHostBuilder。在Cake Frosting 1.0中,可以直接使用CakeHost来创建CakeHost对象。

在Cake Frosting 0.38.x中:

// 创建主机。
var host =
    new CakeHostBuilder()
       .WithArguments(args)
       .UseStartup<Program>()
       .Build();

// 运行主机。
return host.Run();

在Cake Frosting 1.0中:

// 创建和运行主机。
return
    new CakeHost()
        .UseContext<BuildContext>()
        .Run(args);

删除ICakeServices

已删除ICakeServices。在Cake Frosting 1.0中,您不再需要在Program类中实现IFrostingStartup接口。配置可以直接在CakeHost对象上完成。

在Cake Frosting 0.38.x中:

public class Program : IFrostingStartup
{
    public static int Main(string[] args)
    {
        // 创建主机。
        var host =
            new CakeHostBuilder()
                .WithArguments(args)
                .UseStartup<Program>()
                .Build();

        // 运行主机。
        return host.Run();
    }

    public void Configure(ICakeServices services)
    {
        services.UseContext<BuildContext>();
        services.UseLifetime<Lifetime>();
        services.UseWorkingDirectory("..");
    }
}

在Cake Frosting 1.0中:

public class Program : IFrostingStartup
{
    public static int Main(string[] args)
    {
        // 创建和运行主机。
        return
            new CakeHost()
                .UseContext<BuildContext>()
                .UseLifetime<Lifetime>()
                .UseWorkingDirectory("..")
                .Run(args);
    }
}

工具安装改进

不再需要手动注册Cake Frosting的nuget模块。在Cake Frosting中安装工具的方法也已从UseTool更名为InstallTool:

在Cake Frosting 0.38.x中:

public class Program : IFrostingStartup
{
    public static int Main(string[] args)
    {
        // 创建主机。
        var host =
            new CakeHostBuilder()
                .WithArguments(args)
                .UseStartup<Program>()
                .Build();

        // 运行主机。
        return host.Run();
    }

    public void Configure(ICakeServices services)
    {
        // 注册NuGet模块。
        var module = new NuGetModule(new CakeConfiguration(new Dictionary<string, string>()));
        module.Register(services);

        // 注册工具。
        services.UseTool(new Uri("nuget:?package=NUnit.ConsoleRunner&version=3.11.1"));
    }
}

在Cake Frosting 1.0中:

public class Program : IFrostingStartup
{
    public static int Main(string[] args)
    {
        // 创建和运行主机。
        return
            new CakeHost()
                .InstallTool(new Uri("nuget:?package=NUnit.ConsoleRunner&version=3.11.1"));

 .Run(args);
    }
}

Cake CLI更新

作为Cake 1.0的一部分,CLI的重写使得开关的解析现在更严格。

参数语法

在Cake 1.0中,参数应始终使用多破折号语法调用(例如--target=Foo)。当使用单破折号语法(例如-target=Foo)时,将显示类似以下的错误消息:

Error: Unknown command 'Foo'.
       build.cake -target=Foo
                          ^^^^^^ No such command

传递空参数

在以前的Cake版本中,可以定义一个空参数(例如--foo=)或传递一个空值(例如--foo="")。

在Cake 1.0中,将显示类似以下的错误消息:

Error: Expected an option value.

与Cake 1.0的一个关键差异是,除了键/值参数(--key=value),它还支持标志(--flag)以及具有相同名称的多个参数(--key=value1 --key=value2),这比以前更灵活。

在Cake 1.0中,如果值可以为空或null,则使用空格代替=:

--foo ""

如果使用此语法从CI系统传递变量,可以在参数和值之间使用空格作为分隔符:

--foo %myvariable%

Azure DevOps构建任务扩展

确保使用至少版本2.1的Azure DevOps构建任务扩展和版本2.*的任务与Cake 1.0一起使用。


WangShuXian6 commented 1 year ago

基础知识

别名:在Cake构建中使用的便捷方法 扩展:扩展Cake以增加额外功能 工具:与外部工具一起使用的方法

别名

Cake支持一种称为别名的功能。别名是方便的方法,可以直接从Cake构建中轻松访问。在Cake中,每个DSL方法都像别名方法一样实现。

请查看参考文档以获取可用别名的列表。

调用别名

别名是ICakeContext的扩展方法。

在Cake .NET工具中调用别名

在使用Cake .NET工具的Cake脚本时,别名可以直接在任务中调用,无需显式传递上下文:

Task("Clean")
    .Does(() =>
{
    // 删除文件。
    DeleteFile("./file.txt");

    // 清理目录。
    CleanDirectory("./temp");
});

在Cake Frosting中调用别名

在Cake Frosting项目中,别名可以作为传递给任务的Run方法的上下文的扩展方法调用:

public sealed class Clean : FrostingTask<Context>
{
    public override void Run(Context context)
    {
        // 删除文件。
        context.DeleteFile("./file.txt");

        // 清理目录。
        context.CleanDirectory("./temp");
    }
}

自定义别名

可以在插件中定义额外的别名。


扩展

插件:通过额外别名扩展Cake 模块:用于增强、更改或替换Cake的扩展 配方:在多个构建之间共享任务

插件

插件可以为Cake构建提供额外的别名。它们是作为NuGet包提供的.NET程序集。

可用插件 请查看扩展以获取由社区维护的插件列表。

编写自定义插件 请查看文档以了解如何编写自定义插件。

模块

模块是Cake的特殊组件,旨在增强、更改或替换Cake本身的内部逻辑。模块可以用于替换内置的Cake构建日志、进程运行器或工具定位器,仅举几例。在内部,这是Cake管理其“运作部分”的方式,但您还可以在运行构建脚本的过程中加载模块,这将允许您在构建代码的一部分中替换/更改Cake的工作方式。

可用模块 请查看扩展以获取由社区维护的模块列表。

编写自定义模块 请查看文档以了解如何编写自定义模块。

示例 Recipes

Cake构建脚本可以发布为NuGet包,称为Recipes示例。这些包可以包含共享任务,并可以被其他构建脚本使用。

请查看示例NuGet包以获取编写和使用Cake示例的说明。

工具

在构建过程中,需要执行诸如编译、代码检查、测试等任务。Cake本身仅是一个构建编排器。为了完成前面提到的任务,Cake会调用不同的工具(如MsBuild、NUnit等)。

Cake支持安装分发为NuGet包的工具,并提供在运行时查找工具位置的逻辑。

有关详细信息,请参阅工具操作。

WangShuXian6 commented 1 year ago

运行构建

运行器:有关不同构建运行器的信息 配置:有关配置Cake的信息

运行器

Cake有两种不同的版本,需要不同的运行器:

版本 运行器
Cake脚本 Cake .NET工具
标准.NET控制台应用程序 Cake Frosting

控制台应用程序具有完整的IDE支持,如智能感知、重构和调试,但需要一个完整的.NET项目。脚本化方法可以更容易地解决简单的构建场景,因为它允许使用单个文件。

功能概述

运行器 最低要求的.NET版本 支持 智能感知
Cake .NET工具 .NET 6 [1]√
Cake Frosting .NET 6

[1]:在Visual Studio Code中有限支持。请参阅Visual Studio Code中的智能感知

支持的操作系统

以下表格显示了每个运行器支持的操作系统。

运行器 Windows macOS Linux
Cake .NET工具
Cake Frosting

支持的平台

以下表格显示了每个运行器支持的平台。

请注意,运行构建的平台不会限制其构建能力。例如,可以在运行.NET 6的Cake上构建.NET Framework应用程序。

运行器 .NET 6 .NET 5 .NET Core 3.1
Cake .NET工具
Cake Frosting

支持的构建系统

以下表格显示了Cake提供特定集成的构建系统。

Cake可以在任何构建系统上运行,即使不包含在此列表中。对于列出的构建系统,Cake提供了开箱即用的集成。有关详细信息,请参阅构建系统。

运行器 AppVeyor Azure Pipelines Bamboo Bitbucket Pipelines Bitrise Continua CI GitHub Actions GitLab CI GoCD Jenkins MyGet TeamCity TravisCI
Cake .NET工具
Cake Frosting

Cake .NET Tool

Cake .NET Tool是一种运行Cake脚本的工具。

有关如何开始使用Cake .NET Tool的教程,请参阅“设置新的Cake .NET Tool项目”教程。

要求

Cake.Tool NuGet包是为.NET Core 3.1或更新版本编译的.NET Core工具。

用法

dotnet cake [脚本] [开关]
开关
开关 描述 最低可用版本
--bootstrap 下载/安装由#module指令定义的模块,但不运行构建。从1.0.0-rc0001开始,运行构建时默认进行引导。 0.24.0
-d, --debug 以调试模式启动脚本。 0.12.0
--description 显示有关任务的描述。 0.1.10
--dryrun 执行干运行。 0.2.0
-e, --exclusive 执行单个任务,没有任何依赖项。 0.29.0
-h, --help 打印帮助信息。 0.1.12
--info 显示有关Cake执行的附加信息。 0.31.0
--skip-bootstrap 运行构建时跳过引导。 1.0.0-rc0001
--tree 显示任务依赖关系树。 0.31.0
-v, --verbosity 指定要显示的信息量(安静,最小,正常,详细,诊断)。 0.1.1
--version 显示版本信息。 0.1.12

--target=<target> 不是运行工具的开关,而是脚本通常用来调用特定任务的自定义开关。

自定义开关

Cake未识别的所有开关都将添加到传递给构建脚本的参数列表中。有关如何在脚本中读取参数的详细信息,请参阅参数和环境变量。

如果开关的值可以为空或null,使用空格代替=

--foo ""

用于.NET Tool的引导

引导脚本确保已安装Cake和其他必需的依赖项。引导程序脚本还负责调用Cake。

以下说明要求.NET Core 3.0或更新版本。有关详细信息和其他选项,请参阅如何管理.NET Core工具。

安装

配置仓库以使用Cake .NET工具需要一次性设置。

如果您的环境中已经有.NET Tool,可以跳过本章中的步骤。

确保在您的存储库中有一个工具清单,或者使用以下命令创建一个:

dotnet new tool-manifest

使用dotnet tool命令将Cake安装为本地工具:

dotnet tool install Cake.Tool --version 3.1.0

您可以将3.1.0替换为您想要使用的Cake的不同版本。

获取引导程序

使用引导程序是可选的。如果您喜欢,也可以直接调用.NET CLI。

Cake .NET工具的引导程序位于Cake资源存储库中,可以使用下面的命令之一安装,具体取决于您的操作系统:

1-Windows

打开新的PowerShell窗口,并运行以下命令:

Invoke-WebRequest https://cakebuild.net/download/bootstrapper/dotnet-tool/windows -OutFile build.ps1

有时,PowerShell可能会阻止您运行build.ps1。请确保启用了RemoteSigned策略。有关详细信息,请参阅执行策略。

如果已启用RemoteSigned策略,但仍然出现错误,可能是因为文件是从Internet下载并被阻止了。以下命令将解锁文件:

Unblock-File path\to\build.ps1

有关详细信息,请参阅Unblock-File。

2-Linux

打开一个新的Shell窗口,运行以下命令:

curl -Lsfo build.sh https://cakebuild.net/download/bootstrapper/dotnet-tool/linux

如果您在Windows机器上下载build.sh文件,可以使用以下命令为脚本授予执行权限:

git update-index --add --chmod=+x build.sh

这假设您已安装了Git命令行工具。

3-MacOS

打开一个新的Shell窗口,运行以下命令:

curl -Lsfo build.sh https://cakebuild.net/download/bootstrapper/dotnet-tool/osx

如果您在Windows机器上下载build.sh文件,可以使用以下命令为脚本授予执行权限:

git update-index --add --chmod=+x build.sh

这假设您已安装了Git命令行工具。

运行构建脚本

要启动Cake,请运行引导程序:

1-Windows

打开新的PowerShell窗口,并运行以下命令:

./build.ps1

按照约定,这将执行名为build.cake的构建脚本。您可以通过另外传递构建脚本的名称来覆盖此行为。

2-Linux / MacOS

打开一个新的Shell窗口,运行以下命令:

./build.sh

按照惯例,这将执行名为build.cake的构建脚本。您还可以通过额外传递构建脚本的名称来覆盖此行为。

扩展引导程序

直接从cakebuild.net获取的引导程序是一个起点,可以用于解决您自己的要求。扩展引导程序取决于开发人员的自由裁量权。

使用预发布版本

Cake使用Azure Artifacts作为NuGet feed用于测试和预发布构建。使用这些预发布构建可以访问并利用Cake的下一个版本,以获取最新功能,或测试addins或构建脚本,以了解在您需要升级时下一个发布是否安全。


Cake Frosting

Cake Frosting是一个.NET主机,允许您将构建脚本编写为控制台应用程序。

请参阅“设置新的Cake Frosting项目”教程,了解如何开始使用Cake Frosting。

要求

Cake.Frosting可用于编写针对netcoreapp3.1或更新版本的控制台应用程序。

用法

dotnet Cake.Frosting.dll [开关]
开关 Switches
开关 描述 最低可用版本
--description 显示有关任务的描述。 1.0.0-rc0002
--dryrun 执行干运行。 0.30.0
-e、--exclusive 执行没有任何依赖项的单个任务。 1.0.0-rc0002
-h、--help 打印帮助信息。 0.30.0
--info 显示有关Cake执行的附加信息。 1.0.0-rc0002
-t、--target 设置构建目标。默认值为Default。 0.30.0
--tree 显示任务依赖关系树 1.0.0-rc0002
-v、--verbosity 指定要显示的信息量(quiet、minimal、normal、verbose、diagnostic)。 0.30.0
--version 显示Cake.Frosting版本号。 0.30.0
-w、--working 设置工作目录。 0.30.0
自定义开关

所有未被Cake识别的开关都将添加到传递给构建脚本的参数列表中。请参阅关于如何在您的脚本中读取参数的“参数和环境变量”。

如果开关的值可以为空或为null,请使用空格而不是=

--foo ""

Cake Frosting的引导

从模板创建新的Cake Frosting项目时,默认会创建适用于Windows、macOS和Linux的引导脚本。

以下说明需要.NET Core 3.1.301或更新版本。您可以在https://dotnet.microsoft.com/download上找到SDK。

设置

要创建一个新的Cake Frosting项目,您需要安装Frosting模板:

dotnet new --install Cake.Frosting.Template

创建一个新的Frosting项目:

dotnet new cakefrosting

这将创建Cake Frosting项目和引导脚本。

运行构建脚本

运行构建脚本:

1-Windows

./build.ps1

如果在没有明确指定目标的情况下启动构建脚本,则将运行默认目标。

2-Linux \ MacOS

build.sh

使用预发布版本

Cake使用Azure Artifacts作为NuGet源来进行测试和预发布构建。使用这些预发布构建,可以访问并利用Cake的下一个版本,以获取最新功能,或测试插件或构建脚本,以了解下一个发布是否安全,以便在需要升级时使用。


已弃用

以前的Cake版本附带了以下其他的运行时:

运行时 最低要求的.NET版本 支持的Cake版本
.NET Framework的Cake运行时 .NET Framework 4.6.1或Mono 5.0.12 0.x, 1.x
.NET Core的Cake运行时 .NET Core 2.0 0.x, 1.x

待补充


配置

Cake可以进行配置,以便您可以在构建期间控制Cake的内部操作方式。

设置配置值 设置配置值的方式 默认配置值 可用的配置选项 自定义配置 自定义配置

设置配置值

目前,Cake Frosting不支持配置。

Cake .NET Tool支持外部配置的概念,允许根据指定的优先级控制Cake的内部操作方式,可以从以下位置控制:

这些配置选项按照上述顺序进行优先级排序。这意味着配置文件会覆盖任何环境变量,并且直接传递给Cake的参数会覆盖环境变量和配置文件设置。

举个可以应用可覆盖配置的示例,让我们看看Cake如何确定从哪里下载NuGet包。默认情况下,Cake会通过下载用户配置的NuGet包源来执行此操作。然而,可能需要(例如,在离线/本地环境中运行时)从替代源下载这些NuGet包。这就是Cake配置发挥作用的地方。

请参阅默认配置值,了解所有可用的配置选项列表。

环境变量

通过创建一个名为CAKE_NUGET_SOURCE的环境变量,并将值设置为所需的URL,Cake将使用此替代下载源,而不是默认源。

配置文件

或者,您可以创建一个具有以下内容的cake.config文件:

; Cake的配置文件。

[Nuget]
Source=https://mycustomurl

配置文件应位于与您的Cake脚本相同的目录中。

在配置文件中指定的配置值将覆盖等效环境变量中存储的相同配置值。

环境变量替换

配置文件支持对值(等号右侧)进行环境变量替换。不能将节和键替换为环境变量。

在以下示例中,如果将NUGET_REPOSITORY设置为环境变量,那么当Cake读取配置文件时,它的值将替换为%NUGET_REPOSITORY%:

Source=https://%NUGET_REPOSITORY%/api/v2

环境变量替换仅适用于值,并且必须使用带有%符号的Windows注释语法,无论操作系统如何。

命令行

最后,您可以以以下格式直接向Cake指定输入参数:

--nuget_source=http://mycustomurl

直接将配置值传递给Cake将覆盖环境变量中存储的相同配置值以及本地配置文件中存储的配置值。

默认配置值

目前,Cake Frosting 不支持配置。

以下显示了当前在 Cake .NET Tool 中可用的所有配置选项以及它们的默认值。

有关如何使用配置文件设置配置值的说明,请参阅设置配置值。

插件 NuGet 依赖项

自 Cake 0.22.0 起可用。

当使用 In-Process NuGet 安装时,您还可以选择自动安装和引用 NuGet 包依赖项。

默认值:false

有效值:true、false

环境变量名称

CAKE_NUGET_LOADDEPENDENCIES

配置文件内容

[NuGet]
LoadDependencies=true

参数名称

--nuget_loaddependencies=true

插件路径

允许配置用于恢复插件的插件文件夹。

默认值:./tools/Addins

环境变量名称

CAKE_PATHS_ADDINS

配置文件内容

[Paths]
Addins=./tools/Addins

参数名称

--paths_addins=./tools/Addins

缓存已编译的脚本到磁盘

自 Cake 2.2.0 起可用。

这允许 Cake .NET Tool 缓存脚本编译,以便在未更改脚本的情况下,后续执行脚本速度显著提高。

默认值:false

有效值:true、false

环境变量名称

CAKE_SETTINGS_ENABLESCRIPTCACHE

配置文件内容

[Settings]
EnableScriptCache=true

参数名称

--settings_enablescriptcache=true

缓存位置路径

自 Cake 2.2.0 起可用。

这允许配置文件夹的配置,该文件夹由 Cake .NET Tool 用于缓存编译的脚本。

默认值:./tools/cache

环境变量名称

CAKE_PATHS_CACHE

配置文件内容

[Paths]
Cache=./tools/cache

参数名称

--paths_cache=./tools/cache

禁用输出文本中的颜色

自 Cake 1.1.0 起可用。

默认情况下,当 Cake 检测到正在运行支持 ANSI 转义代码的环境时,它会输出带颜色的文本。

要禁用带颜色的文本输出,请设置名为 NO_COLOR 的环境变量并赋予任何值。

环境变量名称

NO_COLOR

In-Process NuGet 安装

自 Cake 0.25.0 起可用。

自 Cake 0.25.0 起,默认情况下使用 In-Process NuGet 客户端。如果您需要使用 NuGet.exe,可以通过将该值设置为 false 来选择退出。

默认值:true

有效值:true、false

环境变量名称

CAKE_NUGET_USEINPROCESSCLIENT

配置文件内容

[NuGet]
UseInProcessClient=false

参数名称

--nuget_useinprocessclient=false

模块路径

允许配置加载自定义模块时 Cake 使用的模块文件夹。

默认值:./tools/Modules

环境变量名称

CAKE_PATHS_MODULES

配置文件内容

[Paths]
Modules=./tools/Modules

参数名称

--paths_modules=./tools/Modules

NuGet 配置文件路径

允许配置 NuGet 配置文件的路径,以覆盖默认文件。

默认值:如果未指定 NuGet 配置,则将使用 NuGet 的默认机制来解析它。

环境变量名称

CAKE_NUGET_CONFIGFILE

配置文件内容

[NuGet]
ConfigFile=./NuGet.config

参数名称

--nuget_configfile=./NuGet.config

NuGet 下载 URL

允许控制 Cake 下载 NuGet 包的位置,当使用插件和工具预处理指令时,这可能在需要在离线模式下工作时非常有用,即无法直接访问 nuget.org。

可以通过分号分隔的多个来源来传递多个源。

默认值:https://api.nuget.org/v3/index.json

环境变量名称

CAKE_NUGET_SOURCE

配置文件内容 使用单个源:

[Nuget]
Source=http://myfeed/nuget/

使用多个源:

[Nuget]
Source=http://myfeed/nuget/;http://myotherfeed/nuget>参数名称

参数名称 使用单个源:

--nuget_source=http://myfeed/nuget/

使用多个源:

--nuget_source=http://myfeed/nuget/;http://myotherfeed/nuget

显示进程命令行

当 Cake 运行工具时,当使用诊断日志详细程度时,默认行为是仅在使用时记录文件名和参数。此设置将指示 Cake 始终记录文件名和参数,无论日志详细程度设置如何。

默认值:false

有效值:true、false

环境变量名称

CAKE_SETTINGS_SHOWPROCESSCOMMANDLINE

配置文件内容

[Settings]
ShowProcessCommandLine=true

参数名称

--settings_showprocesscommandline=true

跳过验证

如果对 Cake 引入任何破坏性更改,我们将设置最低支持的 Cake.Core 程序集版本。任何引用较旧版本的 Cake.Core 的插件/程序集都将生成异常,并最终中止脚本的执行。这是为了避免在执行脚本期间发生运行时错误。

但如果您真的需要使用插件/程序集,并已经验证引入的破坏性更改不直接涉及插件/程序集,即它不使用已删除的属性或更改的接口,对于这种情况,我们将允许您暂时退出程序集验证,直到插件/程序集作者发布一个定位到 Cake.Core 最低所需版本的程序集版本。

此设置对您的脚本引用的所有插件/程序集都是全局的,因此应将其视为临时的快速修复。

默认值:false

有效值:true、false

环境变量名称

CAKE_SETTINGS_SKIPVERIFICATION

配置文件内容

[Settings]
SkipVerification=true

参数名称

--settings_skipverification=true

工具路径

允许配置在恢复工具时 Cake 使用的工具文件夹。

默认值:./tools

环境变量名称

CAKE_PATHS_TOOLS

配置文件内容

[Paths]
Tools=./tools

参数名称

--paths_tools=./tools

启用高级控制台输出

自 Cake 3.0.0 起可用。

当启用时(即设置为 true),Cake 的控制台输出将通过 Spectre.Console 库呈现。这包括在构建结束时的任务摘要表中的一个附加列,该列列出了为什么在构建期间跳过任务的原因(如果可用)。

默认值:false

有效值:true、false

环境变量名称

CAKE_SETTINGS_USESPECTRECONSOLEFORCONSOLEOUTPUT

配置文件内容

CAKE_SETTINGS_USESPECTRECONSOLEFORCONSOLEOUTPUT

参数名称

CAKE_SETTINGS_USESPECTRECONSOLEFORCONSOLEOUTPUT

自定义配置

当前不支持为 Cake Frosting 进行配置。

除了 Cake 中可用的内置配置外,还可以使用自定义配置。

与内置配置类似,自定义配置也分为不同的部分和键。

访问配置值

可以使用 IConfiguration.GetValue 来访问配置。部分和键需要用下划线(_)分隔。配置的访问不区分大小写。

var value = Context.Configuration.GetValue("MySection_MyKey");

设置配置值

环境变量

# 通过在前缀 'CAKE_' 后加上部分和键的下划线来设置环境变量。
[Environment]::SetEnvironmentVariable("CAKE_MYSECTION_MYKEY", "MyValue", [EnvironmentVariableTarget]::User)

cake.config 文件

; Use the ini-format to set a section and provide key-value-pairs.
[MySection]
MyKey=MyValue

命令行

# provide the setting as option to the command line
# by separating section and key with an underscore.
dotnet cake build.cake --MySection_MyKey=MyValue
WangShuXian6 commented 1 year ago

编写构建

任务 如何编写任务 设置和拆卸 设置和拆卸事件 运行目标 如何运行目标和任务 参数和环境变量 如何处理参数和环境变量 预处理器指令 可用的预处理器指令 控制台输出 如何将内容输出到控制台 可重复生成的构建 如何实现可重复生成的构建 共享构建状态 如何在任务之间共享状态 工具 如何使用外部工具 重用构建 如何在不同项目和仓库中重用构建代码

任务

任务在 Cake 中代表了一个工作单元,您可以使用它们按特定顺序执行特定工作。一个任务可以具有依赖关系、条件和与之相关的错误处理,例如。

定义任务 如何定义任务 依赖关系 如何使任务相互依赖 条件 如何为任务定义条件 为集合运行任务 如何运行集合项的代码 错误处理 如何在任务中实现错误处理 最终块 如何确保始终执行某个任意代码块 异步任务 如何在构建脚本中使用异步代码

定义任务

在 Cake .NET Tool 中定义任务

要在 Cake .NET Tool 脚本中定义任务,请使用 Task 方法:

Task("A")
    .Does(() =>
{
});

在 Cake .NET Tool 脚本中,每个任务在执行时可以有一个或多个要执行的操作。可以使用 Does(参见上文)和 DoesForEach(参见用于集合的任务)方法来定义这些操作。这两种方法都可以链接在一起,以定义每个任务的多个操作。例如:

Task("A")
.Does(() => 
{
   Information("这个动作首先运行。");
}).DoesForEach(GetFiles("./**/*"), f => 
{
   Information("找到文件:" + f);
}).Does(() => {
   Information("这个动作最后运行。");
});

在 Cake Frosting 中定义任务

要在 Cake Frosting 中定义任务,请创建一个继承自 FrostingTask 的类:

[TaskName("A")]
public class TaskA : FrostingTask
{
}

要定义 Cake Frosting 中任务的操作,请重写 Run 方法:

[TaskName("A")]
public class TaskA : FrostingTask<Context>
{
    public override void Run(Context context)
    {
        context.Information("这个任务运行...");
    }
}

依赖关系

任务依赖关系

Cake .NET Tool 中的任务依赖关系

在 Cake .NET Tool 中,可以使用 IsDependentOn 方法来定义对另一个任务的依赖关系。

Task("A")
    .Does(() =>
{
});

Task("B")
    .IsDependentOn("A")
    .Does(() =>
{
});

RunTarget("B");

这将按预期先执行目标 A,然后执行 B。

Cake Frosting 中的任务依赖关系

在 Cake Frosting 中,可以使用 IsDependentOn 属性来定义对另一个任务的依赖关系。
[TaskName("A")]
public sealed class TaskA : FrostingTask
{
    public override void Run()
    {
    }
}

[TaskName("B")]
[IsDependentOn(typeof(TaskA))]
public sealed class TaskB : FrostingTask
{
    public override void Run()
    {
    }
}

当执行任务 B 时,它将确保任务 A 已在之前执行。

反向任务依赖关系

Cake .NET Tool 中的反向任务依赖关系

自 Cake 0.23.0 起可用。

在 Cake .NET Tool 中,可以使用 IsDependeeOf 方法来定义反向关系的依赖关系。

前面示例中的任务定义将与以下示例相同:

Task("A")
    .IsDependeeOf("B")
    .Does(() =>
{
});

Task("B")
    .Does(() =>
{
});

RunTarget("B");

Cake Frosting 中的反向任务依赖关系

在 Cake Frosting 中,可以使用 IsDependeeOf 属性来定义反向关系的依赖关系。

前面示例中的任务定义将与以下示例相同:

[TaskName("A")]
[IsDependeeOf(typeof(TaskB))]
public sealed class TaskA : FrostingTask
{
    public override void Run()
    {
    }
}

[TaskName("B")]
public sealed class TaskB : FrostingTask
{
    public override void Run()
    {
    }
}

多个依赖关系

Cake .NET Tool 中的多个依赖关系
Task("A")
    .Does(() =>
{
});

Task("B")
    .Does(() =>
{
});

Task("C")
    .IsDependentOn("A")
    .IsDependentOn("B")
    .Does(() =>
{
});

RunTarget("C");

运行目标 C 将执行 A,然后执行 B。如果多次引用任务,则只会执行一次。

Cake Frosting 中的多个依赖关系

[TaskName("A")]
public sealed class TaskA : FrostingTask
{
    public override void Run()
    {
    }
}

[TaskName("B")]
public sealed class TaskB : FrostingTask
{
    public override void Run()
    {
    }
}

[TaskName("C")]
[IsDependentOn(typeof(TaskA))]
[IsDependentOn(typeof(TaskB))]
public sealed class TaskC : FrostingTask
{
    public override void Run()
    {
    }
}

运行任务 C 将执行 A,然后执行 B。如果多次引用任务,则只会执行一次。

使用任务对象引用依赖关系

在 Cake .NET Tool 中使用任务对象引用依赖关系

这种方法是使用任务而不是字符串名称来添加依赖关系。

var taskA = Task("A")
    .Does(() =>
{
});

Task("B")
    .IsDependentOn(taskA)
    .Does(() =>
{
});

RunTarget("B");

这将按预期先执行目标 A,然后执行 B。

Criteria

Cake .NET Tool

当使用 Cake .NET Tool 时,您可以通过提供条件来控制和影响构建脚本执行的流程。这是一个必须满足的谓词,任务才能执行。但是,这些条件不会影响后续任务的执行。

Task("A")
    .WithCriteria(DateTime.Now.Second % 2 == 0)
    .Does(() =>
    {
    });

Task("B")
    .WithCriteria(() => DateTime.Now.Second % 2 == 0)
    .IsDependentOn("A")
    .Does(() =>
    {
    });

RunTarget("B");

任务 A 的条件将在创建任务时设置,而任务 B 的条件将在任务执行时评估。

在一个实际项目中,我们通常根据不同的环境状态、存储库分支等来控制任务的执行顺序。在这种情况下,我们从外部获取两个条件,以检测是否为本地构建并且是否在主分支上工作。请注意,我们正在使用 AppVeyor Build System,您也可以使用其他构建系统进行类似的操作。

var isLocalBuild = BuildSystem.IsLocalBuild;
var isMasterBranch = StringComparer.OrdinalIgnoreCase.Equals("master",
    BuildSystem.AppVeyor.Environment.Repository.Branch));

var deployUrl = HasArgument("DeployUrl")
    ? Argument<string>("DeployUrl")
    : EnvironmentVariable("DEPLOY_URL");

var target = "Default";

Task("Clean")
    .Does(() =>
    {
    });

Task("Restore")
    .Does(() =>
    {
    });

Task("Build")
    .Does(() =>
    {
    });

Task("Migrate")
    .WithCriteria(!isLocalBuild)
    .WithCriteria(isMasterBranch)
    .Does(() =>
    {
    });

Task("Deploy")
    .WithCriteria(!isLocalBuild)
    .WithCriteria(isMasterBranch)
    .Does(() =>
    {
        // 使用内容和 deployUrl 部署到某个服务器
    });

Task("Default")
    .IsDependentOn("Clean")
    .IsDependentOn("Restore")
    .IsDependentOn("Build")
    .IsDependentOn("Migrate")
    .IsDependentOn("Deploy")
    .Does(() =>
    {
    });

RunTarget(target);

对于可能在构建脚本执行过程中更改的具有状态的条件,请考虑使用 Lambda 替代方法。

在上面的示例中,我们添加了一个本地变量,用于在 Migration 任务中出现错误时进入恢复模式。

...
var target = "Default";

var isRecoveryMode = false;

Task("Migrate")
    .WithCriteria(!isLocalBuild)
    .WithCriteria(isMasterBranch)
    .Does(() =>
    {
    })
    .OnError(ex =>
    {
        isRecoveryMode = true;
    });

Task("Deploy")
    .WithCriteria(!isLocalBuild)
    .WithCriteria(isMasterBranch)
    .WithCriteria(() => !isRecoveryMode)
    .Does(() =>
    {
        // 使用内容和 deployUrl 部署到某个服务器
    });

Task("Recovery")
    .WithCriteria(!isLocalBuild)
    .WithCriteria(isMasterBranch)
    .WithCriteria(() => isRecoveryMode)
    .Does(() =>
    {
        // 恢复数据库
    });

Task("Default")
    .IsDependentOn("Clean")
    .IsDependentOn("Restore")
    .IsDependentOn("Build")
    .IsDependentOn("Migrate")
    .IsDependentOn("Deploy")
    .IsDependentOn("Recovery")
    .Does(() =>
    {
    });

RunTarget(target);

在 Criteria 中打印消息 可以向 Criteria 传递消息,当条件不满足并且任务被跳过时,消息将显示在输出中。

示例:

Task("A")
    .WithCriteria(() => DateTime.Now.Second % 2 == 0, "需要偶数秒。")
    .Does(() => {

    });

RunTarget("A");

输出:

========================================
A
========================================
跳过任务:需要偶数秒。

要显示消息,Verbosity 需要设置为 Verbose 或 Diagnostic。

Cake Frosting

要在 Cake Frosting 中实现任务的条件执行,可以重写任务中的 ShouldRun 方法:

public sealed class MyTask : FrostingTask<Context>
{
    public override bool ShouldRun(Context context)
    {
        // 在此处设置条件
        return true;
    }

    public override void Run(Context context)
    {
    }
}

有关示例项目,请参阅 Cake.Frosting.Example。

针对集合运行任务

DoesForEach 允许将一组项目或返回一组项目的委托添加为给定任务的操作。对于返回集合的委托,在任务执行时才会执行该委托。这允许任务查找在首次运行脚本时不存在的项目,例如构建产物。

要定义 DoesForEach,请使用 Task 方法。

Task("A")
    .DoesForEach(GetFiles("**/*.txt"), (file) =>
{
    // 对文件执行操作。
});

错误处理

为了对来自个别任务引发的错误采取措施,您可以使用 OnError 任务扩展。这将为您提供处理错误的机会。如果希望错误按照正常方式传播,可以重新抛出异常。

Task("A")
    .Does(() =>
{
})
.OnError(exception =>
{
    // 在这里处理错误。
});

忽略错误

要自动忽略任务中发生的错误,可以使用 ContinueOnError 任务扩展。ContinueOnError 扩展不能与 OnError 组合使用。

Task("A")
    .ContinueOnError()
    .Does(() =>
{

});

报告错误

如果要报告错误而不影响其传播或导致的堆栈跟踪,可以使用 ReportError 任务扩展。在 ReportError 作用域中引发的任何异常都将被忽略。

Task("A")
    .Does(() =>
{
})
.ReportError(exception =>
{
    // 报告错误。
});

终止构建

如果出现了无法恢复的问题,您应该引发异常以指示问题。然后,Cake 脚本运行器将记录错误(使用 Error 方法)并返回退出码 1,表示发生了错误。

Task("Check-ReleaseNotes")
    .Does(() =>
{
    var releaseNotes = ParseReleaseNotes("./ReleaseNotes.md");
    if(releaseNotes.Version.ToString() != nugetVersion)
    {
        throw new Exception(String.Format("发布说明缺少 v{0} 的条目。最新的发布说明是 v{1} 的。", nugetVersion, releaseNotes.Version));
    }
});

延迟处理错误

DeferOnError 允许特定任务能够将所有异常推迟到任务执行结束时。这样,任务可以在失败之前运行所有操作。这在处理多个单元测试项目或多次发布等情况时可能有一定价值。您可以查看整个任务的输出,而不仅仅是失败的部分。

Task("A")
    .Does(() =>
{
    throw new Exception();
})
.DoesForEach(GetFiles("**/*.txt"), (file) =>
{
   // 对文件执行操作。
})
.DeferOnError();

最终块

如果您希望无论任务如何退出都执行某些任意代码片段,您可以使用 Finally 任务扩展。

Task("A")
    .Does(() =>
{
})
.Finally(() =>
{
    // 执行特定操作。
});

异步任务

自 Cake 版本 0.23.0 起,Cake 支持异步任务,这将允许您在任务内部使用 C# 的 async 和 await 特性。

任务仍然会按照之前的方式单线程顺序执行,但这真的简化了异步编程以及在 Cake 脚本中利用异步 API。

Task("复制到内存-异步")
    .Does(async () =>
    {
        IFile file = Context.FileSystem.GetFile("./test.txt");
        using (Stream
            inputStream = testFile.OpenRead(),
            outputStream = new MemoryStream())
        {
            await inputStream.CopyToAsync(outputStream);
            await outputStream.FlushAsync();
            Information("已复制 {0} 字节到内存。",
                outputStream.Length
            );
        }
    });

您还可以在任务上使用任何并行机制,如 Parallel.ForEach 或 Parallel.Invoke。

var projectPaths = new [] {
    "./src/First/First.csproj",
    "./src/Second/Second.csproj",
};

Task("并行构建项目")
    .Does(() =>
    {
        BuildInParallel(projectPaths);
    });

Task("默认")
    .IsDependentOn("并行构建项目")
    .Does(() =>
    {
    });

RunTarget(target);

public void BuildInParallel(
    IEnumerable<string> filePaths,
    int maxDegreeOfParallelism = -1,
    CancellationToken cancellationToken = default(CancellationToken))
{
    var actions = new List<Action>();
    foreach (var filePath in filePaths) {
        actions.Add(() =>
            MSBuild(filePath, configurator =>
                configurator.SetConfiguration("Release"))
        );
    }

    var options = new ParallelOptions {
        MaxDegreeOfParallelism = maxDegreeOfParallelism,
        CancellationToken = cancellationToken
    };

    Parallel.Invoke(options, actions.ToArray());
}

设置与清理

Cake .NET Tool

在使用 Cake .NET Tool 时,您可以使用以下方法来控制设置和清理。

全局生命周期

如果您想在第一个任务运行之前或最后一个任务运行之后执行某些操作,可以使用设置 (Setup) 和清理 (Teardown)。一个典型的用例是当您需要启动某种服务器并确保它正确关闭时。

Setup(context =>
{
    // 在第一个任务之前执行。
});

Teardown(context =>
{
    // 在最后一个任务之后执行。
});

只有在调用 RunTarget 时且依赖关系图正确时才会调用 Setup。如果 Cake 不运行任何任务,那么 Setup 和 Teardown 都不会被调用。

任务生命周期

您还可以使用 TaskSetup 和 TaskTeardown,如果您想在每个任务运行之前和之后执行某些操作。一个典型的用例是当您需要为每个执行的任务使用自定义日志记录时。

TaskSetup(setupContext =>
{
    var message = string.Format("任务:{0}", setupContext.Task.Name);
    // 自定义日志记录
});

TaskTeardown(teardownContext =>
{
    var message = string.Format("任务:{0}", teardownContext.Task.Name);
    // 自定义日志记录
});

如果在调用 Setup 或 Teardown 方法之前调用了 RunTarget,则它们将无法正确设置并且不会工作。

Cake Frosting

在使用 Cake Frosting 时,您可以实现以下方法。

全局生命周期

实现 IFrostingLife 来控制全局生命周期,并在 Cake 主机上使用 UseLifetime 进行注册。有两个基本实现可以继承:FrostingLifetime 和 FrostingLifetime

以下示例展示了一个用于具有 BuildContext 类型的构建上下文的脚本的生命周期实现:

public static class Program
{
    public static int Main(string[] args)
    {
        return new CakeHost()
            .UseContext<BuildContext>()
            .UseLifetime<BuildLifetime>()
            .Run(args);
    }
}

public class BuildLifetime : FrostingLifetime<BuildContext>
{
    public override void Setup(BuildContext context, ISetupContext info)
    {
        // 在第一个任务之前执行。
    }

    public override void Teardown(BuildContext context, ITeardownContext info)
    {
        // 在最后一个任务之后执行。
    }
}

任务生命周期

实现 IFrostingTaskLife 来控制任务生命周期,并在 Cake 主机上使用 UseTaskLifetime 进行注册。有两个基本实现可以继承:FrostingTaskLifetime 和 FrostingTaskLifetime

以下示例展示了一个用于具有 BuildContext 类型的构建上下文的脚本的任务生命周期实现:

public static class Program
{
    public static int Main(string[] args)
    {
        return new CakeHost()
            .UseContext<BuildContext>()
            .UseTaskLifetime<TaskLifetime>()
            .Run(args);
    }
}

public class TaskLifetime : FrostingTaskLifetime<BuildContext>
{
    public override void Setup(BuildContext context, ITaskSetupContext info)
    {
        // 在每个任务之前执行。
    }

    public override void Teardown(BuildContext context, ITaskTeardownContext info)
    {
        // 在每个任务之后执行。
    }
}

运行目标

Cake .NET Tool

在使用 Cake .NET Tool 时,您可以使用 RunTarget 方法来运行一个目标。RunTarget 方法应该放在脚本的末尾。

Task("Default")
    .Does(() =>
{
    Information("Hello World!");
});

RunTarget("Default");

向脚本传递目标

所有传递给 Cake 的参数也可以从 Cake 脚本中访问。您可以使用参数 DSL 来访问这些参数。

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

Task("Build")
    .Does(() =>
{
});

Task("Publish")
    .IsDependentOn("Build")
    .Does(() =>
{
});

RunTarget(target);

使用这个 Cake 脚本,您可以通过传递 --target 参数给 Cake 来运行特定的目标。因此,我们可以通过以下参数调用 Cake 来运行 "Publish" 目标:

--target=Publish

--exclusive 参数使 RunTarget 仅运行指定的目标,而不运行任何依赖项。以下参数将运行 "Publish" 目标,而不运行 "Build" 目标:

--target=Publish --exclusive

Cake Frosting

Cake Frosting 默认会调用名为 Default 的任务。

在 Cake Frosting 中,无法定义除 Default 之外的任务,默认情况下在您的构建脚本中运行 Default 任务。

向脚本传递目标

为了覆盖应该运行的任务,Cake Frosting 提供了 --target 开关:

--target=Publish

--exclusive 参数使 Cake Frosting 仅运行指定的目标,而不运行任何依赖项。以下参数将运行 "Publish" 目标,而不运行 "Build" 目标:

--target=Publish --exclusive

参数与环境变量

本页面介绍了如何将设置传递到 Cake 文件中。

传递和读取参数

在您的 Cake 文件中调用 Argument 别名以从命令行读取参数:

Argument<bool>("myargument", false);

可以在运行 Cake 时传递参数:

--myargument=true

转换使用类型转换器来将字符串值转换为所需的类型。

读取环境变量

在您的 Cake 文件中调用 Environment variables 别名以获取环境变量。

以下示例将读取 BUILD_NUMBER 环境变量的值,如果环境变量未定义,则返回 42:

Information(EnvironmentVariable<int>("BUILD_NUMBER", 42));

预处理指令

Cake 脚本支持预处理器行指令,这些指令在执行脚本之前运行。这些指令可以用于引用其他脚本、程序集、命名空间等等。

在使用 Cake Frosting 运行时,预处理器指令不是必需的,也不可用。

Addin 指令

支持版本:Cake .NET Tool | .NET Framework 上的 Cake 运行器 | .NET Core 上的 Cake 运行器

Addin 指令用于安装和引用 NuGet 包中的插件:

#addin nuget:?package=Cake.Foo&version=1.0.0

Addin 指令也支持可选的引号:

#addin "nuget:?package=Cake.Foo&version=1.0.0"

在使用 Cake Frosting 运行时,#addin 指令不可用。相反,插件可以作为 NuGet 包添加到 Cake Frosting 项目中。

addin 指令支持以下 URI 参数:

Source(来源) 这不是一个命名参数,但根据 URI 定义是允许的。默认情况下,提供程序将尝试从 nuget.org 安装插件。如果包托管在其他源上,则可以覆盖安装源。

示例:从 myget.org 下载插件

#addin nuget:https://myget.org/f/Cake/?package=Cake.Foo

示例:从本地目录安装插件

#addin nuget:file://C:/MyPackages/?package=Cake.Foo

Package(包) 应安装的 NuGet 包的名称。

示例:

#addin nuget:?package=Cake.Foo

Version(版本) 应安装的 NuGet 包的具体版本。如果未提供版本,则将安装可用的最新版本的包。

示例:

#addin nuget:?package=Cake.Foo&version=1.2.3

Prerelease(预发行版) 要安装预发行版工具而不定义特定版本(#addin nuget:?package=Cake.Foo&version=1.2.3-beta),需要传递 prerelease 参数。

示例:

#addin nuget:?package=Cake.Foo&prerelease

Dependencies(依赖项) 自 Cake 0.22.0 起可用。

默认情况下,不加载在 NuGet 包上定义的依赖项。loaddependencies 参数允许获取和加载依赖的 NuGet 包。

此功能要求配置 Cake 以使用内置 NuGet 客户端而不是外部的 nuget.exe。

示例:

#addin nuget:?package=Cake.Foo&loaddependencies=true

Include(包含) include 参数允许定义应包含的文件。

示例:

#addin nuget:?package=Cake.Foo&include=/**/NoFoo.dll

Exclude(排除) exclude 参数允许排除特定文件。

示例:

#tool nuget:?package=Cake.Foo&exclude=/**/Foo.dll

Diagnostic(诊断) 可以通过 Cake 执行的日志详细程度来更改日志详细程度。

当使用外部 NuGet 客户端时,可以将 Show Process Command Line 配置值设置为显示执行的命令,即使没有启用诊断详细程度。

示例:

./build.sh --verbosity=diagnostic

Load 指令

Load 指令用于引用外部的 Cake 脚本。这在你拥有常用的实用函数等情况下非常有用。从 0.18.0 开始,你还可以从 NuGet 中加载 Cake 脚本。

用法

该指令有一个参数,即脚本的位置,可以选择包含一个方案:local(本地)或 nuget(NuGet)。默认是本地。

默认

l "scripts/utilities.cake"

load "scripts/utilities.cake"

尝试从 scripts 目录加载 utilities.cake。

本地方案

#l "local:?path=scripts/utilities.cake"
或
#load "local:?path=scripts/utilities.cake"

尝试从本地的 scripts 目录加载 utilities.cake。

NuGet 方案

#l "nuget:?package=utilities.cake"
或
#load "nuget:?package=utilities.cake"

尝试从 NuGet 加载 utilities.cake。

包括和排除选项

#load nuget:?package=utilities.cake&include=/**/NoFoo.cake
或
#load nuget:?package=utilities.cake&exclude=/**/Foo.cake

Reference 指令

Reference 指令用于引用外部程序集,以供在你的脚本中使用。

用法

该指令有一个参数,即要加载的 dll 的路径。

#r "bin/myassembly.dll"
或
#reference "bin/myassembly.dll"

Tool 指令

Tool 指令用于安装外部命令行工具。

可用提供程序

工具可以使用不同的提供程序进行安装。以下提供程序默认可用。单击提供程序以获取详细文档。

通过模块还提供了更多提供程序。

.NET 工具提供程序

.NET 工具提供程序用于使用 dotnet CLI 安装工具的包。

dotnet 包安装程序支持以下 URI 参数。

NuGet 提供程序

NuGet 提供程序用于安装打包为 NuGet 包的工具。

nuget 包安装程序支持以下 URI 参数。

Shebang 指令

在类 Unix 操作系统下,当带有 Shebang 的脚本被作为程序运行时,程序加载器将解析脚本初始行的其余部分作为解释器指令;指定的解释器程序将被运行,作为参数传递给它的是在尝试运行脚本时最初使用的路径。

这些仅用于 shell 以识别如何运行脚本,并在 Cake 编译脚本时被省略。

用法示例:

#!path/to/launch/cake

Break 指令

当放置在 Cake 文件中的任何行上时,break 指令将导致在运行时发出 System.Diagnostics.Debugger.Break();。因此,当与 -debug 参数一起使用(可以传递给 Cake.exe),调试器将自动停在这些行上。

如果调试器当前没有附加,那么 #break 指令将被简单地忽略。

用法示例:

#break

模块指令

模块指令允许您通过从 NuGet 源下载它们来引导 Cake 模块。

使用示例:

#module nuget:?package=Cake.UrlLoadDirective.Module&version=1.0.2
#module nuget:https://myget.org/f/Cake/?package=Cake.UrlLoadDirective.Module&version=1.0.3-beta&prerelease

由于模块可以更改和扩展 Cake 的内部功能,因此需要在 Cake 执行之前进行这种引导。通过在正常执行脚本之前使用 --bootstrap 参数调用 Cake 来解决此问题。

使用示例:

./cake.exe build.cake --bootstrap
./cake.exe build.cake

定义指令

定义指令 - #define 创建一个符号,它可以在以后用于决定 Cake 将执行什么。您可以像在 C# 中一样使用它。要检查符号是否已定义,您必须使用 #if ... #else ... #endif 指令。

使用示例:

#define FOO

#if (FOO)
    // 此分支中的代码将执行
#else
    // 此分支中的代码将被跳过
#endif

预定义符号 根据环境,Cake 可以预定义一些符号。

符号名称 描述 可用版本
CAKE 始终对由 Cake 执行的代码定义 v0.35.0
NETCOREAPP 当 CLR 为 .NET Core 时定义 v0.35.0
NETFRAMEWORK 当 CLR 为 .NET Framework 时定义 v0.35.0
NET461 当运行时框架为 .NET Framework 4.6.1 时定义 v0.35.0
NETCOREAPP2_0 当运行时框架为 .NET Core 2.0 时定义 v0.35.0
NETCOREAPP2_1 当运行时框架为 .NET Core 2.1 时定义 v0.35.0
NETCOREAPP2_2 当运行时框架为 .NET Core 2.2 时定义 v0.35.0
NETCOREAPP3_0 当运行时框架为 .NET Core 3.0 时定义 v0.35.0
NETCOREAPP3_1 当运行时框架为 .NET Core 3.1 时定义 v0.35.0
NET5_0 当运行时框架为 .NET 5 时定义 v1.0.0
NETSTANDARD2_0 当无法确定运行时框架但兼容 .NET Standard 2.0 时定义 v0.35.0

控制台输出

日志记录

Cake 提供了用于将日志消息写入控制台的日志记录别名。

高级输出

Cake 集成了 Spectre.Console,它提供了将内容输出到控制台的高级功能,如进度条、旋转器、表格、树、柱状图或 FIGlet 文本。

使用 AnsiConsole 类来在控制台上呈现高级小部件。

有关详细信息,请参阅 Spectre.Console 文档。


可复制构建

为了能够实现可复制的构建,也称为确定性构建,整个构建系统都需要变得确定性。本页包含一些关于如何使用 Cake 编写可复制构建的技巧。

有关此主题的更多信息,请参见以下视频:https://youtu.be/xq41JgaGN7k

锁定 Cake 版本:如何使 Cake 构建可复制 锁定 Addin 版本:在使用插件时如何使构建可复制 锁定工具版本:在使用外部工具时如何使构建可复制 锁定模块版本:在使用模块时如何使构建可复制

锁定 Cake 版本

要实现确定性构建,非常重要的一点是在每次构建中都使用相同版本的 Cake。

Cake .NET 工具

当安装为本地工具时,Cake 将始终在清单文件中指定的版本中进行恢复,该清单文件通常位于 .config/dotnet-tools.json 中。

我们建议将此清单文件存储在源代码控制中,以便每次克隆存储库并运行 dotnet tool restore 时,您都将获得清单文件中指定的 Cake .NET 工具的相同版本。

Cake Frosting

确保在 *.csproj 文件中为 Cake.Frosting 使用固定的版本号:

<PackageReference Include="Cake.Frosting" Version="3.1.0" />

要在锁定版本后更新使用的 Cake 版本,您只需要将 Cake.Frosting NuGet 包更新到您想要使用的新版本即可。

.NET Framework 的 Cake 运行器

锁定 Cake 版本在 tools/packages.config 文件中:

<?xml version="1.0" encoding="utf-8"?>
<packages>
    <package id="Cake" version="3.1.0" />
</packages>

将 tools/packages.config 文件提交到源代码控制存储库中。

这将需要对您的 .gitignore 文件进行一些调整。以下是所需的调整。第一行表示忽略工具目录下的所有文件。第二行表示不要忽略 packages.config 文件。

tools/*
!tools/packages.config

要在锁定版本后更新使用的 Cake 版本,只需将 packages.config 文件中的版本更新为您想要使用的新版本即可。

.NET Core 的 Cake 运行器

将 Cake 的版本锁定在 tools/packages.config 文件中:

<?xml version="1.0" encoding="utf-8"?>
<packages>
    <package id="Cake.CoreCLR" version="3.1.0" />
</packages>

将 tools/packages.config 文件提交到源代码控制存储库中。

这将需要对您的 .gitignore 文件进行一些调整。以下是所需的调整。第一行表示忽略工具目录下的所有文件。第二行表示不要忽略 packages.config 文件。

tools/*
!tools/packages.config

要在锁定版本后更新使用的 Cake 版本,只需将 packages.config 文件中的版本更新为您想要使用的新版本即可。

固定 Addin 版本

Cake .NET Tool

在使用 Cake .NET Tool 时,可以使用 #addin 预处理器指令来锁定引用的 Addin 版本,如下所示:

#addin nuget:?package=Cake.Foo&version=1.2.3

Cake Frosting

在使用 Cake Frosting 时,可以像锁定其他 NuGet 包一样锁定 Addin 版本,示例如下:

<PackageReference Include="Cake.Foo" Version="1.2.3" />

固定工具版本

Cake .NET Tool

在使用 Cake .NET Tool 时,可以使用 #tool 预处理器指令来锁定引用的工具版本,如下所示:

#tool nuget:?package=Tool.Foo&version=1.2.3

Cake Frosting

在使用 Cake Frosting 时,可以像锁定其他 NuGet 包一样锁定从 NuGet 包中获取的工具版本,示例如下:

<PackageReference Include="Tool.Foo" Version="1.2.3" />

锁定模块版本

Cake .NET Tool 在使用 Cake .NET Tool 时,可以使用 #module 预处理器指令来锁定引用的模块版本,如下所示:

#module nuget:?package=Cake.BuildSystems.Module&version=3.0.0

Cake Frosting 在使用 Cake Frosting 时,可以像锁定其他 NuGet 包一样锁定从 NuGet 包中获取的模块版本,示例如下:

<PackageReference Include="Cake.BuildSystems.Module" Version="3.0.0" />

共享构建状态

要在构建之间共享变量和状态,可以使用几种不同的方式,具体取决于要共享的状态以及跨何种范围共享。

类型化上下文

从 Cake 0.28.0 开始可用。

您可以使用类型化上下文轻松地在任务之间共享复杂的状态,而无需使用全局变量或静态成员。在脚本中使用类型化上下文分为三个部分:上下文本身、设置方法和各个任务方法。

有关类型化上下文的更多背景信息,请查看发布博客文章。

创建您的类型化上下文

首先,您需要一个用作类型化上下文的类。这可以是任何标准的 C# 类,不需要包含任何特定于 Cake 的代码。在此示例中,我们将使用以下简单类:

public class BuildData
{
    public string Configuration { get; }
    public bool BuildPackages { get; }
    public List<string> Frameworks { get; set; }
    // 您可以使用只读或可变属性

    public BuildData(
        string configuration,
        bool buildPackages)
    {
        Configuration = configuration;
        BuildPackages = buildPackages;
    }
}

从设置返回您的上下文

要使脚本使用类型化上下文,您需要从正确类型的设置方法中返回设置类的实例。您可以使用此方法稍后更改任务的运行方式。使用上面的示例:

Setup<BuildData>(setupContext =>
{
    return new BuildData(
        configuration: Argument("configuration", "Release"),
        buildPackages: !BuildSystem.IsLocalBuild
    )
    {
        Frameworks = IsRunningOnUnix()
            ? new List<string> { "netcoreapp2.1" }
            : new List<string> { "net472", "netcoreapp2.1" }
    };
});

在任务中使用您的上下文

最后,您可以从任何任务中访问您的类型化上下文,通过向任务声明的 Does、DoesForEach 或 WithCriteria 方法提供类型参数:

Task("Build-Packages")
    .WithCriteria<BuildData>((context, data) => data.BuildPackages) // 您的类型化上下文是第二个参数
    .Does<BuildData>(data => // 确保您在此处使用正确的类型参数
    {
        Information("Packages were {0}", data.BuildPackages ? "built" : "not built");
    });

您还可以在 Teardown 方法中使用您的类型化上下文:

Teardown<BuildData>((context, data) => // 确保您在此处使用类型参数
{
    Information($"已完成 {(string.Join(", ", data.Frameworks))} 构建");
});

全局变量

在构建脚本中共享变量或状态的最简单方法是使用全局变量。

要做到这一点,只需在任务方法的范围之外声明任何变量。这些变量的惯例是将它们放在脚本的开头。

///////////////////////////////////////////////////////////////////////////////
// VARIABLES
///////////////////////////////////////////////////////////////////////////////

var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
var artifacts = "./dist/";
var testResultsPath = MakeAbsolute(Directory(artifacts + "./test-results"));

然后,您可以在任何任务方法中访问这些变量。

Setup(setupContext =>
{
    Information($"使用 {configuration} 构建配置");
});

Task("Clean")
    .Does(() =>
{
    // 清理构件目录
    CleanDirectory(artifacts);
});

工具

安装和使用工具 如何安装和使用外部工具 工具解析 外部工具的定位方式

安装和使用工具

从NuGet安装工具 Cake提供了多种方式来安装作为构建的一部分提供的工具可执行文件,这些工具以NuGet包的形式提供。

安装方法 Cake .NET工具 Cake Frosting 预处理器指令
InstallTool
通过预处理器指令安装工具 Cake .NET工具的#tool预处理器指令可用于自动下载工具并将其安装在tools文件夹中。

开箱即用支持NuGet和.NET工具(自Cake 1.1以来)。更多提供程序可通过模块获得支持。

以下示例会在执行构建脚本的过程中下载xunit.runner.console包:

#tool "nuget:?package=xunit.runner.console&version=2.4.1"

有关更多信息,请参阅#tool预处理器指令。

使用InstallTool安装工具 Cake Frosting提供了InstallTool方法来下载工具并安装它:

开箱即用支持NuGet和.NET工具(自Cake 1.1以来)。更多提供程序可通过模块获得支持。

以下示例会在执行构建脚本的过程中下载xunit.runner.console包:

public class Program : IFrostingStartup
{
    public static int Main(string[] args)
    {
        // 创建并运行主机。
        return
            new CakeHost()
                .InstallTool(new Uri("nuget:?package=xunit.runner.console&version=2.4.1"))
                .Run(args);
    }
}

有关支持的URI字符串参数的更多信息,请参阅#tool预处理器指令。

从其他提供程序安装工具 开箱即用支持NuGet和.NET工具(自Cake 1.1以来)作为预处理器指令和InstallTool的提供程序。更多提供程序可通过模块获得支持。

使用来自磁盘的工具 如果要使用不通过NuGet提供或者您更喜欢将工具存储在本地的工具,可以使用Cake的工具解析约定来解析工具的路径,并通过进程别名调用它:

Task("Install-XUnit")
    .Does(()=> {
    FilePath nugetPath = Context.Tools.Resolve("nuget.exe");
    StartProcess(nugetPath, new ProcessSettings {
        Arguments = new ProcessArgumentBuilder()
            .Append("install")
            .Append("xunit.runner.console")
        });
});

工具解析

Cake的哲学是减少Cake的依赖项数量,以及不将可执行文件存储在源代码存储库中。而是使用一组约定来定位磁盘上的可执行文件。

通过在实现工具时继承Tool类,您将免费获得这些约定。

您可以使用ICakeContext上的IToolLocator Tools属性覆盖和注册工具路径:

Setup(context => {
    context.Tools.RegisterFile("C:/ProgramData/chocolatey/bin/NuGet.exe");
});

如果要在Cake脚本中使用工具解析执行通用任务,例如启动进程,那当然可以使用Resolve(string)方法:

Task("NuGet-Help-Install")
    .Does(()=> {
    FilePath nugetPath = Context.Tools.Resolve("nuget.exe");
    StartProcess(nugetPath, new ProcessSettings {
        Arguments = new ProcessArgumentBuilder()
            .Append("help")
            .Append("install")
        });
});

重用构建

Cake支持多种方法来在多个项目和存储库之间共享构建代码。

方法 共享类 共享别名 共享任务
示例 NuGet包 x
插件 x
NuGet包中的程序集 x x

示例 NuGet包 Cake构建脚本可以发布为NuGet包,称为"示例"。这些包可以包含共享任务,并可被其他构建脚本使用。

编写示例 NuGet包 要创建示例NuGet包,请将.cake文件添加到NuGet包的Content文件夹中。

使用示例 NuGet包 确保选择与您的运行时兼容的示例NuGet包。

Cake .NET工具 当使用Cake .NET工具时,可以使用"nuget"方案的load指令下载示例NuGet包,并加载Content文件夹中的所有.cake文件。以下示例加载版本为1.0.0的MyExamplePackage NuGet包:

#load nuget:?package=MyExamplePackage&version=1.0.0

Cake Frosting 在使用Cake Frosting时,可以像处理任何其他NuGet包一样引用示例NuGet包:

<PackageReference Include="MyExamplePackage" Version="1.0.0" />

插件 代码可以作为Cake插件共享,这些插件提供了可用于Cake构建的别名。

编写插件 请参阅创建插件以了解如何创建自定义插件的说明。

使用插件 可以使用插件指令加载插件。

NuGet包中的程序集 可以在NuGet包中部署的.NET程序集中共享类。

从NuGet包中使用程序集 可以使用插件指令加载NuGet包。

WangShuXian6 commented 1 year ago

集成

编辑器

与编辑器和集成开发环境(IDE)的集成

Atom

支持 Atom 编辑器的功能

语法高亮

Cake .NET Tool Atom 版本高于1.0.19的情况下,.cake 文件支持开箱即用的语法高亮。

Cake Frosting Cake Frosting 项目的语法高亮是通过 OmniSharp 提供的。

智能感知

Cake .NET Tool 目前,.cake 文件在 Atom 中不支持智能感知功能。

Cake Frosting Cake Frosting 项目的智能感知支持是通过 OmniSharp 提供的。

Rider

JetBrains Rider 的扩展和支持功能 Cake 在 JetBrains Rider 中的插件引入了以下功能:

运行配置 工具 项目模板、文件模板和代码模板 支持结构视图和临时文件 通过 Code Vision 直接在文件中双击生成任务

安装与配置

请参阅 Cake 在 Rider 中的插件以获取有关如何安装和配置插件的说明。

Cake 在 Rider 中的插件支持 Rider 版本 2023.1。

子页面

Rider 中的智能感知 Rider 中的智能感知支持 Rider 运行配置 Cake 任务的运行配置 Rider 资源 有关 JetBrains Rider 支持的资源 Rider 模板 模板支持 Rider 中的工具 Rider 的工具

Rider 中的智能感知

启用智能感知

要在 Rider 中启用智能感知支持,请按照以下步骤操作:

Cake .NET Tool 目前 Rider 不支持在 .cake 脚本文件中使用智能感知。

Cake Frosting Cake Frosting 项目具有 .NET 控制台应用程序的所有功能,包括智能感知。

Rider运行配置

可以将Cake任务作为运行配置: image

目前只支持运行配置,不支持调试配置。

配置运行配置

要使用运行配置,您必须在计算机上或解决方案中安装了Cake。

安装Cake

Cake .NET工具 要使用Cake .NET工具,它需要全局安装:

dotnet tool install --global Cake.Tool

这是Rider中的Cake的默认设置。或者,也可以使用Cake .NET工具的项目本地安装。

Cake Frosting 目前不支持Cake Frosting的运行配置。

支持的运行器
运行器 支持 备注
Cake .NET工具
Cake Frosting
设置

在“文件 | 设置 | 构建、执行、部署 | Cake”下有多个配置设置。

所有设置都是特定于项目的,并存储在.idea文件夹中。要在开发者之间共享设置,请确保将CakeRider.xml放在源代码控制下。

通用设置 任务正则表达式 此正则表达式用于从Cake文件中解析任务。默认值:Task\s?(\s?"(.?)"\s?) 详细程度 这是直接从Cake任务窗口运行任务或创建新的运行配置时使用的默认详细程度。默认值:正常 搜索路径 允许修改用于查找在Cake任务窗口中显示的所有Cake文件的搜索路径。

搜索路径 一个或多个搜索Cake文件的起始点。路径相对于项目根目录,应在目录之间使用/作为分隔符。默认值:.(项目目录的根目录。) 排除表达式 正则表达式来排除搜索路径。在搜索期间找到的每个路径都与所有配置的表达式匹配。匹配项将被排除。默认值:./tools/. 运行器设置 允许定义要使用的运行器。

第一个选项“使用'dotnet cake'而不是可执行文件”将使用dotnet cake作为运行器。 dotnet可执行文件必须在路径中可用,并且Cake .NET工具必须全局安装在计算机上或本地安装在项目中。如果设置了此选项,则设置页面上的所有其他选项都将被忽略。

或者,如果未设置“使用'dotnet cake'而不是可执行文件”,则必须提供到Cake可执行文件(dotnet-cake.exe或cake.exe)的路径:

可以通过定义与系统属性os.name匹配的正则表达式来设置不同操作系统的不同运行器。

Cake运行器设置能够处理环境变量:使用特定变量,如${VARIABLE},当调用运行器时,环境变量将被展开。

默认值为~/.dotnet/tools/dotnet-cake和${USERPROFILE}.dotnet\tools\dotnet-cake.exe(对于Windows)。

使用运行配置
创建运行配置

可以从现有的Cake任务使用Cake任务窗口创建配置,也可以使用运行配置编辑器手动创建。

编辑运行配置

有一个运行配置编辑器可用:

image

运行配置中的设置

脚本路径:Cake文件的路径。(作为传递给运行器的第一个参数。) 任务:要运行的任务的名称(这是通过--task=传递给运行器的。) 详细程度:Cake输出的详细程度。(这是通过--verbosity=传递给运行器的。) 参数:传递给运行器的任意附加参数。 启动前活动 确保.NET工具(全局):在运行Cake之前确保全局安装了Cake .NET工具。 恢复.NET工具:在运行构建之前还原.NET工具,实际上是在运行构建之前调用dotnet tool restore。 image

直接运行构建 Cake任务窗口列出了所有Cake脚本及其任务:

image

双击任务将立即运行该任务:

image

或者,可以使用Cake任务窗口顶部的按钮来立即运行任务,或创建新的运行配置。

Rider 资源

这里有一个视频播放列表,展示了 Cake 插件 for Rider 每个版本的新功能: https://youtu.be/NtbSFQOMJVI?list=PL84yg23i9GBixvjta7rPypA3oFdMK25gH

Rider 模板

配置模板

模板由 Cake for Rider 插件提供。

项目模板

在项目窗口中,选择解决方案的上下文菜单,然后选择“添加 | 新建项目”来创建新项目。

image

文件模板

在项目窗口中,选择项目项(项目或文件夹)的上下文菜单,然后选择“添加 | Cake 文件”以创建一个包含一些示例代码的新 Cake 文件。

image

Live 模板(有时称为代码片段)

1-Cake

Cake 中提供的可用 Live 模板:

cake-addin

提供基本的 #addin 预处理指令,可以更改包名称和版本 默认值:#addin "nuget:?package=Cake.Foo&version=1.2.3"

cake-addin-full

提供更完整的 #addin 预处理指令,可以更改源、包名称和版本 默认值:#addin "nuget:https://www.nuget.org/api/v2?package=Cake.Foo&version=1.2.3"

cake-argument

提供基本的输入参数解析代码,可以更改变量名称、参数名称和默认值 默认值:var argumentName = Argument("Argument name", "Default value");

cake-load

提供基本的 #load 预处理指令,可以更改到 .cake 文件的路径 默认值:#load "scripts/utilities.cake"

cake-load-nuget

提供更复杂的 #load 预处理指令,可以更改包名称和版本 默认值:#load "nuget:?package=Cake.Foo&version=1.2.3"

cake-load-nuget-full

提供更复杂的 #load 预处理指令,可以更改源、包名称和版本 默认值:#load "nuget:https://www.nuget.org/api/v2?package=Cake.Foo&version=1.2.3"

cake-module-nuget

提供 #module 预处理指令,可以更改包名称和版本 默认值:#module "nuget:?package=Cake.Foo.module&version=1.2.3"

cake-module-nuget-full

提供更复杂的 #module 预处理指令,可以更改源、包名称和版本 默认值:#module "nuget:https://www.nuget.org/api/v2?package=Cake.Foo.module&version=1.2.3"

cake-reference

提供基本的 #reference 预处理指令,可以更改到程序集的路径 默认值:#reference "bin/myassembly.dll"

cake-sample

提供包括设置和拆卸操作、单个任务和参数解析的完整示例构建 Cake 脚本

cake-tool

提供基本的 #tool 预处理指令,可以更改包名称和版本 默认值:#tool "nuget:?package=Cake.Foo&version=1.2.3"

cake-tool-full

提供更完整的 #tool 预处理指令,可以更改源、包名称和版本 默认值:#tool "nuget:https://www.nuget.org/api/v2?package=Cake.Foo&version=1.2.3"

setup

提供示例设置定义

task-simple

提供基本任务定义,可以更改任务名称 默认值:Task("name");

task-action

提供更复杂的任务定义,包括 .Does 主体,可以更改任务名称

teardown

提供示例拆卸定义

2-Cake Frosting Cake Frosting 中的可用 Live 模板:

cake-task 提供基本的任务定义类 cake-task-ctx 提供基本的任务定义类,使用自定义上下文 cake-async-task 提供异步任务定义类 cake-async-task-ctx 提供异步任务定义类,使用自定义上下文

Rider 中的工具

配置工具

工具由 Cake for Rider 插件提供。

使用工具

Cake for Rider 在主菜单的 Tools | Cake 下提供以下工具:

工具 描述
安装:Cake .NET Tool(全局) 全局安装(或更新).NET Cake Tool。
安装:配置文件 将示例配置文件安装到项目的根文件夹中。
安装:引导程序:... ... 将引导程序之一安装到项目的根文件夹中。

Visual Studio Code

Visual Studio Code 的扩展和支持功能

Visual Studio Code 的 Cake 扩展为 Visual Studio Code 带来以下功能:

用于处理 Cake 文件的命令 支持 Cake 构建脚本的语言支持 支持在 Cake 文件中进行代码大纲和面包屑导航 集成以通过内置的 Tasks: Run Task 命令运行 Cake 任务 CodeLens 允许您运行和调试任务 代码片段

安装和配置

请查看 Cake 扩展 for Visual Studio Code,了解如何安装和配置此扩展。

子页面

Visual Studio Code 中的智能感知 智能感知的支持 Visual Studio Code 代码片段 代码片段的支持 Visual Studio Code 命令 用于处理 Cake 的可用命令 Visual Studio Code 资源 关于 Visual Studio Code 支持的资源

在 Visual Studio Code 中启用 IntelliSense

要在 Visual Studio Code 中启用 IntelliSense 支持,请按照以下步骤进行操作:

Cake .NET Tool

IntelliSense 支持 .cake 文件是通过 Visual Studio Code 的 C# 扩展和 Cake.Bakery 提供的。

  1. 打开 Visual Studio Code 并导航到包含 Cake 文件的文件夹。
  2. 安装 Visual Studio Code 的 Cake 扩展。确保至少安装版本 0.10.1。

有关在 Visual Studio Code 中安装扩展的说明,请参阅扩展市场文档。

  1. 安装 Visual Studio Code 的 C# 扩展。确保至少安装版本 1.13.0。

有关在 Visual Studio Code 中安装扩展的说明,请参阅扩展市场文档。

  1. 使用以下任一选项安装 Cake.Bakery:

    • 使用 Visual Studio Code 的 Cake 扩展:

      • 打开命令面板(Ctrl+Shift+P)。
      • 输入 "Cake"。
      • 选择 "Install intellisense support" 命令。
    • 在 Windows 上使用 Chocolatey:

      • 复制以下命令并运行:
      choco install cake-bakery.portable
    • 下载发布版 ZIP 文件,解压缩并将其添加到 PATH 环境变量中。

    如果您想在 PATH 环境变量之外安装 Cake.Bakery,您可以使用 OmniSharp 配置系统指定 Cake.Bakery.exe 的路径。

  2. 创建一个名为 "omnisharp.json" 的文件,位于 %USERPROFILE%/.omnisharp/(Linux/macOS 上为 ~/.omnisharp/),并包含以下内容(将 "" 替换为 Cake.Bakery 的路径):

{
  "cake": {
    "bakeryPath": "<custom_path>/Cake.Bakery/tools/Cake.Bakery.exe"
  }
}

Cake Frosting Cake Frosting 项目的 IntelliSense 支持通过 Visual Studio Code 的 C# 扩展提供。

请安装 Visual Studio Code 的 C# 扩展。

有关如何在 Visual Studio Code 中安装扩展的说明,请参阅扩展市场文档。

故障排除

如果按照上述步骤操作后仍未启用 IntelliSense,请执行以下故障排除步骤:

如果没有看到上述信息,您可能在安装 Visual Studio Code 的 C# 扩展时遇到了问题。请卸载该扩展,然后尝试重新安装。如果您使用的是 Windows 操作系统,请查找 %userprofile%.vscode\extensions\ms-vscode.csharp-1.13.0.omnisharp\ 目录,如果您在运行 Linux 或 macOS,则查找 ~/.vscode/extensions/ms-vscode.csharp-1.13.0/.omnisharp/ 目录(将 1.13.0 替换为您安装的 Visual Studio Code C# 扩展的版本号)。

如何使用 OmniSharp 的预发行版本 若要使用 OmniSharp 的预发行版本,请按照以下步骤操作:

  1. 打开命令面板(Ctrl+Shift+P)。

  2. 选择“打开用户设置”命令。

  3. 打开用户设置。 image

  4. 搜索 omnisharp.path 并在 settings.json 中单击“编辑”。 image

  5. 配置 omnisharp.path 设置。

  6. 将 "omnisharp.path" 的值设置为 "latest",然后保存设置。

  7. 如果要重新启动 OmniSharp 服务器,请回答相关问题并选择“是”。

  8. 等待 OmniSharp 的新版本下载、安装和启动。

如果问题仍未解决,请参阅 "获取帮助" 获取进一步协助。

Visual Studio Code 代码片段

配置代码片段

在 Visual Studio Code 中,代码片段由 Visual Studio Code 的 Cake 扩展提供。

有关如何在 Visual Studio Code 中安装扩展的说明,请参阅扩展市场文档。

支持的运行程序
运行程序 支持情况 备注
Cake .NET 工具 适用于所有 .cake 文件。
Cake Frosting ×
可用的代码片段

cake-addin 提供了一个基本的插件预处理指令,可以更改包名称和版本 默认值:#addin "nuget:?package=Cake.Foo&version=1.2.3" cake-addin-full 提供了一个更完整的插件预处理指令,可以更改源、包名称和版本 默认值:#addin "nuget:https://www.nuget.org/api/v2?package=Cake.Foo&version=1.2.3" cake-argument 提供了用于基本输入参数解析的代码,可以更改变量名称、参数名称和默认值 默认值:var target = Argument("target", "Default"); cake-load 提供了一个基本的加载预处理指令,可以更改到 .cake 文件的路径 默认值:#load "scripts/utilities.cake" cake-load-nuget 提供了一个更复杂的加载预处理指令,可以更改源、包名称和版本 默认值:#load "nuget:https://www.nuget.org/api/v2?package=Cake.Foo&version=1.2.3" cake-reference 提供了一个基本的引用预处理指令,可以更改到程序集的路径 默认值:#reference "bin/myassembly.dll" cake-sample 提供了一个完整的示例构建 Cake 脚本,包括设置和拆卸操作、单个任务以及参数解析 cake-tool 提供了一个基本的工具预处理指令,可以更改包名称和版本 默认值:#tool "nuget:?package=Cake.Foo&version=1.2.3" cake-tool-full 提供了一个更完整的工具预处理指令,可以更改源、包名称和版本 默认值:#tool "nuget:https://www.nuget.org/api/v2?package=Cake.Foo&version=1.2.3" task 提供了一个基本的任务定义,可以更改任务的名称 默认值:Task("name"); task(带有动作) 提供了一个更复杂的任务定义,包括 .Does 主体,可以更改任务的名称

Visual Studio Code 命令

配置命令

命令由 Visual Studio Code 的 Cake 扩展提供。

使用命令

Visual Studio Code 的 Cake 扩展在命令面板中提供以下命令,用于处理 Cake 文件:

命令 描述
Cake: 安装引导程序 在根文件夹中安装适用于 Windows、macOS 或 Linux 的 Cake 引导程序。
Cake: 安装到工作区 一次运行所有可用命令,以避免逐个运行它们。
Cake: 安装调试依赖项 在全局安装 Cake .NET 工具,或在工具文件夹中下载 Cake .NET Core 运行器。
Cake: 安装示例构建文件 安装一个包含设置和拆卸操作、示例任务和参数解析的示例 Cake 文件。
Cake: 从 NuGet 添加 addin 在指定的 Cake 文件中添加或更新来自 NuGet 的 addin。
Cake: 从 NuGet 添加工具 在指定的 Cake 文件中添加或更新来自 NuGet 的工具。
Cake: 从 NuGet 添加模块 在模块包配置中添加或更新来自 NuGet 的模块。
Cake: 安装配置文件 安装默认的 Cake 配置文件,用于控制 Cake 的内部组件。
Cake: 安装智能感知支持 下载 Cake.Bakery NuGet 包到工具文件夹,与 OmniSharp 一起为 Cake 文件提供智能感知支持。详细信息请参阅《在 Visual Studio Code 中使用智能感知》。

Visual Studio Code 资源

您可以在此处找到展示 Cake 扩展的每个版本中新功能的视频播放列表:

链接到视频播放列表

Visual Studio

Visual Studio 的扩展和支持功能

在Visual Studio中启用IntelliSense

要在Visual Studio中启用IntelliSense支持,请按照以下步骤操作:

Cake .NET工具

目前,在Visual Studio中的.cake脚本文件中不支持Intellisense。

Cake Frosting Cake Frosting项目具有.NET控制台应用程序的所有功能,包括IntelliSense。

Visual Studio模板

配置模板

Visual Studio模板由Visual Studio的Cake扩展提供。

项目模板

从“文件”>“新建”>“项目”菜单中选择Cake类别,以快速创建新的Cake插件、模块或插件测试项目:

image

项目模板

该扩展包括一个用于构建脚本的项目模板: image

Visual Studio命令

配置命令

命令由Visual Studio的Cake扩展提供。https://marketplace.visualstudio.com/items?itemName=vs-publisher-1392591.CakeforVisualStudio

使用命令

从“生成”菜单中选择“Cake Build”以快速安装默认的引导程序脚本或Cake配置文件到您的解决方案中。

image

Visual Studio代码片段

配置代码片段

Visual Studio中的代码片段由Visual Studio的Cake扩展提供。

支持的运行器

运行器 支持 备注
Cake .NET Tool 适用于所有.cake文件。
Cake Frosting ×

Visual Studio任务运行器

配置任务运行器

Visual Studio任务运行器集成由Visual Studio的Cake扩展提供。

安装Cake

为了使用任务运行器,您必须在您的计算机上或您的解决方案中安装Cake。

Cake .NET Tool

要使用Cake .NET工具,需要全局安装:

dotnet tool install --global Cake.Tool

Cake Frosting 目前不支持Cake Frosting的任务运行器。

支持的运行器
运行器 支持 备注
Cake .NET Tool 仅适用于全局安装。
Cake Frosting ×
使用任务运行器

您可以通过右键单击解决方案资源管理器中的文件并选择任务运行器资源管理器来打开任务运行器资源管理器窗口:

image

左侧将列出各个任务:

image

双击任务即可执行每个任务:

image

绑定

任务绑定使您可以将单个任务与Visual Studio事件(如项目打开、生成或清理)关联起来。这些绑定存储在您的cake.config文件中。

image

Visual Studio资源

这里有一个播放列表,展示了Cake扩展的每个版本中的新功能:

播放列表链接

构建系统

与构建服务器的集成

Cake可以在任何构建系统上运行。对于最常见的构建系统,Cake提供了开箱即用的助手,以便与构建系统集成。

此外,对于一些构建系统,还提供了特定的运行程序或额外的扩展。

AppVeyor 与AppVeyor的集成 Azure Pipelines 与Azure Pipelines的集成 Bamboo 与Atlassian Bamboo的集成 Bitbucket Pipelines 与Atlassian Bitbucket Pipelines的集成 Bitrise 与Bitrise的集成 Continua CI 与Continua CI的集成 GitHub Actions 与GitHub Actions的集成 GitLab CI/CD 与GitLab CI/CD的集成 GoCD 与GoCD的集成 Jenkins 与Jenkins的集成 MyGet 与MyGet构建服务的集成 TeamCity 与TeamCity的集成 Travis CI 与Travis CI的集成

AppVeyor

开箱即用支持

AppVeyor别名返回一个IAppVeyorProvider实例,可用于与AppVeyor环境交互。

以下示例在AppVeyor上运行时写入错误消息:

if (BuildSystem.AppVeyor.IsRunningOnAppVeyor)
{
    BuildSystem.AppVeyor.AddMessage(
            "This is a error message.",
            AppVeyorMessageCategoryType.Error,
            "Error details."
        );
}
else
{
    Information("Not running on AppVeyor");
}

有关详细信息以及与AppVeyor交互的可用方法,请参阅IAppVeyorProvider。

可用的第三方扩展

Cake.AppVeyor 由Jonathan Dick https://cakebuild.net/extensions/cake-appveyor/ 最新版本:5.0.1 上次更新2年前 appveyor 一组用于访问AppVeyor REST API的Cake别名

Cake.Issues.PullRequests.AppVeyor 由Pascal Berger https://cakebuild.net/extensions/cake-issues-pullrequests-appveyor/ 最新版本:3.0.0 上次更新2个月前 issues, pull requests, appveyor Cake.Issues插件的AppVeyor支持允许您将找到的问题作为消息写入AppVeyor构建。此插件提供了用于写入AppVeyor构建的别名。它还需要核心Cake.Issues和Cake.Issues.PullRequests插件以及一个或多个问题提供程序。请参阅cakeissues.net,了解有关在Cake脚本中处理问题的整个生态系统的概述。

Azure Pipelines

开箱即用支持

AzurePipelines别名返回一个IAzurePipelinesProvider实例,可用于与Azure Pipelines环境交互。

以下示例在Azure Pipelines上运行时写入错误消息:

if (BuildSystem.AzurePipelines.IsRunningOnAzurePipelines)
{
    BuildSystem.AzurePipelines.Commands.WriteError(
            "This is a error message.");
}
else
{
    Information("Not running on Azure Pipelines");
}

有关详细信息以及与Azure Pipelines交互的可用方法,请参阅IAzurePipelinesProvider。

可用的第三方扩展

Cake.AzureDevOps 由Pascal Berger https://cakebuild.net/extensions/cake-azuredevops/ 最新版本:3.0.0 上次更新7个月前 azure devops, azure devops server 适用于Cake构建自动化系统的插件,用于与Azure DevOps或Azure DevOps Server一起使用。

Cake.Issues.PullRequests.AzureDevOps 由BBT Software AG和贡献者 https://cakebuild.net/extensions/cake-issues-pullrequests-azuredevops/ 最新版本:3.0.0 上次更新2个月前 cake issues, cake pullrequestsystem, issues, pullrequest, tfs, azure devops, azure devops server Cake.Issues插件的Azure DevOps支持允许您将找到的问题作为评论写入Azure DevOps拉取请求。此插件提供了用于编写Azure DevOps拉取请求的别名。它还需要核心Cake.Issues和Cake.Issues.PullRequests插件以及一个或多个问题提供程序。请参阅cakeissues.net,了解有关在Cake脚本中处理问题的整个生态系统的概述。

Cake.Tfs.AutoMerge 由mabreu https://cakebuild.net/extensions/cake-tfs-automerge/ 最新版本:0.1.3 上次更新5年前 tfs 使用TFS拉取请求自动合并Git分支的Cake别名。

Cake.Tfs.Build.Variables 由Attila Kemeny https://cakebuild.net/extensions/cake-tfs-build-variables/ 最新版本:0.0.9 上次更新10个月前 tfs 从参数或环境变量中检索TFS变量。

Azure DevOps构建任务扩展

Cake Azure DevOps构建任务使直接运行Cake脚本变得容易,无需调用PowerShell或其他命令行脚本。这使得即使对Cake不熟悉的团队成员也可以添加或调整传递给构建脚本的参数。

安装Azure DevOps扩展

要安装Azure DevOps扩展,请转到Visual Studio Marketplace上的Cake Build Task页面,然后单击"安装"。

添加构建任务

转到Azure DevOps租户中的"构建"部分,创建一个构建定义,或选择一个现有的。通过单击"添加构建步骤..."按钮添加一个新的构建步骤。

image

应该会弹出一个包含不同任务的对话框。选择"Cake"任务,然后单击"添加"按钮一次。之后,单击"关闭"按钮关闭窗口。

image

配置构建任务

现在,您可以编辑构建任务信息,例如要执行哪个构建脚本、要运行哪个构建目标、日志记录的数量(详细程度)以及发送到构建脚本的附加参数。

默认情况下,Cake构建步骤(当添加到构建时)将尝试使用目标Default运行构建.cake构建脚本(在存储库根目录中找到)。如果您希望运行另一个构建脚本或构建目标,可以在构建步骤设置中更改此设置。

image 对于已经使用Cake并使用引导程序文件的人,使用Azure DevOps任务时不会调用引导程序文件。要使用引导程序文件,您应该添加一个"PowerShell"或"Shell脚本"任务。

关于变量的注意事项

在Azure DevOps中标记为机密的环境变量默认情况下无法使用EnvironmentVariable()在Cake脚本中解析。它们可以作为参数传递给构建脚本,或在YAML构建定义中显式映射。您可以在Azure DevOps文档中详细了解此限制。

Bamboo

开箱即用的支持

Bamboo别名,返回一个IBambooProvider实例,可用于与Atlassian Bamboo环境交互。

以下示例在Atlassian Bamboo上运行时打印构建编号:

if (BuildSystem.Bamboo.IsRunningOnBamboo)
{
    Information(BuildSystem.Bamboo.Environment.Build.Number);
}
else
{
    Information("Not running on Atlassian Bamboo");
}

查看IBambooProvider以获取与Atlassian Bamboo交互的详细信息和可用方法。

可用的第三方扩展

未找到扩展。

Bitbucket Pipelines

开箱即用的支持

BitbucketPipelines别名,返回一个IBitbucketPipelinesProvider实例,可用于与Atlassian Bitbucket Pipelines环境交互。

以下示例在Atlassian Bitbucket Pipelines上运行时写入拉取请求ID:

if (BuildSystem.BitbucketPipelines.IsRunningOnBitbucketPipelines)
{
    Information(BuildSystem.BitbucketPipelines.Environment.PullRequest.Id);
}
else
{
    Information("Not running on Atlassian Bitbucket Pipelines");
}

查看IBitbucketPipelinesProvider以获取与Atlassian Bitbucket Pipelines交互的详细信息和可用方法。

可用的第三方扩展

未找到扩展。

Bitrise

开箱即用的支持

Bitrise别名,返回一个IBitriseProvider实例,可用于与Bitrise环境交互。

以下示例在Bitrise上运行时打印构建编号:

if (BuildSystem.Bitrise.IsRunningOnBitrise)
{
    Information(BuildSystem.Bitrise.Environment.Build.BuildNumber);
}
else
{
    Information("Not running on Bitrise");
}

查看IBitriseProvider以获取与Bitrise交互的详细信息和可用方法。

可用的第三方扩展

未找到扩展。

Continua CI

开箱即用的支持

ContinuaCI别名,返回一个IContinuaCIProvider实例,可用于与Continua CI环境交互。

以下示例在Continua CI上运行时写入错误消息:

if (BuildSystem.ContinuaCI.IsRunningOnContinuaCI)
{
    BuildSystem.ContinuaCI.WriteMessage(
            "This is a error message.",
            ContinuaCIMessageType.Error
        );
}
else
{
    Information("Not running on Continua CI");
}

查看IContinuaCIProvider以获取与Continua CI交互的详细信息和可用方法。

可用的第三方扩展

未找到扩展。

GitHub Actions

开箱即用的支持

GitHubActions别名,返回一个IGitHubActionsProvider实例,可用于与GitHub Actions环境交互。

以下示例打印出是否在GitHub Actions上运行的拉取请求构建:

if (BuildSystem.GitHubActions.IsRunningOnGitHubActions)
{
    Information(BuildSystem.GitHubActions.Environment.PullRequest.IsPullRequest);
}
else
{
    Information("Not running on GitHub Actions");
}

查看IGitHubActionsProvider以获取与GitHub Actions交互的详细信息和可用方法。

可用的第三方扩展

GitLab CI/CD

开箱即用的支持

GitLabCI别名,返回一个IGitLabCIProvider实例,可用于与GitLab CI/CD环境交互。

以下示例在GitLab CI/CD上运行时打印构建编号:

if (BuildSystem.GitLabCI.IsRunningOnGitLabCI)
{
    Information(BuildSystem.GitLabCI.Environment.Build.Id);
}
else
{
    Information("Not running on GitLab CI/CD");
}

查看IGitLabCIProvider以获取与GitLab CI/CD交互的详细信息和可用方法。

可用的第三方扩展

GoCD

开箱即用支持

GoCD别名,返回一个IGoCDProvider实例,可用于与GoCD环境进行交互。

以下示例在GoCD上运行时打印了流水线运行的次数:

if (BuildSystem.GoCD.IsRunningOnGoCD)
{
    Information(BuildSystem.GoCD.Environment.Pipeline.Counter);
}
else
{
    Information("Not running on GoCD");
}

请查看IGoCDProvider,了解与GoCD进行交互的详细信息和可用方法。

第三方扩展可用性

无扩展可用

Jenkins

开箱即用支持

Jenkins别名,返回一个IJenkinsProvider实例,可用于与Jenkins环境进行交互。

以下示例在Jenkins上运行时打印了构建编号:

if (BuildSystem.Jenkins.IsRunningOnJenkins)
{
    Information(BuildSystem.Jenkins.Environment.Build.BuildNumber);
}
else
{
    Information("Not running on Jenkins");
}

请查看IJenkinsProvider,了解与Jenkins进行交互的详细信息和可用方法。

第三方扩展可用性

无扩展可用

MyGet

开箱即用支持

MyGet别名,返回一个IMyGetProvider实例,可用于与MyGet环境进行交互。

以下示例在MyGet上运行时写入了一个错误消息:

if (BuildSystem.MyGet.IsRunningOnMyGet)
{
    BuildSystem.MyGet.WriteStatus(
            "This is a error message.",
            MyGetBuildStatus.Error,
            "Error details."
        );
}
else
{
    Information("Not running on MyGet");
}

请查看IMyGetProvider,了解与MyGet进行交互的详细信息和可用方法。

第三方扩展可用性

无扩展可用

TeamCity

开箱即用支持

TeamCity别名,返回一个ITeamCityProvider实例,可用于与TeamCity环境进行交互。

以下示例在TeamCity上运行时写入了一个错误消息:

if (BuildSystem.TeamCity.IsRunningOnTeamCity)
{
    BuildSystem.TeamCity.WriteStatus(
            "This is a error message.",
            "error",
            "Error details."
        );
}
else
{
    Information("Not running on TeamCity");
}

请查看ITeamCityProvider,了解与TeamCity进行交互的详细信息和可用方法。

第三方扩展可用性

Travis CI

开箱即用支持

TravisCI别名,返回一个ITravisCIProvider实例,可用于与Travis CI环境进行交互。

以下示例在Travis CI上运行时打印构建编号:

if (BuildSystem.TravisCI.IsRunningOnTravisCI)
{
    Information(BuildSystem.TravisCI.Environment.Build.BuildId);
}
else
{
    Information("Not running on Travis CI");
}

请查看ITravisCIProvider,了解与Travis CI进行交互的详细信息和可用方法。

第三方扩展可用性

WangShuXian6 commented 1 year ago

扩展 Cake

Cake 提供不同的扩展点:

插件

插件允许通过附加脚本别名来扩展DSL。

创建插件 如何创建自定义插件 编写插件的最佳实践 编写插件的最佳实践

创建Addins

首先,创建一个新的类库项目,然后通过包管理器向其中添加对Cake.Core NuGet包的引用。

PM> Install-Package Cake.Core

添加您希望在Cake脚本中公开的别名方法。脚本别名方法只是标记了CakeMethodAliasAttribute属性的ICakeContext的扩展方法。该方法可以使用任何标准的CLR功能,包括可选参数。

您还可以添加一个脚本别名属性,它的工作方式与脚本别名方法相同,只是不接受任何参数,并且标记有CakePropertyAliasAttribute属性。

using Cake.Core;
using Cake.Core.Annotations;

public static class MyCakeExtension
{
    [CakeMethodAlias]
    public static int GetMagicNumber(this ICakeContext context, bool value)
    {
        return value ? int.MinValue : int.MaxValue;
    }

    [CakeMethodAlias]
    public static int GetMagicNumberOrDefault(this ICakeContext context, bool value, Func<int> defaultValueProvider = null)
    {
        if (value)
        {
            return int.MinValue;
        }

        return defaultValueProvider == null ? int.MaxValue : defaultValueProvider();
    }

    [CakePropertyAlias]
    public static int TheAnswerToLife(this ICakeContext context)
    {
        return 42;
    }
}

导入命名空间

您的脚本别名可能需要在Cake脚本中导入一个或多个命名空间。Cake支持在属性处自动导入带有属性的命名空间。

可以在方法、类或程序集级别应用CakeNamespaceImportAttribute,或者将它们组合在一起使用。

// 仅为此方法导入Cake.Common.IO.Paths命名空间到Cake脚本
[CakeNamespaceImport("Cake.Common.IO.Paths")]
public static ConvertableDirectoryPath Directory(this ICakeContext context, string path)
{...}
// 为类中使用的任何别名方法导入Cake.Common.IO.Paths命名空间到Cake脚本
[CakeNamespaceImport("Cake.Common.IO.Paths")]
public static class DirectoryAliases
{...}
// 为程序集中使用的任何别名方法导入Cake.Common.IO.Paths命名空间到Cake脚本
[assembly: CakeNamespaceImport("Cake.Common.IO.Paths")]

使用Addin

编译该程序集,并通过#r指令在构建脚本中引用它。

#r "tools/MyCakeExtension.dll"

现在,您应该能够从脚本中调用该方法。

Task("GetSomeAnswers")
    .Does(() =>
{
    // 将值写入控制台。
    Information("魔法数字:{0}", GetMagicNumber(false));
    Information("生命之答案:{0}", TheAnswerToLife);
});

编写Addins的最佳实践

本页面提供了编写Cake Addins的最佳实践。每个指南都描述了一个好的或不好的做法。

每个指南的措辞表明了建议的强度:

Do(执行)指南几乎总是应该遵循的。您需要一个非常不寻常的情况才能违反Do指南。

Consider(考虑)指南通常应该遵循。如果您完全理解指南背后的含义并且有充分的理由这样做,可以偏离Consider指南。

Avoid(避免)指南表示您几乎永远不应该做某事。

命名

§1.1 Do 使用"Cake.xxx"作为Addins的命名模式,其中"xxx"是一个有意义且唯一描述Addin功能的名称。

为什么?遵循约定使用户更容易找到和使用Addins。自动化的AddinDiscoverer用于审计和保持网站更新,它也使用这种约定来识别Cake Addins。

示例:

Cake.Email是一个清晰标识Cake Addin的名称,该Addin允许从构建脚本发送电子邮件。这个名称在GitHub仓库中使用,它是解决方案文件的名称,项目文件的名称,生成的程序集的名称,最后,它也是NuGet包的名称。

§1.2 Do 使用相同的名称命名GitHub仓库、C#解决方案名称、从项目生成的程序集和NuGet包。

为什么?在不同的构件中使用相同的名称使用户更容易并改进了自动化过程的结果。

参考

Cake参考 §2.1 Do 引用与最新版本(目前为3.0.0)API兼容的Cake的最低版本。

为什么?这为不同版本的Cake提供了最佳支持。根据较新版本的Cake构建的Addins可能与较早版本的Cake不兼容,反之亦然,根据较旧版本构建的Addins可能与未来版本的Cake不兼容(特别是当未来版本的Cake引入破坏性更改时)。

与特定Addin API兼容的Cake版本将在将Addin添加到Cake网站时显示。

§2.2 Do 如果Addin需要特定功能,则引用高于Cake 3.0.0的版本。

为什么?如果Addin需要Cake的特定功能,则应引用引入此功能的Cake的最低版本,以便访问该功能并为不同版本的Cake提供最佳支持。

§2.3 Do 如果Cake的版本引入了破坏性更改,请将Addin更新到较新的Cake版本。

为什么?Cake将输出警告,表示Addin是根据不兼容的Cake版本构建的,可能不再起作用。Addin作者有责任升级其引用并发布新版本的NuGet包。

§2.4 Avoid 在NuGet包中引用Cake.Core和Cake.Common。

为什么?这些引用由Cake引擎隐式添加。

示例:

dotnet CLI / MSBuild nuget.exe CLI 需要在项目文件中将对Cake.Core和Cake.Common的引用标记为私有资产:

<ItemGroup>
  <PackageReference Include="Cake.Core" Version="1.0.0" PrivateAssets="All" />
  <PackageReference Include="Cake.Common" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

.NET目标版本 §2.5 Do 多目标选择net6.0和net7.0。

为什么?多目标选择net6.0和net7.0对于大多数Addins来说应该可以支持可用Cake运行程序、操作系统和平台的最新版本。

包元数据

图标 §3.1 Do 为NuGet包定义一个图标。

为什么?图标帮助用户识别Cake Addins。

§3.2 Consider 使用Cake Contrib图标。

为什么?

当Addin没有自己的产品图标时,使用Cake Contrib图标可以为Cake Addins提供共同的品牌标识。

§3.3 Avoid 使用Cake图标。

为什么?Cake图标保留给核心Cake包使用。

§3.4 Do 将图标嵌入到包中。

为什么?使用嵌入在包中的图标比链接到托管图标的外部网站更可靠。

示例:

这可以通过在Addins的.csproj中添加以下行来完成:

<PackageIcon>PackageIcon.png</PackageIcon>

Addins的.csproj还应包含对png文件的引用:

<ItemGroup>
    <None Include="..\PackageIcon.png" Pack="true" PackagePath="" />
</ItemGroup>

请注意Pack属性,这对于确保文件嵌入在NuGet包中非常重要。

直到2019年初,推荐的做法是引用托管在rawgit CDN上的Cake Contrib图标,但rawgit宣布将在2019年10月关闭,因此建议改为引用托管在jsDelivr CDN上的Cake Contrib图标。这个建议在2019年秋天再次改变,当NuGet开始支持嵌入式图标时。

标签 §3.5 Do 将"cake-addin"添加到NuGet标签中。

为什么?自NuGet/NuGetGallery#8381以来,NuGet可以显示有关如何安装Cake包的说明。只有使用了正确的标签,才能显示正确的安装说明。

文档

§4.1 Do 遵循Cake文档指南。

为什么?正确的XML注释和使用CakeAliasCategoryAttribute对于在将Addin添加到Cake网站时显示Addin文档非常重要。

§4.2 Do 将文档XML文件添加到NuGet包中。

为什么?XML文档XML文件用于在Cake网站上显示由Addin提供的别名和API的文档。

测试

§5.1 Do 使用不同的运行程序测试Addin。

为什么?.NET工具和Cake Frosting在加载运行程序的依赖项以及如何加载依赖项方面存在细微差异。

不与Addin兼容的运行程序应该在包含别名的类的XML注释中进行文档化。

§5.2 Do 在不同Cake运行程序支持的所有操作系统上测试Addin。

为什么?不同的平台在文件系统或可用工具等方面存在差异。

不与Addin兼容的操作系统应该在包含别名的类的XML注释中进行文档化。

§5.3 Do 在不同Cake运行程序支持的所有平台上测试Addin。

不与Cake支持的平台兼容的Addin应该在包含别名的类的XML注释中进行文档化。

模块

模块是一种特殊的Cake组件,旨在增强、更改或替换Cake本身的内部逻辑。例如,模块可用于替换内置的Cake构建日志、进程运行器或工具定位器等等。在内部,这就是Cake管理其“运行部分”的方式,但您也可以在运行构建脚本的过程中加载模块,从而允许您在构建代码的一部分中替换/更改Cake的工作方式。

编写模块的最佳实践 查看详情 模块资源 [开发自定义模块的资源]

编写模块的最佳实践

本页面提供了编写Cake模块的一些最佳实践。每个指南都描述了良好或不良的实践。

每个指南的措辞表明了建议的强度:

Do(应该) 指南几乎总是应该遵循的。除非有非常特殊的情况,否则不应违反Do指南。

Consider(请考虑) 指南通常应该遵循。如果您完全理解指南背后的含义并有充分的理由,可以偏离Consider指南。

Avoid(避免) 指南表示您几乎永远不应该做某事。

命名 §1.1 应该 使用Cake.xxx.Module作为模块的命名模式,其中xxx是一个有意义且唯一的名称,用于描述模块的功能是什么。

为什么? 遵循约定可以使用户更容易找到并使用模块。用于审计和保持网站最新的自动化AddinDiscoverer也使用此约定来识别Cake模块。

示例: Cake.Npm.Module是一个明确标识的名称,用于Cake为构建脚本中的工具安装提供npm包管理器支持的模块。这个名称在GitHub存储库中使用,它是解决方案文件的名称,项目文件的名称,生成的程序集的名称,最后,它也是NuGet包的名称。

§1.2 应该 使用相同的名称命名GitHub存储库、C#解决方案名称、从项目生成的程序集和NuGet包。

为什么? 在不同的工件之间使用相同的名称使用户更容易,并改善了自动化过程的结果。

引用 Cake引用 §2.1 应该 引用与最新版本(当前为3.0.0)具有API兼容性的Cake的最低版本。

为什么? 这为不同版本的Cake提供了最佳支持。根据较新版本的Cake构建的模块可能与较早版本的Cake不兼容,反之亦然;根据较早版本构建的模块可能与未来版本的Cake不兼容(特别是当未来版本的Cake引入重大更改时)。

模块与特定模块API兼容的Cake版本将在将模块添加到Cake网站时显示。

§2.2 应该 如果模块需要特定功能,则引用比Cake 3.0.0更新的版本。

为什么? 如果模块需要Cake的特定功能,应引用引入此功能的Cake的最低版本,以便访问该功能并获得对不同版本的Cake的最佳支持。

§2.3 应该 如果可用,将模块更新到较新版本的Cake,如果Cake的版本出现重大更改。

为什么? Cake将输出警告,表示模块是针对不兼容的Cake版本构建的,模块可能不再起作用。模块的作者有责任升级其引用并发布新版本的NuGet包。

§2.4 避免 在NuGet包中引用Cake.Core和Cake.Common的依赖项。

为什么? 这些引用是由Cake引擎隐式添加的。

示例: dotnet CLI / MSBuild nuget.exe CLI 需要在项目文件中将对Cake.Core和Cake.Common的引用标记为私有资产:

<ItemGroup>
  <PackageReference Include="Cake.Core" Version="1.0.0" PrivateAssets="All" />
  <PackageReference Include="Cake.Common" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

.NET目标版本 §2.5 应该 目标为net6.0。

为什么? 目标为net6.0应该适用于大多数模块,以支持可用Cake运行程序、操作系统和平台的最新版本。

§2.6 避免 目标额外的框架,比如net7.0。

为什么? 由于目前存在关于如何加载模块的限制(1, 2),Cake尝试加载模块的NuGet包的所有目标中包含的所有程序集,这会导致显示警告,并产生模块未加载和/或不工作的印象。一旦这些限制得到解决,我们将更新此建议,以与Cake Addin的建议一致。

包元数据 图标 §3.1 应该 为NuGet包定义一个图标。

为什么? 图标有助于用户识别Cake模块。

§3.2 请考虑 使用Cake Contrib图标。

为什么? 当模块没有自己的产品图标时,使用Cake Contrib图标可以为Cake模块提供共同的品牌。

§3.3 避免 使用Cake图标。

为什么? Cake图标保留给核心Cake包。

§3.4 应该 将图标嵌入到包中。

**为什

么?** 使用嵌入在包中的图标比链接到托管图标的外部网站更可靠。

示例: 可以在模块的.csproj文件中使用以下行来完成:

<PackageIcon>PackageIcon.png</PackageIcon>

模块的.csproj还应包含对png文件的引用:

<ItemGroup>
  <None Include="..\PackageIcon.png" Pack="true" PackagePath="" />
</ItemGroup>

请注意Pack属性,这对于确保文件嵌入在NuGet包中非常重要。

直到2019年初,建议是引用托管在rawgit CDN上的Cake Contrib图标,但rawgit宣布将于2019年10月关闭,因此建议更改为引用在jsDelivr CDN上托管的Cake Contrib图标。这个建议在2019年秋季再次更改,当NuGet开始支持嵌入式图标时。

标签 §3.5 应该 将cake-module添加到NuGet标签。

为什么? 自NuGet/NuGetGallery#8381以来,NuGet可以显示如何在Cake中安装包的说明。只有使用正确的标签,才能显示正确的安装说明。

文档 §4.1 应该 遵循Cake文档指南。

为什么? 适当的XML注释和使用CakeModuleAttribute是能够在将模块添加到Cake网站时显示模块文档的重要因素。

§4.2 应该 将文档XML文件添加到NuGet包中。

为什么? XML文档文件用于在Cake网站上显示模块提供的API的文档。

测试 §5.1 应该 使用不同的运行程序测试模块。

为什么? .NET工具、脚本运行程序和Cake Frosting在运行程序加载的依赖项以及如何加载依赖项方面存在轻微差异。

模块不兼容的运行程序应该在实现ICakeModule接口的类的XML注释中进行记录。

§5.2 应该 在所有由不同的Cake运行程序支持的操作系统上测试模块。

为什么? 不同的平台在文件系统或可用工具等方面存在差异。

不兼容的操作系统应该在实现ICakeModule接口的类的XML注释中进行记录。

§5.3 应该 在不同的Cake运行程序支持的所有平台上测试模块。

为什么? 不同的平台在实现上存在轻微差异,可能会破坏模块。

不兼容的平台应该在实现ICakeModule接口的类的XML注释中进行记录。

模块资源

目前,最全面的可用资源是Alistair Chapman的以下视频,其中详细介绍了从零开始构建新Cake模块的过程。完整视频可在YouTube上观看。 https://youtu.be/MS_PIHLQgPc

团队

认识Cake的核心维护团队。然而,Cake的存在离不开我们的赞助商、支持者和贡献者。