

亚马逊 CodeCatalyst 不再向新买家开放。现有客户可以继续正常使用该服务。有关更多信息，请参阅 [如何从中迁移 CodeCatalyst](migration.md)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 开发自定义蓝图以满足项目要求
<a name="develop-bp"></a>

在发布自定义蓝图之前，您可以开发蓝图以满足特定要求。您可以通过在预览时创建项目来开发自定义蓝图并测试蓝图。您可以开发自定义蓝图以包含项目组件，例如特定的源代码、账户连接、工作流、事务或可在 CodeCatalyst 中创建的任何其他组件。

**重要**  
如果要使用来自外部来源的蓝图包，请考虑使用这些包可能带来的风险。您对添加到空间中的自定义蓝图以及这些蓝图生成的代码负责。

**重要**  
要在 CodeCatalyst 空间中开发自定义蓝图，您必须使用在该空间中具有**空间管理员**或**高级用户**角色的账户进行登录。

**开发或更新自定义蓝图**

1. 恢复您的开发环境。有关更多信息，请参阅 [恢复开发环境](devenvironment-resume.md)。

   如果您没有开发环境，则必须先创建一个。有关更多信息，请参阅 [创建开发环境](devenvironment-create.md)。

1. 在您的开发环境中打开工作终端。

1. 如果您在创建蓝图时选择了发布工作流，则会自动发布最新的蓝图版本。提取更改以确保 `package.json` 文件具有递增版本。使用以下命令：

   ```
   git pull
   ```

