機能追加PRの作成
前提知識
CDKアプリケーションの構成
CDKアプリケーションはAppをルートとして、複数のStack, Constructから構成されています。

このうち、Constructは以下の3つのタイプに分けられます。
- L1 Construct
- Cloudformationのリソースと1対1に対応するConstruct
- Cloudformationから自動生成される
 
- L2 Construct
- L1を抽象化したConstruct
- 型情報や関数などが追加されている
- ユーザのPull Requestで作成・更新する
 
- L3 Construct
- 複数のL1, L2を組み合わせたConstruct
 
L2 Constructへの引数追加
Cloudformationで新しい引数が作成された場合、L1 Constructには自動で追加されますが、L2 Constructには自動では追加されません。
L2で使うためには、引数を追加する修正を手動で行う必要があります。
export interface TopicProps {  ..., // 既存のプロパティ  displayName?: string;};
export class Topic extends TopicBase {  constructor(scope: Construct, id: string, props: TopicProps) {    super(scope, id, props);
    const resource = new CfnTopic(this, 'Resource', {      ...,      displayName: props.displayName    });  };};このように、L2で未対応の引数を追加するPRをこれから作成してみましょう。
概要
SNS Topicには表示名を設定することができ、Eメール通知における件名などに利用されます。

Cloudformation及びCDKのL1コンストラクトでは DisplayName というプロパティが提供されており、これを利用することで表示名を設定することができます。
const topic = sns.CfnTopic(this, 'MyTopic', {  displayName: 'MyTopicDisplayName'})しかし、ワークショップ向けCDKのL2コンストラクト(sns.Topic)では displayName がサポートされていません。そこで、L2コンストラクトに displayName プロパティを追加してみます。
目標
PRの作成には以下の要素を含める必要があります。
- L2コンストラクト(packages/aws-cdk-lib/aws-sns/lib/topic.ts)のコード変更
- TopicPropsに- displayNameプロパティを追加
- Topicクラスのconstructor関数中の- CfnTopicクラスのインスタンス作成時に- displayNameプロパティを設定
 
- ユニットテスト(packages/aws-cdk-lib/aws-sns/test/topic.test.ts)の追加
- displayNameプロパティがCloudformationテンプレートに正しく反映されるか
 
- 統合テスト(packages/@aws-cdk-testing/framework-integ/test/aws-sns/test)の追加
- displayNameを設定したSNS Topicが正しく作成されるか
 
- READMEの更新
- 機能追加に関する説明を追加
 
手順
ブランチ作成
まずは、この機能追加用のブランチを作成します。
git switch -c add-sns-topic-display-nameL2コンストラクトのコード変更
TopicPropsへdisplayNameの追加
aws-cdk/packages/aws-cdk-lib/aws-sns/lib/topic.tsを開き、TopicPropsにreadonlyなdisplayNameプロパティを追加します。
既存のPropsに新たな引数を追加するとき、必須なものを追加すると破壊的変更になってしまうため、optionalなプロパティとして追加することに注意してください。
jsdocにはdisplayNameプロパティの説明をCloudformationのドキュメントからコピーしてきましょう。
また、上記の通りoptionalなプロパティであることを示すために?を付け、デフォルトの挙動を@defaultに記述します。
export interface TopicProps {  ..., // 既存のプロパティ  /**   * The display name to use for an Amazon SNS topic with SMS subscriptions.   *   * The display name must be maximum 100 characters long, including hyphens (-), underscores (_), spaces, and tabs.   *   * @default - no display name   */  readonly displayName?: string;};Topicクラスのconstructor関数の変更
Topicクラスのconstructor関数内で、CfnTopicクラスのインスタンス作成時にdisplayName引数を設定します。
export class Topic extends TopicBase {  constructor(scope: Construct, id: string, props: TopicProps) {    super(scope, id, props);
    const resource = new CfnTopic(this, 'Resource', {      ..., // 既存のプロパティ      displayName: props.displayName    });  };};以上で機能修正は完了です。一連の内容をcommitしておきましょう。
ユニットテストの追加
テストファイルの修正
続いてユニットテストを追加します。テストファイルはaws-cdk/packages/aws-cdk-lib/aws-sns/test/sns.test.tsです。
ユニットテストでは、displayNameプロパティがCloudformationテンプレートに正しく反映されるかを確認します。
test('specify displayName', () => {  const stack = new cdk.Stack();
  new sns.Topic(stack, 'MyTopic', {     displayName: 'MyDisplayName',  });
  Template.fromStack(stack).hasResourceProperties('AWS::SNS::Topic', {    DisplayName: 'MyDisplayName',  });});テストの実行
ユニットテストを実行して、テストが正常に通ることを確認します。
cd packages/aws-cdk-libyarn test aws-sns/test/sns.test.tsこれでユニットテストの追加は完了です。一連の内容をcommitしておきましょう。
統合テストの追加
テストファイルの作成
続いて統合テストを追加します。統合テストでは、displayNameを設定したSNS Topicが正しく作成されるかを確認します。
テストファイルはpackages/@aws-cdk-testing/framework-integ/test/aws-sns/testに作成します。
今回は新規の統合テストファイル(integ.sns-display-name.ts)を作成します。
// packages/@aws-cdk-testing/framework-integ/test/aws-sns/test/integ.sns-display-name.tsimport { App, Stack, StackProps } from 'aws-cdk-lib';import { Topic } from 'aws-cdk-lib/aws-sns';import * as integ from '@aws-cdk/integ-tests-alpha';
// テスト用のStackを定義class TestStack extends Stack {  constructor(scope: App, id: string, props?: StackProps) {    super(scope, id, props);
    new Topic(this, 'MyTopic', {      topicName: 'MyTopicName',      // displayNameを設定      displayName: 'MyDisplayName',    });  }}
const app = new App();
const stack = new TestStack(app, 'DisplayNameTopicTestStack');
// 統合テストの実行new integ.IntegTest(app, 'SnsTest', {  testCases: [stack],});統合テストの実行
下準備
本ワークショップでの統合テストでは us-east-1 リージョンに対してデプロイが行われます。内部的に cdk deploy が実行されるため、事前に bootstrap が必要になります。 もし、今までに一度もus-east-1にcdk deployを実行していない場合は、以下のコマンドを実行してください。
cdk bootstrap aws://{ACCOUNT_ID}/us-east-1ビルド及び実行
統合テストを実行して、テストが正常に通ることを確認します。 各ビルドコマンドは1分程度かかるため、別ターミナルで並列実行してもOKです。
# Topicクラスを含めたSNSのコンストラクトを再ビルドcd /packages/aws-cdk-libyarn tsc
cd packages/@aws-cdk-testing/framework-integ# integ ファイルのビルド/トランスパイルをして、javascript ファイルを生成yarn tsc# 実際にinteg テストを実行するyarn integ aws-sns/test/integ.sns-display-name.js --update-on-failed自動でCloudformationテンプレートの作成, スタックのデプロイ及び削除が行われます。エラーなく完了すれば統合テストも完了です。
作成したテストファイル及び生成されたスナップショットファイルをコミットしておきましょう。
READMEの更新
最後に、この機能追加に関する説明をREADMEに追加します。
## Display Name
You can set a display name for the topic.To set a display name, use the `displayName` property:
```tsconst topic = new sns.Topic(this, 'Topic', {  displayName: 'MyDisplayName',});\```以上で必要な変更はすべて完了しました。
PRの提出
最後にPRを提出します。
PRルールに則り、以下のようなPRを作成しましょう。
| 項目 | 内容 | 記入例 | 
|---|---|---|
| PRタイトル | PRの目的 | feat(sns): add displayNameproperty to a Topic | 
| Issue # (if applicable) | 関連するIssue番号 | Closes #1 | 
| Reason for this change | 変更理由 | We can set a display name for an SNS topic from cloudformation, but this was not supported in the AWS CDK L2 construct. | 
| Description of changes | 変更内容の詳細 | Add displayNameproperty toTopicPropsand set it in theCfnTopicconstructor. | 
| Description of how you validated changes | 変更の検証方法 | Added both unit and integration tests. | 
以上でPRの作成は完了です。おつかれさまでした!