Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Relic deployment records & Production TTA Plan import #376

Merged
merged 24 commits into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b1facb2
add app id's to .circleci
dcmcand Mar 10, 2021
3d249f4
add deployment notifications
dcmcand Mar 10, 2021
fe4ad01
update app id's
dcmcand Mar 11, 2021
ffc568c
add pipeline to parameters
dcmcand Mar 11, 2021
62fd63a
change pipeline.parameter.revision to pipeline.git.revision
dcmcand Mar 11, 2021
620ee14
deploy to sandbox
dcmcand Mar 11, 2021
3a0dea1
Squashed commit of the following:
dcmcand Mar 11, 2021
0cefbab
Squashed commit of the following:
dcmcand Mar 11, 2021
1c29f3e
Merge branch 'main' into cm-363-record-deployments
dcmcand Mar 11, 2021
e851018
fix merge conflict
dcmcand Mar 11, 2021
2782bf2
Squashed commit of the following:
dcmcand Mar 11, 2021
40f393e
Squashed commit of the following:
dcmcand Mar 11, 2021
0fc63b8
Merge branch 'main' into cm-363-record-deployments
dcmcand Mar 11, 2021
09c2521
update config.yml
dcmcand Mar 11, 2021
e3570ca
Merge branch 'main' into cm-363-record-deployments
dcmcand Mar 11, 2021
c369866
fix circleci parameters
dcmcand Mar 11, 2021
9bca319
update config.yml
dcmcand Mar 12, 2021
2c33c8a
add rest api key for new relic
dcmcand Mar 12, 2021
19cabc5
update app id parameter
dcmcand Mar 12, 2021
a88570d
Merge branch 'main' into cm-363-record-deployments
dcmcand Mar 12, 2021
215b0bb
Merge pull request #229 from adhocteam/cm-363-record-deployments
dcmcand Mar 12, 2021
68f12cc
Retrieve goal import CSVs from s3
rahearn Mar 12, 2021
66cf6d0
Linter fixes
rahearn Mar 12, 2021
008d2bd
Merge pull request #231 from adhocteam/goal-import-production
rahearn Mar 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,33 @@ commands:
- run:
name: Combine package-lock.json files to single file
command: cat yarn.lock frontend/yarn.lock > << parameters.filename >>
notify_new_relic:
description: "Notify new relic of a deploy"
parameters:
env_name:
description: "Name of the environment. Ex. sandbox, dev, staging, prod"
type: string
new_relic_app_id:
description: "App ID used in New Relic"
type: string
new_relic_api_key:
description: "API key from New Relic"
type: string
steps:
- run:
name: Notify New Relic
command: |
curl -X POST "https://api.newrelic.com/v2/applications/<< parameters.new_relic_app_id >>/deployments.json" \
-H "X-Api-Key: << parameters.new_relic_api_key >>" -i \
-H "Content-Type: application/json" \
-d \
"{
\"deployment\": {
\"revision\": \"<< pipeline.git.revision >>\",
\"description\": \"<< parameters.env_name >> Successfully Deployed\"
}
}"

