From c3957b970d985f710c12086cfa6426d311e0312d Mon Sep 17 00:00:00 2001 From: senti Date: Sat, 15 Jul 2023 15:44:06 -0700 Subject: [PATCH] feat: github ci/cd hooks --- ant.config.ts | 67 ++++++++++++++++++- package.json | 3 + .../src/cdk/constructs/GitHub/GitHub.ts | 14 ++-- .../src/cdk/constructs/GitHub/index.ts | 1 + pnpm-lock.yaml | 44 +++--------- 5 files changed, 88 insertions(+), 41 deletions(-) create mode 100644 packages/ant-stack/src/cdk/constructs/GitHub/index.ts diff --git a/ant.config.ts b/ant.config.ts index 15124c01..fba5d8f4 100644 --- a/ant.config.ts +++ b/ant.config.ts @@ -6,8 +6,12 @@ * import * as cdk from 'aws-cdk-lib' * ``` */ +import { consola } from "consola"; +import core from "@actions/core"; +import github from "@actions/github"; import { App, Stack } from "aws-cdk-lib/core"; import { Api } from "ant-stack/constructs/Api"; +import { GitHub } from "ant-stack/constructs/GitHub"; /** * @see https://github.com/evanw/esbuild/issues/1921#issuecomment-1491470829 @@ -26,7 +30,7 @@ export class MyStack extends Stack { constructor(scope: App, id: string) { super(scope, id); - new Api(this, "Api", { + const api = new Api(this, "Api", { directory: "apps/api", constructs: {}, runtime: { @@ -44,6 +48,67 @@ export class MyStack extends Stack { }, }, }); + + new GitHub(this, "GitHub", { + outputs: { + invokeUrl: { + value: api.api.arnForExecuteApi(), + }, + }, + callbacks: { + async onPostDeploy(outputs) { + const GITHUB_TOKEN = process.env.GITHUB_TOKEN ?? core.getInput("GITHUB_TOKEN"); + const PR_NUM = github.context.payload.pull_request?.number; + + if (!PR_NUM) { + throw new Error("❌ Error: Pull request number not detected."); + } + + const octokit = github.getOctokit(GITHUB_TOKEN); + + const owner = github.context.repo.owner; + const repo = github.context.repo.repo; + const ref = github.context.ref; + + const apiDeployment = await octokit.rest.repos.createDeployment({ + owner, + repo, + ref, + required_contexts: [], + environment: "staging - docs", + }); + + if (apiDeployment.status !== 201) { + throw new Error("❌ Deployment failed!"); + } + + const apiDeploymentStatus = await octokit.rest.repos.createDeploymentStatus({ + repo, + owner, + deployment_id: apiDeployment.data.id, + state: "success", + description: "Deployment succeeded", + environment_url: outputs.invokeUrl, + auto_inactive: false, + }); + + consola.info("ℹī¸ API deployment status: ", apiDeploymentStatus.data); + + await octokit.rest.issues.createComment({ + owner, + repo, + issue_number: PR_NUM, + body: `\ +🚀 Staging instances deployed! + +API - ${apiDeploymentStatus.data.environment_url} + +Docs - ${apiDeploymentStatus.data.environment_url} +`, + }); + }, + }, + }); } } diff --git a/package.json b/package.json index 17799bde..ec9d56df 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,9 @@ } }, "dependencies": { + "@actions/core": "^1.10.0", + "@actions/github": "^5.1.1", + "consola": "^3.1.0", "constructs": "^10.2.69" }, "devDependencies": { diff --git a/packages/ant-stack/src/cdk/constructs/GitHub/GitHub.ts b/packages/ant-stack/src/cdk/constructs/GitHub/GitHub.ts index cf89e4f7..7a76d29c 100644 --- a/packages/ant-stack/src/cdk/constructs/GitHub/GitHub.ts +++ b/packages/ant-stack/src/cdk/constructs/GitHub/GitHub.ts @@ -24,8 +24,8 @@ export type GitHubCallbacks = { export interface GitHubConfig { outputsFile?: string; - outputs: T; - callbacks: GitHubCallbacks; + outputs?: T; + callbacks?: Partial>; } /** @@ -53,7 +53,7 @@ export class GitHub extends Construct { this.stackName = Stack.of(this).stackName; - this.outputs = Object.entries(config.outputs).reduce((outputs, [key, value]) => { + this.outputs = Object.entries(config.outputs ?? {}).reduce((outputs, [key, value]) => { outputs[key] = new CfnOutput(this, key, value); return outputs; }, {} as Record); @@ -71,19 +71,19 @@ export class GitHub extends Construct { } public onPreDeploy() { - return this.config.callbacks.onPreDeploy(this.parseOutputs()); + return this.config.callbacks?.onPreDeploy?.(this.parseOutputs()); } public onPostDeploy() { - return this.config.callbacks.onPostDeploy(this.parseOutputs()); + return this.config.callbacks?.onPostDeploy?.(this.parseOutputs()); } public onPreDestroy() { - return this.config.callbacks.onPreDestroy(this.parseOutputs()); + return this.config.callbacks?.onPreDestroy?.(this.parseOutputs()); } public onPostDestroy() { - return this.config.callbacks.onPostDestroy(this.parseOutputs()); + return this.config.callbacks?.onPostDestroy?.(this.parseOutputs()); } } diff --git a/packages/ant-stack/src/cdk/constructs/GitHub/index.ts b/packages/ant-stack/src/cdk/constructs/GitHub/index.ts new file mode 100644 index 00000000..b65d02c3 --- /dev/null +++ b/packages/ant-stack/src/cdk/constructs/GitHub/index.ts @@ -0,0 +1 @@ +export * from "./GitHub.js"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c51c09cb..18fc1fe6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,15 @@ importers: .: dependencies: + '@actions/core': + specifier: ^1.10.0 + version: 1.10.0 + '@actions/github': + specifier: ^5.1.1 + version: 5.1.1 + consola: + specifier: ^3.1.0 + version: 3.1.0 constructs: specifier: ^10.2.69 version: 10.2.69 @@ -4031,7 +4040,7 @@ packages: lodash.merge: 4.6.2 lodash.uniq: 4.5.0 resolve-from: 5.0.0 - ts-node: 10.9.1(@types/node@20.2.5)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@20.2.5)(typescript@5.0.4) typescript: 4.9.5 transitivePeerDependencies: - '@swc/core' @@ -9309,7 +9318,7 @@ packages: dependencies: '@types/node': 20.2.5 cosmiconfig: 8.1.3 - ts-node: 10.9.1(@types/node@20.2.5)(typescript@4.9.5) + ts-node: 10.9.1(@types/node@20.2.5)(typescript@5.0.4) typescript: 4.9.5 dev: true @@ -15851,37 +15860,6 @@ packages: yargs-parser: 21.1.1 dev: true - /ts-node@10.9.1(@types/node@20.2.5)(typescript@4.9.5): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.2.5 - acorn: 8.10.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - /ts-node@10.9.1(@types/node@20.2.5)(typescript@5.0.4): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true