From 751bb99a9e7fc6111130991d1775e5142004863e Mon Sep 17 00:00:00 2001 From: mkleszcz Date: Fri, 20 Sep 2024 11:27:37 +0200 Subject: [PATCH] feat: #611 Remove AWS CodeCommit from stack (#619) --- .github/workflows/actions/deploy/action.yml | 35 ++++++ .github/workflows/deploy-prod.yml | 25 ++++ .github/workflows/deploy-qa.yml | 25 ++++ .github/workflows/infra.yml | 1 - .github/workflows/main.yml | 22 ---- .versionrc.js | 4 - bitbucket-pipelines.yml | 50 ++++---- .../infra/infra-core/src/lib/env-config.ts | 5 - packages/infra/infra-functions/.gitignore | 7 -- .../deployment/triggerEntrypoint.ts | 40 ------- .../infra/infra-functions/eslint.config.js | 8 -- .../infra-functions.conf.local.yml | 19 --- .../infra-functions/infra-functions.conf.yml | 32 ----- packages/infra/infra-functions/package.json | 19 --- packages/infra/infra-functions/project.json | 39 ------ packages/infra/infra-functions/serverless.yml | 33 ----- .../infra/infra-functions/tsconfig.app.json | 9 -- packages/infra/infra-functions/tsconfig.json | 10 -- packages/infra/infra-shared/src/index.ts | 2 - packages/infra/infra-shared/src/lib/names.ts | 18 --- .../src/stacks/ci/ciEntrypoint.ts | 108 +++-------------- .../infra-shared/src/stacks/ci/ciPipeline.ts | 1 - .../infra/infra-shared/src/stacks/ci/stack.ts | 15 +-- .../global/resources/globalCodeCommit.ts | 54 --------- .../src/stacks/global/resources/index.ts | 9 +- .../cli/src/commands/ci/create-credentials.ts | 83 ------------- .../src/commands/ci/get-artifacts-bucket.ts | 50 ++++++++ .../internal/cli/src/commands/infra/deploy.ts | 4 - packages/internal/cli/src/config/aws.ts | 5 +- packages/internal/cli/src/config/env.ts | 5 - packages/internal/cli/src/config/init.ts | 10 +- .../docs/docs/aws/cicd/auto-deploy.mdx | 113 +++++++++--------- .../docs/aws/cicd/trigger-cicd-manually.mdx | 18 ++- .../create-env-stage-in-repo.mdx | 9 -- packages/internal/docs/sidebars.js | 2 +- .../internal/status-dashboard/project.json | 4 +- .../tools/scripts/clean-codebuild-branches.sh | 17 --- pnpm-lock.yaml | 55 ++------- 38 files changed, 271 insertions(+), 694 deletions(-) create mode 100644 .github/workflows/actions/deploy/action.yml create mode 100644 .github/workflows/deploy-prod.yml create mode 100644 .github/workflows/deploy-qa.yml delete mode 100644 .github/workflows/main.yml delete mode 100644 packages/infra/infra-functions/.gitignore delete mode 100644 packages/infra/infra-functions/deployment/triggerEntrypoint.ts delete mode 100644 packages/infra/infra-functions/eslint.config.js delete mode 100644 packages/infra/infra-functions/infra-functions.conf.local.yml delete mode 100644 packages/infra/infra-functions/infra-functions.conf.yml delete mode 100644 packages/infra/infra-functions/package.json delete mode 100644 packages/infra/infra-functions/project.json delete mode 100644 packages/infra/infra-functions/serverless.yml delete mode 100644 packages/infra/infra-functions/tsconfig.app.json delete mode 100644 packages/infra/infra-functions/tsconfig.json delete mode 100644 packages/infra/infra-shared/src/lib/names.ts delete mode 100644 packages/infra/infra-shared/src/stacks/global/resources/globalCodeCommit.ts delete mode 100644 packages/internal/cli/src/commands/ci/create-credentials.ts create mode 100644 packages/internal/cli/src/commands/ci/get-artifacts-bucket.ts delete mode 100755 packages/internal/tools/scripts/clean-codebuild-branches.sh diff --git a/.github/workflows/actions/deploy/action.yml b/.github/workflows/actions/deploy/action.yml new file mode 100644 index 000000000..b447cbdd3 --- /dev/null +++ b/.github/workflows/actions/deploy/action.yml @@ -0,0 +1,35 @@ +name: "Deploy environment" +description: "Trigger deployment of the specified environment" + +inputs: + environment-name: + required: true + default: "production" + artifacts-s3-bucket: + required: true + +runs: + using: "composite" + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: 'true' + + - name: Set VERSION in environment + shell: bash + run: | + app_version=$(git describe --tags --first-parent --abbrev=11 --long --dirty --always) + echo "VERSION=${app_version}" >> .env + + - name: Zip artifact + shell: bash + run: | + artifact_name="${{ inputs.environment-name }}-entrypoint.zip" + zip -r -q $artifact_name . + + - name: Send artifact to S3 + shell: bash + run: | + artifact_name="${{ inputs.environment-name }}-entrypoint" + aws s3 cp "${artifact_name}.zip" "s3://${{ inputs.artifacts-s3-bucket }}/${artifact_name}" diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml new file mode 100644 index 000000000..e7f8ef332 --- /dev/null +++ b/.github/workflows/deploy-prod.yml @@ -0,0 +1,25 @@ +name: "Deploy to production" + +concurrency: Production + +on: + workflow_dispatch: + +jobs: + deployment: + runs-on: ubuntu-latest + environment: Production + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: 'true' + + - uses: ./.github/workflows/actions/deploy + with: + environment-name: 'saas-prod' + artifacts-s3-bucket: '${{ secrets.SB_CI_ARTIFACTS_BUCKET }}' + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/deploy-qa.yml b/.github/workflows/deploy-qa.yml new file mode 100644 index 000000000..0806c48da --- /dev/null +++ b/.github/workflows/deploy-qa.yml @@ -0,0 +1,25 @@ +name: "Deploy to QA" + +concurrency: QA + +on: + workflow_dispatch: + +jobs: + deployment: + runs-on: ubuntu-latest + environment: QA + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: 'true' + + - uses: ./.github/workflows/actions/deploy + with: + environment-name: 'saas-qa' + artifacts-s3-bucket: '${{ secrets.SB_CI_ARTIFACTS_BUCKET }}' + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/infra.yml b/.github/workflows/infra.yml index 7765a592e..d496bf4a3 100644 --- a/.github/workflows/infra.yml +++ b/.github/workflows/infra.yml @@ -14,7 +14,6 @@ jobs: infra-lib-name: - infra-core - infra-shared - - infra-functions steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index ce587f3c1..000000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: "Push code to AWS CodeCommit" - -on: - push: - branches: ['**'] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - shell: bash - env: - CODE_COMMIT_REPO: ${{ secrets.CODE_COMMIT_REPO }} - if: env.CODE_COMMIT_REPO != '' - run: | - git remote add codecommit "$CODE_COMMIT_REPO" - git push -u codecommit ${GITHUB_REF#refs/heads/} --force - git push codecommit --tags diff --git a/.versionrc.js b/.versionrc.js index 6f16cd9f4..244ca4b7b 100644 --- a/.versionrc.js +++ b/.versionrc.js @@ -90,10 +90,6 @@ module.exports = { filename: './packages/infra/infra-core/package.json', type: 'json', }, - { - filename: './packages/infra/infra-functions/package.json', - type: 'json', - }, { filename: './packages/infra/infra-shared/package.json', type: 'json', diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index 2ca9260da..8f5c3abf8 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -51,14 +51,20 @@ definitions: --filter=webapp... steps: - - step: &codecommitPush - name: Push code to CodeCommit + - step: &deploy-current-branch + name: Deploy environment + trigger: manual clone: depth: full script: - - git remote add codecommit "$CODE_COMMIT_REPO" - - git push --force -u codecommit "$BITBUCKET_BRANCH" - - git push codecommit --tags --force + - *setupAwsCli + - sudo apt-get install zip + - | + app_version=$(git describe --tags --first-parent --abbrev=11 --long --dirty --always) + echo "VERSION=${app_version}" >> .env + artifact_name="${SB_DEPLOY_ENVIRONMENT_NAME}-entrypoint" + zip -r -q "${artifact_name}.zip" . + aws s3 cp "${artifact_name}.zip" "s3://${SB_CI_ARTIFACTS_BUCKET}/${artifact_name}" - step: &webappTest name: 'webapp: Lint & test' @@ -443,21 +449,6 @@ definitions: - pnpminfrashared - clis - - step: &infraFunctionsBuild - name: 'infra/infra-functions: Lint & build' - image: atlassian/default-image:4 - script: - - *initializeStep - - pnpm install - --include-workspace-root - --frozen-lockfile - --filter=infra-functions... - - pnpm nx run infra-functions:lint - - pnpm nx run infra-functions:build - caches: - - pnpminfrafunctions - - clis - # Internal steps - step: &internalDocsBuild @@ -513,8 +504,6 @@ definitions: pipelines: default: - parallel: - - step: *codecommitPush - - step: *webappTest - step: *webappBuild - step: *webappCoreTest @@ -535,7 +524,6 @@ pipelines: - step: *infraCoreBuild - step: *infraSharedBuild - - step: *infraFunctionsBuild - step: *internalDocsBuild - step: *internalStatusDashboardBuild @@ -544,8 +532,6 @@ pipelines: branches: master: - parallel: - - step: *codecommitPush - - step: *webappTest - step: *webappBuild - step: *webappCoreTest @@ -566,12 +552,16 @@ pipelines: - step: *infraCoreBuild - step: *infraSharedBuild - - step: *infraFunctionsBuild - step: *internalDocsBuild - step: *internalStatusDashboardBuild - step: *internalToolsBuild - - step: - name: Delete unused branches from CodeCommit - script: - - /bin/bash packages/internal/tools/scripts/clean-codebuild-branches.sh + + - step: + <<: *deploy-current-branch + name: Deploy to Production env + deployment: production + - step: + <<: *deploy-current-branch + name: Deploy to QA env + deployment: qa \ No newline at end of file diff --git a/packages/infra/infra-core/src/lib/env-config.ts b/packages/infra/infra-core/src/lib/env-config.ts index 620f065ac..11f5fba95 100644 --- a/packages/infra/infra-core/src/lib/env-config.ts +++ b/packages/infra/infra-core/src/lib/env-config.ts @@ -13,7 +13,6 @@ declare const process: { SB_LOAD_BALANCER_CERTIFICATE_ARN: string; SB_HOSTED_ZONE_ID: string; SB_HOSTED_ZONE_NAME: string; - SB_DEPLOY_BRANCHES: string; PROJECT_NAME: string; ENV_STAGE: string; VERSION: string; @@ -77,7 +76,6 @@ interface CIConfig { export interface EnvironmentSettings { appBasicAuth: string | null | undefined; - deployBranches: Array; domains: EnvConfigFileDomains; envStage: string; hostedZone: EnvConfigHostedZone; @@ -97,7 +95,6 @@ interface ConfigFileContent { } export interface EnvConfigFileContent { - deployBranches: Array; hostedZone: EnvConfigHostedZone; basicAuth: string | null | undefined; domains: EnvConfigFileDomains; @@ -163,7 +160,6 @@ async function readEnvConfig(envStage: string): Promise { id: process.env.SB_HOSTED_ZONE_ID ?? '', name: hostedZoneName, }, - deployBranches: process.env.SB_DEPLOY_BRANCHES?.split(',') ?? [], }; } @@ -192,7 +188,6 @@ export async function loadEnvSettings(): Promise { appBasicAuth: envConfig.basicAuth, hostedZone: envConfig.hostedZone, domains: envConfig.domains, - deployBranches: envConfig.deployBranches, webAppEnvVariables: { ...(config?.webAppConfig?.envVariables || {}), ...(envConfig?.webAppConfig?.envVariables || {}), diff --git a/packages/infra/infra-functions/.gitignore b/packages/infra/infra-functions/.gitignore deleted file mode 100644 index 9bfcccbd2..000000000 --- a/packages/infra/infra-functions/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# package directories -node_modules -jspm_packages - -# Serverless directories -.serverless -.esbuild diff --git a/packages/infra/infra-functions/deployment/triggerEntrypoint.ts b/packages/infra/infra-functions/deployment/triggerEntrypoint.ts deleted file mode 100644 index c6faaddb5..000000000 --- a/packages/infra/infra-functions/deployment/triggerEntrypoint.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { CodeBuild } from '@aws-sdk/client-codebuild'; -import globToRegExp from 'glob-to-regexp'; - -export const handler = async (event) => { - console.log('Start trigger entrypoint', { event }); - - const codebuild = new CodeBuild({ region: process.env.AWS_DEFAULT_REGION }); - const branches = process.env.DEPLOY_BRANCHES?.split(',') ?? []; - const projectName = process.env.PROJECT_NAME; - if (!projectName) { - throw 'Invalid project name'; - } - const { - detail: { referenceName }, - } = event; - // check if referenceName is in branches - const filteredBranches = branches - .map((branch) => ({ - branch, - regex: globToRegExp(branch, { globstar: true }), - })) - .filter((pattern) => pattern.regex.test(referenceName)); - - if (filteredBranches.length > 0) { - console.log('Trigger deploy:', referenceName, filteredBranches[0]); - await codebuild - .startBuild({ - projectName, - sourceVersion: referenceName, - }) - .then((response) => { - console.log('Codebuild started!', response); - }) - .catch((error) => { - console.log('Run codebuild error', error); - }); - } - - return { event, branches, filteredBranches }; -}; diff --git a/packages/infra/infra-functions/eslint.config.js b/packages/infra/infra-functions/eslint.config.js deleted file mode 100644 index aa676052d..000000000 --- a/packages/infra/infra-functions/eslint.config.js +++ /dev/null @@ -1,8 +0,0 @@ -const baseConfig = require('../../../eslint.config.js'); - -module.exports = [ - ...baseConfig, - { - ignores: ['node_modules/**/*', '.serverless/**/*', 'cdk.out/**/*'], - }, -]; diff --git a/packages/infra/infra-functions/infra-functions.conf.local.yml b/packages/infra/infra-functions/infra-functions.conf.local.yml deleted file mode 100644 index 7fd760ed2..000000000 --- a/packages/infra/infra-functions/infra-functions.conf.local.yml +++ /dev/null @@ -1,19 +0,0 @@ -stackName: "${env:PROJECT_NAME}-functions" - -iam: [] - -environment: {} - -vpc: {} - -TriggerMigrationsJob: - environment: {} - -esbuild: - bundle: true - minify: false - target: [ 'es2020' ] - sourcemap: false - sourcesContent: false - tsconfig: tsconfig.app.json - define: { 'require.resolve': undefined } diff --git a/packages/infra/infra-functions/infra-functions.conf.yml b/packages/infra/infra-functions/infra-functions.conf.yml deleted file mode 100644 index 2053e628f..000000000 --- a/packages/infra/infra-functions/infra-functions.conf.yml +++ /dev/null @@ -1,32 +0,0 @@ -stackName: "${self:custom.projectEnvName}-infra-functions" - -iam: - - Effect: "Allow" - Action: - - "codebuild:StartBuild" - Resource: - - "${self:custom.conf.entrypointCodeBuildProjectArn}" - -environment: - PROJECT_NAME: ${self:custom.projectEnvName} - ENVIRONMENT_NAME: ${self:provider.stage} - DEPLOY_BRANCHES: ${env:SB_DEPLOY_BRANCHES} - -vpc: - securityGroupIds: - - Fn::ImportValue: "${self:custom.projectEnvName}-lambdaSecurityGroupId" - subnetIds: - - Fn::ImportValue: "${self:custom.projectEnvName}-privateSubnetOneId" - - Fn::ImportValue: "${self:custom.projectEnvName}-privateSubnetTwoId" - -migrationsStateMachineArn: arn:aws:states:${aws:region}:${aws:accountId}:stateMachine:${env:PROJECT_NAME}-${env:ENV_STAGE}-migrations -entrypointCodeBuildProjectArn: arn:aws:codebuild:${aws:region}:${aws:accountId}:project/${self:custom.projectEnvName} - -esbuild: - bundle: true - minify: true - target: [ 'es2020' ] - sourcemap: true - sourcesContent: false - tsconfig: tsconfig.app.json - define: { 'require.resolve': undefined } diff --git a/packages/infra/infra-functions/package.json b/packages/infra/infra-functions/package.json deleted file mode 100644 index 203636bfa..000000000 --- a/packages/infra/infra-functions/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@sb/infra-functions", - "version": "4.0.0", - "description": "", - "main": "handler.js", - "author": "", - "license": "ISC", - "scripts": { - "diff": "echo 'no-diff-available'", - "remove": "sls remove" - }, - "dependencies": { - "glob-to-regexp": "^0.4.1" - }, - "devDependencies": { - "serverless": "^3.38.0", - "serverless-esbuild": "^1.48.0" - } -} diff --git a/packages/infra/infra-functions/project.json b/packages/infra/infra-functions/project.json deleted file mode 100644 index cbde58c33..000000000 --- a/packages/infra/infra-functions/project.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "infra-functions", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "packages/infra/infra-functions", - "targets": { - "invoke": { - "executor": "nx:run-commands", - "options": { - "cwd": "packages/infra/infra-functions", - "color": true, - "command": "node_modules/.bin/sls invoke --stage $ENV_STAGE" - } - }, - "build": { - "executor": "nx:run-commands", - "options": { - "cwd": "packages/infra/infra-functions", - "color": true, - "command": "pnpm sls package" - } - }, - "deploy": { - "executor": "nx:run-commands", - "options": { - "cwd": "packages/infra/infra-functions", - "color": true, - "command": "pnpm sls deploy" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": ["packages/infra/infra-functions/**/*.ts"] - } - } - }, - "tags": ["service"] -} diff --git a/packages/infra/infra-functions/serverless.yml b/packages/infra/infra-functions/serverless.yml deleted file mode 100644 index 1aecea041..000000000 --- a/packages/infra/infra-functions/serverless.yml +++ /dev/null @@ -1,33 +0,0 @@ -service: "${env:PROJECT_NAME}-infra-functions" - -frameworkVersion: '3' - -provider: - name: aws - runtime: nodejs18.x - versionFunctions: false - stage: "${env:ENV_STAGE}" - region: "${env:AWS_REGION, env:AWS_DEFAULT_REGION}" - stackName: ${self:custom.conf.stackName} - iamRoleStatements: ${self:custom.conf.iam} - environment: ${self:custom.conf.environment} - -functions: - TriggerEntrypoint: - handler: deployment/triggerEntrypoint.handler - - -custom: - esbuild: ${self:custom.conf.esbuild} - - projectEnvName: "${env:PROJECT_NAME}-${env:ENV_STAGE}" - conf: ${file(./${self:custom.confFile.${self:provider.stage}})} - confFile: - local: infra-functions.conf.local.yml - dev: infra-functions.conf.yml - qa: infra-functions.conf.yml - prod: infra-functions.conf.yml - - -plugins: - - serverless-esbuild diff --git a/packages/infra/infra-functions/tsconfig.app.json b/packages/infra/infra-functions/tsconfig.app.json deleted file mode 100644 index 7d148db97..000000000 --- a/packages/infra/infra-functions/tsconfig.app.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": ["node"] - }, - "exclude": ["**/*.spec.ts"], - "include": ["**/*.ts"] -} \ No newline at end of file diff --git a/packages/infra/infra-functions/tsconfig.json b/packages/infra/infra-functions/tsconfig.json deleted file mode 100644 index 79d6e8983..000000000 --- a/packages/infra/infra-functions/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - } - ] -} \ No newline at end of file diff --git a/packages/infra/infra-shared/src/index.ts b/packages/infra/infra-shared/src/index.ts index c0da811dc..1ee11688c 100644 --- a/packages/infra/infra-shared/src/index.ts +++ b/packages/infra/infra-shared/src/index.ts @@ -7,8 +7,6 @@ import { MainKmsKey } from './stacks/main/mainKmsKey'; import { MainRedisCluster } from './stacks/main/mainRedisCluster'; import { UsEastResourcesStack } from './stacks/usEastResources'; -export * from './lib/names'; - export { MainKmsKey, MainDatabase, diff --git a/packages/infra/infra-shared/src/lib/names.ts b/packages/infra/infra-shared/src/lib/names.ts deleted file mode 100644 index 8aa217a4b..000000000 --- a/packages/infra/infra-shared/src/lib/names.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { EnvironmentSettings } from '@sb/infra-core'; -import { Stack } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; - -export const getInfraFunctionArnByName = ( - scope: Construct, - functionName: string, - { envSettings }: { envSettings: EnvironmentSettings } -) => { - const stack = Stack.of(scope); - return [ - 'arn:aws:lambda', - stack.region, - stack.account, - 'function', - `${envSettings.projectName}-infra-functions-${envSettings.envStage}-${functionName}`, - ].join(':'); -}; diff --git a/packages/infra/infra-shared/src/stacks/ci/ciEntrypoint.ts b/packages/infra/infra-shared/src/stacks/ci/ciEntrypoint.ts index c532da378..81564e6f4 100644 --- a/packages/infra/infra-shared/src/stacks/ci/ciEntrypoint.ts +++ b/packages/infra/infra-shared/src/stacks/ci/ciEntrypoint.ts @@ -1,30 +1,25 @@ import { Construct } from 'constructs'; -import { aws_events_targets as targets } from 'aws-cdk-lib'; import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as codecommit from 'aws-cdk-lib/aws-codecommit'; -import * as codebuild from 'aws-cdk-lib/aws-codebuild'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as events from 'aws-cdk-lib/aws-events'; import * as cloudtrail from 'aws-cdk-lib/aws-cloudtrail'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { CfnOutput } from 'aws-cdk-lib'; import { EnvConstructProps, EnvironmentSettings } from '@sb/infra-core'; -import { getInfraFunctionArnByName } from '../../lib/names'; +import { GlobalResources } from '../global/resources'; -export interface CiEntrypointProps extends EnvConstructProps { - codeRepository: codecommit.IRepository; -} +export interface CiEntrypointProps extends EnvConstructProps {} export class CiEntrypoint extends Construct { public artifactsBucket: s3.Bucket; - private readonly codeBuildProject: codebuild.Project; - private readonly triggerFunction: lambda.IFunction; - private readonly onDeployCommitRule: events.Rule; - - static getArtifactsIdentifier(envSettings: EnvironmentSettings) { + static getArtifactsName(envSettings: EnvironmentSettings) { return `${envSettings.projectEnvName}-entrypoint`; } - static getArtifactsName(envSettings: EnvironmentSettings) { - return `${envSettings.projectEnvName}-entrypoint`; + private retrieveExternalCIUser() { + return iam.User.fromUserName( + this, + 'ExternalCiUser', + GlobalResources.getExternalCIUserName(), + ); } constructor(scope: Construct, id: string, props: CiEntrypointProps) { @@ -34,6 +29,9 @@ export class CiEntrypoint extends Construct { versioned: true, }); + const externalCiUser = this.retrieveExternalCIUser(); + this.artifactsBucket.grantWrite(externalCiUser); + const trail = new cloudtrail.Trail(this, 'CloudTrail'); trail.addS3EventSelector( [ @@ -47,81 +45,9 @@ export class CiEntrypoint extends Construct { }, ); - this.codeBuildProject = this.createBuildProject( - this.artifactsBucket, - props, - ); - - this.triggerFunction = lambda.Function.fromFunctionArn( - this, - 'TriggerLambda', - getInfraFunctionArnByName(this, 'TriggerEntrypoint', { - envSettings: props.envSettings, - }), - ); - this.onDeployCommitRule = props.codeRepository.onCommit('OnDeployCommit', { - target: new targets.LambdaFunction(this.triggerFunction), - }); - // add permissions resource-based permissions to imported lambda - new lambda.CfnPermission(this, 'AllowOnDeployCommit', { - action: 'lambda:InvokeFunction', - functionName: this.triggerFunction.functionName, - principal: 'events.amazonaws.com', - sourceArn: this.onDeployCommitRule.ruleArn, - }); - } - - private createBuildProject( - artifactsBucket: s3.Bucket, - props: CiEntrypointProps, - ) { - return new codebuild.Project(this, 'Project', { - projectName: props.envSettings.projectEnvName, - description: `Run this project to deploy ${props.envSettings.envStage} environment`, - buildSpec: this.createBuildSpec(), - cache: codebuild.Cache.local(codebuild.LocalCacheMode.SOURCE), - source: codebuild.Source.codeCommit({ repository: props.codeRepository }), - artifacts: codebuild.Artifacts.s3({ - identifier: CiEntrypoint.getArtifactsIdentifier(props.envSettings), - bucket: artifactsBucket, - name: CiEntrypoint.getArtifactsName(props.envSettings), - includeBuildId: false, - path: '', - }), - environment: { - buildImage: codebuild.LinuxBuildImage.STANDARD_7_0, - }, - environmentVariables: { - CI: { - type: codebuild.BuildEnvironmentVariableType.PLAINTEXT, - value: 'true', - }, - PROJECT_NAME: { - type: codebuild.BuildEnvironmentVariableType.PLAINTEXT, - value: props.envSettings.projectName, - }, - ENV_STAGE: { - type: codebuild.BuildEnvironmentVariableType.PLAINTEXT, - value: props.envSettings.envStage, - }, - }, - }); - } - - private createBuildSpec() { - return codebuild.BuildSpec.fromObject({ - version: '0.2', - phases: { - build: { - commands: [ - 'app_version=$(git describe --tags --first-parent --abbrev=11 --long --dirty --always)', - 'echo "VERSION=${app_version}" >> .env', - ], - }, - }, - artifacts: { - files: ['**/*'], - }, + new CfnOutput(this, 'ArtifactsBucketName', { + exportName: `${props.envSettings.projectEnvName}-artifactsBucketName`, + value: this.artifactsBucket.bucketName, }); } } diff --git a/packages/infra/infra-shared/src/stacks/ci/ciPipeline.ts b/packages/infra/infra-shared/src/stacks/ci/ciPipeline.ts index 5d6e14654..280685971 100644 --- a/packages/infra/infra-shared/src/stacks/ci/ciPipeline.ts +++ b/packages/infra/infra-shared/src/stacks/ci/ciPipeline.ts @@ -19,7 +19,6 @@ import { DocsCiConfig } from './ciDocs'; export interface CiPipelineProps extends EnvConstructProps { entrypointArtifactBucket: Bucket; backendRepository: ecr.IRepository; - codeRepository: cc.IRepository; } export class CiPipeline extends Construct { diff --git a/packages/infra/infra-shared/src/stacks/ci/stack.ts b/packages/infra/infra-shared/src/stacks/ci/stack.ts index 88fb17603..16b581b50 100644 --- a/packages/infra/infra-shared/src/stacks/ci/stack.ts +++ b/packages/infra/infra-shared/src/stacks/ci/stack.ts @@ -1,10 +1,8 @@ import { App, Stack, StackProps } from 'aws-cdk-lib'; import * as ecr from 'aws-cdk-lib/aws-ecr'; -import * as codecommit from 'aws-cdk-lib/aws-codecommit'; import { EnvConstructProps } from '@sb/infra-core'; import { GlobalECR } from '../global/resources/globalECR'; -import { GlobalCodeCommit } from '../global/resources/globalCodeCommit'; import { CiPipeline } from './ciPipeline'; import { CiEntrypoint } from './ciEntrypoint'; @@ -15,34 +13,23 @@ export class EnvCiStack extends Stack { super(scope, id, props); const backendRepository = this.retrieveBackendECRRepository(props); - const codeRepository = this.retrieveCodeRepository(props); const entrypoint = new CiEntrypoint(this, 'Entrypoint', { envSettings: props.envSettings, - codeRepository, }); new CiPipeline(this, 'PipelineConfig', { envSettings: props.envSettings, - codeRepository, backendRepository, entrypointArtifactBucket: entrypoint.artifactsBucket, }); } - private retrieveCodeRepository(props: EnvCiStackProps) { - return codecommit.Repository.fromRepositoryName( - this, - 'CodeRepository', - GlobalCodeCommit.getCodeRepositoryName(props.envSettings) - ); - } - private retrieveBackendECRRepository(props: EnvCiStackProps) { return ecr.Repository.fromRepositoryName( this, 'ECRBackendRepository', - GlobalECR.getBackendRepositoryName(props.envSettings) + GlobalECR.getBackendRepositoryName(props.envSettings), ); } } diff --git a/packages/infra/infra-shared/src/stacks/global/resources/globalCodeCommit.ts b/packages/infra/infra-shared/src/stacks/global/resources/globalCodeCommit.ts deleted file mode 100644 index bba4a311f..000000000 --- a/packages/infra/infra-shared/src/stacks/global/resources/globalCodeCommit.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Construct } from 'constructs'; -import { CfnOutput } from 'aws-cdk-lib'; -import * as codecommit from 'aws-cdk-lib/aws-codecommit'; -import * as iam from 'aws-cdk-lib/aws-iam'; -import { - EnvConstructProps, - EnvironmentSettings, -} from '@sb/infra-core'; - -export class GlobalCodeCommit extends Construct { - repository: codecommit.Repository; - - static getCodeRepositoryName(envSettings: EnvironmentSettings) { - return `${envSettings.projectName}-code`; - } - - static getCodeRepoUserNameOutputExportName(envSettings: EnvironmentSettings) { - return `${envSettings.projectName}-codeRepoUserName`; - } - - static getCodeRepoCloneUrlHttpOutputExportName( - envSettings: EnvironmentSettings - ) { - return `${envSettings.projectName}-codeRepoCloneUrlHttp`; - } - - constructor(scope: Construct, id: string, props: EnvConstructProps) { - super(scope, id); - - this.repository = new codecommit.Repository(this, 'CodeRepo', { - repositoryName: GlobalCodeCommit.getCodeRepositoryName(props.envSettings), - description: `${props.envSettings.projectName} code mirror repository used to source CodePipeline`, - }); - - const user = new iam.User(this, 'CodeRepoUser', { - userName: `${props.envSettings.projectName}-code`, - }); - this.repository.grantPullPush(user); - - new CfnOutput(this, 'CodeRepoUserName', { - exportName: GlobalCodeCommit.getCodeRepoUserNameOutputExportName( - props.envSettings - ), - value: user.userName, - }); - - new CfnOutput(this, 'CodeRepoCloneUrlHttp', { - exportName: GlobalCodeCommit.getCodeRepoCloneUrlHttpOutputExportName( - props.envSettings - ), - value: this.repository.repositoryCloneUrlHttp, - }); - } -} diff --git a/packages/infra/infra-shared/src/stacks/global/resources/index.ts b/packages/infra/infra-shared/src/stacks/global/resources/index.ts index 0f542a30b..5d254349c 100644 --- a/packages/infra/infra-shared/src/stacks/global/resources/index.ts +++ b/packages/infra/infra-shared/src/stacks/global/resources/index.ts @@ -3,12 +3,10 @@ import * as iam from 'aws-cdk-lib/aws-iam'; import { EnvConstructProps } from '@sb/infra-core'; import { GlobalECR } from './globalECR'; -import { GlobalCodeCommit } from './globalCodeCommit'; import { GlobalBuildSecrets } from './globalBuildSecrets'; export class GlobalResources extends Construct { ecr: GlobalECR; - codeCommit: GlobalCodeCommit; buildSecrets: GlobalBuildSecrets; externalCiUser: iam.User; @@ -16,10 +14,13 @@ export class GlobalResources extends Construct { super(scope, id); this.ecr = new GlobalECR(this, 'ECRGlobal', props); - this.codeCommit = new GlobalCodeCommit(this, 'CodeCommit', props); this.buildSecrets = new GlobalBuildSecrets(this, 'GlobalBuildSecrets'); this.externalCiUser = new iam.User(this, 'ExternalCiUser', { - userName: 'external-ci', + userName: GlobalResources.getExternalCIUserName(), }); } + + static getExternalCIUserName() { + return 'external-ci'; + } } diff --git a/packages/internal/cli/src/commands/ci/create-credentials.ts b/packages/internal/cli/src/commands/ci/create-credentials.ts deleted file mode 100644 index 969f92070..000000000 --- a/packages/internal/cli/src/commands/ci/create-credentials.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { - CloudFormationClient, - DescribeStacksCommand, -} from '@aws-sdk/client-cloudformation'; -import { - CreateServiceSpecificCredentialCommand, - IAMClient, -} from '@aws-sdk/client-iam'; -import { indexBy, prop } from 'ramda'; -import * as URL from 'url'; - -import { initConfig } from '../../config/init'; -import { BaseCommand } from '../../baseCommand'; - -type GetOutputsFromGlobalStackOptions = { - stackName: string; -}; -async function getOutputsFromGlobalStack({ - stackName, -}: GetOutputsFromGlobalStackOptions) { - const client = new CloudFormationClient(); - const describeStackResult = await client.send( - new DescribeStacksCommand({ StackName: stackName }) - ); - const stack = describeStackResult?.Stacks?.[0]; - return indexBy(prop('ExportName'), stack?.Outputs ?? []); -} - -type CreateCredentialsOptions = { - repoUserName: string; -}; -function createCredentials({ repoUserName }: CreateCredentialsOptions) { - const client = new IAMClient(); - - return client.send( - new CreateServiceSpecificCredentialCommand({ - UserName: repoUserName, - ServiceName: 'codecommit.amazonaws.com', - }) - ); -} - -export default class CiCreateCredentials extends BaseCommand< - typeof CiCreateCredentials -> { - static description = - 'Create CI/CD repository credentials. They can be used in Bitbucket, Github, Gitlab, etc ' + - 'to push code changes to CodeCommit'; - - static examples = [`$ <%= config.bin %> <%= command.id %>`]; - - static flags = {}; - - async run(): Promise { - const { projectName } = await initConfig(this, { requireAws: true }); - - const globalStackOutputs = await getOutputsFromGlobalStack({ - stackName: `${projectName}-GlobalStack`, - }); - const { OutputValue: repoUserName } = - globalStackOutputs[`${projectName}-codeRepoUserName`] ?? {}; - const { OutputValue: repoUrl } = - globalStackOutputs[`${projectName}-codeRepoCloneUrlHttp`] ?? {}; - - if (!repoUserName || !repoUrl) { - this.error('Failed to fetch repository username and URL'); - } - - const response = await createCredentials({ repoUserName }); - - if (!response.ServiceSpecificCredential) { - this.error('Failed to create service specific credentials'); - } - - const { ServicePassword: password, ServiceUserName: userName } = - response.ServiceSpecificCredential; - - const urlParts = URL.parse(repoUrl); - urlParts.auth = `${userName}:${password}`; - - this.log(URL.format(urlParts)); - } -} diff --git a/packages/internal/cli/src/commands/ci/get-artifacts-bucket.ts b/packages/internal/cli/src/commands/ci/get-artifacts-bucket.ts new file mode 100644 index 000000000..e65c6871e --- /dev/null +++ b/packages/internal/cli/src/commands/ci/get-artifacts-bucket.ts @@ -0,0 +1,50 @@ +import { + CloudFormationClient, + DescribeStacksCommand, +} from '@aws-sdk/client-cloudformation'; +import { indexBy, prop } from 'ramda'; + +import { initConfig } from '../../config/init'; +import { BaseCommand } from '../../baseCommand'; + +type GetOutputsFromStackOptions = { + stackName: string; +}; +async function getOutputsFromStack({ stackName }: GetOutputsFromStackOptions) { + const client = new CloudFormationClient(); + const describeStackResult = await client.send( + new DescribeStacksCommand({ StackName: stackName }), + ); + const stack = describeStackResult?.Stacks?.[0]; + return indexBy(prop('ExportName'), stack?.Outputs ?? []); +} + +export default class CiGetArtifactsBucket extends BaseCommand< + typeof CiGetArtifactsBucket +> { + static description = + 'Returns name of the bucket that external-ci user can upload code artifact to trigger a deployment'; + + static examples = [`$ <%= config.bin %> <%= command.id %>`]; + + static flags = {}; + + async run(): Promise { + const { projectEnvName } = await initConfig(this, { + requireAws: true, + skipERCLogin: true, + }); + + const globalStackOutputs = await getOutputsFromStack({ + stackName: `${projectEnvName}-CiStack`, + }); + const { OutputValue: artifactsBucketName } = + globalStackOutputs[`${projectEnvName}-artifactsBucketName`] ?? {}; + + if (!artifactsBucketName) { + this.error('Failed to fetch bucket name'); + } + + this.log(`Bucket name: ${artifactsBucketName}`); + } +} diff --git a/packages/internal/cli/src/commands/infra/deploy.ts b/packages/internal/cli/src/commands/infra/deploy.ts index c6357051d..00b42e943 100644 --- a/packages/internal/cli/src/commands/infra/deploy.ts +++ b/packages/internal/cli/src/commands/infra/deploy.ts @@ -9,7 +9,6 @@ enum StackName { Global = 'global', Main = 'main', Db = 'db', - Functions = 'functions', Ci = 'ci', Components = 'components', } @@ -66,9 +65,6 @@ export default class InfraDeploy extends BaseCommand { if (!args.stackName || args.stackName === StackName.Db) { await runCommand('pnpm', ['nx', 'run', `infra-shared:${verb}:db`]); } - if (!args.stackName || args.stackName === StackName.Functions) { - await runCommand('pnpm', ['nx', 'run', `infra-functions:${verb}`]); - } if (!args.stackName || args.stackName === StackName.Ci) { await runCommand('pnpm', ['nx', 'run', `infra-shared:${verb}:ci`]); } diff --git a/packages/internal/cli/src/config/aws.ts b/packages/internal/cli/src/config/aws.ts index de4fa0c26..af7ce8fa2 100644 --- a/packages/internal/cli/src/config/aws.ts +++ b/packages/internal/cli/src/config/aws.ts @@ -20,6 +20,7 @@ const tracer = trace.getTracer('config:aws'); type LoadAWSCredentialsOptions = { envStage: string; validateEnvStageVariables: boolean; + skipERCLogin?: boolean; }; async function loadStageEnv( @@ -132,8 +133,10 @@ export const initAWS = async ( options.validateEnvStageVariables, ); + const { skipERCLogin = false } = options; + const awsRegion = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION; - if (awsAccountId && awsRegion) { + if (awsAccountId && awsRegion && !skipERCLogin) { await loginToECR(context, { awsAccountId, awsRegion, diff --git a/packages/internal/cli/src/config/env.ts b/packages/internal/cli/src/config/env.ts index a87ecd497..d2409a02a 100644 --- a/packages/internal/cli/src/config/env.ts +++ b/packages/internal/cli/src/config/env.ts @@ -93,11 +93,6 @@ export async function validateStageEnv() { desc: 'A domain used to static assets delivery', example: 'cdn.example.com', }), - SB_DEPLOY_BRANCHES: envalid.str({ - default: '', - desc: 'A comma separated list of branches that will trigger automatic deployment of the environment', - example: 'master,main', - }), SB_BASIC_AUTH: envalid.str({ default: '', desc: 'Username and password separated by colon (":") used to protect website form unauthorized access', diff --git a/packages/internal/cli/src/config/init.ts b/packages/internal/cli/src/config/init.ts index a1ba83ead..a835269b6 100644 --- a/packages/internal/cli/src/config/init.ts +++ b/packages/internal/cli/src/config/init.ts @@ -2,7 +2,12 @@ import { Command } from '@oclif/core'; import { color } from '@oclif/color'; import { trace } from '@opentelemetry/api'; -import { ENV_STAGE_LOCAL, getRootPath, loadVersionEnv, disableNxEnvFiles } from './env'; +import { + ENV_STAGE_LOCAL, + getRootPath, + loadVersionEnv, + disableNxEnvFiles, +} from './env'; import { initAWS } from './aws'; import { loadEnvStage } from './storage'; @@ -12,6 +17,7 @@ type InitConfigOptions = { requireAws?: boolean | 'allow-local'; validateEnvStageVariables?: boolean; requireLocalEnvStage?: boolean; + skipERCLogin?: boolean; }; export const initConfig = async ( @@ -20,6 +26,7 @@ export const initConfig = async ( requireAws = false, validateEnvStageVariables = true, requireLocalEnvStage = false, + skipERCLogin = false, }: InitConfigOptions, ) => { return tracer.startActiveSpan('initConfig', async (span) => { @@ -57,6 +64,7 @@ Please call \`saas aws set-env local\` first or open a new terminal.`, const awsMetadata = await initAWS(context, { envStage, validateEnvStageVariables, + skipERCLogin, }); awsAccountId = awsMetadata.awsAccountId; diff --git a/packages/internal/docs/docs/aws/cicd/auto-deploy.mdx b/packages/internal/docs/docs/aws/cicd/auto-deploy.mdx index b7971aae4..2c8df685b 100644 --- a/packages/internal/docs/docs/aws/cicd/auto-deploy.mdx +++ b/packages/internal/docs/docs/aws/cicd/auto-deploy.mdx @@ -2,50 +2,30 @@ title: Configure Automatic Deployments --- -import useBaseUrl from '@docusaurus/useBaseUrl'; - -Each deployed environment comes with a preconfigured CI/CD implemented with AWS CodeCommit, AWS CodeBuild, -and AWS CodePipeline. The general idea of the deployment is for the user to push the code to a `master` branch of the -CodeCommit repository created by the Ci CDK Stack. +Each deployed environment comes with a preconfigured CI/CD pipeline using AWS S3 bucket, AWS CodeBuild, and AWS +CodePipeline. The general idea of the deployment is for the user to upload zipped code artifact to the S3 bucket, +triggering CodeBuild and CodePipeline to execute the deployment. Artifacts are prepared by the CI pipeline +(GitHub Actions or Bitbucket Pipelines). ## Automatically synchronize external repository -### Get authenticated repository URL - -AWS Boilerplate generates a user for you that has minimal permissions required for pushing code to the CodeCommit -repository. In order to implement a synchronization logic we need to get a repository URL and credentials of the user. -You can create both using a following command: - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import CodeBlock from '@theme/CodeBlock'; - - - - - saas aws est-env qa -
- saas ci create-credentials | pbcopy -
-
- - - saas aws est-env qa -
- saas ci create-credentials | xclip -sel clip -
-
-
- -The result will be copied to your clipboard. Make sure you save it in some secure place. You can only create two such -URLs so if something goes wrong just open `external-ci` user's page in AWS IAM's web panel and delete appropriate key. - -### Get authentication credentials for ECR repository - -All CI pipeline builds are running within a docker image; some services, such as web app, utilise a base image that -contain preinstalled packages to speed up the whole process. Such base images automatically update on every -push to a `master` branch, so they are up to date with your code, and you don't have to really do anything besides -providing access to pull them! +### Get artifacts bucket name + +SaaS Boilerplate generates a user for you that has minimal permissions required for uploading code artifact to the S3 +bucket. In order to implement a synchronization logic we need to get a bucket name and credentials of the user. +To get the bucket name use the following command: +```shell +pnpm saas ci get-artifacts-bucket +``` + +Alternatively, you can find the bucket name in the AWS console under the source of the AWS CodePipeline of the +environment. + +### Get authentication credentials for CI AWS user + +In order to upload the code artifact to the S3 bucket, the CI pipeline needs to authenticate with AWS. SaaS Boilerplate +generates a `external-ci` user for you that has minimal permissions required for uploading code artifact to the S3 +bucket. To get the credentials of the user follow these steps: 1. Open `IAM` service in web console. @@ -61,11 +41,9 @@ providing access to pull them! 1. Open `Settings` page of your repository. -2. Go to `Secrets` subpage. +2. Go to `Security` > `Secrets and variables` > `Actions` subpage. -3. Create following secrets: - - - `CODE_COMMIT_REPO` – [authenticated repository URL](#get-authenticated-repository-url) +3. Create following secrets under `Repository secrets`: - `AWS_ACCESS_KEY_ID` – [external-ci](#get-authentication-credentials-for-ecr-repository) user access key id @@ -73,33 +51,56 @@ providing access to pull them! - `AWS_DEFAULT_REGION` – set to a region to which your system is deployed -4. Test by pushing some code to your Github repository. After couple of seconds the code should be synchronized in CodeCommit. +4. Go to `Code and automation` > `Environments` subpage under repository settings. Add you environment and select it. + + :::info + You can learn more about environments on GitHub [here](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment). + ::: + +5. Create following secrets under `Environment secrets`: + + - `SB_CI_ARTIFACTS_BUCKET` – [artifacts bucket name](#get-artifacts-bucket-name) + +6. Create following secrets under `Environment variables`: + + - `SB_DEPLOY_STAGE` – set to the name of the environment + +7. Edit the `.github/workflows/deploy-*.yml` files to match your environments. + + :::info + Learn more about deployments using GitHub Actions [here](https://docs.github.com/en/actions/use-cases-and-examples/deploying/deploying-with-github-actions). + ::: ### Configure Bitbucket 1. Open `Repository Settings` page of your repository. -2. Go to `Pipeline / Settings` sub-page. +2. Go to `Pipelines` > `Settings` sub-page. 3. Enable Bitbucket Pipelines. -4. Go to `Pipeline / Repository variables` sub-page. +4. Go to `Pipelines` > `Repository variables` sub-page. 5. Create following variables: - - `CODE_COMMIT_REPO` – set value to - [authenticated repository URL](#get-authenticated-repository-url) - - `AWS_ACCESS_KEY_ID` – `external-ci` user access key id - `AWS_SECRET_ACCESS_KEY` – `external-ci` user access key secret - `AWS_DEFAULT_REGION` – set to a region to which your system is deployed -6. Test by pushing some code to your BitBucket repository. After couple of seconds the code should be synchronized in CodeCommit. + :::info + Learn more about repository variables on Bitbucket [here](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/#Repository-variables). + ::: + +6. Go to `Pipelines` > `Deployments` sub-page. And configure your deployment environment. + + :::info + Learn more about deployments on Bitbucket [here](https://support.atlassian.com/bitbucket-cloud/docs/deployments/). + ::: + +7. Create following variables for the environment: -## Trigger deployment automatically + - `SB_CI_ARTIFACTS_BUCKET` – [artifacts bucket name](#get-artifacts-bucket-name) -If you want a branch to be deployed automatically for every pushed commit the only thing you need to do is to name this branch -in your environment configuration file using `SB_DEPLOY_BRANCHES` environment variable. Check out the -[environment docs](/api-reference/env-files#envenv-id) for more details. + - `SB_DEPLOY_ENVIRONMENT_NAME` - set to the name of the full project environment name (`saas-qa` for example) \ No newline at end of file diff --git a/packages/internal/docs/docs/aws/cicd/trigger-cicd-manually.mdx b/packages/internal/docs/docs/aws/cicd/trigger-cicd-manually.mdx index 6a377a449..7df7b06cd 100644 --- a/packages/internal/docs/docs/aws/cicd/trigger-cicd-manually.mdx +++ b/packages/internal/docs/docs/aws/cicd/trigger-cicd-manually.mdx @@ -1,20 +1,18 @@ # Trigger CI/CD deployment manually -You can also trigger a deployment manually using AWS Console! +You can also trigger a deployment manually using GitHub Actions. -1. Navigate to `CodeBuild` service. +### Run GitHub Actions manually -2. Find the entrypoint project named `-` (e.g. `mypro-qa`) and navigate to it by pressing - its name. +If you have [GitHub Actions configured](./auto-deploy) in your repository, you can trigger a deployment manually. -3. Press the "Start build with overrides" button. +1. Go to the GitHub repository and navigate to the "Actions" tab. -4. Select the source branch and optionally a commit ID. +2. Select `Deploy to {ENVIRONMENT}` workflow. -5. Submit by pressing "Start build" button. - -6. The Pipeline should start in a few seconds. +3. Press the "Run workflow" button. :::info -You can also build and deploy apps from your local device. [Read more](../deploy-to-aws/run-deployment-commands#deploy-applications-code) +Learn how to run GitHub Actions manually from the +[documentation](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/manually-running-a-workflow). ::: diff --git a/packages/internal/docs/docs/aws/deploy-to-aws/create-env-stage-in-repo.mdx b/packages/internal/docs/docs/aws/deploy-to-aws/create-env-stage-in-repo.mdx index f807814a5..fd6d58119 100644 --- a/packages/internal/docs/docs/aws/deploy-to-aws/create-env-stage-in-repo.mdx +++ b/packages/internal/docs/docs/aws/deploy-to-aws/create-env-stage-in-repo.mdx @@ -137,15 +137,6 @@ if this isn't a production environment. pnpm saas aws set-var SB_BASIC_AUTH username:password ``` -### \[Optional\] Configure automatic deployment for selected branches - -If you want a deployment to be stared automatically when a commit is pushed to certain branch you can list them in the -`SB_DEPLOY_BRANCHES` variable. - -```shell -pnpm saas aws set-var SB_DEPLOY_BRANCHES master -``` - ### \[Optional\] Set tools env variables The `tools` package during CI deployment is responsible for uploading the information of the version of deployed diff --git a/packages/internal/docs/sidebars.js b/packages/internal/docs/sidebars.js index 9343edfd4..eabbc8ede 100644 --- a/packages/internal/docs/sidebars.js +++ b/packages/internal/docs/sidebars.js @@ -193,8 +193,8 @@ module.exports = { id: 'aws/cicd/index', }, items: [ - 'aws/cicd/trigger-cicd-manually', 'aws/cicd/auto-deploy', + 'aws/cicd/trigger-cicd-manually', 'aws/cicd/configure-cicd-notifications', 'aws/cicd/setup-docker-hub', ], diff --git a/packages/internal/status-dashboard/project.json b/packages/internal/status-dashboard/project.json index dd22d0384..2f8a5da67 100644 --- a/packages/internal/status-dashboard/project.json +++ b/packages/internal/status-dashboard/project.json @@ -71,7 +71,7 @@ "deploy": { "executor": "nx:run-commands", "options": { - "cwd": "packages/infra/infra-functions", + "cwd": "packages/internal/status-dashboard", "color": true, "command": "pnpm cdk deploy *StatusDashboardStack" } @@ -79,7 +79,7 @@ "diff": { "executor": "nx:run-commands", "options": { - "cwd": "packages/infra/infra-functions", + "cwd": "packages/internal/status-dashboard", "color": true, "command": "pnpm cdk diff *StatusDashboardStack" } diff --git a/packages/internal/tools/scripts/clean-codebuild-branches.sh b/packages/internal/tools/scripts/clean-codebuild-branches.sh deleted file mode 100755 index 0a643fd5f..000000000 --- a/packages/internal/tools/scripts/clean-codebuild-branches.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -eu - -git remote add codecommit "$CODE_COMMIT_REPO" - -git ls-remote codecommit --heads 'refs/heads/*' | while read line; do - branch_name=$(echo "${line}" | awk '{print $2}' | sed s/"refs\/heads\/"//) - origin_branch=$(git ls-remote origin --heads "refs/heads/${branch_name}") - - if [ -z "${origin_branch}" ] ; then - echo "Deleting branch: $branch_name" - git branch -D codecommit "$branch_name" - else - echo "Keeping branch: $branch_name" - fi -done diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af5b6d5e3..de7270d8d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -372,19 +372,6 @@ importers: specifier: ^3.10.1 version: 3.10.1 - packages/infra/infra-functions: - dependencies: - glob-to-regexp: - specifier: ^0.4.1 - version: 0.4.1 - devDependencies: - serverless: - specifier: ^3.38.0 - version: 3.38.0(encoding@0.1.13) - serverless-esbuild: - specifier: ^1.48.0 - version: 1.48.0(esbuild@0.21.4) - packages/infra/infra-shared: devDependencies: '@aws-cdk/aws-apigatewayv2-alpha': @@ -1221,6 +1208,7 @@ packages: '@aws-cdk/aws-apigatewayv2-alpha@2.66.0-alpha.0': resolution: {integrity: sha512-ekFNe220j0HJaeC0BntrZoIoO8oRWfaEDowkTVoCKzBaZcPrRoMQz6b6KjedZHd+zKh0HaYRZSqLrunzcfx0CA==} engines: {node: '>= 14.15.0'} + deprecated: This package has been stabilized and moved to aws-cdk-lib peerDependencies: aws-cdk-lib: ^2.66.0 constructs: ^10.0.0 @@ -4601,10 +4589,12 @@ packages: '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -4612,6 +4602,7 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead '@humanwhocodes/retry@0.3.0': resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} @@ -7656,6 +7647,7 @@ packages: abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -9664,6 +9656,7 @@ packages: domexception@4.0.0: resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead domhandler@3.3.0: resolution: {integrity: sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==} @@ -10984,6 +10977,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported global-dirs@3.0.1: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} @@ -11518,6 +11512,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.3: resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} @@ -15335,6 +15330,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true ripemd160@2.0.2: @@ -15577,16 +15573,6 @@ packages: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} - serverless-esbuild@1.48.0: - resolution: {integrity: sha512-KHos/HBbJbH/ftsguNiX/jivj4rKHdyMg+ciMCxTqWndgJv3Wwg8POGZqSy9fr+S/b748PTwIfxYYFEiEVpXUg==} - engines: {node: '>=14.18.0'} - peerDependencies: - esbuild: '>=0.8 <0.20' - esbuild-node-externals: ^1.0.0 - peerDependenciesMeta: - esbuild-node-externals: - optional: true - serverless-esbuild@1.52.1: resolution: {integrity: sha512-sTEVoJMFO213SJyEEvW4yf3FbxRkn3jZgp/bA2zOguVXv2veNptVzo3Cmn7pZVIrjv8HKH6uEq/E65bJhOO5yA==} engines: {node: '>=14.18.0'} @@ -16167,7 +16153,7 @@ packages: superagent@7.1.6: resolution: {integrity: sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g==} engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please downgrade to v7.1.5 if you need IE/ActiveXObject support OR upgrade to v8.0.0 as we no longer support IE and published an incorrect patch version (see https://github.com/visionmedia/superagent/issues/1731) + deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} @@ -18599,7 +18585,7 @@ snapshots: - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-ini@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)': + '@aws-sdk/credential-provider-ini@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))': dependencies: '@aws-sdk/client-sts': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0) '@aws-sdk/credential-provider-env': 3.577.0 @@ -18639,7 +18625,7 @@ snapshots: dependencies: '@aws-sdk/credential-provider-env': 3.577.0 '@aws-sdk/credential-provider-http': 3.577.0 - '@aws-sdk/credential-provider-ini': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0) + '@aws-sdk/credential-provider-ini': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)) '@aws-sdk/credential-provider-process': 3.577.0 '@aws-sdk/credential-provider-sso': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0) '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0) @@ -38717,23 +38703,6 @@ snapshots: transitivePeerDependencies: - supports-color - serverless-esbuild@1.48.0(esbuild@0.21.4): - dependencies: - acorn: 8.10.0 - acorn-walk: 8.2.0 - anymatch: 3.1.3 - archiver: 5.3.2 - bestzip: 2.2.1 - chokidar: 3.5.3 - esbuild: 0.21.4 - execa: 5.1.1 - fp-ts: 2.16.1 - fs-extra: 11.2.0 - globby: 11.1.0 - p-map: 4.0.0 - ramda: 0.28.0 - semver: 7.5.4 - serverless-esbuild@1.52.1(esbuild@0.21.4): dependencies: acorn: 8.11.3