From 76c64a581df530f34f9531b4fb7413eca482703d Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 22 Dec 2020 16:06:24 +0530 Subject: [PATCH 01/23] Add the performance testing code --- .circleci/config.yml | 62 ++- JMeter_README.md | 153 ++++++++ pom.xml | 241 ++++++++++++ .../jmeter/15UV Ultimate Thread-Group.jmx | 357 ++++++++++++++++++ src/test/jmeter/path.csv | 9 + src/test/jmeter/projects.csv | 101 +++++ 6 files changed, 917 insertions(+), 6 deletions(-) create mode 100644 JMeter_README.md create mode 100644 pom.xml create mode 100644 src/test/jmeter/15UV Ultimate Thread-Group.jmx create mode 100644 src/test/jmeter/path.csv create mode 100644 src/test/jmeter/projects.csv diff --git a/.circleci/config.yml b/.circleci/config.yml index d9851d0d..0800f707 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -40,7 +40,7 @@ deploy_steps: &deploy_steps ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -s ${LOGICAL_ENV}-global-appvar,${LOGICAL_ENV}-${APPNAME}-appvar -i ${APPNAME} jobs: - test: + build: docker: - image: circleci/node:12.16.1 - image: circleci/postgres:9.6.2-alpine @@ -102,23 +102,73 @@ jobs: APPNAME: "projects-api" steps: *deploy_steps + Connect-Performance-Testing: + docker: + # specify the version you desire here + - image: circleci/openjdk:8-jdk + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/postgres:9.4 + + working_directory: ~/repo + + environment: + # Customize the JVM maximum heap limit + MAVEN_OPTS: -Xmx3200m + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "pom.xml" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: mvn dependency:go-offline + + - save_cache: + paths: + - ~/.m2 + key: v1-dependencies-{{ checksum "pom.xml" }} + + - run: mvn verify + + - store_artifacts: + path: target/jmeter/reports + + - store_test_results: + path: target/jmeter/test-results + workflows: version: 2 - build: + Connect Project Services: jobs: - - test: + - build: context : org-global - deployDev: context : org-global requires: - - test + - build filters: branches: only: ['develop'] - deployProd: context : org-global requires: - - test + - build filters: branches: - only: ['master'] + only: ['master'] + - Hold [Performance-Testing]: + type: approval + requires: + - build + - deployDev + - deployProd + - Connect-Performance-Testing: + requires: + - Hold [Performance-Testing] \ No newline at end of file diff --git a/JMeter_README.md b/JMeter_README.md new file mode 100644 index 00000000..713c28e4 --- /dev/null +++ b/JMeter_README.md @@ -0,0 +1,153 @@ +# Performance Testing for Topcoder Connect App + +## Description + +Topcoder Connect is a web application that makes it easy to tap into the power of crowdsourcing to get more work done faster. Connect is ideal for projects that include application design and/or development work. You can crowdsource the entire application development lifecycle or just the specific stages where you need help. Common deliverables include application wireframes, UI/UX designs, prototypes, MVPs, and production-ready apps for any kind of device—mobile, wearables, or the web. + +## Dependencies + +- Jmeter maven plugin 2.9.0 +- Maven 3.5.2 +- JDK between 8 and 11 + +## Prerequisite + +- We have already included the workflow into the circleci conf file with the usual dev builds. + +## Directory Structure + +- .circleci (Circleci configuration file) +- \src\test\jmeter - Includes the JMX file(s) and CSV data files +- pom file + +### **Setup and Runtime** + +Add the plugin to your project: Add the plugin to the build section of your pom's project + +``` + + com.lazerycode.jmeter + jmeter-maven-plugin + 3.2.0 + + + + configuration + + configure + + + + + jmeter-tests + + jmeter + + + + + jmeter-check-results + + results + + + + +``` + +This simple load test is already integrated with the current build process + +``` +workflows: + version: 2 + Connect Project Services: + jobs: + - build: + context : org-global + - deployDev: + context : org-global + requires: + - build + filters: + branches: + only: ['develop'] + - deployProd: + context : org-global + requires: + - build + filters: + branches: + only: ['master'] + - Hold [Performance-Testing]: + type: approval + requires: + - build + - deployDev + - deployProd + - Connect-Performance-Testing: + requires: + - Hold [Performance-Testing] +``` + +- Hold [Performance-Testing] - This is the approval job we needs manual interaction. +- It requires `build`, `deployDev` and `deployProd` jobs to run first. +- Actual performance testing job is `Connect-Performance-Testing` and it requires `Hold [Performance-Testing]` job to finish. + +### **Configuration** + + + + +This performance test is for 15 virtual users. The parameters for this test plan is as below; + +- Start Thread Count +- Initial Deplay, sec (Startup Time + Hold Load For) +- Startup Time, sec (Start Thread Count = Startup Time) +- Hold Load For, sec +- Shutdown Time (Next row `Initial Deplay`) + +**Formulas:** + +``` +Initial time of a record = initialtime + start up time/ramp-up time + holdtime of the previous record +``` + +``` +start up time/ramp-up time = Shutdown time/ramp-down time of the previous record +``` + +This setup is configured to run 6min with 15 UVs. + +**Token Details** + +- `audience` - https://m2m.topcoder-dev.com/ +- `grant_type` - client_credentials +- `content-type` - application/json +- `client_id` - jGIf2pd3f44B1jqvOai30BIKTZanYBfU +- `client_secret` - ldzqVaVEbqhwjM5KtZ79sG8djZpAVK8Z7qieVcC3vRjI4NirgcinKSBpPwk6mYYP + +To extract the token we are using the variable `access_token` + +TO pass the `access_token` varaible globally we are using the beanshell Assertion + +`${__setProperty(access_token, ${access_token})};` + +**Random Controller** + +We are using Random Controller to randomize the requests sent to the server to simulate the different request. + +**Think Time** + +We are using this parameter to implement a random wait time in betweent the request to simulate the real user experience. + +**HTTP Requets** + +- Access Tabs - Simulate user accessing different tabs +- Access Projects - Simulate user accessing different projetcs +- Assets Library (Link Insert) - Add Links to the projects + +## Check the reports and data + +After running the job using the circleci user can view the report by clicking on the Job: `Connect-Performance-Testing` > Artifacts > `target/jmeter/reports/15UV Ultimate Thread-Group/index.html` + +eg: https://2728-60865675-gh.circle-artifacts.com/0/target/jmeter/reports/15UV%20Ultimate%20Thread-Group/index.html \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..8cb902e2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,241 @@ + + 4.0.0 + com.ubikingenierie.ubikloadpack + jmeter-maven-plugin-demo + 0.0.1-SNAPSHOT + + UTF-8 + + 2.9.0 + + + + commons-codec + commons-codec + 1.11 + + + org.slf4j + slf4j-api + 1.7.25 + + + org.apache.jmeter + ApacheJMeter_core + 5.1 + + + + + + + + + + standalone + + true + + + + + com.lazerycode.jmeter + jmeter-maven-plugin + ${jmeter-maven-plugin.version} + + true + 60 + false + + ${project.version} + 7 + 30 + + + kg.apc:jmeter-plugins-casutg:2.8 + + + com.ubikingenierie.ubikloadpack:jmeter-maven-plugin-demo:${project.version} + + + org.slf4j:slf4j-nop + avalon-framework:* + org.apache.tika:* + excalibur-datasource:excalibur-datasource + excalibur-instrument:excalibur-instrument + excalibur-logger:excalibur-logger + excalibur-pool:* + org.beanshell:bsh:jar:2.0b5 + + + + -XX:MaxMetaspaceSize=256m + -Xmx1024m + -Xms1024m + + + + + + jmeter-tests + verify + + + + jmeter + results + + + + + + + + + worker + + + + org.codehaus.groovy.maven + gmaven-plugin + 1.0 + + + generate-resources + + execute + + + + project.properties["hostname"] = InetAddress.getLocalHost().getHostName() + + + + + + + com.lazerycode.jmeter + jmeter-maven-plugin + ${jmeter-maven-plugin.version} + + + true + + + kg.apc:jmeter-plugins-casutg:2.8 + + + com.ubikingenierie.ubikloadpack:jmeter-maven-plugin-demo:${project.version} + + + org.slf4j:slf4j-nop + avalon-framework:* + org.apache.tika:* + excalibur-datasource:excalibur-datasource + excalibur-instrument:excalibur-instrument + excalibur-logger:excalibur-logger + excalibur-pool:* + org.beanshell:bsh:jar:2.0b5 + + + + -XX:MaxMetaspaceSize=256m + -Xmx1024m + -Xms1024m + + + ${hostname} + 3010 + + + + start-jmeter-server + + + + remote-server + + verify + + false + + + + + + + + + + controller + + + + com.lazerycode.jmeter + jmeter-maven-plugin + ${jmeter-maven-plugin.version} + + + true + + + ${project.version} + 7 + 30 + + true + + kg.apc:jmeter-plugins-casutg:2.8 + + + com.ubikingenierie.ubikloadpack:jmeter-maven-plugin-demo:${project.version} + + + org.slf4j:slf4j-nop + avalon-framework:* + org.apache.tika:* + excalibur-datasource:excalibur-datasource + excalibur-instrument:excalibur-instrument + excalibur-logger:excalibur-logger + excalibur-pool:* + org.beanshell:bsh:jar:2.0b5 + + + + -XX:MaxMetaspaceSize=256m + -Xmx1024m + -Xms1024m + + + + ${serverList} + true + + + + + performance-test + + + + jmeter + results + + verify + + + + + + + + \ No newline at end of file diff --git a/src/test/jmeter/15UV Ultimate Thread-Group.jmx b/src/test/jmeter/15UV Ultimate Thread-Group.jmx new file mode 100644 index 00000000..2135f040 --- /dev/null +++ b/src/test/jmeter/15UV Ultimate Thread-Group.jmx @@ -0,0 +1,357 @@ + + + + + Check the Performance of the Connect App + false + true + false + + + + + + + + Retrive the token + continue + + false + 1 + + 1 + 1 + false + + + true + + + + + + + false + https://m2m.topcoder-dev.com/ + = + true + audience + + + false + client_credentials + = + true + grant_type + + + false + application/json + = + true + content-type + + + false + jGIf2pd3f44B1jqvOai30BIKTZanYBfU + = + true + client_id + + + false + ldzqVaVEbqhwjM5KtZ79sG8djZpAVK8Z7qieVcC3vRjI4NirgcinKSBpPwk6mYYP + = + true + client_secret + + + + topcoder-dev.auth0.com + + https + + /oauth/token + POST + true + false + true + false + + + + + + + Get the {access_token} + access_token + access_token + + + + + Set the {access_token} globally + ${__setProperty(access_token, ${access_token})}; + + + false + + + + + + + 5 + 0 + 5 + 60 + 10 + + + 10 + 65 + 10 + 60 + 10 + + + 10 + 135 + 10 + 120 + 10 + + + 10 + 265 + 10 + 60 + 10 + + + 5 + 335 + 5 + 60 + 0 + + + + false + -1 + + Check the server is holding for 25 VU at any point + +Initial time of a record = initialtime + start up time/ramp-up time + holdtime of the previous record +start up time/ramp-up time = Shutdown time/ramp-down time of the previous record + continue + + + + 1 + + + + 1 + 0 + 0 + + + + 1000 + 100 + + + + + + + + api.topcoder-dev.com + + https + + ${path} + GET + true + false + true + false + + + + User accessing different tabs All Projects, Active, In Review, Reviewed, Completed, Cancelled and Paused + + + + path.csv + + + false + , + false + true + false + shareMode.all + + + + + + Authorization + Bearer ${__property(access_token)} + + + + + + + + + + api.topcoder-dev.com + + https + + /v5/projects/${projects} + GET + true + false + true + false + + + + User accessing different projects from the list + + + + + projects.csv + + + false + , + false + true + false + shareMode.all + + + + + + Authorization + Bearer ${__property(access_token)} + + + + + + + + + + false + link + = + true + type + + + false + JMeter Performance Test Link Addition + = + true + title + + + false + https://connect.topcoder-dev.com/ + = + true + path + + + + api.topcoder-dev.com + + https + + /v5/projects/${projects}/attachments + POST + true + false + true + false + + + + User accessing different projects from the list + + + + + projects.csv + + + false + , + false + true + false + shareMode.all + + + + + + Authorization + Bearer ${__property(access_token)} + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + diff --git a/src/test/jmeter/path.csv b/src/test/jmeter/path.csv new file mode 100644 index 00000000..330442cc --- /dev/null +++ b/src/test/jmeter/path.csv @@ -0,0 +1,9 @@ +path +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1 +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1&status=in_review +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1&status=active +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1&status=reviewed4 +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1&status=completed +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1&status=cancelled +/v5/projects/?fields=id,name,description,members,invites,status,type,actualPrice,estimatedPrice,createdAt,updatedAt,createdBy,updatedBy,details,lastActivityAt,lastActivityUserId,version,templateId&sort=lastActivityAt+desc&perPage=20&page=1&status=paused +/v5/projects/metadata/orgConfig?orgId=20000001,20000014,d6bf6bb6-457c-461c-a4d6-0a6b1a87fde9,f325869a-ab0d-47b1-af28-4e117709ca71 \ No newline at end of file diff --git a/src/test/jmeter/projects.csv b/src/test/jmeter/projects.csv new file mode 100644 index 00000000..1c3e75f7 --- /dev/null +++ b/src/test/jmeter/projects.csv @@ -0,0 +1,101 @@ +projects +16685 +16684 +16683 +16682 +16681 +16680 +16679 +16678 +16677 +16676 +16675 +16674 +16673 +16672 +16671 +16670 +16669 +16668 +16667 +16666 +16665 +16664 +16663 +16662 +16661 +16660 +16659 +16658 +16657 +16656 +16655 +16654 +16653 +16652 +16651 +16650 +16649 +16648 +16647 +16646 +16645 +16644 +16643 +16642 +16641 +16640 +16639 +16638 +16637 +16636 +16635 +16634 +16633 +16632 +16631 +16630 +16629 +16628 +16627 +16626 +16625 +16624 +16623 +16622 +16621 +16620 +16619 +16618 +16617 +16616 +16615 +16614 +16613 +16612 +16611 +16610 +16609 +16608 +16607 +16606 +16605 +16604 +16603 +16602 +16601 +16600 +16599 +16598 +16597 +16596 +16595 +16594 +16593 +16592 +16591 +16590 +16589 +16588 +16587 +16586 \ No newline at end of file From accc73ae4101e63bc4220f5cd3140511b29c55ca Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 22 Dec 2020 16:59:04 +0530 Subject: [PATCH 02/23] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9302d11a..152763b1 100644 --- a/README.md +++ b/README.md @@ -357,6 +357,10 @@ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbmlzdHJhdG9yIl0sImlzcyI ``` It's been signed with the secret 'secret'. This secret should match your entry in config/local.js. You can generate your own token using https://jwt.io +## Performance Testing + +- [Performance Testing Readme](README.md) + ## Documentation - [Projects Service Architecture](./docs/guides/architercture/architecture.md) From c05fc864be3124023a1df88a762057b0fd73cb1c Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 22 Dec 2020 18:52:48 +0530 Subject: [PATCH 03/23] Update config.yml --- .circleci/config.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0800f707..1ec2e230 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -139,9 +139,6 @@ jobs: - store_artifacts: path: target/jmeter/reports - - - store_test_results: - path: target/jmeter/test-results workflows: version: 2 @@ -155,7 +152,7 @@ workflows: - build filters: branches: - only: ['develop'] + only: ['develop', 'connect-performance-testing'] - deployProd: context : org-global requires: From ff43cb4344ecb490472a5abb2f9c564b1e57c384 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Wed, 23 Dec 2020 19:15:41 +0530 Subject: [PATCH 04/23] Update config.yml --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1ec2e230..6c690908 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -40,7 +40,7 @@ deploy_steps: &deploy_steps ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -s ${LOGICAL_ENV}-global-appvar,${LOGICAL_ENV}-${APPNAME}-appvar -i ${APPNAME} jobs: - build: + test: docker: - image: circleci/node:12.16.1 - image: circleci/postgres:9.6.2-alpine @@ -144,26 +144,26 @@ workflows: version: 2 Connect Project Services: jobs: - - build: + - test: context : org-global - deployDev: context : org-global requires: - - build + - test filters: branches: only: ['develop', 'connect-performance-testing'] - deployProd: context : org-global requires: - - build + - test filters: branches: only: ['master'] - Hold [Performance-Testing]: type: approval requires: - - build + - test - deployDev - deployProd - Connect-Performance-Testing: From 7d712748a8bb1f70f868dd574c94842efb43e8b9 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Wed, 6 Jan 2021 11:50:15 +0530 Subject: [PATCH 05/23] Update config.yml --- .circleci/config.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c690908..17d467bb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -148,22 +148,17 @@ workflows: context : org-global - deployDev: context : org-global - requires: - - test filters: branches: only: ['develop', 'connect-performance-testing'] - deployProd: context : org-global - requires: - - test filters: branches: only: ['master'] - Hold [Performance-Testing]: type: approval requires: - - test - deployDev - deployProd - Connect-Performance-Testing: From 3009b3d4a966e38871b45658f072c6bb2d708fe5 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Wed, 6 Jan 2021 11:57:34 +0530 Subject: [PATCH 06/23] Update config.yml --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 17d467bb..994ee4b0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -148,6 +148,8 @@ workflows: context : org-global - deployDev: context : org-global + requires: + - test filters: branches: only: ['develop', 'connect-performance-testing'] From a30c70319321f10b9c04a210cee553d2755540dc Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Wed, 6 Jan 2021 12:27:24 +0530 Subject: [PATCH 07/23] Update JMeter_README.md --- JMeter_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JMeter_README.md b/JMeter_README.md index 713c28e4..64e2e085 100644 --- a/JMeter_README.md +++ b/JMeter_README.md @@ -150,4 +150,4 @@ We are using this parameter to implement a random wait time in betweent the requ After running the job using the circleci user can view the report by clicking on the Job: `Connect-Performance-Testing` > Artifacts > `target/jmeter/reports/15UV Ultimate Thread-Group/index.html` -eg: https://2728-60865675-gh.circle-artifacts.com/0/target/jmeter/reports/15UV%20Ultimate%20Thread-Group/index.html \ No newline at end of file +eg: https://2728-60865675-gh.circle-artifacts.com/0/target/jmeter/reports/15UV%20Ultimate%20Thread-Group/index.html From ac6312d4419d8cc95a8238c0506fda87b990b8fb Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Wed, 6 Jan 2021 14:53:17 +0530 Subject: [PATCH 08/23] Update config.yml --- .circleci/config.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 994ee4b0..d47e9423 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -144,12 +144,8 @@ workflows: version: 2 Connect Project Services: jobs: - - test: - context : org-global - deployDev: context : org-global - requires: - - test filters: branches: only: ['develop', 'connect-performance-testing'] From bf6f03d30c49cb85154de72172c80c9a1de1fbbc Mon Sep 17 00:00:00 2001 From: maxceem Date: Wed, 6 Jan 2021 18:52:53 +0200 Subject: [PATCH 09/23] Revert "chore: temporary disable jobs creation" This reverts commit 7269344ed09dcd199bafa573136919f6bb8438d7. --- src/events/projects/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index cc109d6b..7810e361 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -187,8 +187,7 @@ async function projectCreatedKafkaHandler(app, topic, payload) { await Promise.all(topicPromises); app.logger.debug('Topics for phases are successfully created.'); } - // TODO: temporary disable this feature, until we release TaaS APP - if (false === true && project.type === 'talent-as-a-service') { + if (project.type === 'talent-as-a-service') { const specialists = _.get(project, 'details.taasDefinition.specialists'); if (!specialists || !specialists.length) { app.logger.debug(`no specialists found in the project ${project.id}`); From 8a3544a663478079218f1d93ee87a52ba73f1737 Mon Sep 17 00:00:00 2001 From: maxceem Date: Thu, 7 Jan 2021 13:22:29 +0200 Subject: [PATCH 10/23] feat: updated TaaS Job creation data --- src/events/projects/index.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index 7810e361..3db2ccef 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -188,40 +188,41 @@ async function projectCreatedKafkaHandler(app, topic, payload) { app.logger.debug('Topics for phases are successfully created.'); } if (project.type === 'talent-as-a-service') { - const specialists = _.get(project, 'details.taasDefinition.specialists'); - if (!specialists || !specialists.length) { + const jobs = _.get(project, 'details.taasDefinition.jobs'); + if (!jobs || !jobs.length) { app.logger.debug(`no specialists found in the project ${project.id}`); return; } - const targetSpecialists = _.filter(specialists, specialist => Number(specialist.people) > 0); // must be at least one people + const targetJobs = _.filter(jobs, job => Number(job.people) > 0); // must be at least one people await Promise.all( _.map( - targetSpecialists, - (specialist) => { + targetJobs, + (job) => { const startDate = new Date(); - const endDate = moment(startDate).add(Number(specialist.duration), 'M'); // the unit of duration is month + const endDate = moment(startDate).add(Number(job.duration), 'M'); // the unit of duration is month // make sure that skills would be unique in the list const skills = _.uniq( // use both, required and additional skills for jobs - specialist.skills.concat(specialist.additionalSkills) + job.skills.concat(job.additionalSkills) // only include skills with `skillId` and ignore custom skills in jobs .filter(skill => skill.skillId).map(skill => skill.skillId), ); return createTaasJob({ projectId: project.id, externalId: '0', // hardcode for now - description: specialist.roleTitle, + title: job.title, + description: job.description, startDate, endDate, skills, - numPositions: Number(specialist.people), - resourceType: specialist.role, + numPositions: Number(job.people), + resourceType: _.get(job, 'role.value', ''), rateType: 'hourly', // hardcode for now - workload: _.get(specialist, 'workLoad.title', '').toLowerCase(), - }).then((job) => { - app.logger.debug(`jobId: ${job.id} job created for roleTitle ${specialist.roleTitle}`); + workload: _.get(job, 'workLoad.title', '').toLowerCase(), + }).then((createdJob) => { + app.logger.debug(`jobId: ${createdJob.id} job created with title "${createdJob.title}"`); }).catch((err) => { - app.logger.error(`Unable to create job for ${specialist.roleTitle}: ${err.message}`); + app.logger.error(`Unable to create job for ${job.title}: ${err.message}`); }); }, ), From f94ae6a5eabf31f458c615aef769a6f72883b6bb Mon Sep 17 00:00:00 2001 From: maxceem Date: Thu, 7 Jan 2021 16:39:45 +0200 Subject: [PATCH 11/23] fix: creating taas jobs --- src/events/projects/index.js | 79 ++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index 3db2ccef..f12cb895 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -175,7 +175,6 @@ async function projectCreatedKafkaHandler(app, topic, payload) { if (result.error) { throw new Error(result.error); } - const project = payload; if (project.phases && project.phases.length > 0) { @@ -187,46 +186,46 @@ async function projectCreatedKafkaHandler(app, topic, payload) { await Promise.all(topicPromises); app.logger.debug('Topics for phases are successfully created.'); } - if (project.type === 'talent-as-a-service') { - const jobs = _.get(project, 'details.taasDefinition.jobs'); - if (!jobs || !jobs.length) { - app.logger.debug(`no specialists found in the project ${project.id}`); - return; + try { + if (project.type === 'talent-as-a-service') { + const jobs = _.get(project, 'details.taasDefinition.jobs'); + if (!jobs || !jobs.length) { + app.logger.debug(`no jobs found in the project id: ${project.id}`); + return; + } + app.logger.debug(`${jobs.length} jobs found in the project id: ${project.id}`); + await Promise.all( + _.map( + jobs, + (job) => { + const startDate = new Date(); + const endDate = moment(startDate).add(Number(job.duration), 'M'); // the unit of duration is month + // make sure that skills would be unique in the list and only include ones with 'skillId' (actually they all suppose to be with skillId) + const skills = _.chain(job.skills).map('skillId').uniq().compact() + .value(); + return createTaasJob({ + projectId: project.id, + externalId: '0', // hardcode for now + title: job.title, + description: job.description, + startDate, + endDate, + skills, + numPositions: Number(job.people), + resourceType: _.get(job, 'role.value', ''), + rateType: 'hourly', // hardcode for now + workload: _.get(job, 'workLoad.title', '').toLowerCase(), + }).then((createdJob) => { + app.logger.debug(`jobId: ${createdJob.id} job created with title "${createdJob.title}"`); + }).catch((err) => { + app.logger.error(`Unable to create job with title "${job.title}": ${err.message}`); + }); + }, + ), + ); } - const targetJobs = _.filter(jobs, job => Number(job.people) > 0); // must be at least one people - await Promise.all( - _.map( - targetJobs, - (job) => { - const startDate = new Date(); - const endDate = moment(startDate).add(Number(job.duration), 'M'); // the unit of duration is month - // make sure that skills would be unique in the list - const skills = _.uniq( - // use both, required and additional skills for jobs - job.skills.concat(job.additionalSkills) - // only include skills with `skillId` and ignore custom skills in jobs - .filter(skill => skill.skillId).map(skill => skill.skillId), - ); - return createTaasJob({ - projectId: project.id, - externalId: '0', // hardcode for now - title: job.title, - description: job.description, - startDate, - endDate, - skills, - numPositions: Number(job.people), - resourceType: _.get(job, 'role.value', ''), - rateType: 'hourly', // hardcode for now - workload: _.get(job, 'workLoad.title', '').toLowerCase(), - }).then((createdJob) => { - app.logger.debug(`jobId: ${createdJob.id} job created with title "${createdJob.title}"`); - }).catch((err) => { - app.logger.error(`Unable to create job for ${job.title}: ${err.message}`); - }); - }, - ), - ); + } catch (error) { + app.logger.error(`Error while creating TaaS jobs: ${error}`); } } From 4ff4dac7ac88192eae3a6df1436eb125d2d94cd8 Mon Sep 17 00:00:00 2001 From: maxceem Date: Thu, 7 Jan 2021 20:57:30 +0200 Subject: [PATCH 12/23] fix: rename field of TaaS Jobs --- src/events/projects/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index f12cb895..263f73c7 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -188,7 +188,7 @@ async function projectCreatedKafkaHandler(app, topic, payload) { } try { if (project.type === 'talent-as-a-service') { - const jobs = _.get(project, 'details.taasDefinition.jobs'); + const jobs = _.get(project, 'details.taasDefinition.taasJobs'); if (!jobs || !jobs.length) { app.logger.debug(`no jobs found in the project id: ${project.id}`); return; From f6177a1355acd2168a2d4166bc2dfe69909b3475 Mon Sep 17 00:00:00 2001 From: maxceem Date: Mon, 11 Jan 2021 22:56:09 +0200 Subject: [PATCH 13/23] fix: use "weekly" rateType for create jobs --- src/events/projects/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index 263f73c7..8e87f9e3 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -213,7 +213,7 @@ async function projectCreatedKafkaHandler(app, topic, payload) { skills, numPositions: Number(job.people), resourceType: _.get(job, 'role.value', ''), - rateType: 'hourly', // hardcode for now + rateType: 'weekly', // hardcode for now workload: _.get(job, 'workLoad.title', '').toLowerCase(), }).then((createdJob) => { app.logger.debug(`jobId: ${createdJob.id} job created with title "${createdJob.title}"`); From b2f1a4390e2c49a8bbfd79547d9c720dc8695e5d Mon Sep 17 00:00:00 2001 From: maxceem Date: Tue, 12 Jan 2021 09:02:08 +0200 Subject: [PATCH 14/23] feat: don't set unknown fields for Jobs --- src/events/projects/index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index 8e87f9e3..fd9d2738 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -198,18 +198,13 @@ async function projectCreatedKafkaHandler(app, topic, payload) { _.map( jobs, (job) => { - const startDate = new Date(); - const endDate = moment(startDate).add(Number(job.duration), 'M'); // the unit of duration is month // make sure that skills would be unique in the list and only include ones with 'skillId' (actually they all suppose to be with skillId) const skills = _.chain(job.skills).map('skillId').uniq().compact() .value(); return createTaasJob({ projectId: project.id, - externalId: '0', // hardcode for now title: job.title, description: job.description, - startDate, - endDate, skills, numPositions: Number(job.people), resourceType: _.get(job, 'role.value', ''), From 2581421527f5f38de9c6c355582827fbfa201a97 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:11:06 +0530 Subject: [PATCH 15/23] Add unit test to the circleci conf file --- .circleci/config.yml | 4 +++- src/test/jmeter/15UV Ultimate Thread-Group.jmx | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d47e9423..ddcddb9d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -40,7 +40,7 @@ deploy_steps: &deploy_steps ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -s ${LOGICAL_ENV}-global-appvar,${LOGICAL_ENV}-${APPNAME}-appvar -i ${APPNAME} jobs: - test: + UnitTests: docker: - image: circleci/node:12.16.1 - image: circleci/postgres:9.6.2-alpine @@ -144,6 +144,8 @@ workflows: version: 2 Connect Project Services: jobs: + - UnitTests: + context : org-global - deployDev: context : org-global filters: diff --git a/src/test/jmeter/15UV Ultimate Thread-Group.jmx b/src/test/jmeter/15UV Ultimate Thread-Group.jmx index 2135f040..fb616889 100644 --- a/src/test/jmeter/15UV Ultimate Thread-Group.jmx +++ b/src/test/jmeter/15UV Ultimate Thread-Group.jmx @@ -204,6 +204,10 @@ start up time/ramp-up time = Shutdown time/ramp-down time of the previous record + + 100 + + From c0599abde4796e39cb31f915a22f8713caa03093 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:12:41 +0530 Subject: [PATCH 16/23] Update config.yml --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index ddcddb9d..04dd7aa2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -148,6 +148,8 @@ workflows: context : org-global - deployDev: context : org-global + requires: + - UnitTests filters: branches: only: ['develop', 'connect-performance-testing'] From 743ef07f44af908ae92cbb0d50029087bc4d5b73 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:16:56 +0530 Subject: [PATCH 17/23] Update config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 04dd7aa2..ee92fffd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -148,7 +148,7 @@ workflows: context : org-global - deployDev: context : org-global - requires: + requires: - UnitTests filters: branches: From 41c04d3673afeb1a77c57c18bf7819ba5501e7e9 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:20:03 +0530 Subject: [PATCH 18/23] Update config.yml --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ee92fffd..994ee4b0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -40,7 +40,7 @@ deploy_steps: &deploy_steps ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -s ${LOGICAL_ENV}-global-appvar,${LOGICAL_ENV}-${APPNAME}-appvar -i ${APPNAME} jobs: - UnitTests: + test: docker: - image: circleci/node:12.16.1 - image: circleci/postgres:9.6.2-alpine @@ -144,12 +144,12 @@ workflows: version: 2 Connect Project Services: jobs: - - UnitTests: + - test: context : org-global - deployDev: context : org-global requires: - - UnitTests + - test filters: branches: only: ['develop', 'connect-performance-testing'] From cbbc13fa586a0018e3357a72f45fe8cfbe67a890 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:42:55 +0530 Subject: [PATCH 19/23] Update config.yml --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 994ee4b0..57dc0518 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -155,6 +155,8 @@ workflows: only: ['develop', 'connect-performance-testing'] - deployProd: context : org-global + requires: + - test filters: branches: only: ['master'] From 2d2ab63ffe878365e5f62f90fbc01926125a9d5f Mon Sep 17 00:00:00 2001 From: maxceem Date: Tue, 12 Jan 2021 10:14:18 +0200 Subject: [PATCH 20/23] fix: lint --- src/events/projects/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/events/projects/index.js b/src/events/projects/index.js index fd9d2738..07c91986 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -6,7 +6,6 @@ import Joi from 'joi'; import Promise from 'bluebird'; import config from 'config'; import axios from 'axios'; -import moment from 'moment'; import util from '../../util'; import models from '../../models'; import { createPhaseTopic } from '../projectPhases'; From 8c062b8e4d20b0b11603c96ea11916794ccb1a87 Mon Sep 17 00:00:00 2001 From: codejam <42398485+codejamtc@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:47:31 +0530 Subject: [PATCH 21/23] Update config.yml --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 57dc0518..0be8e121 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -40,7 +40,7 @@ deploy_steps: &deploy_steps ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -s ${LOGICAL_ENV}-global-appvar,${LOGICAL_ENV}-${APPNAME}-appvar -i ${APPNAME} jobs: - test: + UnitTests: docker: - image: circleci/node:12.16.1 - image: circleci/postgres:9.6.2-alpine @@ -144,19 +144,19 @@ workflows: version: 2 Connect Project Services: jobs: - - test: + - UnitTests: context : org-global - deployDev: context : org-global requires: - - test + - UnitTests filters: branches: only: ['develop', 'connect-performance-testing'] - deployProd: context : org-global requires: - - test + - UnitTests filters: branches: only: ['master'] From cb0f4f68f48b1c5056529da261e3ff4eecc84e94 Mon Sep 17 00:00:00 2001 From: maxceem Date: Sat, 23 Jan 2021 16:33:38 +0200 Subject: [PATCH 22/23] feat: update "project.terms" type to string ref issue #614 --- docs/swagger.yaml | 10 ++++------ migrations/20212201_project_terms_update_type.sql | 7 +++++++ src/events/projects/index.js | 2 +- src/models/project.js | 2 +- src/routes/projects/create.js | 2 +- src/routes/projects/update.js | 2 +- src/routes/projects/update.spec.js | 4 ++-- src/utils/es-config.js | 2 +- 8 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 migrations/20212201_project_terms_update_type.sql diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 3fc88ec2..74418510 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -4939,8 +4939,7 @@ definitions: terms: type: array items: - type: number - format: integer + type: string external: type: object description: 'READ-ONLY, OPTIONAL. Refernce to external task/issue.' @@ -5070,8 +5069,7 @@ definitions: terms: type: array items: - type: number - format: integer + type: string name: type: string description: project name @@ -5254,7 +5252,7 @@ definitions: type: type: string description: The attachment type, one of 'link' or 'file' - enum: + enum: - link - file tags: @@ -6133,7 +6131,7 @@ definitions: type: array items: $ref: '#/definitions/Milestone' - + MilestoneTemplateRequest: title: Milestone template request object type: object diff --git a/migrations/20212201_project_terms_update_type.sql b/migrations/20212201_project_terms_update_type.sql new file mode 100644 index 00000000..6af47aad --- /dev/null +++ b/migrations/20212201_project_terms_update_type.sql @@ -0,0 +1,7 @@ +-- UPDATE EXISTING projects table +-- modify column `terms` + +-- drop existent column first to avoid any issues during type convertion as we don't need the data if there is any +ALTER TABLE projects DROP COLUMN "terms"; +-- now create a column with a new type +ALTER TABLE projects ADD COLUMN "terms" character varying(255)[] NOT NULL DEFAULT ARRAY[]::character varying[]::character varying(255)[]; diff --git a/src/events/projects/index.js b/src/events/projects/index.js index 07c91986..93675382 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -102,7 +102,7 @@ const projectPayloadSchema = Joi.object().keys({ id: Joi.number().integer().positive().required(), createdAt: Joi.date().required(), updatedAt: Joi.date().required(), - terms: Joi.array().items(Joi.number().positive()).optional(), + terms: Joi.array().items(Joi.string()).optional(), name: Joi.string().required(), description: Joi.string().allow(null).allow('').optional(), type: Joi.string().max(45).required(), diff --git a/src/models/project.js b/src/models/project.js index 9d3b39f4..fae58a7f 100644 --- a/src/models/project.js +++ b/src/models/project.js @@ -16,7 +16,7 @@ module.exports = function defineProject(sequelize, DataTypes) { estimatedPrice: { type: DataTypes.DECIMAL(10, 2), allowNull: true }, actualPrice: { type: DataTypes.DECIMAL(10, 2), allowNull: true }, terms: { - type: DataTypes.ARRAY(DataTypes.INTEGER), + type: DataTypes.ARRAY(DataTypes.STRING), allowNull: false, defaultValue: [], }, diff --git a/src/routes/projects/create.js b/src/routes/projects/create.js index a7b7cd71..49487df1 100644 --- a/src/routes/projects/create.js +++ b/src/routes/projects/create.js @@ -45,7 +45,7 @@ const createProjectValidations = { })).optional().allow(null), estimatedPrice: Joi.number().precision(2).positive().optional() .allow(null), - terms: Joi.array().items(Joi.number().positive()).optional(), + terms: Joi.array().items(Joi.string()).optional(), external: Joi.object().keys({ id: Joi.string(), type: Joi.any().valid('github', 'jira', 'asana', 'other'), diff --git a/src/routes/projects/update.js b/src/routes/projects/update.js index 311f1831..f1d2064c 100644 --- a/src/routes/projects/update.js +++ b/src/routes/projects/update.js @@ -46,7 +46,7 @@ const updateProjectValdiations = { status: Joi.any().valid(_.values(PROJECT_STATUS)), estimatedPrice: Joi.number().precision(2).positive().allow(null), actualPrice: Joi.number().precision(2).positive(), - terms: Joi.array().items(Joi.number().positive()), + terms: Joi.array().items(Joi.string()), external: Joi.object().keys({ id: Joi.string(), type: Joi.any().valid('github', 'jira', 'asana', 'other'), diff --git a/src/routes/projects/update.spec.js b/src/routes/projects/update.spec.js index 24c9e9a5..6ac5c481 100644 --- a/src/routes/projects/update.spec.js +++ b/src/routes/projects/update.spec.js @@ -983,7 +983,7 @@ describe('Project', () => { Authorization: `Bearer ${testUtil.jwts.admin}`, }) .send({ - terms: [1, 2, 3], + terms: ['1', '2', '3'], }) .expect(200) .end((err) => { @@ -996,7 +996,7 @@ describe('Project', () => { createEventSpy.calledWith(BUS_API_EVENT.PROJECT_UPDATED, sinon.match({ resource: 'project', id: project1.id, - terms: [1, 2, 3], + terms: ['1', '2', '3'], updatedBy: testUtil.userIds.admin, })).should.be.true; diff --git a/src/utils/es-config.js b/src/utils/es-config.js index 24357857..da0711ac 100644 --- a/src/utils/es-config.js +++ b/src/utils/es-config.js @@ -320,7 +320,7 @@ MAPPINGS[ES_PROJECT_INDEX] = { index: 'not_analyzed', }, terms: { - type: 'integer', + type: 'string', }, type: { type: 'string', From fef4c1708439bd8d97512a988d94d741e8e8cd65 Mon Sep 17 00:00:00 2001 From: maxceem Date: Sun, 24 Jan 2021 13:52:54 +0200 Subject: [PATCH 23/23] feat: add "project.groups" field ref issue #616 --- docs/swagger.yaml | 8 ++++++++ migrations/20212401_project_add_groups_field.sql | 4 ++++ src/events/projects/index.js | 1 + src/models/project.js | 5 +++++ src/routes/projects/create.js | 1 + src/routes/projects/update.js | 1 + src/utils/es-config.js | 3 +++ 7 files changed, 23 insertions(+) create mode 100644 migrations/20212401_project_add_groups_field.sql diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 74418510..d8c6a839 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -4940,6 +4940,10 @@ definitions: type: array items: type: string + groups: + type: array + items: + type: string external: type: object description: 'READ-ONLY, OPTIONAL. Refernce to external task/issue.' @@ -5070,6 +5074,10 @@ definitions: type: array items: type: string + groups: + type: array + items: + type: string name: type: string description: project name diff --git a/migrations/20212401_project_add_groups_field.sql b/migrations/20212401_project_add_groups_field.sql new file mode 100644 index 00000000..38c65b89 --- /dev/null +++ b/migrations/20212401_project_add_groups_field.sql @@ -0,0 +1,4 @@ +-- UPDATE EXISTING projects table +-- add column `groups` + +ALTER TABLE projects ADD COLUMN "groups" character varying(255)[] NOT NULL DEFAULT ARRAY[]::character varying[]::character varying(255)[]; diff --git a/src/events/projects/index.js b/src/events/projects/index.js index 93675382..a3db47c5 100644 --- a/src/events/projects/index.js +++ b/src/events/projects/index.js @@ -103,6 +103,7 @@ const projectPayloadSchema = Joi.object().keys({ createdAt: Joi.date().required(), updatedAt: Joi.date().required(), terms: Joi.array().items(Joi.string()).optional(), + groups: Joi.array().items(Joi.string()).optional(), name: Joi.string().required(), description: Joi.string().allow(null).allow('').optional(), type: Joi.string().max(45).required(), diff --git a/src/models/project.js b/src/models/project.js index fae58a7f..b9191dcd 100644 --- a/src/models/project.js +++ b/src/models/project.js @@ -20,6 +20,11 @@ module.exports = function defineProject(sequelize, DataTypes) { allowNull: false, defaultValue: [], }, + groups: { + type: DataTypes.ARRAY(DataTypes.STRING), + allowNull: false, + defaultValue: [], + }, type: { type: DataTypes.STRING, allowNull: false, diff --git a/src/routes/projects/create.js b/src/routes/projects/create.js index 49487df1..00b61ced 100644 --- a/src/routes/projects/create.js +++ b/src/routes/projects/create.js @@ -46,6 +46,7 @@ const createProjectValidations = { estimatedPrice: Joi.number().precision(2).positive().optional() .allow(null), terms: Joi.array().items(Joi.string()).optional(), + groups: Joi.array().items(Joi.string()).optional(), external: Joi.object().keys({ id: Joi.string(), type: Joi.any().valid('github', 'jira', 'asana', 'other'), diff --git a/src/routes/projects/update.js b/src/routes/projects/update.js index f1d2064c..70ed8e6d 100644 --- a/src/routes/projects/update.js +++ b/src/routes/projects/update.js @@ -47,6 +47,7 @@ const updateProjectValdiations = { estimatedPrice: Joi.number().precision(2).positive().allow(null), actualPrice: Joi.number().precision(2).positive(), terms: Joi.array().items(Joi.string()), + groups: Joi.array().items(Joi.string()), external: Joi.object().keys({ id: Joi.string(), type: Joi.any().valid('github', 'jira', 'asana', 'other'), diff --git a/src/utils/es-config.js b/src/utils/es-config.js index da0711ac..5144c510 100644 --- a/src/utils/es-config.js +++ b/src/utils/es-config.js @@ -322,6 +322,9 @@ MAPPINGS[ES_PROJECT_INDEX] = { terms: { type: 'string', }, + groups: { + type: 'string', + }, type: { type: 'string', index: 'not_analyzed',