cf_deploy:
description: "Login to cloud foundry space with service account credentials
and push application using deployment configuration file."
Expand Down Expand Up @@ -135,6 +162,18 @@ parameters:
sandbox_git_branch: # change to feature branch to test deployment
default: "cm-363-record-deployments"
type: string
prod_new_relic_app_id:
default: "877570491"
type: string
staging_new_relic_app_id:
default: "868729138"
type: string
dev_new_relic_app_id:
default: "867221900"
type: string
sandbox_new_relic_app_id:
default: "867346799"
type: string
jobs:
build_and_lint:
executor: docker-executor
Expand Down Expand Up @@ -319,6 +358,10 @@ jobs:
cf run-task tta-smarthub-sandbox \
--command "yarn db:migrate:prod" \
--name "Reset DB"
- notify_new_relic:
env_name: sandbox
new_relic_app_id: << pipeline.parameters.sandbox_new_relic_app_id >>
new_relic_api_key: $NEW_RELIC_REST_API_KEY
- when: # dev
condition:
and:
Expand All @@ -344,6 +387,10 @@ jobs:
cf run-task tta-smarthub-dev \
--command "yarn db:migrate:prod" \
--name "Reset DB"
- notify_new_relic:
env_name: dev
new_relic_app_id: << pipeline.parameters.dev_new_relic_app_id >>
new_relic_api_key: $NEW_RELIC_REST_API_KEY
- when: # staging
condition:
and:
Expand All @@ -367,6 +414,10 @@ jobs:
name: Run database migrations
command: |
cf run-task tta-smarthub-staging --command "yarn db:migrate:prod" --name migrate
- notify_new_relic:
env_name: staging
new_relic_app_id: << pipeline.parameters.staging_new_relic_app_id >>
new_relic_api_key: $NEW_RELIC_REST_API_KEY
- when: # prod
condition:
and:
Expand All @@ -390,6 +441,10 @@ jobs:
name: Run database migrations
command: |
cf run-task tta-smarthub-prod --command "yarn db:migrate:prod" --name migrate
- notify_new_relic:
env_name: prod
new_relic_app_id: << pipeline.parameters.prod_new_relic_app_id >>
new_relic_api_key: $NEW_RELIC_REST_API_KEY
workflows:
build_test_deploy:
jobs:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"server:debug": "nodemon src/index.js --exec babel-node --inspect",
"client": "yarn --cwd frontend start",
"test": "jest src --runInBand",
"test:ci": "cross-env JEST_JUNIT_OUTPUT_DIR=reports JEST_JUNIT_OUTPUT_NAME=unit.xml POSTGRES_USERNAME=postgres POSTGRES_DB=ttasmarthub CURRENT_USER_ID=5 CI=true jest src --coverage --reporters=default --reporters=jest-junit --forceExit",
"test:ci": "cross-env JEST_JUNIT_OUTPUT_DIR=reports JEST_JUNIT_OUTPUT_NAME=unit.xml POSTGRES_USERNAME=postgres POSTGRES_DB=ttasmarthub CURRENT_USER_ID=5 CI=true jest src --coverage --reporters=default --reporters=jest-junit",
"test:all": "yarn test:ci && yarn --cwd frontend test:ci",
"lint": "eslint src",
"lint:ci": "eslint -f eslint-formatter-multiple src",
Expand Down
12 changes: 6 additions & 6 deletions src/tools/importPlanGoals.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-loop-func */
import { readFileSync } from 'fs';
import parse from 'csv-parse/lib/sync';
import { downloadFile } from '../lib/s3';
import {
Role, Topic, RoleTopic, Goal, TopicGoal, Grant, GrantGoal,
} from '../models';
Expand All @@ -25,9 +25,9 @@ const hubRoles = [
{ name: 'SS', fullName: 'System Specialist' },
];

