diff --git a/README.md b/README.md index 7b95de0..a9b4bc3 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ How to verify the most important user journeys are not broken without writing a repo = "identity", personalAccessToken = config.Tip.personalAccessToken, // remove if you do not need GitHub label functionality label = "Verified in PROD", // remove if you do not need GitHub label functionality - boardSha = BuildInfo.GitHeadSha + boardSha = BuildInfo.GitHeadSha // remove if you do not only one board instead of board per sha ) if (config.App.stage == "PROD") diff --git a/cloud/deploy.sh b/cloud/deploy.sh index 2bfc119..ec69f22 100755 --- a/cloud/deploy.sh +++ b/cloud/deploy.sh @@ -20,5 +20,6 @@ aws lambda update-function-code --function-name tip-create-board --s3-bucket $S3 aws lambda update-function-code --function-name tip-get-board --s3-bucket $S3_BUCKET --s3-key $S3_KEY aws lambda update-function-code --function-name tip-get-head-board --s3-bucket $S3_BUCKET --s3-key $S3_KEY aws lambda update-function-code --function-name tip-verify-path --s3-bucket $S3_BUCKET --s3-key $S3_KEY +aws lambda update-function-code --function-name tip-verify-head-path --s3-bucket $S3_BUCKET --s3-key $S3_KEY echo "Done." \ No newline at end of file diff --git a/cloud/postman_collection.json b/cloud/postman_collection.json index a961791..ebd7a88 100644 --- a/cloud/postman_collection.json +++ b/cloud/postman_collection.json @@ -6,7 +6,6 @@ }, "item": [ { - "_postman_id": "2cf06285-c485-460a-9b73-c62572b71c21", "name": "create board", "request": { "method": "POST", @@ -18,20 +17,14 @@ ], "body": { "mode": "raw", - "raw": "{\n \"sha\": \"testsha2\",\n \"repo\": \"guardian/identity\",\n \"deployTime\": \"2018-07-31T13:28:40Z\",\n \"board\": [\n\n {\n \"name\": \"Register\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Register Guest\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Get User\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Update User\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Web Sign In\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"App Sign in\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Consents Set\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Validation Email\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Get User\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Update User\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Web Sign In\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"App Sign in\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Consents Set\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Validation Email\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Delete Account\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Update Password\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Join Group\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Change Email\",\n \"verified\": false\n }\n\n ]\n }" + "raw": "{\n \"sha\": \"testsha6\",\n \"repo\": \"guardian/identity\",\n \"board\": [\n\n {\n \"name\": \"Register\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Register Guest\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Get User\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Update User\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Web Sign In\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"App Sign in\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Consents Set\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Validation Email\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Delete Account\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Update Password\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Join Group\",\n \"verified\": false\n }\n ,\n {\n \"name\": \"Change Email\",\n \"verified\": false\n }\n\n ]\n }" }, "url": { - "raw": "https://howwf2kle3.execute-api.eu-west-1.amazonaws.com/PROD/board", - "protocol": "https", + "raw": "{{tipCloudApiUrl}}/board", "host": [ - "howwf2kle3", - "execute-api", - "eu-west-1", - "amazonaws", - "com" + "{{tipCloudApiUrl}}" ], "path": [ - "PROD", "board" ] } @@ -39,7 +32,6 @@ "response": [] }, { - "_postman_id": "c059d627-f1a9-4c64-a7f4-908d7b3fda78", "name": "get board", "request": { "method": "GET", @@ -52,26 +44,19 @@ ], "body": {}, "url": { - "raw": "https://howwf2kle3.execute-api.eu-west-1.amazonaws.com/PROD/board/fa315cb5ba207a9e945606903d8e1bf60003c5c1", - "protocol": "https", + "raw": "{{tipCloudApiUrl}}/board/testsha2", "host": [ - "howwf2kle3", - "execute-api", - "eu-west-1", - "amazonaws", - "com" + "{{tipCloudApiUrl}}" ], "path": [ - "PROD", "board", - "fa315cb5ba207a9e945606903d8e1bf60003c5c1" + "testsha2" ] } }, "response": [] }, { - "_postman_id": "d55c9d06-74c7-49f8-a285-de4cef56b681", "name": "verify path", "request": { "method": "POST", @@ -83,13 +68,32 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"sha\": \"fa315cb5ba207a9e945606903d8e1bf60003c5c1\",\n\t\"name\": \"Register\"\n}" + "raw": "{\n\t\"sha\": \"testsha2\",\n\t\"name\": \"Register Guest\"\n}" }, "url": { - "raw": "https://howwf2kle3.execute-api.eu-west-1.amazonaws.com/PROD/board/path", + "raw": "{{tipCloudApiUrl}}/board/path", + "host": [ + "{{tipCloudApiUrl}}" + ], + "path": [ + "board", + "path" + ] + } + }, + "response": [] + }, + { + "name": "head board", + "request": { + "method": "GET", + "header": [], + "body": {}, + "url": { + "raw": "https://i2i2l4x9kl.execute-api.eu-west-1.amazonaws.com/PROD/guardian/identity/boards/head", "protocol": "https", "host": [ - "howwf2kle3", + "i2i2l4x9kl", "execute-api", "eu-west-1", "amazonaws", @@ -97,8 +101,40 @@ ], "path": [ "PROD", - "board", - "path" + "guardian", + "identity", + "boards", + "head" + ] + } + }, + "response": [] + }, + { + "name": "verify head path", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"name\": \"Get User\"\n}" + }, + "url": { + "raw": "{{tipCloudApiUrl}}/guardian/identity/boards/head/paths", + "host": [ + "{{tipCloudApiUrl}}" + ], + "path": [ + "guardian", + "identity", + "boards", + "head", + "paths" ] } }, diff --git a/cloud/tip-cloud.yaml b/cloud/tip-cloud.yaml index e4bb4d4..730ba1b 100644 --- a/cloud/tip-cloud.yaml +++ b/cloud/tip-cloud.yaml @@ -160,6 +160,45 @@ Resources: - ApiHeadResource - tipGetHeadBoardLambda + ApiHeadPathsResource: + Type: AWS::ApiGateway::Resource + Properties: + RestApiId: !Ref Api + ParentId: !Ref ApiHeadResource + PathPart: paths + DependsOn: + - Api + - ApiOwnerResource + - ApiRepoResource + - ApiBoardsResource + - ApiHeadResource + + ApiHeadPathsMethod: + Type: AWS::ApiGateway::Method + Properties: + ApiKeyRequired: false + AuthorizationType: NONE + RestApiId: !Ref Api + ResourceId: !Ref ApiHeadPathsResource + HttpMethod: PATCH + Integration: + Type: AWS_PROXY + IntegrationHttpMethod: POST + IntegrationResponses: + - StatusCode: '200' + Uri: !Sub arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/${tipVerifyHeadPathLambda.Arn}/invocations + MethodResponses: + - StatusCode: '200' + ResponseModels: { 'text/html': 'Empty' } + DependsOn: + - Api + - ApiOwnerResource + - ApiRepoResource + - ApiBoardsResource + - ApiHeadResource + - ApiHeadPathsResource + - tipVerifyHeadPathLambda + AllowApiGatewayToInvokeCreateBoardLambdaPermission: Type: AWS::Lambda::Permission Properties: @@ -180,6 +219,16 @@ Resources: - tipVerifyPathLambda - ApiBoardPathMethod + AllowApiGatewayToInvokeVerifyHeadPathLambdaPermission: + Type: AWS::Lambda::Permission + Properties: + Action: lambda:InvokeFunction + Principal: apigateway.amazonaws.com + FunctionName: !Sub arn:aws:lambda:eu-west-1:${AWS::AccountId}:function:tip-verify-head-path + DependsOn: + - tipVerifyHeadPathLambda + - ApiHeadPathsMethod + AllowApiGatewayToInvokeGetBoardLambdaPermission: Type: AWS::Lambda::Permission Properties: @@ -215,6 +264,7 @@ Resources: - AllowApiGatewayToInvokeVerifyPathLambdaPermission - AllowApiGatewayToInvokeGetBoardLambdaPermission - AllowApiGatewayToInvokeGetHeadBoardLambdaPermission + - AllowApiGatewayToInvokeVerifyHeadPathLambdaPermission # **************************************************************************** # Lambdas @@ -275,6 +325,20 @@ Resources: MemorySize: "128" Timeout: "10" + tipVerifyHeadPathLambda: + Type: "AWS::Lambda::Function" + Properties: + FunctionName: tip-verify-head-path + Description: Verify path on head (latest) board + Handler: "tip-verify-head-path.handler" + Role: !Sub arn:aws:iam::${AWS::AccountId}:role/lambda-dynamodb-full-access-role + Code: + S3Bucket: identity-lambda + S3Key: tip-cloud.zip + Runtime: nodejs8.10 + MemorySize: "128" + Timeout: "10" + # **************************************************************************** # Database # **************************************************************************** diff --git a/cloud/tip-get-head-board.js b/cloud/tip-get-head-board.js index c9ed0b9..2e2b043 100644 --- a/cloud/tip-get-head-board.js +++ b/cloud/tip-get-head-board.js @@ -17,6 +17,20 @@ const getLatestBoard = (boards) => .Items .sort((a,b) => new Date(b.deployTime) - new Date(a.deployTime))[0]; +const buildLinkToCommit = (repo, sha) => { + if (repo == sha) + return `https://github.com/${repo}/commit/master`; + else + return `https://github.com/${repo}/commit/${sha}`; +} + +const buildLinkToCommitHeader = (repo, sha) => { + if (repo == sha) + return `${repo}`; + else + return `${repo} ${sha}`; +} + const renderBoard = (item) => { return new Promise((resolve, reject) => { const pathsWithStatusColour = @@ -40,8 +54,6 @@ const renderBoard = (item) => { const deployTime = item.deployTime; const elapsedTimeSinceDeploy = Date.now() - Date.parse(deployTime); - const linkToCommit = `https://github.com/${repo}/commit/${sha}`; - const html = ` @@ -111,7 +123,7 @@ const renderBoard = (item) => {