透過 AWS Chatbot 與 Slack 的整合,開發團隊可以即時接收佈署通知和監控 CI/CD 流程。首先在 AWS 儀錶板中新增 Slack 應用程式,並設定對應的工作區和頻道,確保 AWS Chatbot 能夠順利傳送訊息。接著,建立 config.json 檔案設定網域名稱和子網域名稱,並分別建立 .env.development 和 .env.production 檔案設定環境變數,用於區分開發和生產環境的佈署組態。更新 infrastructure/lib/constructs/Pipeline/index.ts 檔案中的原始碼,指定 GitHub 儲存函式庫位置和分支,並設定 OAuth 權杖。最後,執行佈署指令,CDK 將自動建立 CI/CD Pipeline。完成佈署後,可以透過瀏覽器驗證開發和生產環境的佈署結果,並在 CloudFormation 中檢視相關堆積疊資訊。
設定AWS Chatbot與Slack整合
在AWS儀錶板中設定Slack的整合需要經過幾個步驟。以下將詳細介紹如何完成這項設定。
步驟1:新增Slack應用程式至AWS儀錶板
首先,您需要在AWS儀錶板中新增Slack應用程式。請按照以下步驟進行:
- 登入AWS管理控制檯。
- 導航至AWS Chatbot設定頁面。
- 選擇Slack作為您的聊天平台。
- 您將被重新導向至Slack的授權頁面,請按照指示完成授權程式。
步驟2:設定Slack工作區
完成授權後,您將被重新導向回AWS儀錶板。請按照以下步驟完成設定:
- 前往「管理應用程式」頁面,您將看到新新增的Slack應用程式。
- 建立兩個新的頻道,分別命名為
book-dev和book-prod。 - 在每個頻道上右鍵點選,選擇「複製」>「複製連結」。頻道的ID位於複製的URL末端,請妥善儲存這些值,因為稍後會用到它們。
複製Slack頻道連結
此圖示展示瞭如何複製Slack頻道的連結。
圖表翻譯: 此圖示用於展示如何在Slack中複製頻道連結的過程。首先,您需要右鍵點選頻道,然後選擇「複製連結」選項。接著,您將獲得一個包含頻道ID的URL。
步驟3:邀請AWS Chatbot加入頻道
為了在每個頻道接收通知,請執行以下操作:
- 在
book-dev和book-prod頻道中,分別執行/invite @AWS命令。 - 這樣,AWS Chatbot就會被邀請加入這兩個頻道。
邀請AWS Chatbot加入Slack頻道
此圖示展示瞭如何在Slack頻道中邀請AWS Chatbot。
圖表翻譯: 此圖示說明瞭邀請AWS Chatbot加入Slack頻道的步驟。透過執行/invite @AWS命令,您可以將AWS Chatbot新增至指定的頻道中。
建立不同環境的佈署
在本章中,為了簡化操作,我們將建立兩個不同的環境來佈署TODO應用程式:開發環境和生產環境。您可以根據需要建立其他環境,例如預發環境或演示環境。
設定config.json檔案
首先,在專案根目錄下建立一個名為config.json的檔案。檔案內容如下所示:
{
"domain_name": "cdkbook.click",
"backend_subdomain": "backend-cdk-book",
"frontend_subdomain": "frontend-cdk-book",
"backend_dev_subdomain": "dev-backend-cdk-book",
"frontend_dev_subdomain": "dev-frontend-cdk-book"
}
請根據您的實際網域名稱組態修改domain_name欄位。
設定環境變數檔案
接下來,在infrastructure目錄下建立兩個檔案:.env.development和.env.production。
.env.development檔案內容
GITHUB_TOKEN=<您的個人存取權杖>
CHANNEL_ID=<BOOK_DEV_CHANNEL_ID>
WORKSPACE_ID=<您的SLACK_CHANNEL_ID>
NODE_ENV=Development
.env.production檔案內容
GITHUB_TOKEN=<您的個人存取權杖>
CHANNEL_ID=<BOOK_PROD_CHANNEL_ID>
WORKSPACE_ID=<您的SLACK_CHANNEL_ID>
NODE_ENV=Production
這些檔案用於載入不同環境下的環境變數。
更新Pipeline原始碼
為了使用分叉的儲存函式庫,請更新infrastructure/lib/constructs/Pipeline/index.ts檔案中的原始碼。具體來說,請找到以下程式碼段並更新owner和repo屬性的值:
this.pipeline.addStage({
stageName: 'Source',
actions: [
new GitHubSourceAction({
actionName: 'Source',
owner: '<您的GitHub使用者名稱>',
repo: '<儲存函式庫名稱>',
branch: `${branch}`,
oauthToken: secretToken,
output: outputSource,
trigger: GitHubTrigger.WEBHOOK,
}),
],
});
程式碼解密:
此段程式碼用於設定CodePipeline的原始碼階段。它指定了GitHub儲存函式庫的位置,包括擁有者、儲存函式庫名稱和分支。此外,它還設定了OAuth權杖以進行身份驗證。
佈署CI/CD Pipeline
完成上述設定後,請在終端機中執行以下命令以佈署CI/CD Pipeline:
$ yarn
$ yarn run cdk:pipeline deploy --profile cdk
當提示時,請輸入Y並按下Enter鍵。CDK將自動建立Pipeline。
檢視Pipeline執行狀態
登入AWS管理控制檯,導航至CodePipeline服務。您將看到兩個Pipeline:Chapter5-Development和Chapter5-Production。請等待它們的狀態變為「Succeeded」。
成功執行的Pipeline
此圖示展示了成功執行的CodePipeline。
圖表翻譯: 此圖示顯示了CodePipeline的成功執行狀態。當Pipeline成功執行時,其狀態將更新為「Succeeded」。
實作穩健的CI/CD流程
現在,讓我們來測試應用程式。選擇您新增到組態中的網域名稱,並在其後新增dev-frontend-cdk-book;在我們的例子中,即dev-frontend-cdk-book.cdkbook。
成功載入開發環境的前端
這是您的開發環境!現在,從該URL中刪除dev-部分,您將獲得生產環境,在本例中應該與開發環境看起來完全相同。但它們是獨立的環境。您可以透過在其中一個環境中新增TODO專案來驗證這一點。它不會出現在另一個環境中。
現在,讓我們進入AWS服務列表中的CloudFormation,看看在那裡發生了什麼:
CloudFormation中的堆積疊列表
我們可以在堆積疊列表中看到,除了我們佈署的Chapter5PipelineStack之外,還有兩個由管道堆積疊為每個開發和生產環境建立的其他堆積疊。本質上,我們的管道堆積疊產生並維護了另外兩個堆積疊!
讓我們回到CodePipeline並檢查其中一個建立的管道。我們將選擇Chapter5-Development。在那裡,您將看到四個階段,希望全部為綠色,分別命名為Source、Back-End-Test、Front-End-Test和Build-and-Deploy。
階段說明
以下是每個階段的簡要說明:
- Source:此階段負責讀取儲存函式庫,並在GitHub儲存函式庫更新時觸發其餘的管道。此階段還使用您生成的個人存取令牌。
- Back-End-Test:此階段安裝後端的yarn依賴項(即server目錄),然後執行後端測試。如果任何測試失敗,此階段將失敗,管道將被中止。
- Front-End-Test:此階段執行與前一階段類別似的工作,但針對前端(即web目錄)。同樣,如果任何測試失敗,管道將停止。
- Build-and-Deploy:正如名稱所示,它執行構建和佈署操作。
內容解密:
此段落描述了CodePipeline中的四個主要階段。它們負責原始碼管理、後端測試、前端測試和最終的構建與佈署。每個階段都有其特定的任務,並且如果任何測試失敗,管道將被終止。
讓我們現在檢查一下所有這些是如何實作的。首先,看看在bin/chapter5.ts下的主要基礎設施檔案:
const app = new cdk.App();
if (['ONLY_DEV'].includes(process.env.CDK_MODE || '')) {
new Chapter5Stack(app, `Chapter5Stack-${process.env.NODE_ENV || ''}`, {
env: {
region: process.env.CDK_DEFAULT_REGION,
account: process.env.CDK_DEFAULT_ACCOUNT,
},
});
}
if (['ONLY_PROD'].includes(process.env.CDK_MODE || '')) {
new Chapter5Stack(app, `Chapter5Stack-${process.env.NODE_ENV || ''}`, {
env: {
region: process.env.CDK_DEFAULT_REGION,
account: process.env.CDK_DEFAULT_ACCOUNT,
},
});
}
if (['ONLY_PIPELINE'].includes(process.env.CDK_MODE || '')) {
new Chapter5PipelineStack(app, 'Chapter5PipelineStack', {
env: {
region: process.env.CDK_DEFAULT_REGION,
account: process.env.CDK_DEFAULT_ACCOUNT,
},
});
}
內容解密:
這段程式碼根據CDK_MODE環境變數的不同值例項化不同的堆積疊。如果CDK_MODE被設定為ONLY_PIPELINE,則會建立Chapter5PipelineStack。這解釋了為什麼在定義cdk:pipeline yarn命令時,將其定義為"cross-env CDK_MODE=ONLY_PIPELINE cdk"。
接下來,讓我們看看在infrastructure/lib/chapter-5-pipeline-stack.ts檔案中定義的Chapter5PipelineStack:
export class Chapter5PipelineStack extends Stack {
constructor(scope: Construct, id: string, props: PipelineProps) {
super(scope, id, props);
new PipelineStack(this, 'Chapter5-Pipeline-Prod', {
environment: 'Production',
});
new PipelineStack(this, 'Chapter5-Pipeline-Dev', {
environment: 'Development',
});
Tags.of(scope).add('Project', 'Chapter5-Pipeline');
}
}
內容解密:
此堆積疊建立了兩個PipelineStack例項,分別對應生產和開發環境。它們分享大部分程式碼,但根據環境的不同有一些差異。最後,還增加了CDK標籤以幫助識別資源。
實作強健的CI/CD流程
在lib/Pipeline/index.ts檔案中,我們定義了CI/CD流程的各個階段。讓我們逐步分析這些階段。
Source階段
this.pipeline.addStage({
stageName: 'Source',
actions: [
new GitHubSourceAction({
actionName: 'Source',
owner: '<change to your username>',
repo: '<change to your repo name>',
branch: `${branch}`,
oauthToken: secretToken,
output: outputSource,
trigger: GitHubTrigger.WEBHOOK,
}),
],
});
這個階段主要負責從GitHub倉函式庫中取得原始碼。其中,secretToken是透過讀取GITHUB_TOKEN環境變數並儲存在Secrets Manager中來建立的。
內容解密:
owner、repo和branch屬性用於指定GitHub倉函式庫的位置和分支。oauthToken屬性用於驗證GitHub倉函式庫的存取許可權。output屬性將原始碼傳遞給下一個階段。
Back-End-Test階段
this.pipeline.addStage({
stageName: 'Back-End-Test',
actions: [
new CodeBuildAction({
actionName: 'Back-End-Test',
project: this.backEndTestProject,
input: outputSource,
outputs: undefined,
}),
],
});
這個階段主要負責執行後端測試。其中,this.backEndTestProject變數定義了一個CodeBuild專案。
內容解密:
project屬性指定了要使用的CodeBuild專案。input屬性接收來自前一階段的原始碼。outputs屬性未定義,表示沒有輸出結果。
CodeBuild專案定義
this.backEndTestProject = new PipelineProject(
scope,
`Chapter5-BackEndTest-PipelineProject-${props.environment}`,
{
projectName: `Chapter5-BackEndTest-PipelineProject-${props.environment}`,
environment: {
buildImage: LinuxBuildImage.fromCodeBuildImageId(
'aws/codebuild/amazonlinux2-x86_64-standard:4.0',
),
},
buildSpec: BuildSpec.fromObject({
version: '0.2',
phases: {
install: {
'runtime-versions': {
nodejs: '16',
},
},
pre_build: {
'on-failure': 'ABORT',
commands: ['cd server/', 'yarn install'],
},
build: {
'on-failure': 'ABORT',
commands: ['echo Testing the Back-End...', 'yarn test'],
},
},
}),
},
);
這個CodeBuild專案定義了一個建置機器,執行後端測試。
內容解密:
projectName屬性定義了專案名稱,包含環境變數。environment屬性定義了建置機器的環境,使用了aws/codebuild/amazonlinux2-x86_64-standard:4.0映像檔。buildSpec屬性定義了建置規格,包括安裝、預建置和建置階段。install階段安裝了Node.js 16執行環境。pre_build階段執行了yarn install指令。build階段執行了後端測試,並在失敗時中止建置。
Front-End-Test階段和Build-and-Deploy階段
Front-End-Test階段與Back-End-Test階段類別似,但執行的是前端測試。Build-and-Deploy階段則執行建置和佈署指令。
pipelineConfig函式
export const pipelineConfig = (env: string) => {
if (env === 'Production') {
return {
path: '.env.production',
buildCommand: 'yarn build:prod',
deployCommand: 'yarn cdk deploy',
branch: 'master',
tag: 'chapter5-production-pipeline',
};
}
return {
path: '.env.development',
buildCommand: 'yarn build:dev',
deployCommand: 'yarn cdk:dev deploy',
branch: 'dev',
tag: 'chapter5-development-pipeline',
};
};
這個函式根據環境變數傳回不同的組態設定。
內容解密:
- 根據環境變數傳回不同的
.env檔案路徑、建置指令、佈署指令、分支和標籤。