diff --git a/.dockerignore b/.dockerignore index eecc08e..704bbb3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,7 +2,7 @@ Dockerfile docker-compose.yml *.ts **/*.ts -src +**/*.test.js .husky .gitignore dev-server.js @@ -11,4 +11,6 @@ service-collection.postman_collection.json tsconfig.json tslint.json logs -cocverage \ No newline at end of file +coverage +node_modules +publish.sh \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f92ced6..b013c94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,11 +19,12 @@ jobs: - name: Setup and install dependencies run: | npm ci - npm run build - - name: Test - run: npm run test - - name: Newman Tests - run: npm run test:newman + - name: Unit tests and Coverage + run: | + npm run test + - name: Newman tests + run: | + npm run test:newman Publish: runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/main' }} diff --git a/.gitignore b/.gitignore index 86025e1..4e01ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -125,4 +125,5 @@ dist ### Node Patch ### # Serverless Webpack directories .webpack/ -app \ No newline at end of file +app/**/*.js +app/**/*.d.ts \ No newline at end of file diff --git a/.releaserc b/.releaserc index 676e3eb..3ca0f47 100644 --- a/.releaserc +++ b/.releaserc @@ -10,7 +10,6 @@ [ "@semantic-release/exec", { - "prepareCmd": "docker build -t lambda-container-service .", "publishCmd": "./publish.sh ${nextRelease.version} ${options.branch} ${commits.length} ${Date.now()}" } ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d3e91..d41cdc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [1.1.0](https://github.com/phenixcoder/lambda-container-service/compare/v1.0.0...v1.1.0) (2021-10-19) + + +### Bug Fixes + +* **newman:** fixed newman test failing due to tsc build config ([13186d2](https://github.com/phenixcoder/lambda-container-service/commit/13186d28968ef5cb7240e52cff4c5ea99dc8ce91)) + + +### Features + +* **health-check:** add health check route to index handler ([bf2d6e2](https://github.com/phenixcoder/lambda-container-service/commit/bf2d6e2a81f0d3e82972d87aae6d613cb8be016e)) + # 1.0.0 (2021-10-16) diff --git a/Dockerfile b/Dockerfile index c225fee..67b2936 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM public.ecr.aws/lambda/nodejs:14 COPY . ${LAMBDA_TASK_ROOT} -RUN npm install +RUN npm ci --only=production # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "app/index.handler" ] \ No newline at end of file diff --git a/app/index.test.ts b/app/index.test.ts new file mode 100644 index 0000000..2602300 --- /dev/null +++ b/app/index.test.ts @@ -0,0 +1,117 @@ +import { + APIGatewayEventRequestContext, + APIGatewayProxyEventV2, +} from 'aws-lambda'; +import { version, name } from '../package.json'; +import { handler } from '.'; + +function mockContext(): APIGatewayEventRequestContext { + return { + accountId: 'string', + apiId: 'string', + authorizer: { + jwt: { + claims: { + foo: 'string', + }, + scopes: [], + }, + }, + protocol: '', + domainName: '', + domainPrefix: 'string', + requestId: '', + routeKey: '', + stage: '', + httpMethod: '', + identity: { + accessKey: '', + accountId: '', + apiKey: '', + apiKeyId: '', + caller: '', + clientCert: null, + cognitoAuthenticationProvider: '', + cognitoAuthenticationType: '', + cognitoIdentityId: '', + cognitoIdentityPoolId: '', + principalOrgId: '', + sourceIp: '0.0.0.0', + user: '', + userAgent: '', + userArn: '', + }, + path: '', + requestTimeEpoch: 0, + resourceId: '', + resourcePath: '', + }; +} + +function mockRequest(): APIGatewayProxyEventV2 { + return { + version: '', + routeKey: '', + rawPath: '', + rawQueryString: '', + headers: {}, + requestContext: { + accountId: 'string', + apiId: 'string', + authorizer: { + jwt: { + claims: { + foo: 'string', + }, + scopes: [], + }, + }, + domainName: '', + domainPrefix: 'string', + timeEpoch: 0, + http: { + method: 'string', + path: 'string', + protocol: 'string', + sourceIp: 'string', + userAgent: 'string', + }, + requestId: '', + routeKey: '', + stage: '', + time: '', + }, + isBase64Encoded: false, + }; +} + +describe('Index Handler', () => { + it('Should return success response', async () => { + const response = await handler(mockRequest(), mockContext()); + expect(response).toStrictEqual({ + body: JSON.stringify({ + hello: 'world', + foo: 'bar', + }), + headers: { + 'content-type': 'text/json', + }, + statusCode: 200, + }); + }); + it('Should return help response when path is __health', async () => { + const req = mockRequest(); + req.rawPath = '__health'; + const response = await handler(req, mockContext()); + expect(response).toStrictEqual({ + body: JSON.stringify({ + version, + name, + }), + headers: { + 'content-type': 'text/json', + }, + statusCode: 200, + }); + }); +}); diff --git a/src/index.ts b/app/index.ts similarity index 65% rename from src/index.ts rename to app/index.ts index 3f61e90..5635233 100644 --- a/src/index.ts +++ b/app/index.ts @@ -4,11 +4,25 @@ import { APIGatewayProxyResultV2, } from 'aws-lambda'; import Logger from './lib/logger'; +import pkg from '../package.json'; export const handler = async ( event: APIGatewayProxyEventV2, _context: APIGatewayEventRequestContext ): Promise => { + if (event.rawPath === '__health') { + return { + statusCode: 200, + headers: { + 'content-type': 'text/json', + }, + body: JSON.stringify({ + version: pkg.version, + name: pkg.name, + }), + }; + } + Logger.debug('This is a log message from handler', event); return { statusCode: 200, diff --git a/src/lib/logger.test.ts b/app/lib/logger.test.ts similarity index 100% rename from src/lib/logger.test.ts rename to app/lib/logger.test.ts diff --git a/src/lib/logger.ts b/app/lib/logger.ts similarity index 100% rename from src/lib/logger.ts rename to app/lib/logger.ts diff --git a/docker-compose.yml b/docker-compose.yml index 1ac599f..ef8caa5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,4 @@ services: app.handler: ports: - '9000:8080' - build: . - volumes: - - .://var/task/ \ No newline at end of file + build: . \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 8cbf894..8d6c213 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,4 +2,5 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', + collectCoverage: true }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b21f64d..a77680e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lambda-container-service", - "version": "0.0.0-development", + "version": "1.2.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "lambda-container-service", - "version": "0.0.0-development", + "version": "1.2.4", "license": "MIT", "dependencies": { "winston": "^3.3.3" diff --git a/package.json b/package.json index c7661fe..240b4e2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "lambda-container-service", "description": "Template to create a aws lambda compatibel function containers", "author": "Balwant", - "version": "0.0.0-development", + "version": "1.0.0", "license": "MIT", "keywords": [ "serverless", @@ -24,11 +24,11 @@ "scripts": { "start": "tsc --watch --preserveWatchOutput & nodemon dev-server.js -e js -w ./app", "build": "tsc", - "test": "jest", - "test:watch": "jest --watch", - "test:newman": "node dev-server.js --test", + "test": "find app -wholename '*.d.ts' -delete && find app -wholename '*.js' -delete && jest", + "test:watch": "npm t -- --watch", + "test:newman": "npm run build && node dev-server.js --test", "lint": "tslint --fix -p ./tsconfig.json", - "prettier": "prettier --write './src/**/*.ts?(x)'", + "prettier": "prettier --write './**/*.ts?(x)'", "release": "semantic-release" }, "husky": { diff --git a/publish.sh b/publish.sh index b0d445f..a63655b 100755 --- a/publish.sh +++ b/publish.sh @@ -1,4 +1,6 @@ #!/bin/bash + +npm version $1 --no-git-tag-version docker build -t lambda-container-service . docker tag lambda-container-service:latest public.ecr.aws/m0q0z2r6/lambda-container-service:$1 docker push public.ecr.aws/m0q0z2r6/lambda-container-service:$1 diff --git a/src/index.test.ts b/src/index.test.ts deleted file mode 100644 index 50a5775..0000000 --- a/src/index.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { - APIGatewayEventRequestContext, - APIGatewayProxyEventV2, -} from 'aws-lambda'; -import { handler } from '.'; -const mockContext: APIGatewayEventRequestContext = { - accountId: 'string', - apiId: 'string', - authorizer: { - jwt: { - claims: { - foo: 'string', - }, - scopes: [], - }, - }, - protocol: '', - domainName: '', - domainPrefix: 'string', - requestId: '', - routeKey: '', - stage: '', - httpMethod: '', - identity: { - accessKey: '', - accountId: '', - apiKey: '', - apiKeyId: '', - caller: '', - clientCert: null, - cognitoAuthenticationProvider: '', - cognitoAuthenticationType: '', - cognitoIdentityId: '', - cognitoIdentityPoolId: '', - principalOrgId: '', - sourceIp: '0.0.0.0', - user: '', - userAgent: '', - userArn: '', - }, - path: '', - requestTimeEpoch: 0, - resourceId: '', - resourcePath: '', -}; -const mockRequest: APIGatewayProxyEventV2 = { - version: '', - routeKey: '', - rawPath: '', - rawQueryString: '', - headers: {}, - requestContext: { - accountId: 'string', - apiId: 'string', - authorizer: { - jwt: { - claims: { - foo: 'string', - }, - scopes: [], - }, - }, - domainName: '', - domainPrefix: 'string', - timeEpoch: 0, - http: { - method: 'string', - path: 'string', - protocol: 'string', - sourceIp: 'string', - userAgent: 'string', - }, - requestId: '', - routeKey: '', - stage: '', - time: '', - }, - isBase64Encoded: false, -}; - -describe('Index Handler', () => { - it('Should return success response', async () => { - const response = await handler(mockRequest, mockContext); - expect(response).toStrictEqual({ - body: JSON.stringify({ - hello: 'world', - foo: 'bar', - }), - headers: { - 'content-type': 'text/json', - }, - statusCode: 200, - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index 2d6cb7f..09808f3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,8 @@ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "app", /* Redirect output structure to the directory. */ - "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "outDir": "app", /* Redirect output structure to the directory. */ + // "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ @@ -37,7 +37,10 @@ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + "rootDirs": [ + "src", + "package.json" + ], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ "types": [ "node",