Skip to content

Merging with master without deployment #2

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

Merged
merged 31 commits into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
822aa6a
adding delta patch
Feb 19, 2018
8152287
execute permission on files
Feb 19, 2018
9c188de
adding context path for the time being.
Feb 19, 2018
903b8a8
Delete .env
Feb 19, 2018
fb3cf16
template mappig setting
Feb 19, 2018
0417e29
Merge branch 'tc-email-delta-patch' of https://github.com/topcoder-pl…
Feb 19, 2018
8812da6
deploy.sh clean-up
Feb 19, 2018
383af4d
adding CircleCI env variables in deploy and build files.
Feb 20, 2018
f4a7026
changes for deploying service through CircleCI.
Feb 20, 2018
84c9b1b
fixing typo.
Feb 20, 2018
feb06fe
setting command line variables
Feb 20, 2018
3fb262e
correcting command line variables
Feb 20, 2018
6b429d9
correcting command line variables value
Feb 20, 2018
931f72d
correcting command line variables value
Feb 20, 2018
13c181b
correcting command line variables value
Feb 20, 2018
7ab522b
correcting command line variables value
Feb 20, 2018
8e9f1e8
correcting command line variables value
Feb 20, 2018
4314920
fix circleci values
Feb 20, 2018
5f25139
clean-up
Feb 20, 2018
aa0fe6c
trying better way for creating task defenition.
Feb 20, 2018
83fadc2
fixing typo
Feb 20, 2018
4ce9d3b
correcting deployment branch in circleci.
Mar 6, 2018
d890d5e
Merge pull request #1 from topcoder-platform/tc-email-delta-patch
Mar 6, 2018
e750e7e
add group consumer
gondzo Mar 6, 2018
46ad0de
Revert "add group consumer"
Mar 7, 2018
d79fb71
adding 'replyTo' support.
Mar 7, 2018
5f215cf
changes in template_map at CircleCI and triggering changes now.
Mar 9, 2018
618cdd4
fixing 'retry' and schedule timer issue.
Mar 12, 2018
7aec748
Temporary disabling the pausing feature as there is chance of losing …
Mar 13, 2018
dd671b5
adding remaining env variables.
Mar 16, 2018
78fca5b
fixing deployment variable setting issue.
Mar 16, 2018
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
86 changes: 86 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
version: 2

jobs:
# Build & Deploy against development backend rer
"build-dev-deploy-test":
docker:
- image: docker:17.06.1-ce-git
steps:
# Initialization.
- checkout
- setup_remote_docker
- run:
name: Installation of build dependencies.
command: apk add --no-cache bash

# Restoration of node_modules from cache.
- restore_cache:
key: docker-tc-email-service-{{ checksum "package-lock.json" }}

# Build of Docker image.
- run:
name: Build of Docker image
command: ./build.sh DEV

# Caching node modules.
- save_cache:
key: docker-tc-email-service-{{ checksum "package-lock.json" }}
paths:
- node_modules

# Deployment.
- run:
name: Installing AWS client
command: |
apk add --no-cache jq py-pip sudo
sudo pip install awscli --upgrade

- deploy:
command: ./deploy.sh DEV $CIRCLE_SHA1

"build-prod":
docker:
- image: docker:17.06.1-ce-git
steps:
# Initialization.
- checkout
- setup_remote_docker
- run:
name: Installation of build dependencies.
command: apk add --no-cache bash

# Restoration of node_modules from cache.
- restore_cache:
key: docker-tc-email-service-{{ checksum "package-lock.json" }}

# Build of Docker image.
- run:
name: Build of Docker image
command: ./build.sh PROD

# Caching node modules.
- save_cache:
key: docker-tc-email-service-{{ checksum "package-lock.json" }}
paths:
- node_modules

# Deployment.
- run:
name: Installing AWS client
command: |
apk add --no-cache jq py-pip sudo
sudo pip install awscli --upgrade

- deploy:
command: ./deploy.sh PROD $CIRCLE_SHA1

workflows:
version: 2
build:
jobs:
# Development builds are executed on "develop" branch only.
- "build-dev-deploy-test":
filters:
branches:
only: "dev"