1. 在 `src/blueprint.ts` 文件中，编辑自定义蓝图的选项。CodeCatalyst 向导会动态解释 `Options` 接口以生成选择用户界面（UI）。您可以通过添加组件和支持的标签来开发自定义蓝图。有关更多信息，请参阅[使用前端向导修改蓝图功能](wizard-bp.md)、[向蓝图添加环境组件](comp-env-bp.md)、[向蓝图添加区域组件](region-comp-bp.md)、[向蓝图添加存储库和源代码组件](comp-repo-source-bp.md)、[向蓝图添加工作流组件](comp-workflow-bp.md)和[向蓝图添加开发环境组件](comp-dev-env-bp.md)。

   在开发自定义蓝图时，还可以查看蓝图 SDK 和示例蓝图以获得其他支持。有关更多信息，请参阅 [open-source GitHub repository](https://github.com/aws/codecatalyst-blueprints)。

在成功合成后，自定义蓝图会提供预览包。项目包代表项目中的源代码、配置和资源，它由 CodeCatalyst 部署 API 操作用来部署到项目中。如果要继续开发自定义蓝图，请重新运行蓝图合成流程。有关更多信息，请参阅 [自定义蓝图概念](custom-bp-concepts.md)。

# 使用前端向导修改蓝图功能
<a name="wizard-bp"></a>

CodeCatalyst 上的蓝图选择向导由 `blueprint.ts` 文件中的 `Options` 接口自动生成。前端向导支持使用 [JSDOC style comments and tags](https://jsdoc.app/about-getting-started.html) 对蓝图的 `Options` 进行修改和特征化。您可以使用 JSDOC 样式注释和标签来执行任务。例如，您可以选择选项上方显示的文本，启用输入验证等功能，或使选项可折叠。该向导的工作原理是解释从 `Options` 接口的 TypeScript 类型生成的抽象语法树（AST）。该向导会根据描述的类型自动进行配置。并非所有类型均受支持。其它支持的类型包括区域选择器和环境选择器。

以下是一个在蓝图的 `Options` 中使用 JSDOC 注释和标签的向导示例：

```
export interface Options {
  /**
   * What do you want to call your new blueprint?
   * @validationRegex /^[a-zA-Z0-9_]+$/
   * @validationMessage Must contain only upper and lowercase letters, numbers and underscores
   */
  blueprintName: string;

  /**
   * Add a description for your new blueprint.
   */
   description?: string;

   /**
    * Tags for your Blueprint:
    * @collapsed true
    */
  tags?: string[];
}
```

默认情况下，`Options` 接口的每个选项的显示名称使用 `camelCase` 显示。在向导中，JSDOC 样式注释中的纯文本将显示为选项上方的文本。

**Topics**
+ [支持的标签](#supported-tags-bp)
+ [支持的 TypeScript 类型](#supported-typescript-bp)
+ [在合成过程中与用户交流](#communication-mid-synthesis)

## 支持的标签
<a name="supported-tags-bp"></a>

前端向导中的自定义蓝图的 `Options` 支持以下 JSDOC 标签。

### @inlinePolicy ./path/to/policy/file.json
<a name="inline-policy-tag"></a>
+ **必需** - `Role` 类型选项。
+ **用法** - 使您能够传达角色所需的内联策略。`policy.json` 路径应位于源代码下。当您需要角色的自定义策略时，请使用此标签。
+ **依赖项** - `blueprint-cli 0.1.12` 及更高版本
+ **示例** – `@inlinePolicy ./deployment-policy.json`

```
environment: EnvironmentDefinition{
    awsAccountConnection: AccountConnection{
      /**
       * @inlinePolicy ./path/to/deployment-policy.json
       */
      cdkRole: Role[];
    };
   };
```

### @trustPolicy ./path/to/policy/file.json
<a name="trust-policy-tag"></a>
+ **必需** - `Role` 类型选项。
+ **用法** - 使您能够传达角色所需的信任策略。`policy.json` 路径应位于源代码下。当您需要角色的自定义策略时，请使用此标签。
+ **依赖项** - `blueprint-cli 0.1.12` 及更高版本
+ **示例** – `@trustPolicy ./trust-policy.json`

```
environment: EnvironmentDefinition{
    awsAccountConnection: AccountConnection{
      /**
       * @trustPolicy ./path/to/trust-policy.json
       */
      cdkRole: Role[];
    };
   };
```

### @validationRegex 正则表达式
<a name="validation-regex-tag"></a>
+ **必需** - 字符串选项。
+ **用法** - 使用给定的正则表达式对选项执行输入验证并显示 `@validationMessage`。
+ **示例** – `@validationRegex /^[a-zA-Z0-9_]+$/`
+ **建议** - 与 `@validationMessage` 一起使用。默认情况下，验证消息为空。

### @validationMessage 字符串
<a name="validation-message-tag"></a>
+ **必需** - `@validationRegex` 或其它错误来查看用法。
+ **用法** - `@validation*` 失败时显示验证消息。
+ **示例** - `@validationMessage Must contain only upper and lowercase letters, numbers, and underscores`。
+ **建议** - 与 `@validationMessage` 一起使用。默认情况下，验证消息为空。

### @collapsed 布尔值（可选）
<a name="collapsed-boolean-tag"></a>
+ **必需** - 不适用
+ **用法** - 使子选项能够折叠的布尔值。如果存在折叠的注释，则其默认值为 true。将该值设置为 `@collapsed false` 可创建最初处于打开状态的可折叠部分。
+ **示例** – `@collapsed true`

### @displayName 字符串
<a name="display-name-tag"></a>
+ **必需** - 不适用
+ **用法** - 更改选项的显示名称。使显示名称能够使用除 camelCase 以外的格式。
+ **示例** – `@displayName Blueprint Name`

### @displayName 字符串
<a name="display-name-tag"></a>
+ **必需** - 不适用
+ **用法** - 更改选项的显示名称。使显示名称能够使用除 [camelCase](https://en.wikipedia.org/wiki/Camel_case) 以外的格式。
+ **示例** – `@displayName Blueprint Name`

### @defaultEntropy 数字
<a name="default-entropy-tag"></a>
+ **必需** - 字符串选项。
+ **用法** - 将指定长度的随机字母数字字符串附加到选项。
+ **示例** – `@defaultEntropy 5`

### @placeholder 字符串（可选）
<a name="placeholder-tag"></a>
+ **必需** - 不适用
+ **用法** - 更改默认文本字段占位符。
+ **示例** – `@placeholder type project name here`

### @textArea 数字（可选）
<a name="text-area-tag"></a>
+ **必需** - 不适用
+ **用法** - 将字符串输入转换为文本区域组件，用于显示较大的文本部分。添加一个数字就定义了行数。默认为五行。
+ **示例** – `@textArea 10`

### @hidden 布尔值（可选）
<a name="hidden-tag"></a>
+ **必需** - 不适用
+ **用法** - 除非验证检查失败，否则向用户隐藏文件。默认值为 true。
+ **示例** – `@hidden`

### @button 布尔值（可选）
<a name="button-tag"></a>
+ **必需** - 不适用
+ **用法** - 注释必须是布尔属性的注释。添加一个按钮，选择后将合成为 true。不是切换按钮。
+ **示例** – `buttonExample: boolean;`

  ```
  /**
    * @button
    */
  buttonExample: boolean;
  ```

### @showName 布尔值（可选）
<a name="show-name-tag"></a>
+ **必需** - 不适用
+ **用法** - 只能用于账户连接类型。显示隐藏的名称输入。默认值为 `default_environment`。
+ **示例** – `@showName true`

  ```
  /**
    * @showName true
    */
  accountConnection: AccountConnection<{
      ...
  }>;
  ```

### @showEnvironmentType 布尔值（可选）
<a name="show-environment-tag"></a>
+ **必需** - 不适用
+ **用法** - 只能用于账户连接类型。显示隐藏的环境类型下拉菜单。所有连接都默认为 `production`。选项有 **Non-production** 或 **Production**。
+ **示例** – `@showEnvironmentType true`

  ```
  /**
    * @showEnvironmentType true
    */
  accountConnection: AccountConnection<{
      ...
  }>;
  ```

### @forceDefault 布尔值（可选）
<a name="force-default-tag"></a>
+ **必需** - 不适用
+ **用法** - 使用蓝图作者提供的默认值，而不是用户之前使用的值。
+ **示例** – `forceDeafultExample: any;`

  ```
  /**
    * @forceDefault
    */
  forceDeafultExample: any;
  ```

### @requires blueprintName
<a name="requires-tag"></a>
+ **必需** - `Options` 接口注释。
+ **用法** - 警告用户将指定的 `blueprintName` 添加到项目中，作为当前蓝图的要求。
+ **示例** – `@requires '@amazon-codecatalyst/blueprints.blueprint-builder'`

  ```
  /*
   * @requires '@amazon-codecatalyst/blueprints.blueprint-builder'
   */
  export interface Options extends ParentOptions {
  ...
  ```

### @filter regex
<a name="filter-regex-tag"></a>
+ **必需** - `Selector` 或 `MultiSelect` 接口注释。
+ **用法** - 将向导中的下拉菜单筛选为与指定正则表达式匹配的选项。
+ **示例** – `@filter /blueprintPackageName/`

  ```
   /**
       * @filter /myPackageName/
       */
      blueprintInstantiation?: Selector<BlueprintInstantiation>;
  ...
  ```

## 支持的 TypeScript 类型
<a name="supported-typescript-bp"></a>

前端向导中的自定义蓝图的 `Options` 支持以下 TypeScript 类型。

### 数字
<a name="number-ts-tag"></a>
+ **必需** - `number` 类型选项。
+ **用法** - 生成数字输入字段。
+ **示例** – `age: number`

```
{
  age: number
  ...
}
```

### 字符串
<a name="string-ts-tag"></a>
+ **必需** - `string` 类型选项。
+ **用法** - 生成字符串输入字段。
+ **示例** – `name: string`

```
{
  age: string
  ...
}
```

### 字符串列表
<a name="string-list-ts-tag"></a>
+ **必需** - `string` 类型数组选项。
+ **用法** - 生成字符串列表输入。
+ **示例** – `isProduction: boolean`

```
{
  isProduction: boolean
  ...
}
```

### Checkbox
<a name="checkbox-ts-tag"></a>
+ **必需** - `boolean` 选项。
+ **用法** - 生成一个复选框。
+ **示例** – `isProduction: boolean`

```
{
  isProduction: boolean
  ...
}
```

### 单选框
<a name="radio-ts-tag"></a>
+ **必需** - 三个或更少字符串的组合选项。
+ **用法** - 生成选定的单选框。
**注意**  
当有四个或更多项目时，此类型将以下拉列表的形式呈现。
+ **示例** – `color: 'red' | 'blue' | 'green'`

```
{
  color: 'red' | 'blue' | 'green'
  ...
}
```

### 下拉菜单
<a name="dropdown-ts-tag"></a>
+ **必需** - 四个或更多字符串的组合选项。
+ **用法** - 生成一个下拉列表。
+ **示例** – `runtimes: 'nodejs' | 'python' | 'java' | 'dotnetcore' | 'ruby'`

```
{
  runtimes: 'nodejs' | 'python' | 'java' | 'dotnetcore' | 'ruby'
  ...
}
```

### 可扩展部分
<a name="expandable-ts-tag"></a>
+ **必需** - 对象选项。
+ **用法** - 生成可扩展部分。对象中的选项将嵌套在向导中的可扩展部分内。
+ **示例** - 

```
{
     expandableSectionTitle: {
         nestedString: string;
         nestedNumber: number;
     }
}
```

### Tuple
<a name="tuple-ts-tag"></a>
+ **必需** - `Tuple` 类型选项。
+ **用法** - 生成键值对输入。
+ **示例** – `tuple: Tuple[string, string]>`

```
{
    tuple: Tuple[string, string]>;
    ...
}
```

### Tuple 列表
<a name="tuple-list-ts-tag"></a>
+ **必需** - `Tuple` 类型数组选项。
+ **用法** - 生成 tuple 列表输入。
+ **示例** – `tupleList: Tuple[string, string]>[]`

```
{
  tupleList: Tuple[string, string]>[];
  ...
}
```

### Selector
<a name="selector-ts-tag"></a>
+ **必需** - `Selector` 类型选项。
+ **用法** - 生成应用于项目的源存储库或蓝图的下拉列表。
+ **示例** – `sourceRepo: Selector<SourceRepository>`

```
{
    sourceRepo: Selector<SourceRepository>;
    sourceRepoOrAdd: Selector<SourceRepository | string>;
    blueprintInstantiation: Selector<BlueprintInstantiation>;
  ...
}
```

### Multiselect
<a name="multiselect-ts-tag"></a>
+ **必需** - `Selector` 类型选项。
+ **用法** - 生成多选输入。
+ **示例** – `multiselect: MultiSelect['A' | 'B' | 'C' | 'D' | 'E']>`

```
{
  multiselect: MultiSelect['A' | 'B' | 'C' | 'D' | 'E']>;
  ...
}
```

## 在合成过程中与用户交流
<a name="communication-mid-synthesis"></a>

作为蓝图作者，您可以与用户交流，而不仅仅是验证消息。例如，空间成员可能会查看一个选项组合，而该组合产生的蓝图并不清晰。自定义蓝图支持通过调用合成向用户反馈错误消息的功能。基本蓝图实现了 `throwSynthesisError(...)` 函数，该函数希望得到明确的错误消息。您可以通过以下方式调用消息：

```
//blueprint.ts
this.throwSynthesisError({
   name: BlueprintSynthesisErrorTypes.BlueprintSynthesisError,
   message: 'hello from the blueprint! This is a custom error communicated to the user.'
})
```

# 生成输入和重新呈现前端向导元素
<a name="comp-dynamic-input-bp"></a>

您可以使用 DynamicKVInput 生成向导输入，并为自定义蓝图动态创建前端向导元素。

**Topics**
+ [创建开发环境](#dynamickvinput-bp)
+ [动态创建向导元素](#create-wizard-elements-bp)

## 创建开发环境
<a name="dynamickvinput-bp"></a>

您可以使用 DynamicKVInput 类型，使用自定义蓝图的默认值生成前端向导输入。要查看最新的架构，请参阅 [DynamicKVInput definition](https://github.com/aws/codecatalyst-blueprints/blob/main/packages/blueprints/blueprint/src/ui-selectors/dynamic-kv-input.ts)。

以下示例说明如何使用 `Options` 塑造对象：

```
import { DynamicKVInput } from '@amazon-codecatalyst/blueprints.blueprint';

export interface Options extends ParentOptions {

  parameters: DynamicKVInput[];

}
```

以下示例说明如何设置多个属性的默认参数：

```
{ 
"parameters": [
        {
            "key": "AWS_REGION",
            "value": "us-west-2",
            "displayType": "region",
            "possibleValues": [
                "us-west-1",
                "us-west-2",
                "us-east-1",
                "us-east-2"
            ],
            "displayName": "AWS Region",
            "description": "AWS Region to deploy the solution to."
        },
        {
            "key": "SchedulingActive",
            "value": "Yes",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Scheduling Active",
            "description": "Activate or deactivate scheduling."
        },
        {
            "key": "ScheduledServices",
            "value": "Both",
            "displayType": "dropdown",
            "possibleValues": [
                "EC2",
                "RDS",
                "Both"
            ],
            "displayName": "Scheduled Services",
            "description": "Services to schedule."
        },
        {
            "key": "ScheduleRdsClusters",
            "value": "No",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Schedule RDS Clusters",
            "description": "Enable scheduling of Aurora clusters for RDS service."
        },
        {
            "key": "CreateRdsSnapshot",
            "value": "No",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Create RDS Snapshot",
            "description": "Create snapshot before stopping RDS instances (does not apply to Aurora Clusters)."
        },
        {
            "key": "MemorySize",
            "value": "128",
            "displayType": "dropdown",
            "possibleValues": [
                "128",
                "384",
                "512",
                "640",
                "768",
                "896",
                "1024",
                "1152",
                "1280",
                "1408",
                "1536"
            ],
            "displayName": "Memory Size",
            "description": "Size of the Lambda function running the scheduler, increase size when processing large numbers of instances."
        },
        {
            "key": "UseCloudWatchMetrics",
            "value": "No",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Use CloudWatch Metrics",
            "description": "Collect instance scheduling data using CloudWatch metrics."
        },
        {
            "key": "LogRetentionDays",
            "value": "30",
            "displayType": "dropdown",
            "possibleValues": [
                "1",
                "3",
                "5",
                "7",
                "14",
                "30",
                "60",
                "90",
                "120",
                "150",
                "180",
                "365",
                "400",
                "545",
                "731",
                "1827",
                "3653"
            ],
            "displayName": "Log Retention Days",
            "description": "Retention days for scheduler logs."
        },
        {
            "key": "Trace",
            "value": "No",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Trace",
            "description": "Enable debug-level logging in CloudWatch logs."
        },
        {
            "key": "EnableSSMMaintenanceWindows",
            "value": "No",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Enable SSM Maintenance Windows",
            "description": "Enable the solution to load SSM Maintenance Windows, so that they can be used for EC2 instance Scheduling."
        },
        {
            "key": "DefaultTimezone",
            "value": "UTC",
            "displayType": "string",
            "displayName": "Default Timezone",
            "description": "Default timezone to use for scheduling."
        },
        {
            "key": "Regions",
            "value": "us-west-2",
            "displayType": "string",
            "displayName": "Regions",
            "description": "List of regions in which instances should be scheduled, leave blank for current region only."
        },
        {
            "key": "UsingAWSOrganizations",
            "value": "No",
            "displayType": "dropdown",
            "possibleValues": [
                "Yes",
                "No"
            ],
            "displayName": "Using AWS Organizations",
            "description": "Use AWS Organizations to automate spoke account registration."
        },
        {
            "key": "Principals",
            "displayType": "string",
			      "optional": false,
            "displayName": "Principals",
            "description": "(Required) If using AWS Organizations, provide the Organization ID. Eg. o-xxxxyyy. Else, provide a comma separated list of spoke account ids to schedule. Eg.: 1111111111, 2222222222 or {param: ssm-param-name}"
        },
        {
            "key": "Namespace",
            "value": "Default",
            "displayType": "string",
            "displayName": "Namespace",
            "description": "Provide unique identifier to differentiate between multiple solution deployments (No Spaces). Example: Dev"
        },
        {
            "key": "SchedulerFrequency",
            "value": 5,
            "displayType": "number",
            "displayName": "Scheduler Frequency",
            "description": "Scheduler running frequency in minutes."
        }
    ]
}
```

## 动态创建向导元素
<a name="create-wizard-elements-bp"></a>

在合成过程中，可以使用与创建向导输入相同的架构来动态地重新呈现向导。在必要时，这可以用来解决用户的后续问题。

```
//blueprint.ts

export interface Options extends ParentOptions {
...
 dynamicOptions: OptionsSchemaDefinition<'optionsIdentifier', KVSchema>;
}
```

然后，可以在合成期间使用 `Options` 组件设置向导。

```
import {
  OptionsSchemaDefinition,
  OptionsSchema,
} from '@amazon-codecatalyst/blueprints.blueprint';

...

  // dynamically renders a number in the place where 'optionsIdentifier' was set in the original options type.
  new OptionsSchema<KVSchema>(this, 'optionsIdentifier', [
    {
            "key": "SchedulerFrequency",
            "value": 5,
            "displayType": "number",
            "displayName": "Scheduler Frequency",
            "description": "Scheduler running frequency in minutes."
    }
   ]);
```

# 向蓝图添加环境组件
<a name="comp-env-bp"></a>

自定义蓝图向导是通过向导公开的 `Options` 界面动态生成的。蓝图支持从公开的类型生成用户界面（UI）组件。

**导入 Amazon CodeCatalyst 蓝图环境组件**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import {...} from '@amazon-codecatalyst/codecatalyst-environments'
```

**Topics**
+ [创建开发环境](#create-dev-env-bp)
+ [环境的列表](#list-env-bp)
+ [模拟接口示例](#examples-comp-env-bp)

## 创建开发环境
<a name="create-dev-env-bp"></a>

以下示例说明如何将您的应用程序部署到云：

```
export interface Options extends ParentOptions {
        ...
        myNewEnvironment:  EnvironmentDefinition{
            thisIsMyFirstAccountConnection: AccountConnection{
                thisIsARole: Role['lambda', 's3', 'dynamo'];
             };
        };
    }
```

该接口会生成一个 UI 组件，要求使用单一账户连接（`thisIsMyFirstAccountConnection`）的新环境（`myNewEnvironment`）。此外还会在账户连接（`thisIsARole`）上生成一个角色，具备 `['lambda', 's3', 'dynamo']` 作为要求的最低角色功能。并非所有用户都具有账户连接，因此您应该检查用户未连接账户或未将账户与角色连接的情况。角色也可以使用 `@inlinePolicies` 进行注释。有关更多信息，请参阅 [@inlinePolicy ./path/to/policy/file.json](wizard-bp.md#inline-policy-tag)。

环境组件需要 `name` 和 `environmentType`。以下代码是所需的最低默认设置：

```
{
  ...
  "myNewEnvironment": {
    "name": "myProductionEnvironment",
    "environmentType": "PRODUCTION"
  },
}
```

然后，用户界面组件会提示您在各种字段中输入内容。当您填写字段时，蓝图会完全展开。出于测试和开发目的，在 `defaults.json` 文件中包含完整的模拟可能会对您有所帮助。

## 环境的列表
<a name="list-env-bp"></a>

指定 `EnvironmentDefinition` 类型的数组将在向导 UI 中生成环境列表。

```
export interface Options extends ParentOptions {
    ...
   /**
     @showName readOnly
   */
    myEnvironments:  EnvironmentDefinition<{
        thisIsMyFirstAccountConnection: AccountConnection<{
            thisIsARole: Role<['lambda', 's3', 'dynamo']>;
        }>;
    }>[];

}
```

以下示例说明环境列表的默认值：

```
{
  ...
  "myEnvironments": [
  {
    "name": "myProductionEnvironment",
    "environmentType": "PRODUCTION"
  },
  {
    "name": "myDevelopmentEnvironment",
    "environmentType": "DEVELOPMENT"
  },
  ]
}
```

## 模拟接口示例
<a name="examples-comp-env-bp"></a>

### 简单的模拟界面
<a name="simple-comp-env-bp"></a>

```
{
    ...
    "thisIsMyEnvironment": {
        "name": "myProductionEnvironment",
        "environmentType": "PRODUCTION",
        "thisIsMySecondAccountConnection": {
            "id": "12345678910",
            "name": "my-account-connection-name",
            "secondAdminRole": {
                "arn": "arn:aws:iam::12345678910:role/ConnectedQuokkaRole",
                "name": "ConnectedQuokkaRole",
                "capabilities": [
                    "lambda",
                    "s3",
                    "dynamo"
                ]
            }
        }
    }
}
```

### 复杂的模拟界面
<a name="complex-comp-env-bp"></a>

```
export interface Options extends ParentOptions {
  /**
   * The name of an environment
   * @displayName This is a Environment Name
   * @collapsed
   */
  thisIsMyEnvironment: EnvironmentDefinition{
    /**
     * comments about the account that is being deployed into
     * @displayName This account connection has an overriden name
     * @collapsed
     */
    thisIsMyFirstAccountConnection: AccountConnection{
      /**
       * Blah blah some information about the role that I expect
       * e.g. here's a copy-pastable policy: [to a link]
       * @displayName This role has an overriden name
       */
      adminRole: Role['admin', 'lambda', 's3', 'cloudfront'];
      /**
       * Blah blah some information about the second role that I expect
       * e.g. here's a copy-pastable policy: [to a link]
       */
      lambdaRole: Role['lambda', 's3'];
    };
    /**
     * comments about the account that is being deployed into
     */
    thisIsMySecondAccountConnection: AccountConnection{
      /**
         * Blah blah some information about the role that I expect
         * e.g. here's a copy-pastable policy: [to a link]
         */
      secondAdminRole: Role['admin', 'lambda', 's3', 'cloudfront'];
      /**
         * Blah blah some information about the second role that I expect
         * e.g. here's a copy-pastable policy: [to a link]
         */
      secondLambdaRole: Role['lambda', 's3'];
    };
  };
}
```

### 完整的模拟界面
<a name="complete-comp-env-bp"></a>

```
{
  ...
  "thisIsMyEnvironment": {
    "name": "my-production-environment",
    "environmentType": "PRODUCTION",
    "thisIsMySecondAccountConnection": {
      "id": "12345678910",
      "name": "my-connected-account",
      "secondAdminRole": {
        "name": "LambdaQuokkaRole",
        "arn": "arn:aws:iam::12345678910:role/LambdaQuokkaRole",
        "capabilities": [
          "admin",
          "lambda",
          "s3",
          "cloudfront"
        ]
      },
      "secondLambdaRole": {
        "name": "LambdaQuokkaRole",
        "arn": "arn:aws:iam::12345678910:role/LambdaQuokkaRole",
        "capabilities": [
          "lambda",
          "s3"
        ]
      }
    },
    "thisIsMyFirstAccountConnection": {
      "id": "12345678910",
      "name": "my-connected-account",
      "adminRole": {
        "name": "LambdaQuokkaRole",
        "arn": "arn:aws:iam::12345678910:role/LambdaQuokkaRole",
        "capabilities": [
          "admin",
          "lambda",
          "s3",
          "cloudfront"
        ]
      },
      "lambdaRole": {
        "name": "LambdaQuokkaRole",
        "arn": "arn:aws:iam::12345678910:role/LambdaQuokkaRole",
        "capabilities": [
          "lambda",
          "s3"
        ]
      }
    }
  },
}
```

# 向蓝图添加密钥组件
<a name="secrets-comp-bp"></a>

可以在 CodeCatalyst 中使用密钥来存储可在工作流中引用的敏感数据。您可以向自定义蓝图添加密钥并在工作流中引用该密钥。有关更多信息，请参阅 [使用密钥遮蔽数据](workflows-secrets.md)。

**导入 Amazon CodeCatalyst 蓝图区域类型**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import { Secret, SecretDefinition } from '@amazon-codecatalyst/blueprint-component.secrets'
```

**Topics**
+ [创建密钥](#comp-create-secrets-bp)
+ [在工作流中引用密钥](#comp-reference-secrets-bp)

## 创建密钥
<a name="comp-create-secrets-bp"></a>

以下示例创建了一个 UI 组件，该组件提示用户输入密钥值和可选描述：

```
export interface Options extends ParentOptions {
    ...
    mySecret: SecretDefinition;
}


export class Blueprint extends ParentBlueprint {
  constructor(options_: Options) {
    new Secret(this, options.secret);
}
```

密钥组件需要 `name`。以下代码是所需的最低默认设置：

```
{
    ...
    "secret": {
        "name": "secretName"
    },

}
```

## 在工作流中引用密钥
<a name="comp-reference-secrets-bp"></a>

以下示例蓝图创建了一个密钥和一个引用该密钥值的工作流。有关更多信息，请参阅 [在工作流中引用密钥](workflows-secrets.using.md#workflows-using-secrets.using-identifier)。

```
export interface Options extends ParentOptions {
    ...
/**
*
* @validationRegex /^\w+$/
*/
  username: string;


  password: SecretDefinition;
}


export class Blueprint extends ParentBlueprint {
  constructor(options_: Options) {
    const password = new Secret(this, options_.password);

    const workflowBuilder = new WorkflowBuilder(this, {
      Name: 'my_workflow',
    });


    workflowBuilder.addBuildAction({
      actionName: 'download_files',
      input: {
        Sources: ['WorkflowSource'],
      },
      output: {
        Artifacts: [{ Name: 'download', Files: ['file1'] }],
      },
      steps: [
        `curl -u ${options_.username}:${password.reference} https://example.com`,
      ],
    });

    new Workflow(
      this,
      repo,
      workflowBuilder.getDefinition(),
    );

}
```

要了解有关在 CodeCatalyst 中使用密钥的更多信息，请参阅[使用密钥遮蔽数据](workflows-secrets.md)。

# 向蓝图添加区域组件
<a name="region-comp-bp"></a>

可以将区域类型添加到自定义蓝图的 `Options` 界面，以便在蓝图向导中生成可输入一个或多个 AWS 区域的组件。可以从 `blueprint.ts` 文件中的基础蓝图导入区域类型。有关更多信息，请参阅 [AWS 区域](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/)。

**要导入 Amazon CodeCatalyst 蓝图，请键入区域类型**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import { Region } from '@amazon-codecatalyst/blueprints.blueprint'
```

区域类型参数是一组可供选择的 AWS 区域代码，您也可以使用 `*` 包含所有受支持的 AWS 区域。

**Topics**
+ [Annotations](#region-annotations-bp)
+ [区域组件示例](#region-components-examples)

## Annotations
<a name="region-annotations-bp"></a>

JSDoc 可以向`Options`界面的每个字段添加标签，以自定义字段在向导中的显示方式和行为。对于区域类型，支持以下标签：
+ `@displayName` 注释可用于在向导中更改字段的标签。

  示例：`@displayName AWS Region`
+ `@placeholder` 注释可用于更改选择/多选组件的占位符。

  示例：`@placeholder Choose AWS Region`

## 区域组件示例
<a name="region-components-examples"></a>

### 从指定列表中选择区域
<a name="region-specified-list-bp"></a>

```
export interface Options extends ParentOptions {
    ...
  /**
   * @displayName Region
   */
  region: Region<['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']>;
}
```

### 从指定列表中选择一个或多个区域
<a name="region-specified-list-bp"></a>

```
export interface Options extends ParentOptions {
    ...
  /**
   * @displayName Regions
   */
  multiRegion: Region<['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']>[];
}
```

### 选择一个 AWS 区域
<a name="region-one-bp"></a>

```
export interface Options extends ParentOptions {
    ...
  /**
   * @displayName Region
   */
  region: Region<['*']>;
}
```

### 从指定列表中选择一个或多个区域
<a name="region-specified-list-bp"></a>

```
export interface Options extends ParentOptions {
    ...
  /**
   * @displayName Regions
   */
  multiRegion: Region<['us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']>[];
}
```

# 向蓝图添加存储库和源代码组件
<a name="comp-repo-source-bp"></a>

Amazon CodeCatalyst 使用存储库来存储代码。存储库将名称用作输入。大多数组件都存储在存储库中，例如源代码文件、工作流和其他组件，例如托管式开发环境（MDE）。源存储库组件还导出用于管理文件和静态资产的各种组件。存储库有名称限制。有关更多信息，请参阅 [使用源存储库存储代码并协作处理代码 CodeCatalyst使用源存储库存储代码并进行协作](source.md)。

```
const repository = new SourceRepository(this, {
  title: 'my-new-repository-title',
});
```

**导入 Amazon CodeCatalyst 蓝图存储库和源代码组件**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import {...} from '@caws-blueprint-component/caws-source-repositories'
```

**Topics**
+ [添加文件](#repo-add-file-bp)
+ [添加通用文件](#repo-add-generic-file-bp)
+ [复制文件](#repo-copy-file-bp)
+ [定位多个文件](#target-multiple-files-bp)
+ [创建新的存储库并添加文件](#repo-code-examples-bp)

## 添加文件
<a name="repo-add-file-bp"></a>

您可以使用 `SourceFile` 构造，将文本文件写入到存储库中。该操作是最常见的应用场景之一，需要使用存储库、文件路径和文本内容。如果存储库中不存在文件路径，则该组件会创建所有必需的文件夹。

```
new SourceFile(repository, `path/to/my/file/in/repo/file.txt`, 'my file contents');
```

**注意**  
如果您将两个文件写入到同一存储库中的相同位置，则最新的实施会覆盖前一个实施。您可以使用该功能对生成的代码进行分层，这对于扩展自定义蓝图可能已生成的代码尤其有用。

## 添加通用文件
<a name="repo-add-generic-file-bp"></a>

您可以向自己的存储库中写入任意位。您可以从缓冲区读取并使用 `File` 构造。

```
new File(repository, `path/to/my/file/in/repo/file.img`, new Buffer(...));

new File(repository, `path/to/my/file/in/repo/new-img.img`, new StaticAsset('path/to/image.png').content());
```

## 复制文件
<a name="repo-copy-file-bp"></a>

您可以复制粘贴起始代码，然后在这个基础上生成更多代码，从而开始使用生成的代码。将代码放在 `static-assets` 目录中，然后使用 `StaticAsset` 构造来定位该代码。在这种情况下，路径始终从 `static-assets` 目录的根目录开始。

```
const starterCode = new StaticAsset('path/to/file/file.txt')
const starterCodeText = new StaticAsset('path/to/file/file.txt').toString()
const starterCodeRawContent = new StaticAsset('path/to/image/hello.png').content()

const starterCodePath = new StaticAsset('path/to/image/hello.png').path()
// starterCodePath is equal to 'path/to/image/hello.png'
```

`StaticAsset` 的子类是 `SubstitutionAsset`。子类的功能完全相同，不过您可以改为对文件执行 Mustache 替换。这对于执行复制和替换样式生成非常有用。

静态资产替换使用 Mustache 模板引擎来呈现植入到所生成的源存储库中的静态文件。Mustache 模板规则是在呈现期间应用的，这意味着默认情况下，所有值都是 HTML 编码值。要呈现未转义的 HTML，请使用三个花括号语法 `{{{name}}}`。有关更多信息，请参阅 [mustache templating rules](https://github.com/janl/mustache.js?tab=readme-ov-file#variables)。

**注意**  
对无法使用文本解释的文件运行替换操作时，可能会产生错误。

```
const starterCodeText = new SubstitionAsset('path/to/file/file.txt').subsitite({
  'my_variable': 'subbed value1',
  'another_variable': 'subbed value2'
})
```

## 定位多个文件
<a name="target-multiple-files-bp"></a>

静态资源支持通过 `StaticAsset` 上的静态函数以及名为 `findAll(...)` 的子类，来进行 glob 定位，这将返回已预加载路径、内容等的静态资源列表。您可以将列表与 `File` 结构链接起来，以便在 `static-assets` 目录中复制和粘贴内容。

```
new File(repository, `path/to/my/file/in/repo/file.img`, new Buffer(...));

new File(repository, `path/to/my/file/in/repo/new-img.img`, new StaticAsset('path/to/image.png').content());
```

## 创建新的存储库并添加文件
<a name="repo-code-examples-bp"></a>

您可以使用存储库组件，在生成的项目中创建新的存储库。然后，您可以将文件或工作流添加到创建的存储库中。

```
import { SourceRepository } from '@amazon-codecatalyst/codecatalyst-source-repositories';
...
const repository = new SourceRepository(this, { title: 'myRepo' });
```

以下示例说明如何向现有存储库添加文件和工作流：

```
import { SourceFile } from '@amazon-codecatalyst/codecatalyst-source-repositories';
import { Workflow } from '@amazon-codecatalyst/codecatalyst-workflows';
...
new SourceFile(repository, 'README.md', 'This is the content of my readme');
new Workflow(this, repository, {/**...workflowDefinition...**/});
```

将这两段代码组合在一起时，可以生成单个名为 `myRepo` 的存储库，其根目录中包含一个源文件 `README.md` 和一个 CodeCatalyst 工作流。

# 向蓝图添加工作流组件
<a name="comp-workflow-bp"></a>

Amazon CodeCatalyst 项目使用工作流，根据触发器运行操作。您可以使用工作流组件来构建和整理工作流 YAML 文件。有关更多信息，请参阅 [工作流 YAML 定义](workflow-reference.md)。

**导入 Amazon CodeCatalyst 蓝图工作流组件**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import { WorkflowBuilder, Workflow } from '@amazon-codecatalyst/codecatalyst-workflows'
```

**Topics**
+ [工作流组件示例](#comp-workflows-examples-bp)
+ [连接到环境](#comp-workflows-connect-env-bp)

## 工作流组件示例
<a name="comp-workflows-examples-bp"></a>

### WorkflowBuilder 组件
<a name="comp-workflows-workflowbuilder-bp"></a>

您可以使用类来构建工作流定义。可以为工作流组件提供定义，以便在存储库中进行呈现。

```
import { WorkflowBuilder } from '@amazon-codecatalyst/codecatalyst-workflows'

const workflowBuilder = new WorkflowBuilder({} as Blueprint, {
  Name: 'my_workflow',
});

// trigger the workflow on pushes to branch 'main'
workflowBuilder.addBranchTrigger(['main']);

// add a build action
workflowBuilder.addBuildAction({
  // give the action a name
  actionName: 'build_and_do_some_other_stuff',

  // the action pulls from source code
  input: {
    Sources: ['WorkflowSource'],
  },

  // the output attempts to autodiscover test reports, but not in the node modules
  output: {
    AutoDiscoverReports: {
      Enabled: true,
      ReportNamePrefix: AutoDiscovered,
      IncludePaths: ['**/*'],
      ExcludePaths: ['*/node_modules/**/*'],
    },
  },
  // execute some arbitrary steps
  steps: [
    'npm install',
    'npm run myscript',
    'echo hello-world',
  ],
  // add an account connection to the workflow
  environment: convertToWorkflowEnvironment(myEnv),
});
```

### 工作流 Projen 组件
<a name="comp-workflows-projen-bp"></a>

以下示例说明如何使用 Projen 组件将工作流 YAML 写入到存储库中：

```
import { Workflow } from '@amazon-codecatalyst/codecatalyst-workflows'

...

const repo = new SourceRepository
const blueprint = this;
const workflowDef = workflowBuilder.getDefinition()

// creates a workflow.yaml at .aws/workflows/${workflowDef.name}.yaml
new Workflow(blueprint, repo, workflowDef);

// can also pass in any object and have it rendered as a yaml. This is unsafe and may not produce a valid workflow
new Workflow(blueprint, repo, {... some object ...});
```

## 连接到环境
<a name="comp-workflows-connect-env-bp"></a>

许多工作流需要在 AWS 账户连接中运行。工作流可让操作使用账户和角色名称规范连接到环境，从而处理这种情况。

```
import { convertToWorkflowEnvironment } from '@amazon-codecatalyst/codecatalyst-workflows'


const myEnv = new Environment(...);

// can be passed into a workflow constructor
const workflowEnvironment = convertToWorkflowEnvironment(myEnv);


// add a build action
workflowBuilder.addBuildAction({
  ...
  // add an account connection to the workflow
  environment: convertToWorkflowEnvironment(myEnv),
});
```

# 向蓝图添加开发环境组件
<a name="comp-dev-env-bp"></a>

托管式开发环境（MDE，Managed Development Environment）用于在 CodeCatalyst 中创建和建立 MDE 工作区。该组件生成一个 `devfile.yaml` 文件。有关更多信息，请参阅 [Introduction to Devfile](https://redhat-developer.github.io/devfile/) 和[编辑开发环境的存储库 devfile](devenvironment-devfile-moving.md)。

```
new Workspace(this, repository, SampleWorkspaces.default);
```

**导入 Amazon CodeCatalyst 蓝图工作区组件**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import {...} from '@amazon-codecatalyst/codecatalyst-workspaces'
```

# 向蓝图添加事务组件
<a name="comp-issues-bp"></a>

在 CodeCatalyst 中，您可以监控项目中涉及的功能、任务、错误以及任何其他工作。每项工作均保存在称为事务的不同记录中。每个事务都可以具有描述、被分派人、状态和其他属性，您可以对这些属性进行搜索、分组和筛选。您可以使用默认视图查看自己的事务，也可以使用自定义筛选、排序或分组来创建自己的视图。有关与事务相关的概念的更多信息，请参阅[事务概念](issues-concepts.md)和 [中的问题配额 CodeCatalyst](issues-quotas.md)。

事务组件可以生成事务的 JSON 表示形式。该组件将 ID 字段和事务定义用作输入。

**导入 Amazon CodeCatalyst 蓝图事务组件**

在您的 `blueprint.ts` 文件中，添加以下内容：

```
import {...} from '@amazon-codecatalyst/blueprint-component.issues'
```

**Topics**
+ [事务组件示例](#comp-issues-examples-bp)

## 事务组件示例
<a name="comp-issues-examples-bp"></a>

### 创建事务
<a name="comp-issues-create-bp"></a>

```
import { Issue } from '@amazon-codecatalyst/blueprint-component.issues';
...
new Issue(this, 'myFirstIssue', {
  title: 'myFirstIssue',
  content: 'This is an example issue.',
});
```

### 创建高优先级事务
<a name="comp-issues-high-priority-bp"></a>

```
import { Workflow } from '@amazon-codecatalyst/codecatalyst-workflows'
...
const repo = new SourceRepository
const blueprint = this;
const workflowDef = workflowBuilder.getDefinition()

// Creates a workflow.yaml at .aws/workflows/${workflowDef.name}.yaml
new Workflow(blueprint, repo, workflowDef);

// Can also pass in any object and have it rendered as a yaml. This is unsafe and may not produce a valid workflow
new Workflow(blueprint, repo, {... some object ...});
```

### 使用标签创建低优先级事务
<a name="comp-issues-low-priority-bp"></a>

```
import { Issue } from '@amazon-codecatalyst/blueprint-component.issues';
...
new Issue(this, 'myThirdIssue', {
  title: 'myThirdIssue',
  content: 'This is an example of a low priority issue with a label.',
  priority: 'LOW',
  labels: ['exampleLabel'],
});
```

# 使用蓝图工具和 CLI
<a name="bp-cli"></a>

[蓝图 CLI](https://www.npmjs.com/package/@amazon-codecatalyst/blueprint-util.cli) 提供了用来管理和使用自定义蓝图的工具。

**Topics**
+ [使用蓝图工具](#working-with-bp-cli)
+ [图像上传工具](#image-upload-tool)

## 使用蓝图工具
<a name="working-with-bp-cli"></a>

**使用蓝图工具**

1. 通过访问 [https://codecatalyst.aws/](https://codecatalyst.aws/) 打开 CodeCatalyst 控制台。

1. 恢复您的开发环境。有关更多信息，请参阅 [恢复开发环境](devenvironment-resume.md)。

   如果您没有开发环境，则必须先创建一个。有关更多信息，请参阅 [创建开发环境](devenvironment-create.md)。

1. 在正运行的终端中，运行以下命令来安装蓝图 CLI：

   ```
   npm install -g @amazon-codecatalyst/blueprint-util.cli
   ```

1. 在 `blueprint.ts` 文件中，按以下格式导入要使用的工具：

   ```
   import { <tooling-function-name> } from '@amazon-codecatalyst/blueprint-util.cli/lib/<tooling-folder-name>/<tooling-file-name>;
   ```
**提示**  
您可以转至 [https://github.com/aws/codecatalyst-blueprints/tree/main/packages/utils/blueprint-cli](https://github.com/aws/codecatalyst-blueprints/tree/main/packages/utils/blueprint-cli)，查找要使用的工具的名称。

   **如果您要使用图像上传工具，请在脚本中添加以下内容：**

   ```
   import { uploadImagePublicly } from '@amazon-codecatalyst/blueprint-util.cli/lib/image-upload-tool/upload-image-to-aws';
   ```

   **示例**
   + **如果您要使用发布功能，请在脚本中添加以下内容：**

     ```
     import { publish } from '@amazon-codecatalyst/blueprint-util.cli/lib/publish/publish';
     ```
   + **如果您要使用图像上传工具，请在脚本中添加以下内容：**

     ```
     import { uploadImagePublicly } from '@amazon-codecatalyst/blueprint-util.cli/lib/image-upload-tool/upload-image-to-aws';
     ```

1. 调用函数。

   **示例**
   + **如果您要使用发布功能，请在脚本中添加以下内容：**

     ```
     await publish(logger, config.publishEndpoint, {<your publishing options>});
     ```
   + **如果您要使用图像上传工具，请在脚本中添加以下内容：**

     ```
     const {imageUrl, imageName} = await uploadImagePublicly(logger, 'path/to/image'));
     ```

## 图像上传工具
<a name="image-upload-tool"></a>

使用图像上传工具，您可将图像上传到自己的 AWS 账户中的 S3 存储桶，然后通过 CloudFront 公开分发图像。该工具将本地存储空间中的图像路径（以及可选的存储桶名称）作为输入内容，并返回公开可用的图像的 URL。有关更多信息，请参阅[什么是 Amazon CloudFront？](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html)以及[什么是 Amazon S3？](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)

**使用图像上传工具**

1. 克隆提供蓝图 SDK 和示例蓝图访问权限的[开源蓝图 GitHub 存储库](https://github.com/aws/codecatalyst-blueprints)。在正运行的终端中，运行以下命令：

   ```
   git clone https://github.com/aws/codecatalyst-blueprints.git
   ```

1. 运行以下命令，导航到蓝图 GitHub 存储库：

   ```
   cd codecatalyst-blueprints
   ```

1. 运行以下命令以安装依赖项：

   ```
   yarn && yarn build
   ```

1. 运行以下命令，确保已安装了最新的蓝图 CLI 版本：

   ```
   yarn upgrade @amazon-codecatalyst/blueprint-util.cli
   ```

1. 使用要将图像上传到的 S3 存储桶登录 AWS 账户。有关更多信息，请参阅 [Configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) 和 [Sign in through the AWS Command Line Interface](https://docs.aws.amazon.com/signin/latest/userguide/command-line-sign-in.html)。

1. 从 CodeCatalyst 存储库的根目录运行以下命令，以便使用蓝图 CLI 导航到该目录：

   ```
   cd packages/utils/blueprint-cli
   ```

1. 运行以下命令，将您的图像上传到 S3 存储桶。

   ```
   yarn blueprint upload-image-public <./path/to/your/image> 
         <optional:optional-bucket-name>
   ```

此时会生成您的图像的 URL。由于部署 CloudFront 分配需要一些时间，因此该 URL 不会立即可用。检查分配状态，获取最新的部署状态。有关更多信息，请参阅[使用分配](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-working-with.html)。

# 通过快照测试评测接口变化
<a name="testing-bp"></a>

支持在蓝图的多个配置中生成快照测试。

蓝图支持对您作为蓝图作者提供的配置进行[快照测试](https://jestjs.io/docs/snapshot-testing)。配置是部分覆盖，合并在蓝图根目录下的 defaults.json 文件之上。启用并配置快照测试后，构建和测试流程会综合给定的配置，并验证综合输出与参考快照相比是否没有变化。要查看快照测试代码，请访问 [CodeCatalyst blueprints GitHub repository](https://github.com/aws/codecatalyst-blueprints/blob/main/packages/utils/projen-blueprint/src/test-snapshot.ts#L12)。

**启用快照测试**

1. 在 `.projenrc.ts` 文件中，用要拍摄快照的文件更新 ProjenBlueprint 的输入对象。例如：

   ```
   {
     ....
     blueprintSnapshotConfiguration: {
       snapshotGlobs: ['**', '!environments/**', '!aws-account-to-environment/**'],
     },
   }
   ```

1. 重新合成蓝图，在蓝图项目中创建 TypeScript 文件。不要编辑源文件，因为它们是由 Projen 维护和重新生成的。使用以下命令：

   ```
   yarn projen
   ```

1. 导航到 `src/snapshot-configurations` 目录，查看带有空对象的 `default-config.json` 文件。用您自己的一个或多个测试配置更新或替换该文件。然后将每个测试配置与项目的 `defaults.json` 文件合并、合成，并在测试时与快照进行比较。使用以下命令进行测试：

   ```
   yarn test
   ```

   首次使用测试命令时，将显示以下消息：`Snapshot Summary › NN snapshots written from 1 test suite`。随后的测试运行验证合成输出与快照相比是否没有变化，并显示以下消息：`Snapshots: NN passed, NN total`。

   如果您有意更改蓝图以产生不同的输出，请运行以下命令更新参考快照：

   ```
   yarn test:update
   ```

快照希望每次运行的合成输出恒定不变。如果您的蓝图生成的文件各不相同，您必须将这些文件排除在快照测试之外。更新 `ProjenBluerpint` 输入对象的 `blueprintSnapshotConfiguration` 对象，添加 `snapshotGlobs` 属性。`snapshotGlobs` 属性是一个 [globs](https://github.com/isaacs/node-glob#glob-primer) 数组，用于确定快照包含或排除哪些文件。

**注意**  
有一个默认的 globs 列表。如果您指定了自己的列表，可能需要明确恢复默认条目。