diff --git a/cdk/kittyhawk/.projenrc.js b/cdk/kittyhawk/.projenrc.js index bbe36081..523298f3 100644 --- a/cdk/kittyhawk/.projenrc.js +++ b/cdk/kittyhawk/.projenrc.js @@ -15,7 +15,7 @@ const project = new TypeScriptProject({ }, }); -project.addFields({['version']: '1.1.4'}); +project.addFields({['version']: '1.1.6'}); project.prettier?.ignoreFile?.addPatterns('src/imports'); project.testTask.steps.forEach(step => { if (step.exec) { diff --git a/cdk/kittyhawk/CHANGELOG.md b/cdk/kittyhawk/CHANGELOG.md index ab55ba4f..289ae707 100644 --- a/cdk/kittyhawk/CHANGELOG.md +++ b/cdk/kittyhawk/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.1.6 (2022-06-27) +* Add feature branch deploy: + * Support `DEPLOY_TO_FEATURE_BRANCH` env variables in resources. + ## 1.1.4 (2022-04-18) * Better handling of custom ports diff --git a/cdk/kittyhawk/package.json b/cdk/kittyhawk/package.json index ba1fd5fc..0484370d 100644 --- a/cdk/kittyhawk/package.json +++ b/cdk/kittyhawk/package.json @@ -51,8 +51,8 @@ }, "dependencies": { "cdk8s": "^2.2.59", - "cdk8s-cli": "^1.0.143", - "constructs": "^10.0.106", + "cdk8s-cli": "^2.0.31", + "constructs": "^10.0.119", "cron-time-generator": "^1.3.0" }, "keywords": [ @@ -65,7 +65,7 @@ "main": "lib/index.js", "license": "MIT", "homepage": "https://kittyhawk.pennlabs.org", - "version": "1.1.4", + "version": "1.1.6", "jest": { "testMatch": [ "/src/**/__tests__/**/*.ts?(x)", diff --git a/cdk/kittyhawk/src/application/base.ts b/cdk/kittyhawk/src/application/base.ts index 49a6cc11..d84e12e1 100644 --- a/cdk/kittyhawk/src/application/base.ts +++ b/cdk/kittyhawk/src/application/base.ts @@ -36,7 +36,8 @@ export class Application extends Construct { // We want to prepend the project name to the name of each component const release_name = process.env.RELEASE_NAME || "undefined_release"; const fullname = `${release_name}-${appname}`; - + const deploy_to_feature_branch = + process.env.DEPLOY_TO_FEATURE_BRANCH == "true"; new Service(this, fullname, props.port); if (props.createServiceAccount) { @@ -48,6 +49,14 @@ export class Application extends Construct { new Deployment(this, fullname, { ...props.deployment, port: props.port, + ...(deploy_to_feature_branch + ? { + env: [ + ...(props.deployment.env ?? []), + { name: "DEPLOY_TO_FEATURE_BRANCH", value: "true" }, + ], + } + : {}), ...(props.createServiceAccount ? { serviceAccountName: release_name } : {}), diff --git a/cdk/kittyhawk/src/cronjob.ts b/cdk/kittyhawk/src/cronjob.ts index 7ce056e0..bba1a4ee 100644 --- a/cdk/kittyhawk/src/cronjob.ts +++ b/cdk/kittyhawk/src/cronjob.ts @@ -58,10 +58,17 @@ export class CronJob extends Construct { // We want to prepend the project name to the name of each component const release_name = process.env.RELEASE_NAME ?? "undefined_release"; + const deploy_to_feature_branch = + process.env.DEPLOY_TO_FEATURE_BRANCH == "true"; const fullname = `${release_name}-${jobname}`; const containers: Container[] = [ new Container({ ...props, + ...(deploy_to_feature_branch + ? { + env: [{ name: "DEPLOY_TO_FEATURE_BRANCH", value: "true" }], + } + : {}), noContainerPorts: true, }), ]; diff --git a/cdk/kittyhawk/test/__snapshots__/application.test.ts.snap b/cdk/kittyhawk/test/__snapshots__/application.test.ts.snap index 1a56915f..4864cd48 100644 --- a/cdk/kittyhawk/test/__snapshots__/application.test.ts.snap +++ b/cdk/kittyhawk/test/__snapshots__/application.test.ts.snap @@ -518,6 +518,190 @@ Array [ ] `; +exports[`Django Application -- Feature Branch Deploy 1`] = ` +Array [ + Object { + "apiVersion": "v1", + "kind": "Service", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-platform", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0-platform", + }, + "spec": Object { + "ports": Array [ + Object { + "port": 80, + "targetPort": 80, + }, + ], + "selector": Object { + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-platform", + }, + "type": "ClusterIP", + }, + }, + Object { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": Object { + "annotations": Object { + "eks.amazonaws.com/role-arn": "arn:aws:iam::TEST_AWS_ACCOUNT_ID:role/RELEASE_NAME-pr-0", + }, + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0", + }, + }, + Object { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-platform", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0-platform", + }, + "spec": Object { + "replicas": 1, + "selector": Object { + "matchLabels": Object { + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-platform", + }, + }, + "strategy": Object { + "rollingUpdate": Object { + "maxSurge": 3, + "maxUnavailable": 0, + }, + "type": "RollingUpdate", + }, + "template": Object { + "metadata": Object { + "labels": Object { + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-platform", + }, + }, + "spec": Object { + "containers": Array [ + Object { + "env": Array [ + Object { + "name": "DOMAINS", + "value": "platform.pennlabs.org", + }, + Object { + "name": "DJANGO_SETTINGS_MODULE", + "value": "Platform.settings.production", + }, + Object { + "name": "DEPLOY_TO_FEATURE_BRANCH", + "value": "true", + }, + Object { + "name": "GIT_SHA", + "value": "TAG_FROM_CI", + }, + ], + "image": "pennlabs/platform:TAG_FROM_CI", + "imagePullPolicy": "IfNotPresent", + "name": "worker", + "ports": Array [ + Object { + "containerPort": 80, + }, + ], + }, + ], + "volumes": Array [], + }, + }, + }, + }, + Object { + "apiVersion": "networking.k8s.io/v1", + "kind": "Ingress", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-platform", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0-platform", + }, + "spec": Object { + "rules": Array [ + Object { + "host": "platform.pennlabs.org", + "http": Object { + "paths": Array [ + Object { + "backend": Object { + "service": Object { + "name": "RELEASE_NAME-pr-0-platform", + "port": Object { + "number": 80, + }, + }, + }, + "path": "/", + "pathType": "Prefix", + }, + ], + }, + }, + ], + "tls": Array [ + Object { + "hosts": Array [ + "platform.pennlabs.org", + ], + "secretName": "platform-pennlabs-org-tls", + }, + ], + }, + }, + Object { + "apiVersion": "cert-manager.io/v1", + "kind": "Certificate", + "metadata": Object { + "finalizers": Array [ + "kubernetes", + ], + "labels": Object { + "app.kubernetes.io/component": "certificate", + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "platform-pennlabs-org", + }, + "name": "platform-pennlabs-org", + }, + "spec": Object { + "dnsNames": Array [ + "platform.pennlabs.org", + "*.platform.pennlabs.org", + ], + "issuerRef": Object { + "group": "cert-manager.io", + "kind": "ClusterIssuer", + "name": "wildcard-letsencrypt-prod", + }, + "secretName": "platform-pennlabs-org-tls", + }, + }, +] +`; + exports[`Django Application -- Undefined Domains Chart 1`] = ` Array [ Object { @@ -1115,6 +1299,175 @@ Array [ ] `; +exports[`React Application -- Feature Branch Deploy 1`] = ` +Array [ + Object { + "apiVersion": "v1", + "kind": "Service", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-react", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0-react", + }, + "spec": Object { + "ports": Array [ + Object { + "port": 80, + "targetPort": 80, + }, + ], + "selector": Object { + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-react", + }, + "type": "ClusterIP", + }, + }, + Object { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-react", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0-react", + }, + "spec": Object { + "replicas": 1, + "selector": Object { + "matchLabels": Object { + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-react", + }, + }, + "strategy": Object { + "rollingUpdate": Object { + "maxSurge": 3, + "maxUnavailable": 0, + }, + "type": "RollingUpdate", + }, + "template": Object { + "metadata": Object { + "labels": Object { + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-react", + }, + }, + "spec": Object { + "containers": Array [ + Object { + "env": Array [ + Object { + "name": "DOMAIN", + "value": "pennclubs.com", + }, + Object { + "name": "PORT", + "value": "80", + }, + Object { + "name": "DEPLOY_TO_FEATURE_BRANCH", + "value": "true", + }, + Object { + "name": "GIT_SHA", + "value": "TAG_FROM_CI", + }, + ], + "image": "pennlabs/penn-clubs-frontend:TAG_FROM_CI", + "imagePullPolicy": "IfNotPresent", + "name": "worker", + "ports": Array [ + Object { + "containerPort": 80, + }, + ], + }, + ], + "volumes": Array [], + }, + }, + }, + }, + Object { + "apiVersion": "networking.k8s.io/v1", + "kind": "Ingress", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-pr-0-react", + "app.kubernetes.io/part-of": "RELEASE_NAME-pr-0", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-pr-0-react", + }, + "spec": Object { + "rules": Array [ + Object { + "host": "pennclubs.com", + "http": Object { + "paths": Array [ + Object { + "backend": Object { + "service": Object { + "name": "RELEASE_NAME-pr-0-react", + "port": Object { + "number": 80, + }, + }, + }, + "path": "/", + "pathType": "Prefix", + }, + ], + }, + }, + ], + "tls": Array [ + Object { + "hosts": Array [ + "pennclubs.com", + ], + "secretName": "pennclubs-com-tls", + }, + ], + }, + }, + Object { + "apiVersion": "cert-manager.io/v1", + "kind": "Certificate", + "metadata": Object { + "finalizers": Array [ + "kubernetes", + ], + "labels": Object { + "app.kubernetes.io/component": "certificate", + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "pennclubs-com", + }, + "name": "pennclubs-com", + }, + "spec": Object { + "dnsNames": Array [ + "pennclubs.com", + "*.pennclubs.com", + ], + "issuerRef": Object { + "group": "cert-manager.io", + "kind": "ClusterIssuer", + "name": "wildcard-letsencrypt-prod", + }, + "secretName": "pennclubs-com-tls", + }, + }, +] +`; + exports[`Redis Application -- Default 1`] = ` Array [ Object { diff --git a/cdk/kittyhawk/test/__snapshots__/cronjob.test.ts.snap b/cdk/kittyhawk/test/__snapshots__/cronjob.test.ts.snap index eeb26e80..7c8593df 100644 --- a/cdk/kittyhawk/test/__snapshots__/cronjob.test.ts.snap +++ b/cdk/kittyhawk/test/__snapshots__/cronjob.test.ts.snap @@ -1,6 +1,88 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Cron Job with limits 1`] = ` +exports[`Cron Job -- Feature Branch Deploy 1`] = ` +Array [ + Object { + "apiVersion": "batch/v1", + "kind": "CronJob", + "metadata": Object { + "labels": Object { + "app.kubernetes.io/managed-by": "kittyhawk", + "app.kubernetes.io/name": "RELEASE_NAME-calculate-waits", + "app.kubernetes.io/part-of": "RELEASE_NAME", + "app.kubernetes.io/version": "TAG_FROM_CI", + }, + "name": "RELEASE_NAME-calculate-waits", + }, + "spec": Object { + "failedJobsHistoryLimit": 1, + "jobTemplate": Object { + "spec": Object { + "template": Object { + "spec": Object { + "containers": Array [ + Object { + "command": Array [ + "python", + "manage.py", + "calculatewaittimes", + ], + "env": Array [ + Object { + "name": "DEPLOY_TO_FEATURE_BRANCH", + "value": "true", + }, + Object { + "name": "GIT_SHA", + "value": "TAG_FROM_CI", + }, + ], + "envFrom": Array [ + Object { + "secretRef": Object { + "name": "penn-courses", + }, + }, + ], + "image": "pennlabs/penn-courses-backend:TAG_FROM_CI", + "imagePullPolicy": "IfNotPresent", + "name": "worker", + "volumeMounts": Array [ + Object { + "mountPath": "/app/ios_key.p8", + "name": "labs-api-server-ios-key", + "subPath": "ios-key", + }, + ], + }, + ], + "restartPolicy": "Never", + "volumes": Array [ + Object { + "name": "labs-api-server-ios-key", + "secret": Object { + "items": Array [ + Object { + "key": "ios-key", + "path": "ios-key", + }, + ], + "secretName": "labs-api-server", + }, + }, + ], + }, + }, + }, + }, + "schedule": "*/5 * * * *", + "successfulJobsHistoryLimit": 1, + }, + }, +] +`; + +exports[`Cron Job -- With limits 1`] = ` Array [ Object { "apiVersion": "batch/v1", @@ -57,7 +139,7 @@ Array [ ] `; -exports[`Cron Job with volume 1`] = ` +exports[`Cron Job -- With volume 1`] = ` Array [ Object { "apiVersion": "batch/v1", diff --git a/cdk/kittyhawk/test/application.test.ts b/cdk/kittyhawk/test/application.test.ts index 4d6b86a8..edfa9cb9 100644 --- a/cdk/kittyhawk/test/application.test.ts +++ b/cdk/kittyhawk/test/application.test.ts @@ -31,6 +31,10 @@ export function buildSimpleChart(scope: Construct) { }); } +beforeEach(() => { + jest.resetModules(); +}); + test("Application -- No Git Sha", () => failingTestNoGitSha(buildSimpleChart)); test("Application -- No ServiceAccount But CreateServiceAccount", () => failingTestNoAWSAccountId(buildRedisChartExample)); @@ -66,21 +70,53 @@ function buildReactChartDuplicateEnv(scope: Construct) { test("Tag Override", () => chartTest(buildTagOverrideChart)); +// Redis tests test("Redis Application -- Default", () => chartTest(buildRedisChartDefault)); test("Redis Application -- Example", () => chartTest(buildRedisChartExample)); +// Django tests test("Django Application -- Default", () => chartTest(buildDjangoChartDefault)); test("Django Application -- Example", () => chartTest(buildDjangoChartExample)); test("Django Application -- Duplicate Env", () => chartTest(buildDjangoChartDuplicateEnv)); +test("Django Application -- Feature Branch Deploy", () => + chartTest(buildDjangoChartDefault, [ + { + env: "DEPLOY_TO_FEATURE_BRANCH", + value: "true", + }, + { + env: "RELEASE_NAME", + value: "RELEASE_NAME-pr-0", + }, + ])); test("Django Application -- Undefined Domains Chart", () => chartTest(buildDjangoIngressUndefinedDomainsChart)); +// React tests test("React Application -- Default", () => chartTest(buildReactChartDefault)); test("React Application -- Example", () => chartTest(buildReactChartExample)); +test("React Application -- Feature Branch Deploy", () => + chartTest(buildReactChartDefault, [ + { + env: "DEPLOY_TO_FEATURE_BRANCH", + value: "true", + }, + { + env: "RELEASE_NAME", + value: "RELEASE_NAME-pr-0", + }, + ])); test("React Application -- Duplicate Env", () => chartTest(buildReactChartDuplicateEnv)); +afterEach(() => { + delete process.env.DEPLOY_TO_FEATURE_BRANCH; + delete process.env.RELEASE_NAME; + delete process.env.GIT_SHA; + delete process.env.AWS_ACCOUNT_ID; +}); + /** * Test Configuration for RedisApplication * diff --git a/cdk/kittyhawk/test/cronjob.test.ts b/cdk/kittyhawk/test/cronjob.test.ts index 43404e47..3c5d567a 100644 --- a/cdk/kittyhawk/test/cronjob.test.ts +++ b/cdk/kittyhawk/test/cronjob.test.ts @@ -32,6 +32,12 @@ export function buildCronjobLimitsChart(scope: Construct) { }); } -test("Cron Job with volume", () => chartTest(buildCronjobVolumeChart)); - -test("Cron Job with limits", () => chartTest(buildCronjobLimitsChart)); +test("Cron Job -- With volume", () => chartTest(buildCronjobVolumeChart)); +test("Cron Job -- Feature Branch Deploy", () => { + process.env.DEPLOY_TO_FEATURE_BRANCH = "true"; + chartTest(buildCronjobVolumeChart); +}); +test("Cron Job -- With limits", () => chartTest(buildCronjobLimitsChart)); +afterEach(() => { + delete process.env.DEPLOY_TO_FEATURE_BRANCH; +}); diff --git a/cdk/kittyhawk/test/ingress.test.ts b/cdk/kittyhawk/test/ingress.test.ts index bf08828a..463a30fd 100644 --- a/cdk/kittyhawk/test/ingress.test.ts +++ b/cdk/kittyhawk/test/ingress.test.ts @@ -4,13 +4,13 @@ import { Application } from "../src/application"; import { chartTest, failingTest } from "./utils"; /* -Ingress Port Behavior +Ingress Port Behavior For the application, the ingress port should never be explicitly defined. This is because the -application port must be uniform with the ingress port provided. +application port must be uniform with the ingress port provided. 1. Default Behavior -If `port` IS NOT specified in `Application`, continue with default behavior in `Application` +If `port` IS NOT specified in `Application`, continue with default behavior in `Application` and other children objects created. For `Ingress`, the default port is assumed. 2. In Application, Not Ingress: Inherits Application port diff --git a/cdk/kittyhawk/test/utils.ts b/cdk/kittyhawk/test/utils.ts index fe85baa6..86456d25 100644 --- a/cdk/kittyhawk/test/utils.ts +++ b/cdk/kittyhawk/test/utils.ts @@ -6,12 +6,22 @@ import { PennLabsChart } from "../src"; * Helper function to run each chart test * @param build function containing the constructs to be generated */ -export const chartTest = (build: (scope: Construct) => void) => { +export const chartTest = ( + build: (scope: Construct) => void, + envOverrides?: { + env: string; + value: string; + }[] +) => { // Overriding env vars for testing purposes process.env.RELEASE_NAME = "RELEASE_NAME"; process.env.GIT_SHA = "TAG_FROM_CI"; process.env.AWS_ACCOUNT_ID = "TEST_AWS_ACCOUNT_ID"; + envOverrides?.forEach(({ env: e, value: v }) => { + process.env[e] = v; + }); + const app = Testing.app(); const chart = new PennLabsChart(app, "kittyhawk"); build(chart); diff --git a/cdk/kittyhawk/yarn.lock b/cdk/kittyhawk/yarn.lock index 782fb1e1..7c5eb34a 100644 --- a/cdk/kittyhawk/yarn.lock +++ b/cdk/kittyhawk/yarn.lock @@ -530,20 +530,20 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jsii/check-node@1.55.1": - version "1.55.1" - resolved "https://registry.yarnpkg.com/@jsii/check-node/-/check-node-1.55.1.tgz#f034cf63cfc31bdaee477008a96443faaf9f5895" - integrity sha512-JC9b+y4CXdIICDE6fYjaN0VKPc65lz4dj1T4lnaqMfbXIBGB7sBMLQJ/szVc9U3Z+o/HBzCJndNn86kGRM+lqw== +"@jsii/check-node@1.61.0": + version "1.61.0" + resolved "https://registry.yarnpkg.com/@jsii/check-node/-/check-node-1.61.0.tgz#ba70e27cd21d4b5dd2af3d3c37f74eaea40dc56d" + integrity sha512-U6b2iNZZweV2qRvidCCZIOLFpTe6Kc8eZc9v8CbUtK2btChNYiWTkms4VUOcONIYT5uPfNlZpHZiqTr+Oqxmkg== dependencies: chalk "^4.1.2" - semver "^7.3.5" + semver "^7.3.7" -"@jsii/spec@1.55.1", "@jsii/spec@^1.55.1": - version "1.55.1" - resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.55.1.tgz#fb8b820a6aa6c809773207e1f6be65f92ff38296" - integrity sha512-KSKKN04eO0rTaqzw6j9RTx8HAzhePdmWRC3iJQ90QeZLv/L8Pj4l+nZ4wn77BGxmeULpXkGXUKbhkceArdr4GA== +"@jsii/spec@1.61.0", "@jsii/spec@^1.61.0": + version "1.61.0" + resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.61.0.tgz#0529432d2bf6963374e3bfd6c36d95800defbefb" + integrity sha512-pv1jAZY+gez62BCiHwfdCnjl2reye88QOKsD5IlCf7XbmvyQ4xFXVV2EnFzv4HUUtr+yuBj/tZz0HjOFsEBUQw== dependencies: - jsonschema "^1.4.0" + ajv "^8.11.0" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -803,7 +803,7 @@ "@typescript-eslint/types" "5.18.0" eslint-visitor-keys "^3.0.0" -"@xmldom/xmldom@^0.8.1": +"@xmldom/xmldom@^0.8.2": version "0.8.2" resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.2.tgz#b695ff674e8216efa632a3d36ad51ae9843380c0" integrity sha512-+R0juSseERyoPvnBQ/cZih6bpF7IpCXlWbHRoCRzYzqpz6gWHOgf8o4MOEf6KBVuOyqU+gCNLkCWVIJAro8XyQ== @@ -959,11 +959,6 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - babel-jest@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" @@ -1113,42 +1108,33 @@ case@^1.6.3: resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== -cdk8s-cli@^1.0.143: - version "1.0.143" - resolved "https://registry.yarnpkg.com/cdk8s-cli/-/cdk8s-cli-1.0.143.tgz#f58f0f842a421fb03b0c30bc10e38ff71b6ef371" - integrity sha512-H2aROcLGTNDjTdpFf1C3wniW8HtsoKkoL9JX/0Yddu+yBx7Kens2B9Hlh83qgb2PWIqWfiXtYpy4ug/jTLAtqA== +cdk8s-cli@^2.0.31: + version "2.0.31" + resolved "https://registry.yarnpkg.com/cdk8s-cli/-/cdk8s-cli-2.0.31.tgz#d91f367a1401987ea6fcd32e23f9ab7f49cbf3a9" + integrity sha512-VlTleZ+Wepi7isPHX0qM2uA6KWqJpBcm07trqgz2ne8dcVyozpOtFMEVL3DE9VxSDNklrOby1F/s0+EzNqTwNA== dependencies: "@types/node" "^12" ajv "^8.11.0" - cdk8s "^1.5.62" - cdk8s-plus-22 "^1.0.0-beta.179" - codemaker "^1.55.1" + cdk8s "^2.3.36" + cdk8s-plus-22 "^2.0.0-rc.28" + codemaker "^1.61.0" colors "1.4.0" - constructs "^3.3.259" + constructs "^10.1.42" fs-extra "^8" - jsii-pacmak "^1.55.1" - jsii-srcmak "^0.1.521" - json2jsii "^0.2.181" - sscaff "^1.2.248" + jsii-pacmak "^1.61.0" + jsii-srcmak "^0.1.599" + json2jsii "^0.3.49" + sscaff "^1.2.274" yaml "2.0.0-11" yargs "^15" -cdk8s-plus-22@^1.0.0-beta.179: - version "1.0.0-beta.180" - resolved "https://registry.yarnpkg.com/cdk8s-plus-22/-/cdk8s-plus-22-1.0.0-beta.180.tgz#a7233c53b0c1eef1af86ab0fef3a2188ea60fbf6" - integrity sha512-7jZonUlzpGSyY7v9TWk42lznAh5GSNKRE/Xq0S4kRsZYMePCDNMgxyodlNp0Yd5mhPZYHAy/D7Rm7V3miuEvLg== +cdk8s-plus-22@^2.0.0-rc.28: + version "2.0.0-rc.29" + resolved "https://registry.yarnpkg.com/cdk8s-plus-22/-/cdk8s-plus-22-2.0.0-rc.29.tgz#31a835f64fcd301d68e9463d02956858a5945e57" + integrity sha512-Q1KzHiLD+lrNQuAvpQKDF35Wk7h++zsJGvcw/GGP98K8pBZozRO/8iJ9w+axNN0gtr2ScFmAkmltgB6PzdkUPA== dependencies: minimatch "^3.1.2" -cdk8s@^1.5.62: - version "1.5.62" - resolved "https://registry.yarnpkg.com/cdk8s/-/cdk8s-1.5.62.tgz#1391cce039a092caab9d91ba49daf6bb84fcce26" - integrity sha512-zspC9PLbuRVlDp+D9mhnqiBD3d4TAcgiIU0E12B6paJUM9gZaJEOi5q/DQcoGXa0AbnnGbSjmd+b0BgHFQJTGg== - dependencies: - fast-json-patch "^2.2.1" - follow-redirects "^1.14.9" - yaml "2.0.0-7" - cdk8s@^2.2.59: version "2.2.59" resolved "https://registry.yarnpkg.com/cdk8s/-/cdk8s-2.2.59.tgz#0c46be19462eeb994058417fba1b795d4e071e0e" @@ -1158,6 +1144,15 @@ cdk8s@^2.2.59: follow-redirects "^1.14.9" yaml "2.0.0-7" +cdk8s@^2.3.36: + version "2.3.36" + resolved "https://registry.yarnpkg.com/cdk8s/-/cdk8s-2.3.36.tgz#76dde273271ab3994870ccc2f938ca40ddcc3448" + integrity sha512-6yefUZNtOIlJtEBeqYC/ibvlF3qsmW3uVdz0EdzQm5ahEQZPrrTdrnNKt8Eraf45I8v3Sg+R4zKyvr3Pk+N4fw== + dependencies: + fast-json-patch "^3.1.1" + follow-redirects "^1.15.1" + yaml "2.0.0-7" + chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1229,14 +1224,14 @@ codecov@^3.8.3: teeny-request "7.1.1" urlgrey "1.0.0" -codemaker@^1.55.1: - version "1.55.1" - resolved "https://registry.yarnpkg.com/codemaker/-/codemaker-1.55.1.tgz#ca2ae0e3c7a3e9909740a603648e68d4a20e1a76" - integrity sha512-W0MZSFgqfr9mgKbYLHsTNYTMKiXQE9hDHs6qke5dC5S9ZlFgcWG2zdpznknwvPLDDuWP8Z5QL71MjAM21hEPOg== +codemaker@^1.61.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/codemaker/-/codemaker-1.61.0.tgz#effa25a75f24db254a850ea04cc691aa67c92918" + integrity sha512-do01ygDHvcw0ZqV4isyzwMMJmAO+LtqROLC3dlp6XJk7XdTaZHoyMXRLoDdB50o4QLmGf2NZEVZmbKEOOXNYRw== dependencies: camelcase "^6.3.0" decamelize "^5.0.1" - fs-extra "^9.1.0" + fs-extra "^10.1.0" collect-v8-coverage@^1.0.0: version "1.0.1" @@ -1294,15 +1289,10 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -constructs@^10.0.106: - version "10.0.106" - resolved "https://registry.yarnpkg.com/constructs/-/constructs-10.0.106.tgz#e57222d13fa7c063de95e8c6c933ef379ded79cf" - integrity sha512-6k8z7O3q6UigE62QW/z34YcSqa1elCDEGz1rTwaMkiVjdL93mB6YLNCpC21FYVUbx+rauTdsQCD3ejVxdAmazg== - -constructs@^3.3.259: - version "3.3.259" - resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.3.259.tgz#949b0dd39570c36c5797d9f2edc83f773e568eb5" - integrity sha512-hI++shPkBPk8yPD/Af48B6nPmnZIXsKx2dnqDiqadoU0i7Z75/G/TqtLVF96h8XC4A6JkzQ89+CxJLpRTqwy8w== +constructs@^10.0.119, constructs@^10.1.42: + version "10.1.42" + resolved "https://registry.yarnpkg.com/constructs/-/constructs-10.1.42.tgz#dc21bfa7d024a1c81c0982b69ed4585e4e9d5712" + integrity sha512-5AELa/PFtZG+WTjn9HoXhqsDZYV6l3J7Li9xw6vREYVMasF8cnVbTZvA4crP1gIyKtBAxAlnZCmzmCbicnH6eg== conventional-changelog-config-spec@^2.1.0: version "2.1.0" @@ -1356,10 +1346,10 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-format@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.6.tgz#f6138b8f17968df9815b3d101fc06b0523f066c5" - integrity sha512-B9vvg5rHuQ8cbUXE/RMWMyX2YA5TecT3jKF5fLtGNlzPlU7zblSPmAm2OImDbWL+LDOQ6pUm+4LOFz+ywS41Zw== +date-format@^4.0.10: + version "4.0.11" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.11.tgz#ae0d1e069d7f0687938fd06f98c12f3a6276e526" + integrity sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw== debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" @@ -1402,27 +1392,6 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-equal@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.5.tgz#55cd2fe326d83f9cbf7261ef0e060b3f724c5cb9" - integrity sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw== - dependencies: - call-bind "^1.0.0" - es-get-iterator "^1.1.1" - get-intrinsic "^1.0.1" - is-arguments "^1.0.4" - is-date-object "^1.0.2" - is-regex "^1.1.1" - isarray "^2.0.5" - object-is "^1.1.4" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.3.0" - side-channel "^1.0.3" - which-boxed-primitive "^1.0.1" - which-collection "^1.0.1" - which-typed-array "^1.1.2" - deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -1528,7 +1497,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: +es-abstract@^1.19.0, es-abstract@^1.19.1: version "1.19.2" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.2.tgz#8f7b696d8f15b167ae3640b4060670f3d054143f" integrity sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w== @@ -1554,20 +1523,6 @@ es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" -es-get-iterator@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" - integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.0" - has-symbols "^1.0.1" - is-arguments "^1.1.0" - is-map "^2.0.2" - is-set "^2.0.2" - is-string "^1.0.5" - isarray "^2.0.5" - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -1847,6 +1802,11 @@ fast-json-patch@^2.2.1: dependencies: fast-deep-equal "^2.0.1" +fast-json-patch@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947" + integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ== + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -1925,10 +1885,10 @@ follow-redirects@^1.14.9: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +follow-redirects@^1.15.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== form-data@^3.0.0: version "3.0.1" @@ -1939,10 +1899,10 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -fs-extra@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" - integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -1997,7 +1957,7 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -2231,14 +2191,6 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -is-arguments@^1.0.4, is-arguments@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -2271,7 +2223,7 @@ is-core-module@^2.8.0, is-core-module@^2.8.1: dependencies: has "^1.0.3" -is-date-object@^1.0.1, is-date-object@^1.0.2: +is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== @@ -2300,11 +2252,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: dependencies: is-extglob "^2.1.1" -is-map@^2.0.1, is-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== - is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -2327,7 +2274,7 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.1.1, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -2335,11 +2282,6 @@ is-regex@^1.1.1, is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-set@^2.0.1, is-set@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== - is-shared-array-buffer@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" @@ -2366,27 +2308,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== - is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -2394,19 +2320,6 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-weakset@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" - integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2935,84 +2848,84 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-pacmak@^1.55.1: - version "1.55.1" - resolved "https://registry.yarnpkg.com/jsii-pacmak/-/jsii-pacmak-1.55.1.tgz#9259a653b65ac570a10f86358b4a7b10e5b7856c" - integrity sha512-E208pgMfxbPbXgmcskDG0/hBbkPLGlU7S79VoXESy1Kegf7TnZjLqpBdJ3mNxIroS5gIC8DToArMHUFAQ6z0lA== +jsii-pacmak@^1.61.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/jsii-pacmak/-/jsii-pacmak-1.61.0.tgz#90b66694305df4c5713fc99615bdc0209f1f7093" + integrity sha512-XFrUx19TZcP+NBO29P5Q/fegRURXs4UaH8l2+/OITn1PXGOhEq/eCA6TDpdrLXtyt6ebkrLemsrDd0ZW4d0Qvg== dependencies: - "@jsii/check-node" "1.55.1" - "@jsii/spec" "^1.55.1" + "@jsii/check-node" "1.61.0" + "@jsii/spec" "^1.61.0" clone "^2.1.2" - codemaker "^1.55.1" + codemaker "^1.61.0" commonmark "^0.30.0" escape-string-regexp "^4.0.0" - fs-extra "^9.1.0" - jsii-reflect "^1.55.1" - jsii-rosetta "^1.55.1" - semver "^7.3.5" - spdx-license-list "^6.4.0" + fs-extra "^10.1.0" + jsii-reflect "^1.61.0" + jsii-rosetta "^1.61.0" + semver "^7.3.7" + spdx-license-list "^6.6.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@^1.55.1: - version "1.55.1" - resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.55.1.tgz#b192d4f1121f1a142581614fd68e26f25abe2dc9" - integrity sha512-/Ak+sCuIjJaRCflCWT2UKPdT88EQhbPYLhtF7F42uuUr2tchlNkybNE15bigZbtqLw7SP1fp/6Dedujvf90N9Q== +jsii-reflect@^1.61.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.61.0.tgz#23a2b0151987dd9cc27fb046abe40c87dee8f8d8" + integrity sha512-nqBylNBqJJoTJR9TpywW5i55zaOWlNxJTHSWyVYJnrp5ZuYI2R0+nMUxux1hT0Zbd77KbRHXeSByW1aQ6Mfi/A== dependencies: - "@jsii/check-node" "1.55.1" - "@jsii/spec" "^1.55.1" + "@jsii/check-node" "1.61.0" + "@jsii/spec" "^1.61.0" chalk "^4" - fs-extra "^9.1.0" - oo-ascii-tree "^1.55.1" + fs-extra "^10.1.0" + oo-ascii-tree "^1.61.0" yargs "^16.2.0" -jsii-rosetta@^1.55.1: - version "1.55.1" - resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.55.1.tgz#30b44111d146534c42c8fef77931d3fdb888de7d" - integrity sha512-ZUzuO2JgnxE01tgIdZorsUZj5jiHP8uxeLDU/vsnmnAU2ZbMHFDT1cWacoAKESDnCyFF8VRCuPXHx8e5/SOXig== +jsii-rosetta@^1.61.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.61.0.tgz#ea82332545481aa373ac5b4826a303d16ec46b13" + integrity sha512-n8y3er0nOchLo17Wh0/yVmCDGNuwlhccp/Liwvl0ewf0hYMC5vICjWTIdCetsRoQQIOuc4pOmMNomldTTlPUUw== dependencies: - "@jsii/check-node" "1.55.1" - "@jsii/spec" "1.55.1" - "@xmldom/xmldom" "^0.8.1" + "@jsii/check-node" "1.61.0" + "@jsii/spec" "1.61.0" + "@xmldom/xmldom" "^0.8.2" commonmark "^0.30.0" fast-glob "^3.2.11" - fs-extra "^9.1.0" - jsii "1.55.1" - semver "^7.3.5" + fs-extra "^10.1.0" + jsii "1.61.0" + semver "^7.3.7" semver-intersect "^1.4.0" sort-json "^2.0.1" - typescript "~3.9.10" - workerpool "^6.2.0" + typescript-3.9 "npm:typescript@~3.9.10" + workerpool "^6.2.1" yargs "^16.2.0" -jsii-srcmak@^0.1.521: - version "0.1.521" - resolved "https://registry.yarnpkg.com/jsii-srcmak/-/jsii-srcmak-0.1.521.tgz#74e7e30e4f98d77ce52184ec0791eff03e9788ea" - integrity sha512-cZv5C7kMUz+UZqZsZpmz+xDWZCC8VNJNRo/nO+1uuzKuBk1XRAvKOEiMI5E//tZqRuv2BXuyGIhyJOMrOpP4dg== +jsii-srcmak@^0.1.599: + version "0.1.599" + resolved "https://registry.yarnpkg.com/jsii-srcmak/-/jsii-srcmak-0.1.599.tgz#09d1e85702a1e7b5cebcd705e9988bfc5c20e765" + integrity sha512-mVl0hsg28XFQG/hCzuOfHUjz1+1BBg52p66lffMBHtoRzOHnoVrAvlvy5gL44HOWH/L2PhFRW/koA/wLPXP3nA== dependencies: fs-extra "^9.1.0" - jsii "^1.55.1" - jsii-pacmak "^1.55.1" + jsii "^1.61.0" + jsii-pacmak "^1.61.0" ncp "^2.0.0" yargs "^15.4.1" -jsii@1.55.1, jsii@^1.55.1: - version "1.55.1" - resolved "https://registry.yarnpkg.com/jsii/-/jsii-1.55.1.tgz#e4018b4d5017b57857c608d2acb850f07a5f94a3" - integrity sha512-9L6BztDV8PwNY5C+vwuLRJTzijh5Kyh3eijaz8NS11Jc7rTeTN8AvLxyWsIaPO+ITTP4JTsDKOU3tBaoWabRzA== +jsii@1.61.0, jsii@^1.61.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/jsii/-/jsii-1.61.0.tgz#085af3c3ccfacaf5450907062a32be0c7ecbd8a1" + integrity sha512-haGNRe3k0bhTqUKjMQ/ZBq9H3BR7gB88+wSdvCzQ9IIN6XJNeTB9SvB5ry9XIwn6qk8THF7LXtaLga9Nzz+gFA== dependencies: - "@jsii/check-node" "1.55.1" - "@jsii/spec" "^1.55.1" + "@jsii/check-node" "1.61.0" + "@jsii/spec" "^1.61.0" case "^1.6.3" chalk "^4" - deep-equal "^2.0.5" - fs-extra "^9.1.0" - log4js "^6.4.2" - semver "^7.3.5" + fast-deep-equal "^3.1.3" + fs-extra "^10.1.0" + log4js "^6.5.2" + semver "^7.3.7" semver-intersect "^1.4.0" sort-json "^2.0.1" - spdx-license-list "^6.4.0" - typescript "~3.9.10" + spdx-license-list "^6.6.0" + typescript-3.9 "npm:typescript@~3.9.10" yargs "^16.2.0" json-parse-even-better-errors@^2.3.0: @@ -3040,10 +2953,10 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json2jsii@^0.2.181: - version "0.2.181" - resolved "https://registry.yarnpkg.com/json2jsii/-/json2jsii-0.2.181.tgz#c36f9c33550e732c259b4bef5d8b8cf68e66546a" - integrity sha512-pFUtkCYepbjES8GBuxzkHXEuQyx7CE2VZp6OouvjbrFYJTx3SbbDXmyPuk/ytiD2pPBblwlpb+9VOohxBxXZsQ== +json2jsii@^0.3.49: + version "0.3.49" + resolved "https://registry.yarnpkg.com/json2jsii/-/json2jsii-0.3.49.tgz#7487bd0d2dfeab87f65b8ac133c8ebb0aa17cf9b" + integrity sha512-3pQYYqZAb/2Ua+gsQCt8VU8LH7LMT9252EaoO3pK4J2mI64mHlRhlvBarG3dHjcR2op2jH1H+n1am8+GNUyzlw== dependencies: camelcase "^6.3.0" json-schema "^0.4.0" @@ -3082,11 +2995,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonschema@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" - integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw== - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -3148,16 +3056,16 @@ lodash@^4.7.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log4js@^6.4.2: - version "6.4.4" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.4.4.tgz#c9bc75569f3f40bba22fe1bd0677afa7a6a13bac" - integrity sha512-ncaWPsuw9Vl1CKA406hVnJLGQKy1OHx6buk8J4rE2lVW+NW5Y82G5/DIloO7NkqLOUtNPEANaWC1kZYVjXssPw== +log4js@^6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.5.2.tgz#9ae371e5b3cb3a3a209c24686e5547f8670834e5" + integrity sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A== dependencies: - date-format "^4.0.6" + date-format "^4.0.10" debug "^4.3.4" flatted "^3.2.5" rfdc "^1.3.0" - streamroller "^3.0.6" + streamroller "^3.1.1" lower-case@^2.0.2: version "2.0.2" @@ -3336,14 +3244,6 @@ object-inspect@^1.12.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== -object-is@^1.1.4: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -3382,10 +3282,10 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.55.1: - version "1.55.1" - resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.55.1.tgz#111b6dd8e2ec8f7068e3e89e687dc29e048880e8" - integrity sha512-wGtYFm45kmxdss2XrdXC14uDUfyekbaqqZJrfvPtYHSa98Bk+RXHdTHHLQ1kwem6HT5c3ogf7+ZUBhX0B034iA== +oo-ascii-tree@^1.61.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.61.0.tgz#06e151afdc3c3051635e94380d7a53512e4e59c1" + integrity sha512-/7aCOm8qkHUdr4iy9qPs3ZbRoWN8FaShpII56LgSFy/YitvskT3SOx92KwcsE5Mipu/X43YcUYFWCS8nUlR3Xw== optionator@^0.8.1: version "0.8.3" @@ -3617,14 +3517,6 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" -regexp.prototype.flags@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" - integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -3741,6 +3633,13 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -3784,7 +3683,7 @@ shx@^0.3.4: minimist "^1.2.3" shelljs "^0.8.5" -side-channel@^1.0.3, side-channel@^1.0.4: +side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== @@ -3848,20 +3747,20 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -spdx-license-list@^6.4.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/spdx-license-list/-/spdx-license-list-6.5.0.tgz#1624b9cd6c517ff8d697610e6c22d7f5b7c63d28" - integrity sha512-28O9GgFrMg2Wp8tVML0Zk+fnXaECy7UbB6pxo+93whHay/nqPyEdM07Cx6B4+j2pniUZTYr57OaIOyNTxsTwtw== +spdx-license-list@^6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/spdx-license-list/-/spdx-license-list-6.6.0.tgz#403e1807fd87ef2b4781677bc91896d23eaed4ea" + integrity sha512-vLwdf9AWgdJQmG8cai2HKfkInFsliKaCCOwXmdVonClIhdURTX61KdDOoXC1qcQ7gDaZj+CUTcrMJeAdnCtrKA== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -sscaff@^1.2.248: - version "1.2.248" - resolved "https://registry.yarnpkg.com/sscaff/-/sscaff-1.2.248.tgz#b6bfa40f346db8a111913ca42a653b970377bde3" - integrity sha512-rHpwuR6VXLYvHowk/AZTNbTbhnxQ20+G6izyrdCXH7qxIcU05sbo328b8WdglFi3ncm6FF9Rn2PmGEc2HGaY/Q== +sscaff@^1.2.274: + version "1.2.274" + resolved "https://registry.yarnpkg.com/sscaff/-/sscaff-1.2.274.tgz#3ae52042fbeb244b01b89542a56ce5b247284be9" + integrity sha512-sztRa50SL1LVxZnF1au6QT1SC2z0S1oEOyi2Kpnlg6urDns93aL32YxiJcNkLcY+VHFtVqm/SRv4cb+6LeoBQA== stack-utils@^2.0.3: version "2.0.5" @@ -3877,14 +3776,14 @@ stream-events@^1.0.5: dependencies: stubs "^3.0.0" -streamroller@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.0.6.tgz#52823415800ded79a49aa3f7712f50a422b97493" - integrity sha512-Qz32plKq/MZywYyhEatxyYc8vs994Gz0Hu2MSYXXLD233UyPeIeRBZARIIGwFer4Mdb8r3Y2UqKkgyDghM6QCg== +streamroller@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.1.tgz#679aae10a4703acdf2740755307df0a05ad752e6" + integrity sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ== dependencies: - date-format "^4.0.6" + date-format "^4.0.10" debug "^4.3.4" - fs-extra "^10.0.1" + fs-extra "^10.1.0" string-length@^4.0.1: version "4.0.2" @@ -4167,16 +4066,16 @@ typedoc@^0.21.4: shiki "^0.9.8" typedoc-default-themes "^0.12.10" +"typescript-3.9@npm:typescript@~3.9.10": + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== + typescript@^4.6.3: version "4.6.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== -typescript@~3.9.10: - version "3.9.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" - integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== - uglify-js@^3.1.4: version "3.15.3" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.3.tgz#9aa82ca22419ba4c0137642ba0df800cb06e0471" @@ -4310,7 +4209,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0: tr46 "^2.1.0" webidl-conversions "^6.1.0" -which-boxed-primitive@^1.0.1, which-boxed-primitive@^1.0.2: +which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== @@ -4321,33 +4220,11 @@ which-boxed-primitive@^1.0.1, which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== - dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -4365,10 +4242,10 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -workerpool@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" - integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== +workerpool@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== wrap-ansi@^6.2.0: version "6.2.0" diff --git a/cdk/kraken/.projenrc.js b/cdk/kraken/.projenrc.js index a8dd1404..02eeb760 100644 --- a/cdk/kraken/.projenrc.js +++ b/cdk/kraken/.projenrc.js @@ -12,7 +12,7 @@ const project = new TypeScriptProject({ ...common.options, }); -project.addFields({['version']: '0.8.6'}); +project.addFields({['version']: '0.8.9'}); project.prettier?.ignoreFile?.addPatterns('src/imports'); project.testTask.steps.forEach(step => { if (step.exec) { diff --git a/cdk/kraken/CHANGELOG.md b/cdk/kraken/CHANGELOG.md index 370c3704..b7e91b38 100644 --- a/cdk/kraken/CHANGELOG.md +++ b/cdk/kraken/CHANGELOG.md @@ -2,6 +2,19 @@ ## X.Y.Z (UNRELEASED) +## 0.8.9 (2022-06-30) +* Fix nuke job bugs. +* Sticky announcement message (design considerations [here](https://github.com/pennlabs/infrastructure/pull/98#issuecomment-1168086333)) + +## 0.8.8 (2022-06-27) +* Announce successful feature branch deployment. + +## 0.8.7 (2022-06-20) +* Add feature branch deployment related workflow objects: + * Nonprod deployment configuration for `DeployJob`. + * Add `NukeJob`. + * Enable feature branch deployment on `LabsApplicationStack`. + ## 0.8.6 (2022-04-08) * Upgrade dependencies and fix projen version configuration diff --git a/cdk/kraken/package.json b/cdk/kraken/package.json index 4c67044c..b2969b7d 100644 --- a/cdk/kraken/package.json +++ b/cdk/kraken/package.json @@ -50,7 +50,7 @@ }, "dependencies": { "cdkactions": "^0.2.3", - "constructs": "^3.2.80", + "constructs": "^3.2.109", "ts-dedent": "^2.2.0" }, "keywords": [ @@ -63,7 +63,7 @@ "main": "lib/index.js", "license": "MIT", "homepage": "https://kraken.pennlabs.org", - "version": "0.8.6", + "version": "0.8.9", "jest": { "testMatch": [ "/src/**/__tests__/**/*.ts?(x)", diff --git a/cdk/kraken/src/cdk.ts b/cdk/kraken/src/cdk.ts index 206dd63e..56a766c9 100644 --- a/cdk/kraken/src/cdk.ts +++ b/cdk/kraken/src/cdk.ts @@ -1,6 +1,7 @@ import { CheckoutJob, Workflow, Stack, WorkflowProps } from "cdkactions"; import { Construct } from "constructs"; import dedent from "ts-dedent"; +import { defaultBranch } from "./utils"; /** * Optional props to configure the CDK publish stack. @@ -38,7 +39,7 @@ export class CDKPublishStack extends Stack { ) { // Build config const fullConfig: Required = { - defaultBranch: "master", + defaultBranch, nodeVersion: "14", ...config, }; @@ -120,7 +121,7 @@ export class CDKPublishStack extends Stack { personal_token: "${{ secrets.BOT_GITHUB_PAT }}", external_repository: `pennlabs/${id}-docs`, cname: `${id}.pennlabs.org`, - publish_branch: "master", + publish_branch: defaultBranch, publish_dir: `${path}/docs`, user_name: "github-actions", user_email: "github-actions[bot]@users.noreply.github.com", diff --git a/cdk/kraken/src/deploy.ts b/cdk/kraken/src/deploy.ts index 19957bf8..fcec9e3a 100644 --- a/cdk/kraken/src/deploy.ts +++ b/cdk/kraken/src/deploy.ts @@ -1,5 +1,6 @@ -import { CheckoutJob, Workflow, JobProps } from "cdkactions"; +import { CheckoutJob, Workflow, JobProps, StepsProps } from "cdkactions"; import dedent from "ts-dedent"; +import { defaultBranch } from "./utils"; /** * Optional props to configure the deploy job. @@ -16,6 +17,18 @@ export interface DeployJobProps { * @default master */ defaultBranch?: string; + + /** + * Deploy to a specific feature branch. + * @default false + */ + deployToFeatureBranch?: boolean; + + /** + * Domains used to access the deployment. These help form the urls sent + * in a Github Actions message once deployment successfully completes. + */ + deploymentUrls?: string[]; } /** @@ -36,51 +49,125 @@ export class DeployJob extends CheckoutJob { // Build config const fullConfig: Required = { deployTag: "${{ github.sha }}", - defaultBranch: "master", + defaultBranch, + deployToFeatureBranch: false, + deploymentUrls: [], ...config, }; - super(scope, "deploy", { - runsOn: "ubuntu-latest", - if: `github.ref == 'refs/heads/${fullConfig.defaultBranch}'`, - steps: [ - { - id: "synth", - name: "Synth cdk8s manifests", - run: dedent`cd k8s - yarn install --frozen-lockfile + const featureBranchPreDeploySteps: StepsProps[] = [ + { + name: "Get Pull Request Metadata", + id: "pr", + run: dedent` + echo "::set-output name=pull_request_number::$(gh pr view --json number -q .number || echo "")" + echo "::set-output name=pull_request_closed::$(gh pr view --json closed -q .closed || echo "")" + `, + env: { + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}", + }, + }, + ]; - # get repo name (by removing owner/organization) - export RELEASE_NAME=\${REPOSITORY#*/} + const featureBranchPostDeploySteps: StepsProps[] = [ + { + name: "Find announcement if exists", + uses: "peter-evans/find-comment@v2", + id: "find-announcement", + with: { + "issue-number": "${{ steps.pr.outputs.pull_request_number }}", + "body-includes": "Deployment preview for", + token: "${{ secrets.GITHUB_TOKEN }}", + }, + }, + { + name: "Announce successful feature branch deployment", + uses: "peter-evans/create-or-update-comment@v2", + with: { + "comment-id": "${{ steps.find-announcement.outputs.comment-id }}", + "issue-number": "${{ steps.pr.outputs.pull_request_number }}", + "edit-mode": "replace", + body: + fullConfig.deploymentUrls.length > 0 + ? dedent` + Deployment preview for commit \`\${{ github.sha }}\` ready at: + ${fullConfig.deploymentUrls.map( + (url) => + dedent`[pr-\${{ steps.pr.outputs.pull_request_number }}.${url}](https://pr-\${{ steps.pr.outputs.pull_request_number }}.${url})` + )}` + : "Deployment preview for commit ${{ github.sha }} ready.", + }, + }, + ]; + + super( + scope, + fullConfig.deployToFeatureBranch ? "feature-branch-deploy" : "deploy", + { + runsOn: "ubuntu-latest", + if: fullConfig.deployToFeatureBranch + ? `startsWith(github.ref, 'refs/heads/feat/') == true` + : `github.ref == 'refs/heads/${fullConfig.defaultBranch}'`, + steps: [ + ...(fullConfig.deployToFeatureBranch + ? featureBranchPreDeploySteps + : []), + { + id: "synth", + name: "Synth cdk8s manifests", + ...(fullConfig.deployToFeatureBranch + ? { + if: "(steps.pr.outputs.pull_request_number) && (steps.pr.outputs.pull_request_closed == 'false')", + } + : {}), + run: dedent`cd k8s + yarn install --frozen-lockfile + + # Get repo name (by removing owner/organization)${ + fullConfig.deployToFeatureBranch + ? "\nexport DEPLOY_TO_FEATURE_BRANCH=true" + : "" + } + export RELEASE_NAME=${ + fullConfig.deployToFeatureBranch + ? "${REPOSITORY#*/}-pr-${{ steps.pr.outputs.pull_request_number }}" + : "${REPOSITORY#*/}" + } # Export RELEASE_NAME as an output echo "::set-output name=RELEASE_NAME::$RELEASE_NAME" yarn build`, - env: { - GIT_SHA: fullConfig.deployTag, - REPOSITORY: "${{ github.repository }}", - AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}", + env: { + PR_NUMBER: "${{ steps.pr.outputs.pull_request_number }}", + GIT_SHA: fullConfig.deployTag, + REPOSITORY: "${{ github.repository }}", + AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}", + }, }, - }, - { - name: "Deploy", - run: dedent`aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl + { + name: "Deploy", + if: "steps.synth.outcome == 'success'", + run: dedent`aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::${"${AWS_ACCOUNT_ID}"}:role/kubectl - # get repo name from synth step - RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} + # Get repo name from synth step + RELEASE_NAME=${"${{ steps.synth.outputs.RELEASE_NAME }}"} - # Deploy - kubectl apply -f k8s/dist/ -l app.kubernetes.io/component=certificate - kubectl apply -f k8s/dist/ --prune -l app.kubernetes.io/part-of=$RELEASE_NAME`, - env: { - AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}", - AWS_ACCESS_KEY_ID: "${{ secrets.GH_AWS_ACCESS_KEY_ID }}", - AWS_SECRET_ACCESS_KEY: "${{ secrets.GH_AWS_SECRET_ACCESS_KEY }}", + # Deploy + kubectl apply -f k8s/dist/ -l app.kubernetes.io/component=certificate + kubectl apply -f k8s/dist/ --prune -l app.kubernetes.io/part-of=$RELEASE_NAME`, + env: { + AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}", + AWS_ACCESS_KEY_ID: "${{ secrets.GH_AWS_ACCESS_KEY_ID }}", + AWS_SECRET_ACCESS_KEY: "${{ secrets.GH_AWS_SECRET_ACCESS_KEY }}", + }, }, - }, - ], - ...overrides, - }); + ...(fullConfig.deployToFeatureBranch + ? featureBranchPostDeploySteps + : []), + ], + ...overrides, + } + ); } } diff --git a/cdk/kraken/src/index.ts b/cdk/kraken/src/index.ts index 2b192394..c184df77 100644 --- a/cdk/kraken/src/index.ts +++ b/cdk/kraken/src/index.ts @@ -6,6 +6,7 @@ export * from "./django"; export * from "./docker"; export * from "./integration-tests"; export * from "./labs-application"; +export * from "./nuke"; export * from "./postintegrationimagepublishjob"; export * from "./pypi"; export * from "./react-project"; diff --git a/cdk/kraken/src/labs-application.ts b/cdk/kraken/src/labs-application.ts index 5cc49a0c..bd175b99 100644 --- a/cdk/kraken/src/labs-application.ts +++ b/cdk/kraken/src/labs-application.ts @@ -8,8 +8,10 @@ import { IntegrationTestsJob, IntegrationTestsJobProps, } from "./integration-tests"; +import { NukeJob } from "./nuke"; import { ReactCheckJobProps } from "./react"; import { ReactProject } from "./react-project"; +import { defaultBranch } from "./utils"; /** * Props to configure the LabsApplication stack @@ -27,6 +29,12 @@ export interface LabsApplicationStackProps { */ frontendPath?: string; + /** + * If true, workflows for feature branch deployment will be generated. + * @default false + */ + enableFeatureBranchDeploy?: boolean; + /** * If true, run integration tests using docker-compose. * @default false @@ -103,6 +111,11 @@ export interface LabsApplicationStackProps { * Optional overrides for the deploy job. */ deployOverrides?: Partial; + + /** + * Urls sent in a message once deployment successfully completes. + */ + deploymentUrls?: string[]; } /** @@ -129,6 +142,7 @@ export class LabsApplicationStack extends Stack { const fullConfig: Required = { backendPath: "backend", frontendPath: "frontend", + enableFeatureBranchDeploy: false, integrationTests: false, djangoCheckProps: {}, djangoCheckOverrides: {}, @@ -142,11 +156,21 @@ export class LabsApplicationStack extends Stack { integrationOverrides: {}, deployProps: {}, deployOverrides: {}, + deploymentUrls: [], ...config, }; fullConfig.djangoDockerProps.noPublish = fullConfig.integrationTests; fullConfig.reactDockerProps.noPublish = fullConfig.integrationTests; + if (config.enableFeatureBranchDeploy) { + const publishCondition = `\${{ github.ref == 'refs/heads/${ + fullConfig.deployProps.defaultBranch ?? defaultBranch + }' || startsWith(github.ref, 'refs/heads/feat/') == true }}`; + + fullConfig.reactDockerProps.push = publishCondition; + fullConfig.djangoDockerProps.push = publishCondition; + } + // Create stack super(scope, "application"); const workflow = new Workflow(this, "build-and-deploy", { @@ -207,5 +231,42 @@ export class LabsApplicationStack extends Stack { ...fullConfig.deployOverrides, needs: deployNeeds, }); + + // Feature Branch Deploy + if (fullConfig.enableFeatureBranchDeploy) { + // Add Feature Branch Deploy to Original Workflow + new DeployJob( + workflow, + { + ...fullConfig.deployProps, + deployToFeatureBranch: true, + deploymentUrls: fullConfig.deploymentUrls, + }, + { + ...fullConfig.deployOverrides, + needs: deployNeeds, + } + ); + + // New Feature Branch Nuke Worflow + const featureBranchNukeWorkflow = new Workflow( + this, + "feature-branch-nuke", + { + name: "Feature Branch Nuke", + on: { + pullRequest: { + types: ["closed"], + branches: ["feat/**"], + }, + }, + ...overrides, + } + ); + + new NukeJob(featureBranchNukeWorkflow, fullConfig.deployProps, { + ...fullConfig.deployOverrides, + }); + } } } diff --git a/cdk/kraken/src/nuke.ts b/cdk/kraken/src/nuke.ts new file mode 100644 index 00000000..41b11715 --- /dev/null +++ b/cdk/kraken/src/nuke.ts @@ -0,0 +1,89 @@ +import { CheckoutJob, Workflow, JobProps } from "cdkactions"; +import dedent from "ts-dedent"; + +/** + * Optional props to configure the nuke job. + */ +export interface NukeJobProps { + /** + * Deploy tag to set in kittyhawk. + * @default current git sha + */ + deployTag?: string; + /** + * Condition for nuke job to run. + * @default "startsWith(github.head_ref, 'refs/heads/feat/') == true" + */ + if?: string; +} + +/** + * A job to undeploy/nuke a product. + * When we nuke, it should ALWAYS be for feature branch deployment, not production. + */ +export class NukeJob extends CheckoutJob { + /** + * + * @param scope cdkactions Workflow instance + * @param config Optional configuration for the deploy job. + * @param overrides Optional overrides for the job. + */ + public constructor( + scope: Workflow, + config?: NukeJobProps, + overrides?: Partial + ) { + // Nuke config + const fullConfig: Required = { + deployTag: "${{ github.sha }}", + if: "startsWith(github.event.pull_request.base.ref, 'feat/') == true", + ...config, + }; + + super(scope, "nuke", { + runsOn: "ubuntu-latest", + if: fullConfig.if, // Nuke only for feature branches + steps: [ + { + id: "synth", + name: "Synth cdk8s manifests", + run: dedent`cd k8s + yarn install --frozen-lockfile + + # Feature Branch nuke set-up + export DEPLOY_TO_FEATURE_BRANCH=true + export RELEASE_NAME=${"${REPOSITORY#*/}"}-pr-$PR_NUMBER + + # Export RELEASE_NAME as an output + echo "::set-output name=RELEASE_NAME::$RELEASE_NAME" + + yarn build`, + env: { + PR_NUMBER: "${{ github.event.pull_request.number }}", + GIT_REF: "${{ github.ref }}", + GIT_SHA: fullConfig.deployTag, + REPOSITORY: "${{ github.repository }}", + AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}", + }, + }, + { + name: "Nuke", + run: dedent`aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::${"${AWS_ACCOUNT_ID}"}:role/kubectl + + # Get repo name from synth step + RELEASE_NAME=${"${{ steps.synth.outputs.RELEASE_NAME }}"} + + # Delete all non-certificate resources + kubectl delete -f k8s/dist/ -l app.kubernetes.io/part-of=$RELEASE_NAME + `, + env: { + AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}", + AWS_ACCESS_KEY_ID: "${{ secrets.GH_AWS_ACCESS_KEY_ID }}", + AWS_SECRET_ACCESS_KEY: "${{ secrets.GH_AWS_SECRET_ACCESS_KEY }}", + }, + }, + ], + ...overrides, + }); + } +} diff --git a/cdk/kraken/src/postintegrationimagepublishjob.ts b/cdk/kraken/src/postintegrationimagepublishjob.ts index ce63ccf0..c1c78178 100644 --- a/cdk/kraken/src/postintegrationimagepublishjob.ts +++ b/cdk/kraken/src/postintegrationimagepublishjob.ts @@ -1,4 +1,5 @@ import { CheckoutJob, Workflow, JobProps } from "cdkactions"; +import { defaultBranch } from "./utils"; /** * Props to configure the post integration test docker image publish job. @@ -51,7 +52,7 @@ export class PostIntegrationPublishJob extends CheckoutJob { ) { // Build config const fullConfig: Required = { - defaultBranch: "master", + defaultBranch, dockerUsername: "${{ secrets.DOCKER_USERNAME }}", dockerPassword: "${{ secrets.DOCKER_PASSWORD }}", ...config, diff --git a/cdk/kraken/src/utils.ts b/cdk/kraken/src/utils.ts index dd82b355..babf5997 100644 --- a/cdk/kraken/src/utils.ts +++ b/cdk/kraken/src/utils.ts @@ -1,3 +1,6 @@ export const buildId = (id: string, suffix: string) => suffix ? `${id}-${suffix}` : id; export const buildName = (name: string, id: string) => `${name} ${id}`.trim(); + +// TODO: migrate to main +export const defaultBranch = "master"; diff --git a/cdk/kraken/test/__snapshots__/custom.test.ts.snap b/cdk/kraken/test/__snapshots__/custom.test.ts.snap index 06ad22a7..dbd7f9c6 100644 --- a/cdk/kraken/test/__snapshots__/custom.test.ts.snap +++ b/cdk/kraken/test/__snapshots__/custom.test.ts.snap @@ -20,6 +20,7 @@ Object { "env": Object { "AWS_ACCOUNT_ID": "\${{ secrets.AWS_ACCOUNT_ID }}", "GIT_SHA": "\${{ github.sha }}", + "PR_NUMBER": "\${{ steps.pr.outputs.pull_request_number }}", "REPOSITORY": "\${{ github.repository }}", }, "id": "synth", @@ -27,7 +28,7 @@ Object { "run": "cd k8s yarn install --frozen-lockfile -# get repo name (by removing owner/organization) +# Get repo name (by removing owner/organization) export RELEASE_NAME=\${REPOSITORY#*/} # Export RELEASE_NAME as an output @@ -41,10 +42,11 @@ yarn build", "AWS_ACCOUNT_ID": "\${{ secrets.AWS_ACCOUNT_ID }}", "AWS_SECRET_ACCESS_KEY": "\${{ secrets.GH_AWS_SECRET_ACCESS_KEY }}", }, + "if": "steps.synth.outcome == 'success'", "name": "Deploy", "run": "aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl -# get repo name from synth step +# Get repo name from synth step RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} # Deploy diff --git a/cdk/kraken/test/__snapshots__/labs-application.test.ts.snap b/cdk/kraken/test/__snapshots__/labs-application.test.ts.snap index 64c197a1..40ec8741 100644 --- a/cdk/kraken/test/__snapshots__/labs-application.test.ts.snap +++ b/cdk/kraken/test/__snapshots__/labs-application.test.ts.snap @@ -143,7 +143,7 @@ jobs: cd k8s yarn install --frozen-lockfile - # get repo name (by removing owner/organization) + # Get repo name (by removing owner/organization) export RELEASE_NAME=\${REPOSITORY#*/} # Export RELEASE_NAME as an output @@ -151,14 +151,16 @@ jobs: yarn build env: + PR_NUMBER: \${{ steps.pr.outputs.pull_request_number }} GIT_SHA: \${{ github.sha }} REPOSITORY: \${{ github.repository }} AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} - name: Deploy + if: steps.synth.outcome == 'success' run: |- aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl - # get repo name from synth step + # Get repo name from synth step RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} # Deploy @@ -174,6 +176,300 @@ jobs: " `; +exports[`enabled feature branch deploy 1`] = ` +"# Generated by cdkactions. Do not modify +# Generated as part of the 'application' stack. +name: Build and Deploy +on: push +jobs: + django-check: + name: Django Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Cache + uses: actions/cache@v2 + with: + path: ~/.local/share/virtualenvs + key: v0-\${{ hashFiles('backend/Pipfile.lock') }} + - name: Install Dependencies + run: |- + cd backend + pip install pipenv + pipenv install --deploy --dev + - name: Lint (flake8) + run: |- + cd backend + pipenv run flake8 . + - name: Lint (black) + run: |- + cd backend + pipenv run black --check . + - name: Test (run in parallel) + run: |- + cd backend + pipenv run coverage run --concurrency=multiprocessing manage.py test --settings=example.settings.ci --parallel + pipenv run coverage combine + - name: Upload Code Coverage + run: |- + ROOT=$(pwd) + cd backend + pipenv run codecov --root $ROOT --flags backend + container: + image: python:3.8-buster + env: + DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres + services: + postgres: + image: postgres:12 + env: + POSTGRES_USER: postgres + POSTGRES_DB: postgres + POSTGRES_PASSWORD: postgres + options: \\"--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5\\" + publish-backend: + name: Publish backend + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: docker/setup-qemu-action@v1 + - uses: docker/setup-buildx-action@v1 + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: buildx-publish-backend + - uses: docker/login-action@v1 + with: + username: \${{ secrets.DOCKER_USERNAME }} + password: \${{ secrets.DOCKER_PASSWORD }} + - name: Build/Publish + uses: docker/build-push-action@v2 + with: + context: backend + file: backend/Dockerfile + push: \${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/feat/') == true }} + cache-from: type=local,src=/tmp/.buildx-cache,type=registry,ref=pennlabs/example-backend:latest + cache-to: type=local,dest=/tmp/.buildx-cache + tags: pennlabs/example-backend:latest,pennlabs/example-backend:\${{ github.sha }} + needs: django-check + react-check: + name: React Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Cache + uses: actions/cache@v2 + with: + path: \\"**/node_modules\\" + key: v0-\${{ hashFiles('frontend/yarn.lock') }} + - name: Install Dependencies + run: |- + cd frontend + yarn install --frozen-lockfile + - name: Lint + run: |- + cd frontend + yarn lint + - name: Test + run: |- + cd frontend + yarn test + - name: Upload Code Coverage + run: |- + ROOT=$(pwd) + cd frontend + yarn run codecov -p $ROOT -F frontend + container: + image: node:14 + publish-frontend: + name: Publish frontend + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: docker/setup-qemu-action@v1 + - uses: docker/setup-buildx-action@v1 + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: buildx-publish-frontend + - uses: docker/login-action@v1 + with: + username: \${{ secrets.DOCKER_USERNAME }} + password: \${{ secrets.DOCKER_PASSWORD }} + - name: Build/Publish + uses: docker/build-push-action@v2 + with: + context: frontend + file: frontend/Dockerfile + push: \${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/feat/') == true }} + cache-from: type=local,src=/tmp/.buildx-cache,type=registry,ref=pennlabs/example-frontend:latest + cache-to: type=local,dest=/tmp/.buildx-cache + tags: pennlabs/example-frontend:latest,pennlabs/example-frontend:\${{ github.sha }} + needs: react-check + deploy: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' + steps: + - uses: actions/checkout@v2 + - id: synth + name: Synth cdk8s manifests + run: |- + cd k8s + yarn install --frozen-lockfile + + # Get repo name (by removing owner/organization) + export RELEASE_NAME=\${REPOSITORY#*/} + + # Export RELEASE_NAME as an output + echo \\"::set-output name=RELEASE_NAME::$RELEASE_NAME\\" + + yarn build + env: + PR_NUMBER: \${{ steps.pr.outputs.pull_request_number }} + GIT_SHA: \${{ github.sha }} + REPOSITORY: \${{ github.repository }} + AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} + - name: Deploy + if: steps.synth.outcome == 'success' + run: |- + aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl + + # Get repo name from synth step + RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} + + # Deploy + kubectl apply -f k8s/dist/ -l app.kubernetes.io/component=certificate + kubectl apply -f k8s/dist/ --prune -l app.kubernetes.io/part-of=$RELEASE_NAME + env: + AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} + AWS_ACCESS_KEY_ID: \${{ secrets.GH_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: \${{ secrets.GH_AWS_SECRET_ACCESS_KEY }} + needs: + - publish-backend + - publish-frontend + feature-branch-deploy: + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/heads/feat/') == true + steps: + - uses: actions/checkout@v2 + - name: Get Pull Request Metadata + id: pr + run: |- + echo \\"::set-output name=pull_request_number::$(gh pr view --json number -q .number || echo \\"\\")\\" + echo \\"::set-output name=pull_request_closed::$(gh pr view --json closed -q .closed || echo \\"\\")\\" + env: + GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }} + - id: synth + name: Synth cdk8s manifests + if: (steps.pr.outputs.pull_request_number) && (steps.pr.outputs.pull_request_closed == 'false') + run: |- + cd k8s + yarn install --frozen-lockfile + + # Get repo name (by removing owner/organization) + export DEPLOY_TO_FEATURE_BRANCH=true + export RELEASE_NAME=\${REPOSITORY#*/}-pr-\${{ steps.pr.outputs.pull_request_number }} + + # Export RELEASE_NAME as an output + echo \\"::set-output name=RELEASE_NAME::$RELEASE_NAME\\" + + yarn build + env: + PR_NUMBER: \${{ steps.pr.outputs.pull_request_number }} + GIT_SHA: \${{ github.sha }} + REPOSITORY: \${{ github.repository }} + AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} + - name: Deploy + if: steps.synth.outcome == 'success' + run: |- + aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl + + # Get repo name from synth step + RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} + + # Deploy + kubectl apply -f k8s/dist/ -l app.kubernetes.io/component=certificate + kubectl apply -f k8s/dist/ --prune -l app.kubernetes.io/part-of=$RELEASE_NAME + env: + AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} + AWS_ACCESS_KEY_ID: \${{ secrets.GH_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: \${{ secrets.GH_AWS_SECRET_ACCESS_KEY }} + - name: Find announcement if exists + uses: peter-evans/find-comment@v2 + id: find-announcement + with: + issue-number: \${{ steps.pr.outputs.pull_request_number }} + body-includes: Deployment preview for + token: \${{ secrets.GITHUB_TOKEN }} + - name: Announce successful feature branch deployment + uses: peter-evans/create-or-update-comment@v2 + with: + comment-id: \${{ steps.find-announcement.outputs.comment-id }} + issue-number: \${{ steps.pr.outputs.pull_request_number }} + edit-mode: replace + body: |- + Deployment preview for commit \`\${{ github.sha }}\` ready at: + [pr-\${{ steps.pr.outputs.pull_request_number }}.example.com](https://pr-\${{ steps.pr.outputs.pull_request_number }}.example.com) + needs: + - publish-backend + - publish-frontend +" +`; + +exports[`enabled feature branch deploy 2`] = ` +"# Generated by cdkactions. Do not modify +# Generated as part of the 'application' stack. +name: Feature Branch Nuke +on: + pull_request: + types: + - closed + branches: + - feat/** +jobs: + nuke: + runs-on: ubuntu-latest + if: startsWith(github.event.pull_request.base.ref, 'feat/') == true + steps: + - uses: actions/checkout@v2 + - id: synth + name: Synth cdk8s manifests + run: |- + cd k8s + yarn install --frozen-lockfile + + # Feature Branch nuke set-up + export DEPLOY_TO_FEATURE_BRANCH=true + export RELEASE_NAME=\${REPOSITORY#*/}-pr-$PR_NUMBER + + # Export RELEASE_NAME as an output + echo \\"::set-output name=RELEASE_NAME::$RELEASE_NAME\\" + + yarn build + env: + PR_NUMBER: \${{ github.event.pull_request.number }} + GIT_REF: \${{ github.ref }} + GIT_SHA: \${{ github.sha }} + REPOSITORY: \${{ github.repository }} + AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} + - name: Nuke + run: |- + aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl + + # Get repo name from synth step + RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} + + # Delete all non-certificate resources + kubectl delete -f k8s/dist/ -l app.kubernetes.io/part-of=$RELEASE_NAME + env: + AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} + AWS_ACCESS_KEY_ID: \${{ secrets.GH_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: \${{ secrets.GH_AWS_SECRET_ACCESS_KEY }} +" +`; + exports[`integration tests 1`] = ` "# Generated by cdkactions. Do not modify # Generated as part of the 'application' stack. @@ -389,7 +685,7 @@ jobs: cd k8s yarn install --frozen-lockfile - # get repo name (by removing owner/organization) + # Get repo name (by removing owner/organization) export RELEASE_NAME=\${REPOSITORY#*/} # Export RELEASE_NAME as an output @@ -397,14 +693,16 @@ jobs: yarn build env: + PR_NUMBER: \${{ steps.pr.outputs.pull_request_number }} GIT_SHA: \${{ github.sha }} REPOSITORY: \${{ github.repository }} AWS_ACCOUNT_ID: \${{ secrets.AWS_ACCOUNT_ID }} - name: Deploy + if: steps.synth.outcome == 'success' run: |- aws eks --region us-east-1 update-kubeconfig --name production --role-arn arn:aws:iam::\${AWS_ACCOUNT_ID}:role/kubectl - # get repo name from synth step + # Get repo name from synth step RELEASE_NAME=\${{ steps.synth.outputs.RELEASE_NAME }} # Deploy diff --git a/cdk/kraken/test/labs-application.test.ts b/cdk/kraken/test/labs-application.test.ts index 3fb5c7a4..527e6ebd 100644 --- a/cdk/kraken/test/labs-application.test.ts +++ b/cdk/kraken/test/labs-application.test.ts @@ -17,6 +17,30 @@ test("default", () => { ).toMatchSnapshot(); }); +test("enabled feature branch deploy", () => { + const app = TestingApp({ createValidateWorkflow: false }); + new LabsApplicationStack(app, { + deploymentUrls: ["example.com"], + djangoProjectName: "example", + dockerImageBaseName: "example", + enableFeatureBranchDeploy: true, + }); + app.synth(); + expect(fs.readdirSync(app.outdir)).toEqual([ + "cdkactions_build-and-deploy.yaml", + "cdkactions_feature-branch-nuke.yaml", + ]); + expect( + fs.readFileSync(`${app.outdir}/cdkactions_build-and-deploy.yaml`, "utf-8") + ).toMatchSnapshot(); + expect( + fs.readFileSync( + `${app.outdir}/cdkactions_feature-branch-nuke.yaml`, + "utf-8" + ) + ).toMatchSnapshot(); +}); + test("integration tests", () => { const app = TestingApp({ createValidateWorkflow: false }); new LabsApplicationStack(app, { diff --git a/cdk/kraken/yarn.lock b/cdk/kraken/yarn.lock index 8f0b2748..cd7c1f3a 100644 --- a/cdk/kraken/yarn.lock +++ b/cdk/kraken/yarn.lock @@ -1184,10 +1184,10 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -constructs@^3.2.80: - version "3.3.261" - resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.3.261.tgz#2d051a33535ce9595eba3375eaccaa26ff0d33ec" - integrity sha512-WAcluBHRkIlTIW0jXOhp9Fm8ZtjS2cF3MbAxN6/VEdAVtjuXlHqKmrBOVIp8V5L26ze/xuMz3mDhq1CrC2pjsw== +constructs@^3.2.109: + version "3.4.39" + resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.4.39.tgz#607085f072221b8c6e80226021cca38d3dba0355" + integrity sha512-tj2m8GUD155rwQXmfHMZvMtBwexTEU4m7rxVkNWSShl1bkhyYV8gVi8hrrG8MtSiizkz4FheYPlkU+O3YIEo/w== conventional-changelog-config-spec@^2.1.0: version "2.1.0" diff --git a/docker/django-base/django-run b/docker/django-base/django-run index 52f22c63..69f0f615 100755 --- a/docker/django-base/django-run +++ b/docker/django-base/django-run @@ -1,7 +1,13 @@ #!/bin/bash +set -e # Django Migrate /usr/local/bin/python3 /app/manage.py migrate --noinput +# If DEPLOY_TO_FEATURE_BRANCH is set, run populate +if [[ ! -z "${DEPLOY_TO_FEATURE_BRANCH}" ]]; then + /usr/local/bin/python3 /app/manage.py populate +fi + # Run UWSGI exec /usr/local/bin/uwsgi --ini /app/setup.cfg