3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"parserOptions": {
"ecmaVersion": 6
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Builds production version of Community App inside Docker container,
# and runs it against the specified Topcoder backend (development or
# production) when container is executed.

FROM node:8.2.1
LABEL app="tc email" version="1.0"

WORKDIR /opt/app
COPY . .
RUN npm install
RUN npm install dotenv --save
RUN npm run lint
CMD ["npm", "start"]
103 changes: 101 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,101 @@
# tc-email-service
General purpose email service
# TOPCODER EMAIL SERIES - EMAIL SERVER


## Dependencies
- nodejs https://nodejs.org/en/ (v8+)
- Heroku Toolbelt https://toolbelt.heroku.com
- git
- PostgreSQL 9.5


## Configuration
Configuration for the notification server is at `config/default.js`.
The following parameters can be set in config files or in env variables:
- LOG_LEVEL: the log level
- PORT: the notification server port
- authSecret: TC auth secret
- authDomain: TC auth domain
- validIssuers: TC auth valid issuers
- jwksUri: TC auth JWKS URI
- DATABASE_URL: URI to PostgreSQL database
- DATABASE_OPTIONS: database connection options
- KAFKA_URL: comma separated Kafka hosts
- KAFKA_TOPIC_IGNORE_PREFIX: ignore this prefix for topics in the Kafka
- KAFKA_GROUP_ID: Kafka consumer group id
- KAFKA_CLIENT_CERT: Kafka connection certificate, optional;
if not provided, then SSL connection is not used, direct insecure connection is used;
if provided, it can be either path to certificate file or certificate content
- KAFKA_CLIENT_CERT_KEY: Kafka connection private key, optional;
if not provided, then SSL connection is not used, direct insecure connection is used;
if provided, it can be either path to private key file or private key content
- TEMPLATE_MAP: the map between topic and SendGrid template id


Configuration for the connect notification server is at `connect/config.js`.
The following parameters can be set in config files or in env variables:
- TEMPLATE_MAP: the map between topic and SendGrid template id
- SUBJECT_MAP: the map between topic and SendGrid email subject
- EMAIL_FROM: from email to use to send email with SendGrid
- SENDGRID_API_KEY: SendGrid API key


Note that the above two configuration are separate because the common notification server config
will be deployed to a NPM package, the connect notification server will use that NPM package,
the connection notification server should only use API exposed by the index.js.

## TC API Admin Token

An admin token is needed to access TC API. This is already configured Postman notification
server API environment TC_ADMIN_TOKEN variable.
In case it expires, you may get a new token in this way:

- use Chrome to browse connect.topcoder-dev.com
- open developer tools, click the Network tab
- log in with suser1 / Topcoder123, or mess / appirio123
- once logged in, open some project, for example https://connect.topcoder-dev.com/projects/1936 and in the network inspector
look for the call to the project api and get the token from the auth header, see
http://pokit.org/get/img/68cdd34f3d205d6d9bd8bddb07bdc216.jpg


## Local deployment
- for local development environment you can set variables as following:
- `authSecret`, `authDomain`, `validIssuers` can get from [tc-project-service config](https://github.com/topcoder-platform/tc-project-service/blob/dev/config/default.json)
- `PORT=4001` because **connect-app** call this port by default
- `jwksUri` - any
- `KAFKA_TOPIC_IGNORE_PREFIX=joan-26673.` (with point at the end)
- `KAFKA_URL`, `KAFKA_CLIENT_CERT` and `KAFKA_CLIENT_CERT_KEY` get from [tc-bus-api readme](https://github.com/topcoder-platform/tc-bus-api/tree/dev)
- start local PostgreSQL db, create an empty database, update the config/default.js DATABASE_URL param to point to the db
- install dependencies `npm i`
- run code lint check `npm run lint`
- start connect notification server `npm start`
- the app is running at `http://localhost:4001`, it also starts Kafka consumer to listen for events, send emails using SendGrid and save emails data to database


## Heroku deployment

- git init
- git add .
- git commit -m 'message'
- heroku login
- heroku create [application-name] // choose a name, or leave it empty to use generated one
- heroku addons:create heroku-postgresql:hobby-dev
- note that you may need to wait for several minutes before the PostgreSQL database is ready
- optionally, to set some environment variables in heroku, run command like:
`heroku config:set KAFKA_CLIENT_CERT=path/to/certificate/file`
`heroku config:set KAFKA_CLIENT_CERT_KEY=path/to/private/key/file`
`heroku config:set KAFKA_GROUP_ID=some-group`
etc.
- git push heroku master // push code to Heroku


## Verification

- start the app following above sections
- Import `docs/tc-email-server-api-local-env.postman_environment.json` and `docs/tc-email-server-api.postman_collection.json` to Postman
- in Postman, using the email server API collection and environment to run the tests


## Swagger

Swagger API definition is provided at `docs/swagger_api.yaml`,
you may check it at `http://editor.swagger.io`.
75 changes: 75 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash
set -eo pipefail

# Builds Docker image of Community App application.
# This script expects a single argument: NODE_ENV, which must be either
# "development" or "production".

NODE_ENV=$1

ENV=$1
AWS_REGION=$(eval "echo \$${ENV}_AWS_REGION")
AWS_ACCESS_KEY_ID=$(eval "echo \$${ENV}_AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY=$(eval "echo \$${ENV}_AWS_SECRET_ACCESS_KEY")
AWS_ACCOUNT_ID=$(eval "echo \$${ENV}_AWS_ACCOUNT_ID")
AWS_REPOSITORY=$(eval "echo \$${ENV}_AWS_REPOSITORY")

#App variables

AUTHDOMAIN=$(eval "echo \$${ENV}_AUTHDOMAIN")
AUTHSECRET=$(eval "echo \$${ENV}_AUTHSECRET")
VALIDISSUERS=$(eval "echo \$${ENV}_VALIDISSUERS")

KAFKA_CLIENT_CERT=$(eval "echo \$${ENV}_KAFKA_CLIENT_CERT")
KAFKA_CLIENT_CERT_KEY=$(eval "echo \$${ENV}_KAFKA_CLIENT_CERT_KEY")
KAFKA_URL=$(eval "echo \$${ENV}_KAFKA_URL")
SENDGRID_API_KEY=$(eval "echo \$${ENV}_SENDGRID_API_KEY")


DB_DATABASE=$(eval "echo \$${ENV}_DB_DATABASE")
DB_HOST=$(eval "echo \$${ENV}_DB_HOST")
DB_PASSWORD=$(eval "echo \$${ENV}_DB_PASSWORD")
DB_PORT=$(eval "echo \$${ENV}_DB_PORT")
DB_USER=$(eval "echo \$${ENV}_DB_USER")
DATABASE_URL=postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_DATABASE;


KAFKA_GROUP_ID=$(eval "echo \$${ENV}_KAFKA_GROUP_ID")
EMAIL_FROM=$(eval "echo \$${ENV}_EMAIL_FROM")
LOG_LEVEL=$(eval "echo \$${ENV}_LOG_LEVEL")
NODE_ENV=$(eval "echo \$${ENV}_NODE_ENV")
NODE_PORT=$(eval "echo \$${ENV}_NODE_PORT")
JWKSURI=$(eval "echo \$${ENV}_JWKSURI")
TEMPLATE_MAP=$(eval "echo \$${ENV}_TEMPLATE_MAP")


TAG=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/tc-email-service:$CIRCLE_SHA1

docker build -t $TAG .

# Copies "node_modules" from the created image, if necessary for caching.
docker create --name app $TAG

if [ -d node_modules ]
then
# If "node_modules" directory already exists, we should compare
# "package-lock.json" from the code and from the container to decide,
# whether we need to re-cache, and thus to copy "node_modules" from
# the Docker container.
mv package-lock.json old-package-lock.json
docker cp app:/opt/app/package-lock.json package-lock.json
# docker cp .env app:/opt/app/
set +eo pipefail
UPDATE_CACHE=$(cmp package-lock.json old-package-lock.json)
set -eo pipefail
else
# If "node_modules" does not exist, then cache must be created.
UPDATE_CACHE=1
fi

if [ "$UPDATE_CACHE" == 1 ]
then
docker cp app:/opt/app/node_modules .
fi


43 changes: 43 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* The configuration file.
*/
module.exports = {
LOG_LEVEL: process.env.LOG_LEVEL,
PORT: process.env.PORT,
authSecret: process.env.authSecret,
authDomain: process.env.authDomain,
jwksUri: process.env.jwksUri,
DATABASE_URL: process.env.DATABASE_URL,
DATABASE_OPTIONS: {
dialect: 'postgres',
dialectOptions: {
ssl: process.env.DATABASE_SSL != null,
},
pool: {
max: 5,
min: 0,
idle: 10000,
},
},
DISABLE_LOGGING: process.env.DISABLE_LOGGING || 'false',

validIssuers: process.env.validIssuers ? process.env.validIssuers.replace(/\\"/g, '') : null,
KAFKA_URL: process.env.KAFKA_URL,
KAFKA_TOPIC_IGNORE_PREFIX: process.env.KAFKA_TOPIC_IGNORE_PREFIX,
KAFKA_GROUP_ID: process.env.KAFKA_GROUP_ID,
KAFKA_CLIENT_CERT: process.env.KAFKA_CLIENT_CERT ? process.env.KAFKA_CLIENT_CERT.replace('\\n', '\n') : null,
KAFKA_CLIENT_CERT_KEY: process.env.KAFKA_CLIENT_CERT_KEY ?
process.env.KAFKA_CLIENT_CERT_KEY.replace('\\n', '\n') : null,

// mapping from event type to sendgrid email template id
TEMPLATE_MAP: process.env.TEMPLATE_MAP,
SENDGRID_API_KEY: process.env.SENDGRID_API_KEY || '',
EMAIL_FROM: process.env.EMAIL_FROM || 'no-reply@topcoder.com',

// temporary not in use feature
EMAIL_MAX_ERRORS: process.env.EMAIL_MAX_ERRORS || 2,
EMAIL_PAUSE_TIME: process.env.EMAIL_PAUSE_TIME || 30,

//in every 2 minutes will retry for failed status
EMAIL_RETRY_SCHEDULE: process.env.EMAIL_RETRY_SCHEDULE || '0 */2 * * * *',
};
7 changes: 7 additions & 0 deletions config/development.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* The development configuration file. These config will override default config.
*/
module.exports = {
LOG_LEVEL: process.env.LOG_LEVEL || 'debug',
PORT: process.env.PORT || 4000,
};
8 changes: 8 additions & 0 deletions config/production.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* The production configuration file. These config will override default config.
*/
module.exports = {
LOG_LEVEL: process.env.LOG_LEVEL || 'error',
PORT: process.env.PORT || 4000,
DISABLE_LOGGING: process.env.DISABLE_LOGGING || 'true',
};
7 changes: 7 additions & 0 deletions config/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* The test configuration file. These config will override default config.
*/
module.exports = {
LOG_LEVEL: process.env.LOG_LEVEL || 'debug',
PORT: process.env.PORT || 4000,
};
Loading