function parseCsv(file) {
async function parseCsv(fileKey) {
let grantees = {};
const csv = readFileSync(file);
const { Body: csv } = await downloadFile(fileKey);
[...grantees] = parse(csv, {
skipEmptyLines: true,
columns: true,
Expand Down Expand Up @@ -59,9 +59,9 @@ async function prePopulateRoles() {
* ...
* (Total 5 goals. Some of them could be empty)
*/
export default async function importGoals(file, region) {
const grantees = parseCsv(file);
const regionId = region || 14; // default to region 14
export default async function importGoals(fileKey, region) {
const grantees = await parseCsv(fileKey);
const regionId = region;
try {
const cleanRoleTopics = [];
const cleanGrantGoals = [];
Expand Down
62 changes: 54 additions & 8 deletions src/tools/importPlanGoals.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { readFileSync } from 'fs';
import importGoals from './importPlanGoals';
import { downloadFile } from '../lib/s3';
import db, {
Role, Topic, RoleTopic, Goal, Grantee, Grant,
} from '../models';

jest.mock('../lib/s3');

describe('Import TTA plan goals', () => {
afterAll(() => {
db.sequelize.close();
beforeEach(() => {
downloadFile.mockReset();
});
afterAll(async () => {
await db.sequelize.close();
});
it('should import Roles table', async () => {
const fileName = 'GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

await Role.destroy({ where: {} });
const rolesBefore = await Role.findAll();

expect(rolesBefore.length).toBe(0);
await importGoals('GranteeTTAPlanTest.csv');
await importGoals(fileName, 14);

const roles = await Role.findAll({
attributes: ['id', 'name', 'fullName'],
Expand Down Expand Up @@ -59,11 +69,14 @@ describe('Import TTA plan goals', () => {
});

it('should import Topics table', async () => {
const fileName = 'GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

await Topic.destroy({ where: {} });
const topicsBefore = await Topic.findAll();

expect(topicsBefore.length).toBe(0);
await importGoals('GranteeTTAPlanTest.csv');
await importGoals(fileName, 14);

const topics = await Topic.findAll();
expect(topics).toBeDefined();
Expand Down Expand Up @@ -104,11 +117,14 @@ describe('Import TTA plan goals', () => {
});

it('should import Goals table', async () => {
const fileName = 'GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

await Goal.destroy({ where: {} });
const goalsBefore = await Goal.findAll();

expect(goalsBefore.length).toBe(0);
await importGoals('GranteeTTAPlanTest.csv');
await importGoals(fileName, 14);

const allGoals = await Goal.findAll();
expect(allGoals).toBeDefined();
Expand Down Expand Up @@ -166,7 +182,10 @@ describe('Import TTA plan goals', () => {
});

it('should have Grantees Goals connection', async () => {
await importGoals('GranteeTTAPlanTest.csv');
const fileName = 'GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

await importGoals(fileName, 14);

// test eager loading
const grantee = await Grantee.findOne({
Expand All @@ -188,23 +207,29 @@ describe('Import TTA plan goals', () => {
});

it('should import RoleTopics table', async () => {
const fileName = 'GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

await Topic.destroy({ where: {} });

const roleTopicsBefore = await RoleTopic.findAll();

expect(roleTopicsBefore.length).toBe(0);
await importGoals('GranteeTTAPlanTest.csv', 14);
await importGoals(fileName, 14);

const roleTopics = await RoleTopic.findAll();
expect(roleTopics).toBeDefined();
expect(roleTopics.length).toBe(20);
});

it('should import goals from another region', async () => {
const fileName = 'R9GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

const goalsBefore = await Goal.findAll();

expect(goalsBefore.length).toBe(12);
await importGoals('R9GranteeTTAPlanTest.csv', 9);
await importGoals(fileName, 9);

const allGoals = await Goal.findAll();
expect(allGoals).toBeDefined();
Expand Down Expand Up @@ -273,4 +298,25 @@ describe('Import TTA plan goals', () => {
});
expect(goalWithTopic.topics[0].roles[0].fullName).toBe('Grantee Specialist');
});

it('is idempotent', async () => {
const fileName = 'GranteeTTAPlanTest.csv';
downloadFile.mockResolvedValue({ Body: readFileSync(fileName) });

await Goal.destroy({ where: {} });
const goalsBefore = await Goal.findAll();

expect(goalsBefore.length).toBe(0);
await importGoals(fileName, 14);

const allGoals = await Goal.findAll();
expect(allGoals).toBeDefined();
expect(allGoals.length).toBe(12);

await importGoals(fileName, 14);

const allGoals2 = await Goal.findAll();
expect(allGoals2).toBeDefined();
expect(allGoals2.length).toBe(12);
});
});
21 changes: 9 additions & 12 deletions src/tools/importTTAPlanGoals.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {} from 'dotenv/config';
import { option } from 'yargs';
import importGoals from './importPlanGoals';
import { logger } from '../logger';

const { argv } = option('file', {
alias: 'f',
Expand All @@ -13,21 +15,16 @@ const { argv } = option('file', {
.help()
.alias('help', 'h');

const defaultInputFile = './GranteeTTAPlan.csv';
const defaultRegion = 14;
const { file, region } = argv;

let file;
let region;
if (argv.file) {
file = argv.file;
} else {
file = defaultInputFile;
if (!file) {
logger.error('File not provided to importTTAPlanGoals');
process.exit(1);
}

if (argv.region) {
region = argv.region;
} else {
region = defaultRegion;
if (!region) {
logger.error('Region not provided to importTTAPlanGoals');
process.exit(1);
}

importGoals(file, region);