Skip to content
This repository has been archived by the owner on Jul 26, 2021. It is now read-only.

Commit

Permalink
Make board sha optional
Browse files Browse the repository at this point in the history
  • Loading branch information
Mario Galic committed Sep 9, 2018
1 parent 7f4000f commit 0b74e0c
Show file tree
Hide file tree
Showing 11 changed files with 253 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
1 change: 1 addition & 0 deletions cloud/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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."
88 changes: 62 additions & 26 deletions cloud/postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
},
"item": [
{
"_postman_id": "2cf06285-c485-460a-9b73-c62572b71c21",
"name": "create board",
"request": {
"method": "POST",
Expand All @@ -18,28 +17,21 @@
],
"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"
]
}
},
"response": []
},
{
"_postman_id": "c059d627-f1a9-4c64-a7f4-908d7b3fda78",
"name": "get board",
"request": {
"method": "GET",
Expand All @@ -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",
Expand All @@ -83,22 +68,73 @@
],
"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",
"com"
],
"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"
]
}
},
Expand Down
64 changes: 64 additions & 0 deletions cloud/tip-cloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -215,6 +264,7 @@ Resources:
- AllowApiGatewayToInvokeVerifyPathLambdaPermission
- AllowApiGatewayToInvokeGetBoardLambdaPermission
- AllowApiGatewayToInvokeGetHeadBoardLambdaPermission
- AllowApiGatewayToInvokeVerifyHeadPathLambdaPermission

# ****************************************************************************
# Lambdas
Expand Down Expand Up @@ -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
# ****************************************************************************
Expand Down
20 changes: 16 additions & 4 deletions cloud/tip-get-head-board.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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 = `
<!DOCTYPE html>
<html>
Expand Down Expand Up @@ -111,7 +123,7 @@ const renderBoard = (item) => {
<div id="container">
<h3>
<a href="${linkToCommit}">${repo} ${sha}</a>
<a href="${buildLinkToCommit(repo, sha)}">${buildLinkToCommitHeader(repo, sha)}</a>
</h3>
<hr>
Expand Down Expand Up @@ -164,4 +176,4 @@ exports.handler = (event, context, callback) => {
.then(boards => getLatestBoard(boards))
.then(latestBoard => renderBoard(latestBoard))
.then(boardAsHtml => callback(null, boardAsHtml));
};
};
46 changes: 46 additions & 0 deletions cloud/tip-verify-head-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-1'});
const ddb = new AWS.DynamoDB.DocumentClient();

function updateBoard(dbItem) {
ddb.put(
{
TableName: 'TipCloud-PROD',
Item: dbItem
}
).promise();
}

const getBoards = (repo) => {
return ddb.scan(
{
TableName: 'TipCloud-PROD',
FilterExpression : 'repo = :repo',
ExpressionAttributeValues : {':repo' : `${repo}`}
}
).promise();
}

function verifyPath(boards, path) {
return new Promise((resolve, reject) => {
const sortedBoards = boards.Items.sort((a,b) => new Date(b.deployTime) - new Date(a.deployTime));
const headBoard = sortedBoards[0];
const index = headBoard.board.findIndex(element => element.name === path);
headBoard.board[index] = { name: path, verified: true };
resolve(headBoard);
});
}

exports.handler = (event, context, callback) => {
const owner = event.pathParameters.owner;
const repo = event.pathParameters.repo;
const slug = `${owner}/${repo}`;

const body = JSON.parse(event.body);
const name = body.name;

getBoards(slug)
.then(data => verifyPath(data, name))
.then(dbItem => updateBoard(dbItem))
.then(() => callback(null, {statusCode: 200, body: null}));
};
7 changes: 3 additions & 4 deletions src/main/scala/com/gu/tip/Configuration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import scala.io.Source

case class TipConfig(owner: String,
repo: String,
cloudEnabled: Boolean = true,
boardSha: String = "",
personalAccessToken: String = "",
label: String = "",
boardSha: String = "")
label: String = "")

class TipConfigurationException(
msg: String = "Missing TiP config. Please refer to README.")
Expand Down Expand Up @@ -64,8 +65,6 @@ class Configuration(config: TipConfig) {
case e: FileNotFoundException => throw new MissingPathConfigurationFile
case _ => throw new PathConfigurationSyntaxError
}.get

def cloudEnabled: Boolean = tipConfig.boardSha.nonEmpty
}

trait ConfigurationIf {
Expand Down
Loading

0 comments on commit 0b74e0c

Please sign in to comment.