From 5f6b4c0fb1ec91d96f527801f67878328f5a830e Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 09:21:31 +0100 Subject: [PATCH 01/35] feat: story/GD-40 unit tests added --- .eslintignore | 7 ++ .github/workflows/build.yml | 214 +++++++++++++++++++++++++++++++++ .gitignore | 4 +- .husky/commit-msg | 4 + .husky/pre-commit | 4 + .husky/pre-push | 4 + app.ts | 82 ------------- aws-toolkit-tsconfig.json | 12 -- babel.config.js | 6 + commitlint.config.js | 9 ++ jest.config.js | 194 ++++++++++++++++++++++++++++++ package.json | 44 ++++--- src/handler.ts | 69 +++++++++++ src/service/s3-provider.ts | 85 +++++++++++++ tests/unit/handler.test.ts | 212 ++++++++++++++++++++++++++++++++ tests/unit/s3-provider.test.ts | 22 ++++ 16 files changed, 861 insertions(+), 111 deletions(-) create mode 100644 .eslintignore create mode 100644 .github/workflows/build.yml create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .husky/pre-push delete mode 100644 app.ts delete mode 100644 aws-toolkit-tsconfig.json create mode 100644 babel.config.js create mode 100644 commitlint.config.js create mode 100644 jest.config.js create mode 100644 src/handler.ts create mode 100644 src/service/s3-provider.ts create mode 100644 tests/unit/handler.test.ts create mode 100644 tests/unit/s3-provider.test.ts diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..6eb9bdc --- /dev/null +++ b/.eslintignore @@ -0,0 +1,7 @@ +node_modules/** +built/** +dist/** +out/** +aws-toolkit-ts-output/** +.storybook/** +storybook-static diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f53cae0 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,214 @@ +name: Build + +on: + push: + branches: [ "main", release/*, story/*, task/* ] + paths: + - 'docs-*/**' + - 'pom.xml' + - '.github/workflows/**' + pull_request: + # branches: [ "main" ] + types: [opened, synchronize, reopened] + paths: + - 'docs-*/**' + - 'pom.xml' + workflow_dispatch: + +env: + API_DOCKER_REGISTRY: ghcr.io + API_DOCKER_IMAGE_NAME: ${{ github.repository_owner }}/docs-func-aws-template-list-v1 + +permissions: + pull-requests: read # allows SonarCloud to decorate PRs with analysis results + +jobs: + build_job: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Install node v18 + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Rebuild local npm repository from cache + uses: actions/cache@v3 + with: + path: | + ~/node_modules + key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Yarn install + run: yarn install + + - name: Yarn build + run: yarn build + + test_job: + name: Run tests + needs: build_job + runs-on: ubuntu-latest + environment: ci + + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Rebuild local npm repository from cache + uses: actions/cache@v3 + with: + path: | + ~/node_modules + key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Yarn install + run: yarn install + + - name: Build project + run: yarn build + + - name: Run tests + env: + repository.template.provider.aws.s3.bucketname: ${{ env.TEST_AWS_BUCKETNAME }} + repository.template.provider.aws.s3.region: ${{ env.TEST_AWS_REGION }} + repository.template.provider.aws.s3.prefix: ${{ env.TEST_AWS_BUCKET_PREFIX }} + + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: yarn test + + analyze_job: + name: Code analysis + needs: + - build_job + - test_job + runs-on: ubuntu-latest + environment: ci + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Rebuild local npm repository from cache + uses: actions/cache@v3 + with: + path: | + ~/node_modules + key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Yarn install + run: yarn install + + - name: Build project + run: yarn build + + - name: Run tests + env: + repository.template.provider.aws.s3.bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} + repository.template.provider.aws.s3.region: ${{ secrets.TEST_AWS_REGION }} + repository.template.provider.aws.s3.prefix: 'testfiles/templates' + + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: yarn test -- --coverage + + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets. SONARCLOUD_TOKEN }} + + docker_build_job: + name: Containerize + needs: + - analyze_job + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by gitHub/codeql-action/upload-sarif to get the Action run status + packages: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Rebuild local npm repository from cache + uses: actions/cache@v3 + with: + path: | + ~/node_modules + key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Yarn install + run: yarn install + + - name: Build project + run: yarn build + +# - name: Build the Docker image +# working-directory: ./docs-generator-api +# run: docker build -t ${{ env.API_DOCKER_REGISTRY }}/${{ env.API_DOCKER_IMAGE_NAME }} --file Dockerfile . + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.API_DOCKER_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v2 + with: + images: ${{ env.API_DOCKER_REGISTRY }}/${{ env.API_DOCKER_IMAGE_NAME }} + tags: | + type=sha + + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: ./docs-generator-api + push: true +# push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Pull back the Docker image for the Trivy scan + working-directory: ./docs-generator-api + run: docker pull ${{ steps.meta.outputs.tags }} + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@7b7aa264d83dc58691451798b4d117d53d21edfe + with: + image-ref: '${{ steps.meta.outputs.tags }}' + format: 'template' + template: '@/contrib/sarif.tpl' + output: 'trivy-results.sarif' + severity: 'CRITICAL,HIGH' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: 'trivy-results.sarif' + diff --git a/.gitignore b/.gitignore index 8ec346b..acba38c 100644 --- a/.gitignore +++ b/.gitignore @@ -83,12 +83,10 @@ dist # SAM directories .aws-sam aws-toolkit-ts-output +aws-toolkit-tsconfig.json built gen -.husky - - /src/.openapi-generator/ /src/api/ /src/model/ diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..fe4c17a --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install commitlint --edit "" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..d37daa0 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install lint-staged diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 0000000..0130859 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install validate-branch-name diff --git a/app.ts b/app.ts deleted file mode 100644 index ece95f9..0000000 --- a/app.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * - * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format - * @param {Object} event - API Gateway Lambda Proxy Input Format - * - * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html - * @param {Object} context - * - * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html - * @returns {Object} object - API Gateway Lambda Proxy Output Format - * - */ - -import {APIGatewayEvent, APIGatewayProxyResultV2, Context} from 'aws-lambda'; -import {GetTemplatesResponse, TemplateDocument} from './src/api'; - -import {S3} from "aws-sdk"; - -const s3 = new S3({ region: process.env["repository.template.provider.aws.s3.region"]! }); - -export const lambdaHandler = async (event: APIGatewayEvent, context: Context): Promise => { - console.log(`Event: ${JSON.stringify(event, null, 2)}`); - console.log(`Context: ${JSON.stringify(context, null, 2)}`); - - const bucketName = process.env["repository.template.provider.aws.s3.bucketname"]!; - const prefix = process.env["repository.template.provider.aws.s3.prefix"]!; - - console.debug(`Listing templates from bucket: s3://${bucketName}/${prefix}...`) - - const templateList: Array = await listFilesFromS3 ({ - Bucket: bucketName, - Prefix: prefix - }, - [] - ); - - const resultObjects: GetTemplatesResponse = { - contents: templateList - }; - - return { - statusCode: 200, - body: JSON.stringify(resultObjects), - }; -}; - -export async function listFilesFromS3 (s3Request: S3.ListObjectsV2Request, - allKeys: Array): Promise> { - - console.info("Retrieving bucket contexts...", JSON.stringify(s3Request, null, 2)); - - try { - const data: S3.ListObjectsV2Output = await s3.listObjectsV2(s3Request).promise(); - let contents = data.Contents; - - console.debug("Items: ", data.KeyCount); - - if (contents) { - contents.forEach(function (content) { - if (content.Key) { - const actDoc: TemplateDocument = { - templateName: content.Key - } - allKeys.push(actDoc); - } - }); - } - - if (data.IsTruncated) { - s3Request.ContinuationToken = data.NextContinuationToken; - console.log("get further list..."); - return listFilesFromS3(s3Request, allKeys); - } else { - console.trace("Retrieved items: ", JSON.stringify(allKeys)); - - return allKeys!; - } - } catch (error) { - console.log(error); - return []; - } -} diff --git a/aws-toolkit-tsconfig.json b/aws-toolkit-tsconfig.json deleted file mode 100644 index 4c2cebd..0000000 --- a/aws-toolkit-tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions" : { - "target" : "es6", - "module" : "commonjs", - "sourceMap" : true, - "outDir" : "C:\\projects\\videki\\docs-func-aws-template-list-v2\\aws-toolkit-ts-output", - "rootDir" : ".", - "sourceRoot" : "C:\\projects\\videki\\docs-func-aws-template-list-v2", - "typeRoots" : [ "C:\\projects\\videki\\docs-func-aws-template-list-v2\\node_modules\\@types" ], - "types" : [ "node" ] - } -} \ No newline at end of file diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..e7118c3 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + ['@babel/preset-env', {targets: {node: 'current'}}], + '@babel/preset-typescript', + ], +}; diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..b09742f --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,9 @@ + +module.exports = { + + extends: ["@commitlint/config-conventional"], + + rules: { + "scope-case": [2, "always", ["lower-case", "kebab-case"]] + } +}; diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..5ce5e9f --- /dev/null +++ b/jest.config.js @@ -0,0 +1,194 @@ +/* + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +module.exports = { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "C:\\Users\\Levente\\AppData\\Local\\Temp\\jest", + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: false, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "babel", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: undefined, + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + testMatch: [ + "**/tests/unit/**/*.test.ts" + ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "\\\\node_modules\\\\", + // "\\.pnp\\.[^\\\\]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; diff --git a/package.json b/package.json index bc572f5..a2684c6 100644 --- a/package.json +++ b/package.json @@ -2,40 +2,49 @@ "name": "docs-func-aws-template-list-v1", "version": "0.0.1", "private": true, - "license": "UNLICENSED", + "license": "Apache-2.0", "description": "Document engine template list", "author": "Document engine contributors", "keywords": [ "yarn" ], + "main": "src/handler.ts", "scripts": { - "build": "openapi-generator-cli generate -g typescript-node --global-property model -i docs/document-api-template-list-v1.yaml -o src && tsc", - "test": "npm run build && node built/app.js", + "prepare": "husky install", + "clean": "rimraf src/gen/*", + "generate-api": "openapi-generator-cli generate -g typescript-node -i docs/document-api-template-list-v1.yaml -o src/gen", + "generate-remove-unwanted": "rimraf src/gen/git_push.sh src/gen/.gitignore src/gen/.openapi-generator-ignore", + "build": "npm run clean && npm run generate-api && npm run generate-remove-unwanted && tsc", + "test": "jest", "commit": "cz", - "lint:format": "eslint --fix packages/" + "lint:format": "eslint --fix src/" }, "dependencies": { - "aws-sdk": "2.1333.0" + "@aws-sdk/client-s3": "^3.295.0", + "@types/aws-lambda": "^8.10.111" }, "devDependencies": { - "@types/aws-lambda": "^8.10.111", "@types/node": "^18", "@types/request": "^2.48.8", "typescript": "^4.9", - "@commitlint/cli": "^17.4.4", - "@commitlint/config-conventional": "^17.4.4", - "commitizen": "^4.3.0", - "cz-conventional-changelog": "^3.3.0", "eslint": "^8.36.0", - "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.7.0", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-prettier": "^4.2.1", "husky": "^8.0.3", "lint-staged": "^13.2.0", "prettier": "^2.8.4", "validate-branch-name": "^1.3.0", + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", + "commitizen": "^4.3.0", + "cz-conventional-changelog": "^3.3.0", + "jest": "^29.5.0", + "@types/jest": "^29.4.1", + "babel-jest": "^29.5.0", + "@babel/core": "^7.21.0", + "@babel/preset-env": "^7.20.2", + "@babel/preset-typescript": "^7.21.0", "@openapitools/openapi-generator-cli": "^2.5.2" }, "config": { @@ -46,6 +55,13 @@ "stylelint": { "extends": "stylelint-config-standard" }, + "husky": { + "hooks": { + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", + "pre-commit": "lint-staged", + "pre-push": "validate-branch-name" + } + }, "lint-staged": { "packages/**/*.+(js|sx|ts|tsx)": [ "eslint --fix ./", @@ -53,8 +69,8 @@ ] }, "validate-branch-name": { - "pattern": "^main$|^release/(v\\d+.\\d+.\\d+){1}$|^prerelease/(v\\d+.\\d+.\\d+){1}$|^(feature|fix){1}/(BSSN-\\d+){1}$", - "errorMsg": "🤦‍♀️ branch name does not comply with the repository conventions" + "pattern": "^main$|^release/(v\\d+.\\d+.\\d+){1}$|^(story|task|bug){1}/(GD-\\d+){1}$", + "errorMsg": "The branch name does not comply with the branching rules" }, "resolutions": { "ansi-regex": "^5.0.1", diff --git a/src/handler.ts b/src/handler.ts new file mode 100644 index 0000000..808406a --- /dev/null +++ b/src/handler.ts @@ -0,0 +1,69 @@ +/** + * + * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format + * @param {Object} event - API Gateway Lambda Proxy Input Format + * + * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html + * @param {Object} context + * + * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html + * @returns {Object} object - API Gateway Lambda Proxy Output Format + * + */ + +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context +} from 'aws-lambda'; + +import { + GetTemplatesResponse, + TemplateDocument +} from './gen/api'; + +import { + S3Provider +} from './service/s3-provider'; + +const region = process.env["repository.template.provider.aws.s3.region"]!; +const bucketName = process.env["repository.template.provider.aws.s3.bucketname"]!; +const prefix = process.env["repository.template.provider.aws.s3.prefix"]!; + +export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Context): Promise => { + console.log(`Event: ${JSON.stringify(event, null, 2)}`); + console.log(`Context: ${JSON.stringify(context, null, 2)}`); + + const s3Provider : S3Provider = new S3Provider(bucketName, region, prefix); + + console.debug(`Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...`); + + const request: any = (event.body) ? JSON.parse(event.body!) : undefined; + let templateId : string | undefined; + if (request) { + templateId = request.templateId; + } + + const templateList: Array | undefined = + await s3Provider.listObjects ({ + Bucket: bucketName, + Prefix: (templateId) ? prefix + '/' + templateId : prefix + }, []); + + const resultObjects: GetTemplatesResponse = { + contents: templateList + }; + + let result: APIGatewayProxyResult = { statusCode: 500, body: ""}; + if (templateList) { + result = { + statusCode: (templateList!.length > 0) ? 200 : 404, + body: JSON.stringify(resultObjects), + }; + } + + console.log(`End - Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...`) + return result; +}; + + diff --git a/src/service/s3-provider.ts b/src/service/s3-provider.ts new file mode 100644 index 0000000..6723010 --- /dev/null +++ b/src/service/s3-provider.ts @@ -0,0 +1,85 @@ + +import { + ListObjectsV2Command, + ListObjectsV2Output, + ListObjectsV2Request, + S3Client +} from "@aws-sdk/client-s3"; +import {TemplateDocument} from "../gen/model/templateDocument"; + +export class S3Provider { + protected _s3Client : any = {}; + private readonly _bucketName : string = ""; + private readonly _region : string = ""; + private readonly _basePath : string | undefined = ""; + + constructor(bucketName?: string, region?: string, basePath?: string) { + if (bucketName && region) { + this._bucketName = bucketName; + this._region = region; + } else { + throw new Error("Bucket name or region not specified."); + } + this._basePath = basePath; + + this._s3Client = new S3Client({ region: this._region }); + } + + + get s3Client() : S3Client { + return this._s3Client; + } + + get bucketName(): string { + return this._bucketName; + } + + get region(): string { + return this._region; + } + + get basePath(): string | undefined { + return this._basePath; + } + + public async listObjects (s3Request: ListObjectsV2Request, + allKeys: Array): Promise | undefined> { + + console.debug("Retrieving bucket contexts...", JSON.stringify(s3Request, null, 2)); + + try { + const listCmd : ListObjectsV2Command = new ListObjectsV2Command(s3Request); + const data: ListObjectsV2Output = await this.s3Client.send(listCmd); + + let contents = data.Contents; + + console.debug("Items: ", data.KeyCount); + + if (contents) { + contents.forEach(function (content) { + if (content.Key) { + const actDoc: TemplateDocument = { + templateName: content.Key + } + allKeys.push(actDoc); + } + }); + } + + if (data.IsTruncated) { + s3Request.ContinuationToken = data.NextContinuationToken; + + console.debug("get further list..."); + return this.listObjects(s3Request, allKeys); + } else { + console.debug("Retrieved items: ", JSON.stringify(allKeys, null, 2)); + + return allKeys!; + } + } catch (error) { + console.log(error); + return []; + } + } +} + diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts new file mode 100644 index 0000000..05d2d9e --- /dev/null +++ b/tests/unit/handler.test.ts @@ -0,0 +1,212 @@ +'use strict'; + +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context +} from "aws-lambda"; +import { lambdaHandler } from "../../src/handler"; +import {GetTemplatesResponse} from "../../src/gen/model/getTemplatesResponse"; +import {S3Provider} from "../../src/service/s3-provider"; + +describe('Lambda handler tests - happy path', function () { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules() + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it('Retrieve templates without template id should return all templates', async () => { + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); + }); + + it('Retrieve given template by existing template id should return template', async () => { + + const event: APIGatewayProxyEvent = { + templateId: "integrationtests/contracts/contract_v09_en.docx" + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43424", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); + }); + + it('Retrieve given template by non-existing template id should return 404', async () => { + + const event: APIGatewayProxyEvent = { + templateId: "integrationtests/contracts/contract_v09_en.docx" + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43424", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); + }); + +}); + +describe('Lambda handler tests - negative tests', function () { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules() + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it('Param error - Invalid bucket name', async () => { + + process.env["repository.template.provider.aws.s3.region"] = "us-east-2"; + process.env["repository.template.provider.aws.s3.bucketname"]; + process.env["repository.template.provider.aws.s3.prefix"]; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + const mockedS3Provider = jest.spyOn(S3Provider.prototype, "listObjects"); + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); + expect(mockedS3Provider).toHaveBeenCalledTimes(1); + }); + + it('Param error - Invalid prefix', async () => { + + process.env["repository.template.provider.aws.s3.prefix"] = "nonexisting_folder"; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + +// const mockedS3Provider = jest.spyOn(S3Provider.prototype, "listObjects"); + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); + }); + + it('Param error - Wrong region', async () => { + + process.env["repository.template.provider.aws.s3.region"] = "us-east-2"; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + +// const mockedS3Provider = jest.spyOn(S3Provider.prototype, "listObjects"); + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); +// expect(mockedS3Provider).toHaveBeenCalledTimes(1); + }); + +}); diff --git a/tests/unit/s3-provider.test.ts b/tests/unit/s3-provider.test.ts new file mode 100644 index 0000000..ca8c625 --- /dev/null +++ b/tests/unit/s3-provider.test.ts @@ -0,0 +1,22 @@ +'use strict'; + +import {S3Provider} from "../../src/service/s3-provider"; + +describe('S3 data provider connectivity', function () { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules() + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it('Init with no params should return throw error', async () => { + expect(() => new S3Provider(undefined, undefined, undefined)) + .toThrow("Bucket name or region not specified."); + }); + +}); From f4fc091caf38112fde25a82818f29b0ade4d7101 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 09:22:47 +0100 Subject: [PATCH 02/35] feat: story/GD-40 unit tests added --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2684c6..ce09cc2 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ ] }, "validate-branch-name": { - "pattern": "^main$|^release/(v\\d+.\\d+.\\d+){1}$|^(story|task|bug){1}/(GD-\\d+){1}$", + "pattern": "^main$|^release/(v\\d+.\\d+.\\d+){1}$|^(story|task|bug){1}/(GD-\\d+-){1}(.)$", "errorMsg": "The branch name does not comply with the branching rules" }, "resolutions": { From f6a313cc43f021d6deb775569ae8e85a1f4ee3b2 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 09:27:29 +0100 Subject: [PATCH 03/35] feat: story/GD-40 unit tests added --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce09cc2..b01ae40 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ ] }, "validate-branch-name": { - "pattern": "^main$|^release/(v\\d+.\\d+.\\d+){1}$|^(story|task|bug){1}/(GD-\\d+-){1}(.)$", + "pattern": "^main$|^release/(v\\d+.\\d+.\\d+){1}$|^(story|task|bug){1}/(GD-\\d+-){1}[\\w_-]*$", "errorMsg": "The branch name does not comply with the branching rules" }, "resolutions": { From 724409066c6ee8fc2755484d25af17f310c8e413 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 09:39:58 +0100 Subject: [PATCH 04/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f53cae0..c9a400b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,9 +78,9 @@ jobs: - name: Run tests env: - repository.template.provider.aws.s3.bucketname: ${{ env.TEST_AWS_BUCKETNAME }} - repository.template.provider.aws.s3.region: ${{ env.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: ${{ env.TEST_AWS_BUCKET_PREFIX }} + repository.template.provider.aws.s3.bucketname: ${{ vars.TEST_AWS_BUCKETNAME }} + repository.template.provider.aws.s3.region: ${{ vars.TEST_AWS_REGION }} + repository.template.provider.aws.s3.prefix: ${{ vars.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 1524b26c372d4301540e6f3bbfad62286407e4fc Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 09:45:29 +0100 Subject: [PATCH 05/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9a400b..6a6f200 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,9 +78,9 @@ jobs: - name: Run tests env: - repository.template.provider.aws.s3.bucketname: ${{ vars.TEST_AWS_BUCKETNAME }} - repository.template.provider.aws.s3.region: ${{ vars.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: ${{ vars.TEST_AWS_BUCKET_PREFIX }} + repository.template.provider.aws.s3.bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} + repository.template.provider.aws.s3.region: ${{ secrets.TEST_AWS_REGION }} + repository.template.provider.aws.s3.prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 3faf6a0ec7c7d2b825f84b33cc1c4ad56f8614b1 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 09:46:09 +0100 Subject: [PATCH 06/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a6f200..601532f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -118,7 +118,7 @@ jobs: env: repository.template.provider.aws.s3.bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} repository.template.provider.aws.s3.region: ${{ secrets.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: 'testfiles/templates' + repository.template.provider.aws.s3.prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 0c936763f136d92ac6b68266df8fa15c88061dc6 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 11:01:12 +0100 Subject: [PATCH 07/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 12 ++++++------ tests/unit/handler.test.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 601532f..9e1e2aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,9 +78,9 @@ jobs: - name: Run tests env: - repository.template.provider.aws.s3.bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} - repository.template.provider.aws.s3.region: ${{ secrets.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} + repository.template.provider.aws.s3.bucketname: ${{ env.TEST_AWS_BUCKETNAME }} + repository.template.provider.aws.s3.region: ${{ env.TEST_AWS_REGION }} + repository.template.provider.aws.s3.prefix: ${{ env.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -116,9 +116,9 @@ jobs: - name: Run tests env: - repository.template.provider.aws.s3.bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} - repository.template.provider.aws.s3.region: ${{ secrets.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} + repository.template.provider.aws.s3.bucketname: ${{ env.TEST_AWS_BUCKETNAME }} + repository.template.provider.aws.s3.region: ${{ env.TEST_AWS_REGION }} + repository.template.provider.aws.s3.prefix: ${{ env.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 05d2d9e..13d5e86 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -118,8 +118,8 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Invalid bucket name', async () => { process.env["repository.template.provider.aws.s3.region"] = "us-east-2"; - process.env["repository.template.provider.aws.s3.bucketname"]; - process.env["repository.template.provider.aws.s3.prefix"]; + process.env["repository.template.provider.aws.s3.bucketname"] = ""; + process.env["repository.template.provider.aws.s3.prefix"] = ""; const event: APIGatewayProxyEvent = { } as any; From 482cdef52634a3e3c6cee9b93008cd8e8c2a5e53 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:10:54 +0100 Subject: [PATCH 08/35] feat: story/GD-40 unit tests added --- src/handler.ts | 8 ++++---- src/service/s3-provider.ts | 5 +++-- tests/unit/handler.test.ts | 37 ++++++++++++------------------------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 808406a..99721af 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -26,14 +26,14 @@ import { S3Provider } from './service/s3-provider'; -const region = process.env["repository.template.provider.aws.s3.region"]!; -const bucketName = process.env["repository.template.provider.aws.s3.bucketname"]!; -const prefix = process.env["repository.template.provider.aws.s3.prefix"]!; - export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Context): Promise => { console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); + const region = process.env["repository.template.provider.aws.s3.region"]!; + const bucketName = process.env["repository.template.provider.aws.s3.bucketname"]!; + const prefix = process.env["repository.template.provider.aws.s3.prefix"]!; + const s3Provider : S3Provider = new S3Provider(bucketName, region, prefix); console.debug(`Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...`); diff --git a/src/service/s3-provider.ts b/src/service/s3-provider.ts index 6723010..b753b5f 100644 --- a/src/service/s3-provider.ts +++ b/src/service/s3-provider.ts @@ -20,7 +20,7 @@ export class S3Provider { } else { throw new Error("Bucket name or region not specified."); } - this._basePath = basePath; + this._basePath = basePath ? basePath : ""; this._s3Client = new S3Client({ region: this._region }); } @@ -78,7 +78,8 @@ export class S3Provider { } } catch (error) { console.log(error); - return []; + + throw new Error("Error retrieving the object list from S3."); } } } diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 13d5e86..d13dcf1 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -7,7 +7,6 @@ import { } from "aws-lambda"; import { lambdaHandler } from "../../src/handler"; import {GetTemplatesResponse} from "../../src/gen/model/getTemplatesResponse"; -import {S3Provider} from "../../src/service/s3-provider"; describe('Lambda handler tests - happy path', function () { const OLD_ENV = process.env; @@ -136,20 +135,15 @@ describe('Lambda handler tests - negative tests', function () { memoryLimitInMB: "512" }; - const mockedS3Provider = jest.spyOn(S3Provider.prototype, "listObjects"); - - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); - - expect(result.statusCode).toEqual(200); - - const resultObjects: GetTemplatesResponse = JSON.parse(result.body); - expect(resultObjects.contents!.length).toBeGreaterThan(0); - expect(mockedS3Provider).toHaveBeenCalledTimes(1); + await expect( + lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + ).rejects.toThrow("Bucket name or region not specified."); }); it('Param error - Invalid prefix', async () => { + process.env["repository.template.provider.aws.s3.region"] = OLD_ENV["repository.template.provider.aws.s3.region"]; + process.env["repository.template.provider.aws.s3.bucketname"] = OLD_ENV["repository.template.provider.aws.s3.bucketname"]; process.env["repository.template.provider.aws.s3.prefix"] = "nonexisting_folder"; const event: APIGatewayProxyEvent = { @@ -167,20 +161,20 @@ describe('Lambda handler tests - negative tests', function () { memoryLimitInMB: "512" }; -// const mockedS3Provider = jest.spyOn(S3Provider.prototype, "listObjects"); - const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); - expect(result.statusCode).toEqual(200); + expect(result.statusCode).toEqual(404); const resultObjects: GetTemplatesResponse = JSON.parse(result.body); - expect(resultObjects.contents!.length).toBeGreaterThan(0); + expect(resultObjects.contents!.length).toBe(0); }); it('Param error - Wrong region', async () => { process.env["repository.template.provider.aws.s3.region"] = "us-east-2"; + process.env["repository.template.provider.aws.s3.bucketname"] = OLD_ENV["repository.template.provider.aws.s3.bucketname"]; + process.env["repository.template.provider.aws.s3.prefix"] = OLD_ENV["repository.template.provider.aws.s3.prefix"]; const event: APIGatewayProxyEvent = { } as any; @@ -197,16 +191,9 @@ describe('Lambda handler tests - negative tests', function () { memoryLimitInMB: "512" }; -// const mockedS3Provider = jest.spyOn(S3Provider.prototype, "listObjects"); - - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); - - expect(result.statusCode).toEqual(200); - - const resultObjects: GetTemplatesResponse = JSON.parse(result.body); - expect(resultObjects.contents!.length).toBeGreaterThan(0); -// expect(mockedS3Provider).toHaveBeenCalledTimes(1); + await expect( + lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + ).rejects.toThrow("Error retrieving the object list from S3."); }); }); From ccc66eaad85d8d1408dbf2dda7aa7b8dffebea59 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:13:14 +0100 Subject: [PATCH 09/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e1e2aa..6c27b6e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,15 +4,17 @@ on: push: branches: [ "main", release/*, story/*, task/* ] paths: - - 'docs-*/**' - - 'pom.xml' + - 'src/**' + - 'events/**' + - 'package.json' - '.github/workflows/**' pull_request: # branches: [ "main" ] types: [opened, synchronize, reopened] paths: - - 'docs-*/**' - - 'pom.xml' + - 'src/**' + - 'events/**' + - 'package.json' workflow_dispatch: env: From feddb755b577eff9a3b65bf376aea997bc2c6f94 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:22:20 +0100 Subject: [PATCH 10/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c27b6e..e2b0b4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,9 +80,9 @@ jobs: - name: Run tests env: - repository.template.provider.aws.s3.bucketname: ${{ env.TEST_AWS_BUCKETNAME }} - repository.template.provider.aws.s3.region: ${{ env.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: ${{ env.TEST_AWS_BUCKET_PREFIX }} + "repository.template.provider.aws.s3.bucketname": ${{ env.TEST_AWS_BUCKETNAME }} + "repository.template.provider.aws.s3.region": ${{ env.TEST_AWS_REGION }} + "repository.template.provider.aws.s3.prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -118,9 +118,9 @@ jobs: - name: Run tests env: - repository.template.provider.aws.s3.bucketname: ${{ env.TEST_AWS_BUCKETNAME }} - repository.template.provider.aws.s3.region: ${{ env.TEST_AWS_REGION }} - repository.template.provider.aws.s3.prefix: ${{ env.TEST_AWS_BUCKET_PREFIX }} + "repository.template.provider.aws.s3.bucketname": ${{ env.TEST_AWS_BUCKETNAME }} + "repository.template.provider.aws.s3.region": ${{ env.TEST_AWS_REGION }} + "repository.template.provider.aws.s3.prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 85109b6e85df6cd4b74793fe5f946149adceec6c Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:26:53 +0100 Subject: [PATCH 11/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2b0b4f..84440cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,6 +30,16 @@ jobs: runs-on: ubuntu-latest steps: + - name: Run tests + env: + "repository.template.provider.aws.s3.bucketname": ${{ env.TEST_AWS_BUCKETNAME }} + "repository.template.provider.aws.s3.region": ${{ env.TEST_AWS_REGION }} + "repository.template.provider.aws.s3.prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} + + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: echo ${repository.template.provider.aws.s3.region} + - name: Git checkout uses: actions/checkout@v3 From 28d5e0775aff6d76882bae2b7ebc626f114c04fa Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:34:24 +0100 Subject: [PATCH 12/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 12 ++++++------ src/handler.ts | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 84440cb..97b4c24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,9 +32,9 @@ jobs: steps: - name: Run tests env: - "repository.template.provider.aws.s3.bucketname": ${{ env.TEST_AWS_BUCKETNAME }} - "repository.template.provider.aws.s3.region": ${{ env.TEST_AWS_REGION }} - "repository.template.provider.aws.s3.prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} + repository_template_provider_aws_s3_bucketname: ${{ env.TEST_AWS_BUCKETNAME }} + repository_template_provider_aws_s3_region": ${{ env.TEST_AWS_REGION }} + repository_template_provider_aws_s3_prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -90,9 +90,9 @@ jobs: - name: Run tests env: - "repository.template.provider.aws.s3.bucketname": ${{ env.TEST_AWS_BUCKETNAME }} - "repository.template.provider.aws.s3.region": ${{ env.TEST_AWS_REGION }} - "repository.template.provider.aws.s3.prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} + repository_template_provider_aws_s3_bucketname: ${{ env.TEST_AWS_BUCKETNAME }} + repository_template_provider_aws_s3_region": ${{ env.TEST_AWS_REGION }} + repository_template_provider_aws_s3_prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/src/handler.ts b/src/handler.ts index 99721af..f8e6d60 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -30,9 +30,9 @@ export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Contex console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); - const region = process.env["repository.template.provider.aws.s3.region"]!; - const bucketName = process.env["repository.template.provider.aws.s3.bucketname"]!; - const prefix = process.env["repository.template.provider.aws.s3.prefix"]!; + const region = process.env["repository_template_provider_aws_s3_region"]!; + const bucketName = process.env["repository_template_provider_aws_s3_bucketname"]!; + const prefix = process.env["repository_template_provider_aws_s3_prefix"]!; const s3Provider : S3Provider = new S3Provider(bucketName, region, prefix); From 30a6b9c5fb24ea9760ecc6e911c3bf20bd908ed9 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:35:39 +0100 Subject: [PATCH 13/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 97b4c24..73eb51c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,16 +30,6 @@ jobs: runs-on: ubuntu-latest steps: - - name: Run tests - env: - repository_template_provider_aws_s3_bucketname: ${{ env.TEST_AWS_BUCKETNAME }} - repository_template_provider_aws_s3_region": ${{ env.TEST_AWS_REGION }} - repository_template_provider_aws_s3_prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} - - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - run: echo ${repository.template.provider.aws.s3.region} - - name: Git checkout uses: actions/checkout@v3 From 6bb8ee9ed30eda58634376cea4accc9b386b21bd Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:41:25 +0100 Subject: [PATCH 14/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 73eb51c..73a243c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,9 +80,9 @@ jobs: - name: Run tests env: - repository_template_provider_aws_s3_bucketname: ${{ env.TEST_AWS_BUCKETNAME }} - repository_template_provider_aws_s3_region": ${{ env.TEST_AWS_REGION }} - repository_template_provider_aws_s3_prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} + repository_template_provider_aws_s3_bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} + repository_template_provider_aws_s3_region": ${{ secrets.TEST_AWS_REGION }} + repository_template_provider_aws_s3_prefix": ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -118,9 +118,9 @@ jobs: - name: Run tests env: - "repository.template.provider.aws.s3.bucketname": ${{ env.TEST_AWS_BUCKETNAME }} - "repository.template.provider.aws.s3.region": ${{ env.TEST_AWS_REGION }} - "repository.template.provider.aws.s3.prefix": ${{ env.TEST_AWS_BUCKET_PREFIX }} + repository_template_provider_aws_s3_bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} + repository_template_provider_aws_s3_region": ${{ secrets.TEST_AWS_REGION }} + repository_template_provider_aws_s3_prefix": ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 38b6ffd1f09ee5c4f4df20bf06fa226e29f5ca8b Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:50:30 +0100 Subject: [PATCH 15/35] feat: story/GD-40 unit tests added --- tests/unit/handler.test.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index d13dcf1..a1648f3 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -37,6 +37,10 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; + process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); @@ -64,6 +68,10 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; + process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); @@ -91,6 +99,10 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; + process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); @@ -116,9 +128,9 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Invalid bucket name', async () => { - process.env["repository.template.provider.aws.s3.region"] = "us-east-2"; - process.env["repository.template.provider.aws.s3.bucketname"] = ""; - process.env["repository.template.provider.aws.s3.prefix"] = ""; + process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; + process.env["repository_template_provider_aws_s3_bucketname"] = ""; + process.env["repository_template_provider_aws_s3_prefix"] = ""; const event: APIGatewayProxyEvent = { } as any; @@ -142,9 +154,9 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Invalid prefix', async () => { - process.env["repository.template.provider.aws.s3.region"] = OLD_ENV["repository.template.provider.aws.s3.region"]; - process.env["repository.template.provider.aws.s3.bucketname"] = OLD_ENV["repository.template.provider.aws.s3.bucketname"]; - process.env["repository.template.provider.aws.s3.prefix"] = "nonexisting_folder"; + process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = "nonexisting_folder"; const event: APIGatewayProxyEvent = { } as any; @@ -172,9 +184,9 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Wrong region', async () => { - process.env["repository.template.provider.aws.s3.region"] = "us-east-2"; - process.env["repository.template.provider.aws.s3.bucketname"] = OLD_ENV["repository.template.provider.aws.s3.bucketname"]; - process.env["repository.template.provider.aws.s3.prefix"] = OLD_ENV["repository.template.provider.aws.s3.prefix"]; + process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; const event: APIGatewayProxyEvent = { } as any; From f7a54c994cf12bca493814908d56e28c671c49d4 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 12:53:50 +0100 Subject: [PATCH 16/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 73a243c..ccc7f0b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,6 +6,7 @@ on: paths: - 'src/**' - 'events/**' + - 'tests/**' - 'package.json' - '.github/workflows/**' pull_request: @@ -14,6 +15,7 @@ on: paths: - 'src/**' - 'events/**' + - 'tests/**' - 'package.json' workflow_dispatch: From 3b9a07af46b840d771374f9867ffd7c03d843134 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:05:34 +0100 Subject: [PATCH 17/35] feat: story/GD-40 unit tests added --- tests/unit/handler-invalid.test.ts | 105 +++++++++++++++++++++++++++++ tests/unit/handler.test.ts | 96 -------------------------- 2 files changed, 105 insertions(+), 96 deletions(-) create mode 100644 tests/unit/handler-invalid.test.ts diff --git a/tests/unit/handler-invalid.test.ts b/tests/unit/handler-invalid.test.ts new file mode 100644 index 0000000..f120f2b --- /dev/null +++ b/tests/unit/handler-invalid.test.ts @@ -0,0 +1,105 @@ +'use strict'; + +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context +} from "aws-lambda"; +import { lambdaHandler } from "../../src/handler"; +import {GetTemplatesResponse} from "../../src/gen/model/getTemplatesResponse"; + +describe('Lambda handler tests - negative tests', function () { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules() + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it('Param error - Invalid bucket name', async () => { + + process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; + process.env["repository_template_provider_aws_s3_bucketname"] = ""; + process.env["repository_template_provider_aws_s3_prefix"] = ""; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + await expect( + lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + ).rejects.toThrow("Bucket name or region not specified."); + }); + + it('Param error - Invalid prefix', async () => { + + process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = "nonexisting_folder"; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(404); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBe(0); + }); + + it('Param error - Wrong region', async () => { + + process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + await expect( + lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + ).rejects.toThrow("Error retrieving the object list from S3."); + }); + +}); diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index a1648f3..23249a7 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -113,99 +113,3 @@ describe('Lambda handler tests - happy path', function () { }); }); - -describe('Lambda handler tests - negative tests', function () { - const OLD_ENV = process.env; - - beforeEach(() => { - jest.resetModules() - process.env = { ...OLD_ENV }; - }); - - afterAll(() => { - process.env = OLD_ENV; - }); - - it('Param error - Invalid bucket name', async () => { - - process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; - process.env["repository_template_provider_aws_s3_bucketname"] = ""; - process.env["repository_template_provider_aws_s3_prefix"] = ""; - - const event: APIGatewayProxyEvent = { - } as any; - - const testContext: Partial = { - awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", - logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", - functionName: "docs-func-aws-template-fill-v1", - functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", - identity: undefined, - clientContext: undefined, - memoryLimitInMB: "512" - }; - - await expect( - lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) - ).rejects.toThrow("Bucket name or region not specified."); - }); - - it('Param error - Invalid prefix', async () => { - - process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = "nonexisting_folder"; - - const event: APIGatewayProxyEvent = { - } as any; - - const testContext: Partial = { - awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", - logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", - functionName: "docs-func-aws-template-fill-v1", - functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", - identity: undefined, - clientContext: undefined, - memoryLimitInMB: "512" - }; - - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); - - expect(result.statusCode).toEqual(404); - - const resultObjects: GetTemplatesResponse = JSON.parse(result.body); - expect(resultObjects.contents!.length).toBe(0); - }); - - it('Param error - Wrong region', async () => { - - process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; - - const event: APIGatewayProxyEvent = { - } as any; - - const testContext: Partial = { - awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", - logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", - functionName: "docs-func-aws-template-fill-v1", - functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", - identity: undefined, - clientContext: undefined, - memoryLimitInMB: "512" - }; - - await expect( - lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) - ).rejects.toThrow("Error retrieving the object list from S3."); - }); - -}); From 923b70d22f3618dd69dc7ebd327bf6d11ace040f Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:14:08 +0100 Subject: [PATCH 18/35] feat: story/GD-40 unit tests added --- tests/unit/handler.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 23249a7..2860931 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -37,10 +37,8 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; - process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; - + console.log("region: " + process.env["repository.template.provider.aws.s3.region"]); + console.log("region: " + OLD_ENV["repository.template.provider.aws.s3.region"]); const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); From 7f3642495caf71938f0ef8e64e2083b9394029db Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:23:02 +0100 Subject: [PATCH 19/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 8 ++++---- tests/unit/handler.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccc7f0b..cb1dd08 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,8 +83,8 @@ jobs: - name: Run tests env: repository_template_provider_aws_s3_bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} - repository_template_provider_aws_s3_region": ${{ secrets.TEST_AWS_REGION }} - repository_template_provider_aws_s3_prefix": ${{ secrets.TEST_AWS_BUCKET_PREFIX }} + repository_template_provider_aws_s3_region: ${{ secrets.TEST_AWS_REGION }} + repository_template_provider_aws_s3_prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -121,8 +121,8 @@ jobs: - name: Run tests env: repository_template_provider_aws_s3_bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} - repository_template_provider_aws_s3_region": ${{ secrets.TEST_AWS_REGION }} - repository_template_provider_aws_s3_prefix": ${{ secrets.TEST_AWS_BUCKET_PREFIX }} + repository_template_provider_aws_s3_region: ${{ secrets.TEST_AWS_REGION }} + repository_template_provider_aws_s3_prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 2860931..812082b 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -37,8 +37,8 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; - console.log("region: " + process.env["repository.template.provider.aws.s3.region"]); - console.log("region: " + OLD_ENV["repository.template.provider.aws.s3.region"]); + console.log("region: " + process.env["repository_template_provider_aws_s3_region"]); + console.log("region: " + OLD_ENV["repository_template_provider_aws_s3_region"]); const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); From b86b99faeac0dd82be25bfde38c211452069c589 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:29:11 +0100 Subject: [PATCH 20/35] feat: story/GD-40 unit tests added --- tests/unit/handler-invalid.test.ts | 105 ----------------------------- tests/unit/handler.test.ts | 104 +++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 114 deletions(-) delete mode 100644 tests/unit/handler-invalid.test.ts diff --git a/tests/unit/handler-invalid.test.ts b/tests/unit/handler-invalid.test.ts deleted file mode 100644 index f120f2b..0000000 --- a/tests/unit/handler-invalid.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; - -import { - APIGatewayProxyEvent, - APIGatewayProxyResult, - Context -} from "aws-lambda"; -import { lambdaHandler } from "../../src/handler"; -import {GetTemplatesResponse} from "../../src/gen/model/getTemplatesResponse"; - -describe('Lambda handler tests - negative tests', function () { - const OLD_ENV = process.env; - - beforeEach(() => { - jest.resetModules() - process.env = { ...OLD_ENV }; - }); - - afterAll(() => { - process.env = OLD_ENV; - }); - - it('Param error - Invalid bucket name', async () => { - - process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; - process.env["repository_template_provider_aws_s3_bucketname"] = ""; - process.env["repository_template_provider_aws_s3_prefix"] = ""; - - const event: APIGatewayProxyEvent = { - } as any; - - const testContext: Partial = { - awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", - logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", - functionName: "docs-func-aws-template-fill-v1", - functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", - identity: undefined, - clientContext: undefined, - memoryLimitInMB: "512" - }; - - await expect( - lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) - ).rejects.toThrow("Bucket name or region not specified."); - }); - - it('Param error - Invalid prefix', async () => { - - process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = "nonexisting_folder"; - - const event: APIGatewayProxyEvent = { - } as any; - - const testContext: Partial = { - awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", - logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", - functionName: "docs-func-aws-template-fill-v1", - functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", - identity: undefined, - clientContext: undefined, - memoryLimitInMB: "512" - }; - - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); - - expect(result.statusCode).toEqual(404); - - const resultObjects: GetTemplatesResponse = JSON.parse(result.body); - expect(resultObjects.contents!.length).toBe(0); - }); - - it('Param error - Wrong region', async () => { - - process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; - - const event: APIGatewayProxyEvent = { - } as any; - - const testContext: Partial = { - awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", - logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", - functionName: "docs-func-aws-template-fill-v1", - functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", - identity: undefined, - clientContext: undefined, - memoryLimitInMB: "512" - }; - - await expect( - lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) - ).rejects.toThrow("Error retrieving the object list from S3."); - }); - -}); diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 812082b..6555ba3 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -37,8 +37,6 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; - console.log("region: " + process.env["repository_template_provider_aws_s3_region"]); - console.log("region: " + OLD_ENV["repository_template_provider_aws_s3_region"]); const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); @@ -66,10 +64,6 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; - process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; - const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); @@ -97,17 +91,109 @@ describe('Lambda handler tests - happy path', function () { memoryLimitInMB: "512" }; + const result: APIGatewayProxyResult = + await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + + expect(result.statusCode).toEqual(200); + + const resultObjects: GetTemplatesResponse = JSON.parse(result.body); + expect(resultObjects.contents!.length).toBeGreaterThan(0); + }); + +}); + +describe('Lambda handler tests - negative tests', function () { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules() + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it('Param error - Invalid bucket name', async () => { + + process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; + process.env["repository_template_provider_aws_s3_bucketname"] = ""; + process.env["repository_template_provider_aws_s3_prefix"] = ""; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + await expect( + lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + ).rejects.toThrow("Bucket name or region not specified."); + }); + + it('Param error - Invalid prefix', async () => { + process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + process.env["repository_template_provider_aws_s3_prefix"] = "nonexisting_folder"; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; const result: APIGatewayProxyResult = await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); - expect(result.statusCode).toEqual(200); + expect(result.statusCode).toEqual(404); const resultObjects: GetTemplatesResponse = JSON.parse(result.body); - expect(resultObjects.contents!.length).toBeGreaterThan(0); + expect(resultObjects.contents!.length).toBe(0); + }); + + it('Param error - Wrong region', async () => { + + process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; + process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; + process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + + const event: APIGatewayProxyEvent = { + } as any; + + const testContext: Partial = { + awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", + logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", + functionName: "docs-func-aws-template-fill-v1", + functionVersion: "$LATEST", + invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + identity: undefined, + clientContext: undefined, + memoryLimitInMB: "512" + }; + + await expect( + lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + ).rejects.toThrow("Error retrieving the object list from S3."); }); }); From 835880d64c529597dc4e5af2a18dd57e87d2d036 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:39:03 +0100 Subject: [PATCH 21/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 12 ++++++------ src/handler.ts | 6 +++--- tests/unit/handler.test.ts | 14 +++++--------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb1dd08..6fe9562 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,9 +82,9 @@ jobs: - name: Run tests env: - repository_template_provider_aws_s3_bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} - repository_template_provider_aws_s3_region: ${{ secrets.TEST_AWS_REGION }} - repository_template_provider_aws_s3_prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} + REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME: ${{ secrets.TEST_AWS_BUCKETNAME }} + REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION: ${{ secrets.TEST_AWS_REGION }} + REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -120,9 +120,9 @@ jobs: - name: Run tests env: - repository_template_provider_aws_s3_bucketname: ${{ secrets.TEST_AWS_BUCKETNAME }} - repository_template_provider_aws_s3_region: ${{ secrets.TEST_AWS_REGION }} - repository_template_provider_aws_s3_prefix: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} + REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME: ${{ secrets.TEST_AWS_BUCKETNAME }} + REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION: ${{ secrets.TEST_AWS_REGION }} + REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX: ${{ secrets.TEST_AWS_BUCKET_PREFIX }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/src/handler.ts b/src/handler.ts index f8e6d60..8d20784 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -30,9 +30,9 @@ export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Contex console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); - const region = process.env["repository_template_provider_aws_s3_region"]!; - const bucketName = process.env["repository_template_provider_aws_s3_bucketname"]!; - const prefix = process.env["repository_template_provider_aws_s3_prefix"]!; + const region = process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION"]!; + const bucketName = process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME"]!; + const prefix = process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"]!; const s3Provider : S3Provider = new S3Provider(bucketName, region, prefix); diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 6555ba3..079b500 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -116,9 +116,9 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Invalid bucket name', async () => { - process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; - process.env["repository_template_provider_aws_s3_bucketname"] = ""; - process.env["repository_template_provider_aws_s3_prefix"] = ""; + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION"] = "us-east-2"; + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME"] = ""; + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"] = ""; const event: APIGatewayProxyEvent = { } as any; @@ -142,9 +142,7 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Invalid prefix', async () => { - process.env["repository_template_provider_aws_s3_region"] = OLD_ENV["repository_template_provider_aws_s3_region"]; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = "nonexisting_folder"; + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"] = "nonexisting_folder"; const event: APIGatewayProxyEvent = { } as any; @@ -172,9 +170,7 @@ describe('Lambda handler tests - negative tests', function () { it('Param error - Wrong region', async () => { - process.env["repository_template_provider_aws_s3_region"] = "us-east-2"; - process.env["repository_template_provider_aws_s3_bucketname"] = OLD_ENV["repository_template_provider_aws_s3_bucketname"]; - process.env["repository_template_provider_aws_s3_prefix"] = OLD_ENV["repository_template_provider_aws_s3_prefix"]; + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION"] = "us-east-2"; const event: APIGatewayProxyEvent = { } as any; From 4b308b35a8a37143d16c69c6b2052bee89dcba8b Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:42:14 +0100 Subject: [PATCH 22/35] feat: story/GD-40 unit tests added --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6fe9562..ea80402 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -132,7 +132,7 @@ jobs: uses: SonarSource/sonarcloud-github-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets. SONARCLOUD_TOKEN }} + SONAR_TOKEN: ${{ secrets. SONAR_TOKEN }} docker_build_job: name: Containerize From dd9f513984ba3db1be11bf77a8d82385570f994c Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 13:55:14 +0100 Subject: [PATCH 23/35] ci: story/GD-40 sonarcloud integration init --- sonar-project.properties | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 sonar-project.properties diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..e69de29 From 36767d0b671378802aaddb1e6636a0e020a0db2d Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 14:01:07 +0100 Subject: [PATCH 24/35] ci: story/GD-40 sonarcloud integration init --- sonar-project.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonar-project.properties b/sonar-project.properties index e69de29..b39c861 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -0,0 +1,3 @@ +sonar.projectKey=get-the-docs_docs-func-aws-template-list-v1 +sonar.organization=get-the-docs +sonar.javascript.lcov.reportPaths=./coverage/lcov.info From c75beae73fee0d02e997c0b20706c53e8928ef24 Mon Sep 17 00:00:00 2001 From: videki Date: Wed, 22 Mar 2023 14:02:06 +0100 Subject: [PATCH 25/35] ci: story/GD-40 sonarcloud integration init --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ea80402..198edd0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -134,6 +134,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets. SONAR_TOKEN }} + docker_build_job: name: Containerize needs: From 90df6ad5966e18dea4224adda6d7d2255a299309 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 13:02:04 +0200 Subject: [PATCH 26/35] build: story/GD-40 eslint fixes --- .eslintignore | 7 -- .eslintrc | 79 ---------------------- .eslintrc.yml | 14 ++++ .github/workflows/build.yml | 2 +- Dockerfile | 7 +- babel.config.js | 6 -- commitlint.config.js | 4 +- jest.config.js | 8 +-- package.json | 47 +++++++------ src/{handler.ts => index.ts} | 54 ++++++++------- tests/unit/handler.test.ts | 125 ++++++++++++++++++----------------- tsconfig.json | 15 ++++- 12 files changed, 156 insertions(+), 212 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc create mode 100644 .eslintrc.yml delete mode 100644 babel.config.js rename src/{handler.ts => index.ts} (54%) diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 6eb9bdc..0000000 --- a/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules/** -built/** -dist/** -out/** -aws-toolkit-ts-output/** -.storybook/** -storybook-static diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index f9e47ce..0000000 --- a/.eslintrc +++ /dev/null @@ -1,79 +0,0 @@ -extends: 'eslint:recommended' - -env: - node: true - es6: true - -parserOptions: - ecmaVersion: 2017 - -rules: - # Possible Errors - no-console: 0 - valid-jsdoc: [0, {requireReturn: false, requireParamDescription: false, requireReturnDescription: false}] - - # Best Practices - consistent-return: 0 - curly: 0 - block-scoped-var: 2 - no-else-return: 2 - no-process-env: 2 - no-self-compare: 2 - no-throw-literal: 2 - no-void: 2 - radix: 2 - wrap-iife: [2, outside] - - # Variables - no-shadow: 0 - no-use-before-define: [2, nofunc] - no-unused-vars: [2, { "argsIgnorePattern": "next" }] - - # Node.js - no-process-exit: 0 - handle-callback-err: [2, err] - no-new-require: 2 - no-path-concat: 2 - - # Stylistic Issues - quotes: [2, single] - camelcase: 0 - indent: [2, 2] - no-lonely-if: 2 - no-floating-decimal: 2 - brace-style: [2, 1tbs, { "allowSingleLine": true }] - comma-style: [2, last] - consistent-this: [0, self] - func-style: 0 - max-nested-callbacks: 0 - new-cap: [2, {capIsNewExceptions: [JID]}] - no-multiple-empty-lines: [2, {max: 1}] - no-nested-ternary: 2 - semi-spacing: [2, {before: false, after: true}] - operator-assignment: [2, always] - padded-blocks: [2, never] - quote-props: [2, as-needed] - space-before-function-paren: [2, always] - keyword-spacing: [2, {after: true}] - space-before-blocks: [2, always] - array-bracket-spacing: [2, never] - computed-property-spacing: [2, never] - space-in-parens: [2, never] - space-unary-ops: [2, {words: true, nonwords: false}] - #spaced-line-comment: [2, always] - wrap-regex: 2 - linebreak-style: [2, unix] - semi: [2, always] - - # ECMAScript 6 - arrow-spacing: [2, {before: true, after: true}] - no-class-assign: 2 - no-const-assign: 2 - no-dupe-class-members: 2 - no-this-before-super: 2 - no-var: 2 - object-shorthand: [2, always] - prefer-arrow-callback: 2 - prefer-const: 2 - prefer-spread: 2 - prefer-template: 2 diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..6c95aab --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,14 @@ +env: + browser: true + es2021: true +extends: + - eslint:recommended + - plugin:@typescript-eslint/recommended +overrides: [] +parser: '@typescript-eslint/parser' +parserOptions: + ecmaVersion: latest + sourceType: module +plugins: + - '@typescript-eslint' +rules: {} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 198edd0..4762ea6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -193,7 +193,7 @@ jobs: - name: Build and push Docker image uses: docker/build-push-action@v3 with: - context: ./docs-generator-api + context: . push: true # push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} diff --git a/Dockerfile b/Dockerfile index 3a7f338..cba40e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,7 @@ FROM public.ecr.aws/lambda/nodejs:18 +WORKDIR ${LAMBDA_TASK_ROOT} -COPY app.ts package*.json ./ +COPY dist/* ./ -#RUN npm install -RUN npm ci --production +CMD ["index.handler"] -CMD ["app.lambdaHandler"] diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index e7118c3..0000000 --- a/babel.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - presets: [ - ['@babel/preset-env', {targets: {node: 'current'}}], - '@babel/preset-typescript', - ], -}; diff --git a/commitlint.config.js b/commitlint.config.js index b09742f..bceeba8 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,9 +1,9 @@ module.exports = { - extends: ["@commitlint/config-conventional"], + extends: ['@commitlint/config-conventional'], rules: { - "scope-case": [2, "always", ["lower-case", "kebab-case"]] + 'scope-case': [2, 'always', ['lower-case', 'kebab-case']] } }; diff --git a/jest.config.js b/jest.config.js index 5ce5e9f..e436251 100644 --- a/jest.config.js +++ b/jest.config.js @@ -23,7 +23,7 @@ module.exports = { // collectCoverageFrom: undefined, // The directory where Jest should output its coverage files - coverageDirectory: "coverage", + coverageDirectory: 'coverage', // An array of regexp pattern strings used to skip coverage collection // coveragePathIgnorePatterns: [ @@ -31,7 +31,7 @@ module.exports = { // ], // Indicates which provider should be used to instrument code for coverage - coverageProvider: "babel", + coverageProvider: 'babel', // A list of reporter names that Jest uses when writing coverage reports // coverageReporters: [ @@ -144,7 +144,7 @@ module.exports = { // snapshotSerializers: [], // The test environment that will be used for testing - testEnvironment: "node", + testEnvironment: 'node', // Options that will be passed to the testEnvironment // testEnvironmentOptions: {}, @@ -154,7 +154,7 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: [ - "**/tests/unit/**/*.test.ts" + '**/tests/unit/**/*.test.ts' ], // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped diff --git a/package.json b/package.json index b01ae40..f9cef7c 100644 --- a/package.json +++ b/package.json @@ -8,44 +8,47 @@ "keywords": [ "yarn" ], - "main": "src/handler.ts", + "main": "src/index.ts", "scripts": { "prepare": "husky install", "clean": "rimraf src/gen/*", "generate-api": "openapi-generator-cli generate -g typescript-node -i docs/document-api-template-list-v1.yaml -o src/gen", "generate-remove-unwanted": "rimraf src/gen/git_push.sh src/gen/.gitignore src/gen/.openapi-generator-ignore", - "build": "npm run clean && npm run generate-api && npm run generate-remove-unwanted && tsc", + "build": "npm run clean && npm run generate-api && npm run generate-remove-unwanted && esbuild src/index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js", "test": "jest", "commit": "cz", - "lint:format": "eslint --fix src/" + "lint:format": "eslint --fix src/*" }, "dependencies": { - "@aws-sdk/client-s3": "^3.295.0", - "@types/aws-lambda": "^8.10.111" + "@aws-sdk/client-s3": "^3.295.0" }, "devDependencies": { + "@babel/core": "^7.21.0", + "@babel/preset-env": "^7.20.2", + "@babel/preset-typescript": "^7.21.0", + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", + "@openapitools/openapi-generator-cli": "^2.5.2", + "@types/aws-lambda": "^8.10.111", + "@types/jest": "^29.4.1", "@types/node": "^18", "@types/request": "^2.48.8", - "typescript": "^4.9", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", + "babel-jest": "^29.5.0", + "commitizen": "^4.3.0", + "cz-conventional-changelog": "^3.3.0", + "esbuild": "^0.17.12", "eslint": "^8.36.0", "eslint-config-prettier": "^8.7.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^4.2.1", "husky": "^8.0.3", + "jest": "^29.5.0", "lint-staged": "^13.2.0", "prettier": "^2.8.4", - "validate-branch-name": "^1.3.0", - "@commitlint/cli": "^17.4.4", - "@commitlint/config-conventional": "^17.4.4", - "commitizen": "^4.3.0", - "cz-conventional-changelog": "^3.3.0", - "jest": "^29.5.0", - "@types/jest": "^29.4.1", - "babel-jest": "^29.5.0", - "@babel/core": "^7.21.0", - "@babel/preset-env": "^7.20.2", - "@babel/preset-typescript": "^7.21.0", - "@openapitools/openapi-generator-cli": "^2.5.2" + "typescript": "^4.9", + "validate-branch-name": "^1.3.0" }, "config": { "commitizen": { @@ -63,8 +66,12 @@ } }, "lint-staged": { - "packages/**/*.+(js|sx|ts|tsx)": [ - "eslint --fix ./", + "src/**/*.+(ts|tsx)": [ + "eslint --fix ", + "prettier --write" + ], + "tests/**/*.+(ts|tsx)": [ + "eslint --fix ", "prettier --write" ] }, diff --git a/src/handler.ts b/src/index.ts similarity index 54% rename from src/handler.ts rename to src/index.ts index 8d20784..488efa7 100644 --- a/src/handler.ts +++ b/src/index.ts @@ -14,56 +14,60 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, - Context -} from 'aws-lambda'; + Context, +} from "aws-lambda"; -import { - GetTemplatesResponse, - TemplateDocument -} from './gen/api'; +import { GetTemplatesResponse, TemplateDocument } from "./gen/api"; -import { - S3Provider -} from './service/s3-provider'; +import { S3Provider } from "./service/s3-provider"; -export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Context): Promise => { +export const handler = async ( + event: APIGatewayProxyEvent, + context: Context +): Promise => { console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); const region = process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION"]!; - const bucketName = process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME"]!; + const bucketName = + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME"]!; const prefix = process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"]!; - const s3Provider : S3Provider = new S3Provider(bucketName, region, prefix); + const s3Provider: S3Provider = new S3Provider(bucketName, region, prefix); - console.debug(`Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...`); + console.debug( + `Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...` + ); - const request: any = (event.body) ? JSON.parse(event.body!) : undefined; - let templateId : string | undefined; + const request: any = event.body ? JSON.parse(event.body!) : undefined; + let templateId: string | undefined; if (request) { templateId = request.templateId; } const templateList: Array | undefined = - await s3Provider.listObjects ({ - Bucket: bucketName, - Prefix: (templateId) ? prefix + '/' + templateId : prefix - }, []); + await s3Provider.listObjects( + { + Bucket: bucketName, + Prefix: templateId ? prefix + "/" + templateId : prefix, + }, + [] + ); const resultObjects: GetTemplatesResponse = { - contents: templateList + contents: templateList, }; - let result: APIGatewayProxyResult = { statusCode: 500, body: ""}; + let result: APIGatewayProxyResult = { statusCode: 500, body: "" }; if (templateList) { result = { - statusCode: (templateList!.length > 0) ? 200 : 404, + statusCode: templateList!.length > 0 ? 200 : 404, body: JSON.stringify(resultObjects), }; } - console.log(`End - Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...`) + console.log( + `End - Listing templates from bucket: s3://${s3Provider.bucketName}/${s3Provider.basePath}...` + ); return result; }; - - diff --git a/tests/unit/handler.test.ts b/tests/unit/handler.test.ts index 079b500..1692d15 100644 --- a/tests/unit/handler.test.ts +++ b/tests/unit/handler.test.ts @@ -1,18 +1,18 @@ -'use strict'; +"use strict"; import { APIGatewayProxyEvent, APIGatewayProxyResult, - Context + Context, } from "aws-lambda"; -import { lambdaHandler } from "../../src/handler"; -import {GetTemplatesResponse} from "../../src/gen/model/getTemplatesResponse"; +import { handler } from "../../src"; +import { GetTemplatesResponse } from "../../src/gen/model/getTemplatesResponse"; -describe('Lambda handler tests - happy path', function () { +describe("Lambda handler tests - happy path", function () { const OLD_ENV = process.env; beforeEach(() => { - jest.resetModules() + jest.resetModules(); process.env = { ...OLD_ENV }; }); @@ -20,25 +20,26 @@ describe('Lambda handler tests - happy path', function () { process.env = OLD_ENV; }); - it('Retrieve templates without template id should return all templates', async () => { - - const event: APIGatewayProxyEvent = { - } as any; + it("Retrieve templates without template id should return all templates", async () => { + const event: APIGatewayProxyEvent = {} as any; const testContext: Partial = { awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logGroupName: "/aws/lambda/docs-func-aws-template-fill-v1", logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", functionName: "docs-func-aws-template-fill-v1", functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + invokedFunctionArn: + "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", identity: undefined, clientContext: undefined, - memoryLimitInMB: "512" + memoryLimitInMB: "512", }; - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + const result: APIGatewayProxyResult = await handler( + event as APIGatewayProxyEvent, + testContext as Context + ); expect(result.statusCode).toEqual(200); @@ -46,26 +47,28 @@ describe('Lambda handler tests - happy path', function () { expect(resultObjects.contents!.length).toBeGreaterThan(0); }); - it('Retrieve given template by existing template id should return template', async () => { - + it("Retrieve given template by existing template id should return template", async () => { const event: APIGatewayProxyEvent = { - templateId: "integrationtests/contracts/contract_v09_en.docx" + templateId: "integrationtests/contracts/contract_v09_en.docx", } as any; const testContext: Partial = { awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43424", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logGroupName: "/aws/lambda/docs-func-aws-template-fill-v1", logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", functionName: "docs-func-aws-template-fill-v1", functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + invokedFunctionArn: + "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", identity: undefined, clientContext: undefined, - memoryLimitInMB: "512" + memoryLimitInMB: "512", }; - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + const result: APIGatewayProxyResult = await handler( + event as APIGatewayProxyEvent, + testContext as Context + ); expect(result.statusCode).toEqual(200); @@ -73,40 +76,41 @@ describe('Lambda handler tests - happy path', function () { expect(resultObjects.contents!.length).toBeGreaterThan(0); }); - it('Retrieve given template by non-existing template id should return 404', async () => { - + it("Retrieve given template by non-existing template id should return 404", async () => { const event: APIGatewayProxyEvent = { - templateId: "integrationtests/contracts/contract_v09_en.docx" + templateId: "integrationtests/contracts/contract_v09_en.docx", } as any; const testContext: Partial = { awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43424", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logGroupName: "/aws/lambda/docs-func-aws-template-fill-v1", logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", functionName: "docs-func-aws-template-fill-v1", functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + invokedFunctionArn: + "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", identity: undefined, clientContext: undefined, - memoryLimitInMB: "512" + memoryLimitInMB: "512", }; - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + const result: APIGatewayProxyResult = await handler( + event as APIGatewayProxyEvent, + testContext as Context + ); expect(result.statusCode).toEqual(200); const resultObjects: GetTemplatesResponse = JSON.parse(result.body); expect(resultObjects.contents!.length).toBeGreaterThan(0); }); - }); -describe('Lambda handler tests - negative tests', function () { +describe("Lambda handler tests - negative tests", function () { const OLD_ENV = process.env; beforeEach(() => { - jest.resetModules() + jest.resetModules(); process.env = { ...OLD_ENV }; }); @@ -114,53 +118,54 @@ describe('Lambda handler tests - negative tests', function () { process.env = OLD_ENV; }); - it('Param error - Invalid bucket name', async () => { - + it("Param error - Invalid bucket name", async () => { process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION"] = "us-east-2"; process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_BUCKETNAME"] = ""; process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"] = ""; - const event: APIGatewayProxyEvent = { - } as any; + const event: APIGatewayProxyEvent = {} as any; const testContext: Partial = { awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logGroupName: "/aws/lambda/docs-func-aws-template-fill-v1", logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", functionName: "docs-func-aws-template-fill-v1", functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + invokedFunctionArn: + "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", identity: undefined, clientContext: undefined, - memoryLimitInMB: "512" + memoryLimitInMB: "512", }; await expect( - lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + handler(event as APIGatewayProxyEvent, testContext as Context) ).rejects.toThrow("Bucket name or region not specified."); }); - it('Param error - Invalid prefix', async () => { - - process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"] = "nonexisting_folder"; + it("Param error - Invalid prefix", async () => { + process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_PREFIX"] = + "nonexisting_folder"; - const event: APIGatewayProxyEvent = { - } as any; + const event: APIGatewayProxyEvent = {} as any; const testContext: Partial = { awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logGroupName: "/aws/lambda/docs-func-aws-template-fill-v1", logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", functionName: "docs-func-aws-template-fill-v1", functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + invokedFunctionArn: + "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", identity: undefined, clientContext: undefined, - memoryLimitInMB: "512" + memoryLimitInMB: "512", }; - const result: APIGatewayProxyResult = - await lambdaHandler(event as APIGatewayProxyEvent, testContext as Context); + const result: APIGatewayProxyResult = await handler( + event as APIGatewayProxyEvent, + testContext as Context + ); expect(result.statusCode).toEqual(404); @@ -168,28 +173,26 @@ describe('Lambda handler tests - negative tests', function () { expect(resultObjects.contents!.length).toBe(0); }); - it('Param error - Wrong region', async () => { - + it("Param error - Wrong region", async () => { process.env["REPOSITORY_TEMPLATE_PROVIDER_AWS_S3_REGION"] = "us-east-2"; - const event: APIGatewayProxyEvent = { - } as any; + const event: APIGatewayProxyEvent = {} as any; const testContext: Partial = { awsRequestId: "cd4b63fd-e407-450d-b24e-1e991ea43425", - logGroupName:"/aws/lambda/docs-func-aws-template-fill-v1", + logGroupName: "/aws/lambda/docs-func-aws-template-fill-v1", logStreamName: "2023/03/01/[$LATEST]12345abcdfe01234567890abcdef1234", functionName: "docs-func-aws-template-fill-v1", functionVersion: "$LATEST", - invokedFunctionArn: "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", + invokedFunctionArn: + "arn:aws:lambda:us-east-2:123456789012:function:docs-func-aws-template-fill-v1", identity: undefined, clientContext: undefined, - memoryLimitInMB: "512" + memoryLimitInMB: "512", }; await expect( - lambdaHandler(event as APIGatewayProxyEvent, testContext as Context) + handler(event as APIGatewayProxyEvent, testContext as Context) ).rejects.toThrow("Error retrieving the object list from S3."); }); - }); diff --git a/tsconfig.json b/tsconfig.json index 6279e19..dbd079f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2017", + "target": "es2020", "strict": true, "preserveConstEnums": true, "noEmit": true, @@ -11,8 +11,17 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "isolatedModules": false, + "outDir": "dist", + "baseUrl": ".", + "paths": { + "*.ts": [ + "./node_modules/*", + "./src/*" + ] + } }, + "include": ["src/**/*.ts"], "exclude": [ - "node_modules", - "**/*.test.ts"] + "./node_modules", + "./**/*.test.ts"] } From c8857463a48975f4574a50ee26944c0fe2ec2e79 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 13:16:17 +0200 Subject: [PATCH 27/35] build: story/GD-40 re-adding babel config --- babel.config.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 babel.config.js diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..1bca1aa --- /dev/null +++ b/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + ['@babel/preset-env', {targets: {node: 'current'}}], + '@babel/preset-typescript', + ], +}; From c86ad8c079fbf1ab3943d761ca5645ea539abbbc Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 13:24:39 +0200 Subject: [PATCH 28/35] ci: story/GD-40 docker pull-back fix --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4762ea6..faefa62 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -166,7 +166,7 @@ jobs: run: yarn build # - name: Build the Docker image -# working-directory: ./docs-generator-api +# working-directory: . # run: docker build -t ${{ env.API_DOCKER_REGISTRY }}/${{ env.API_DOCKER_IMAGE_NAME }} --file Dockerfile . - name: Set up QEMU @@ -200,7 +200,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} - name: Pull back the Docker image for the Trivy scan - working-directory: ./docs-generator-api + working-directory: . run: docker pull ${{ steps.meta.outputs.tags }} - name: Run Trivy vulnerability scanner From ffbb427d18261168ac20b0ac02aa0036f786cd19 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 14:30:01 +0200 Subject: [PATCH 29/35] ci: story/GD-40 gh action deprecation fixes --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index faefa62..fca5393 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -184,14 +184,14 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@v2 + uses: docker/metadata-action@v4 with: images: ${{ env.API_DOCKER_REGISTRY }}/${{ env.API_DOCKER_IMAGE_NAME }} tags: | type=sha - name: Build and push Docker image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . push: true From 042329ee05eb0040af7d435a01900425a72fb806 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 14:46:30 +0200 Subject: [PATCH 30/35] ci: story/GD-40 gh action deprecation fixes - trivy --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fca5393..c37edcd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -176,7 +176,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Log in to the Container registry - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@v2 with: registry: ${{ env.API_DOCKER_REGISTRY }} username: ${{ github.actor }} @@ -204,7 +204,7 @@ jobs: run: docker pull ${{ steps.meta.outputs.tags }} - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@7b7aa264d83dc58691451798b4d117d53d21edfe + uses: aquasecurity/trivy-action@master with: image-ref: '${{ steps.meta.outputs.tags }}' format: 'template' From bc6fb92f3d1d7091918e0dca9bce74757695b720 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 15:55:10 +0200 Subject: [PATCH 31/35] ci: story/GD-40 gh cache usage added --- .github/workflows/build.yml | 54 +++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c37edcd..c1f6b4a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,14 +40,19 @@ jobs: with: node-version: 18 - - name: Rebuild local npm repository from cache + - name: Cache node modules + id: cache-npm uses: actions/cache@v3 + env: + cache-name: cache-node-modules with: path: | - ~/node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + '**/node_modules' + key: ${{ runner.os }}-yarn-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - ${{ runner.os }}-npm- + ${{ runner.os }}-yarn-${{ env.cache-name }}- + ${{ runner.os }}-yarn- + ${{ runner.os }}- - name: Yarn install run: yarn install @@ -65,14 +70,19 @@ jobs: - name: Git checkout uses: actions/checkout@v3 - - name: Rebuild local npm repository from cache + - name: Cache node modules + id: cache-npm uses: actions/cache@v3 + env: + cache-name: cache-node-modules with: path: | - ~/node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + '**/node_modules' + key: ${{ runner.os }}-yarn-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - ${{ runner.os }}-npm- + ${{ runner.os }}-yarn-${{ env.cache-name }}- + ${{ runner.os }}-yarn- + ${{ runner.os }}- - name: Yarn install run: yarn install @@ -103,14 +113,19 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Rebuild local npm repository from cache + - name: Cache node modules + id: cache-npm uses: actions/cache@v3 + env: + cache-name: cache-node-modules with: path: | - ~/node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + '**/node_modules' + key: ${{ runner.os }}-yarn-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - ${{ runner.os }}-npm- + ${{ runner.os }}-yarn-${{ env.cache-name }}- + ${{ runner.os }}-yarn- + ${{ runner.os }}- - name: Yarn install run: yarn install @@ -134,11 +149,11 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets. SONAR_TOKEN }} - docker_build_job: name: Containerize needs: - analyze_job + if: github.ref == 'refs/heads/main' permissions: contents: read # for actions/checkout to fetch code security-events: write # for github/codeql-action/upload-sarif to upload SARIF results @@ -150,14 +165,19 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Rebuild local npm repository from cache + - name: Cache node modules + id: cache-npm uses: actions/cache@v3 + env: + cache-name: cache-node-modules with: path: | - ~/node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/pom.xml') }} + '**/node_modules' + key: ${{ runner.os }}-yarn-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - ${{ runner.os }}-npm- + ${{ runner.os }}-yarn-${{ env.cache-name }}- + ${{ runner.os }}-yarn- + ${{ runner.os }}- - name: Yarn install run: yarn install From 3d9dbfc24b854492b695d22e39084a838abc3945 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 18:04:55 +0200 Subject: [PATCH 32/35] ci: story/GD-40 ecr upload added --- .github/workflows/build.yml | 52 +++++++++++++++---------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c1f6b4a..03ca4b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -153,7 +153,7 @@ jobs: name: Containerize needs: - analyze_job - if: github.ref == 'refs/heads/main' +# if: github.ref == 'refs/heads/main' permissions: contents: read # for actions/checkout to fetch code security-events: write # for github/codeql-action/upload-sarif to upload SARIF results @@ -185,43 +185,33 @@ jobs: - name: Build project run: yarn build -# - name: Build the Docker image -# working-directory: . -# run: docker build -t ${{ env.API_DOCKER_REGISTRY }}/${{ env.API_DOCKER_IMAGE_NAME }} --file Dockerfile . +# - name: Set up QEMU +# uses: docker/setup-qemu-action@v2 +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Log in to the Container registry - uses: docker/login-action@v2 + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 with: - registry: ${{ env.API_DOCKER_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + aws-access-key-id: {{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: {{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: {{ secrets.TEST_AWS_REGION }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.API_DOCKER_REGISTRY }}/${{ env.API_DOCKER_IMAGE_NAME }} - tags: | - type=sha + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 - name: Build and push Docker image - uses: docker/build-push-action@v4 with: context: . - push: true -# push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: Pull back the Docker image for the Trivy scan - working-directory: . - run: docker pull ${{ steps.meta.outputs.tags }} + env: + REGISTRY: ${{ steps.login-ecr.outputs.registry }} + REPOSITORY: docs-func-template-list-v1 + IMAGE_TAG: ${{ github.sha }} + run: | + docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG . + docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master From 0b859c5aeae91c26b3c073dfd2a25c1e766478f4 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 18:11:14 +0200 Subject: [PATCH 33/35] ci: story/GD-40 ecr upload added --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 03ca4b0..570c077 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -160,6 +160,7 @@ jobs: actions: read # only required for a private repository by gitHub/codeql-action/upload-sarif to get the Action run status packages: write runs-on: ubuntu-latest + environment: ci steps: - uses: actions/checkout@v3 with: From 56b7dd33518e313493adbbb352b64bb150bbd221 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 18:12:29 +0200 Subject: [PATCH 34/35] ci: story/GD-40 ecr upload added --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 570c077..29bc627 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -195,9 +195,9 @@ jobs: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v2 with: - aws-access-key-id: {{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: {{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: {{ secrets.TEST_AWS_REGION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.TEST_AWS_REGION }} - name: Login to Amazon ECR id: login-ecr From a326dea2ca180782385781beb464705f1babe8d1 Mon Sep 17 00:00:00 2001 From: videki Date: Sun, 26 Mar 2023 18:15:28 +0200 Subject: [PATCH 35/35] ci: story/GD-40 docker build fixes --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 29bc627..521bfaa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -204,8 +204,8 @@ jobs: uses: aws-actions/amazon-ecr-login@v1 - name: Build and push Docker image - with: - context: . +# with: +# context: . env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} REPOSITORY: docs-func-template-list-v1