switch to pipenv

This commit is contained in:
stvnrlly
2022-11-08 09:44:09 -05:00
parent 51d9d08410
commit e44fe2eb11
7 changed files with 1997 additions and 447 deletions

146
Makefile
View File

@@ -7,16 +7,6 @@ APP_VERSION_FILE = app/version.py
GIT_BRANCH ?= $(shell git symbolic-ref --short HEAD 2> /dev/null || echo "detached")
GIT_COMMIT ?= $(shell git rev-parse HEAD 2> /dev/null || echo "")
CF_API ?= api.cloud.service.gov.uk
CF_ORG ?= govuk-notify
CF_SPACE ?= ${DEPLOY_ENV}
CF_HOME ?= ${HOME}
CF_APP ?= notify-admin
CF_MANIFEST_PATH ?= /tmp/manifest.yml
$(eval export CF_HOME)
NOTIFY_CREDENTIALS ?= ~/.notify-credentials
VIRTUALENV_ROOT := $(shell [ -z $$VIRTUAL_ENV ] && echo $$(pwd)/venv || echo $$VIRTUAL_ENV)
NVMSH := $(shell [ -f "$(HOME)/.nvm/nvm.sh" ] && echo "$(HOME)/.nvm/nvm.sh" || echo "/usr/local/share/nvm/nvm.sh")
@@ -25,7 +15,7 @@ NVMSH := $(shell [ -f "$(HOME)/.nvm/nvm.sh" ] && echo "$(HOME)/.nvm/nvm.sh" || e
.PHONY: bootstrap
bootstrap: generate-version-file ## Set up everything to run the app
pip3 install -r requirements_for_test.txt
pipenv install --dev
source $(NVMSH) --no-use && nvm install && npm ci --no-audit
source $(NVMSH) && npm run build
@@ -35,7 +25,7 @@ watch-frontend: ## Build frontend and watch for changes
.PHONY: run-flask
run-flask: ## Run flask
flask run -p 6012 --host=0.0.0.0
pipenv run flask run -p 6012 --host=0.0.0.0
.PHONY: npm-audit
npm-audit: ## Check for vulnerabilities in NPM packages
@@ -45,14 +35,6 @@ npm-audit: ## Check for vulnerabilities in NPM packages
help:
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.PHONY: virtualenv
virtualenv:
[ -z $$VIRTUAL_ENV ] && [ ! -d venv ] && python3 -m venv venv || true
.PHONY: upgrade-pip
upgrade-pip: virtualenv
${VIRTUALENV_ROOT}/bin/pip install --upgrade pip
.PHONY: generate-version-file
generate-version-file: ## Generates the app version file
@echo -e "__git_commit__ = \"${GIT_COMMIT}\"\n__time__ = \"${DATE}\"" > ${APP_VERSION_FILE}
@@ -62,12 +44,12 @@ test: py-lint py-test js-lint js-test ## Run tests
.PHONY: py-lint
py-lint: ## Run python linting scanners
flake8 .
isort --check-only ./app ./tests
pipenv run flake8 .
pipenv run isort --check-only ./app ./tests
.PHONY: py-test
py-test: ## Run python unit tests
py.test -n auto --maxfail=10 tests/
pipenv run py.test -n auto --maxfail=10 tests/
.PHONY: js-lint
js-lint: ## Run javascript linting scanners
@@ -79,26 +61,23 @@ js-test: ## Run javascript unit tests
.PHONY: fix-imports
fix-imports: ## Fix imports using isort
isort ./app ./tests
pipenv run isort ./app ./tests
.PHONY: freeze-requirements
freeze-requirements: ## create static requirements.txt
pip install --upgrade pip-tools
pip-compile requirements.in
pipenv requirements > requirements.txt
.PHONY: pip-audit
pip-audit:
pip install --upgrade pip-audit
pip-audit -r requirements.txt -l --ignore-vuln PYSEC-2022-237
-pip-audit -r requirements_for_test.txt -l
pipenv run pip-audit -r requirements.txt -l --ignore-vuln PYSEC-2022-237
-pipenv run pip-audit -r requirements_for_test.txt -l
.PHONY: audit
audit: npm-audit pip-audit
.PHONY: static-scan
static-scan:
pip install bandit
bandit -r app/
pipenv run bandit -r app/
.PHONY: a11y-scan
a11y-scan:
@@ -112,101 +91,22 @@ clean:
## DEPLOYMENT
.PHONY: check-env-vars
check-env-vars: ## Check mandatory environment variables
$(if ${DEPLOY_ENV},,$(error Must specify DEPLOY_ENV))
$(if ${DNS_NAME},,$(error Must specify DNS_NAME))
.PHONY: preview
preview: ## Set environment to preview
$(eval export DEPLOY_ENV=preview)
$(eval export DNS_NAME="notify.works")
@true
.PHONY: staging
staging: ## Set environment to staging
$(eval export DEPLOY_ENV=staging)
$(eval export DNS_NAME="staging-notify.works")
@true
.PHONY: production
production: ## Set environment to production
$(eval export DEPLOY_ENV=production)
$(eval export DNS_NAME="notifications.service.gov.uk")
@true
.PHONY: cf-login
cf-login: ## Log in to Cloud Foundry
$(if ${CF_USERNAME},,$(error Must specify CF_USERNAME))
$(if ${CF_PASSWORD},,$(error Must specify CF_PASSWORD))
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
@echo "Logging in to Cloud Foundry on ${CF_API}"
@cf login -a "${CF_API}" -u ${CF_USERNAME} -p "${CF_PASSWORD}" -o "${CF_ORG}" -s "${CF_SPACE}"
.PHONY: generate-manifest
generate-manifest:
$(if ${CF_APP},,$(error Must specify CF_APP))
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
$(if $(shell which gpg2), $(eval export GPG=gpg2), $(eval export GPG=gpg))
$(if ${GPG_PASSPHRASE_TXT}, $(eval export DECRYPT_CMD=echo -n $$$${GPG_PASSPHRASE_TXT} | ${GPG} --quiet --batch --passphrase-fd 0 --pinentry-mode loopback -d), $(eval export DECRYPT_CMD=${GPG} --quiet --batch -d))
@jinja2 --strict manifest.yml.j2 \
-D environment=${CF_SPACE} \
-D CF_APP=${CF_APP} \
--format=yaml \
<(${DECRYPT_CMD} ${NOTIFY_CREDENTIALS}/credentials/${CF_SPACE}/paas/environment-variables.gpg) 2>&1
.PHONY: upload-static ## Upload the static files to be served from S3
upload-static:
aws s3 cp --region us-west-2 --recursive --cache-control max-age=315360000,immutable ./app/static s3://${DNS_NAME}-static
.PHONY: cf-deploy
cf-deploy: ## Deploys the app to Cloud Foundry
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
@cf app --guid notify-admin || exit 1
# cancel any existing deploys to ensure we can apply manifest (if a deploy is in progress you'll see ScaleDisabledDuringDeployment)
cf cancel-deployment ${CF_APP} || true
# .PHONY: cf-failwhale-deployed
# cf-failwhale-deployed:
# @cf app notify-admin-failwhale --guid || (echo "notify-admin-failwhale is not deployed on ${CF_SPACE}" && exit 1)
# generate manifest (including secrets) and write it to CF_MANIFEST_PATH (in /tmp/)
make -s CF_APP=${CF_APP} generate-manifest > ${CF_MANIFEST_PATH}
# reads manifest from CF_MANIFEST_PATH
CF_STARTUP_TIMEOUT=10 cf push ${CF_APP} --strategy=rolling -f ${CF_MANIFEST_PATH}
# delete old manifest file
rm -f ${CF_MANIFEST_PATH}
# .PHONY: enable-failwhale
# enable-failwhale: cf-target cf-failwhale-deployed ## Enable the failwhale app and disable admin
# @cf map-route notify-admin-failwhale ${DNS_NAME} --hostname www
# @cf unmap-route notify-admin ${DNS_NAME} --hostname www
# @echo "Failwhale is enabled"
.PHONY: cf-deploy-prototype
cf-deploy-prototype: cf-target ## Deploys the first prototype to Cloud Foundry
make -s CF_APP=notify-admin-prototype generate-manifest > ${CF_MANIFEST_PATH}
cf push notify-admin-prototype --strategy=rolling -f ${CF_MANIFEST_PATH}
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-deploy-prototype-2
cf-deploy-prototype-2: cf-target ## Deploys the second prototype to Cloud Foundry
make -s CF_APP=notify-admin-prototype-2 generate-manifest > ${CF_MANIFEST_PATH}
cf push notify-admin-prototype-2 --strategy=rolling -f ${CF_MANIFEST_PATH}
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-rollback
cf-rollback: cf-target ## Rollbacks the app to the previous release
cf cancel-deployment ${CF_APP}
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-target
cf-target: check-env-vars
@cf target -o ${CF_ORG} -s ${CF_SPACE}
.PHONY: cf-failwhale-deployed
cf-failwhale-deployed:
@cf app notify-admin-failwhale --guid || (echo "notify-admin-failwhale is not deployed on ${CF_SPACE}" && exit 1)
.PHONY: enable-failwhale
enable-failwhale: cf-target cf-failwhale-deployed ## Enable the failwhale app and disable admin
@cf map-route notify-admin-failwhale ${DNS_NAME} --hostname www
@cf unmap-route notify-admin ${DNS_NAME} --hostname www
@echo "Failwhale is enabled"
.PHONY: disable-failwhale
disable-failwhale: cf-target cf-failwhale-deployed ## Disable the failwhale app and enable admin
@cf map-route notify-admin ${DNS_NAME} --hostname www
@cf unmap-route notify-admin-failwhale ${DNS_NAME} --hostname www
@echo "Failwhale is disabled"
# .PHONY: disable-failwhale
# disable-failwhale: cf-target cf-failwhale-deployed ## Disable the failwhale app and enable admin
# @cf map-route notify-admin ${DNS_NAME} --hostname www
# @cf unmap-route notify-admin-failwhale ${DNS_NAME} --hostname www
# @echo "Failwhale is disabled"

56
Pipfile Normal file
View File

@@ -0,0 +1,56 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
ago = "==0.0.93"
awscli-cwlogs = ">=1.4,<1.5"
blinker = "==1.4"
fido2 = "==0.9.3"
flask = "==2.1.2"
flask-basicauth = "==0.2.0"
flask-login = "==0.6.1"
flask-wtf = "==1.0.1"
gds-metrics = {version = "==0.2.4", ref = "6f1840a57b6fb1ee40b7e84f2f18ec229de8aa72", git = "https://github.com/alphagov/gds_metrics_python.git"}
govuk-bank-holidays = "==0.11"
govuk-frontend-jinja = {version = "==0.5.8-alpha", git = "https://github.com/alphagov/govuk-frontend-jinja.git"}
gunicorn = {version = "==20.1.0", extras = ["eventlet"], ref = "1299ea9e967a61ae2edebe191082fd169b864c64", git = "https://github.com/benoitc/gunicorn.git"}
humanize = "==4.1.0"
itsdangerous = "==2.1.2"
jinja2 = "==3.1.2"
notifications-python-client = "==6.3.0"
notifications-utils = {version = "==56.0.3", git = "https://github.com/GSA/notifications-utils.git"}
prometheus-client = "==0.14.1"
pyexcel = "==0.7.0"
pyexcel-io = "==0.6.6"
pyexcel-ods3 = "==0.6.1"
pyexcel-xls = "==0.7.0"
pyexcel-xlsx = "==0.6.0"
pyproj = "==3.3.1"
python-dotenv = "==0.20.0"
pytz = "==2022.1"
rtreelib = "==0.2.0"
werkzeug = "==2.1.2"
wtforms = "==3.0.1"
[dev-packages]
isort = "==5.10.1"
pytest = "==7.1.2"
pytest-env = "==0.6.2"
pytest-mock = "==3.7.0"
pytest-xdist = "==2.5.0"
beautifulsoup4 = "==4.11.1"
freezegun = "==1.2.1"
flake8 = "==4.0.1"
flake8-bugbear = "==22.4.25"
flake8-print = "==5.0.0"
moto = "==3.1.7"
requests-mock = "==1.9.3"
# used for creating manifest file locally
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
pip-audit = "*"
bandit = "*"
[requires]
python_version = "3.9"

1871
Pipfile.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,43 +1,67 @@
# US Notify Admin
# Notify UI
Cloned from the brilliant work of the team at [GOV.UK Notify](https://github.com/alphagov/notifications-admin), cheers!
This is the Notify front-end for government users and admins. To see it in action, check out [the demo site](https://notify-demo.app.cloud.gov) (contact team for credentials).
US Notify admin application - https://notify-demo.app.cloud.gov (contact team for access)
Through the interface, users can:
- Register and manage users
- Create and manage services
- Send batch emails and SMS by uploading a CSV
- Show history of notifications
- Send batch SMS by uploading a CSV
- View their history of notifications
## QUICKSTART
The [Notify API](https://github.com/GSA/notifications-api) provides the UI's backend and is required for most things to function. Set that up first!
---
**NOTE**: Set up the [notifications-api repo](https://github.com/18F/notifications-api) locally **FIRST**, you'll need both the docker network it provides and a functioning api to make use of the notifications-admin repo. It is expected as a byproduct of getting notifications-api running you will also be running VS Code and the Remote Containers extension, and that docker daemon is running and the API is as well.
## Local setup
Open the notifications-admin repo in VS Code (File->Open Folder, select notifications-admin folder)
### Direct setup
create a .env file as detailed in the .env Setup section below
1. Get the API running
Using VS Code's command pallette (cmd+shift+p), search "Remote Containers: Open folder in Container..."
1. Install [pipenv](https://pipenv.pypa.io/en/latest/)
choose devcontainer-admin folder (note: this is a subfolder of notifications-admin/). This will open a new window, closing the current one in the process. After the new window loads, hit "show logs" link in the bottom-right. If this is the first build it will take a few minutes to create the image. The process completes shortly after running gulp.js and compiling front-end files.
1. Install Python and Node dependencies
Select View->Open View..., then search/select “ports”. Await a green dot on the port view, then open a new terminal and run the web server:
`make run-flask`
`make bootstrap`
Visit [localhost:6012](http://localhost:6012)
1. Create the .env file
NOTE: any .py code changes you make should be picked up automatically in development. If you're developing JavaScript code, open another vscode terminal and run `npm run watch` to achieve the same.
```
cp sample.env .env
# follow the instructions in .env
```
---
## .env Setup
1. Run the Flask server
create a .env file using sample.env as a template
`cp sample.env .env` (or via VS Code file browser)
`make run-flask`
from the notifications-api checkout, copy the values in that repo's .env file for `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` into this repo's .env file.
1. Go to http://localhost:6012
Change `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` to what you'd like them to be for this deployment.
### VS Code && Docker installation
If you're working in VS Code, you can also leverage Docker for a containerized dev environment
1. Get the API running, including the Docker network
1. Create the .env file
```
cp sample.env .env
# follow the instructions in .env
```
1. Install the Remote-Containers plug-in in VS Code
1. Using the command palette (shift+cmd+p) or green button thingy in the bottom left, search and select “Remote Containers: Open Folder in Container...” When prompted, choose **devcontainer-admin** folder (note: this is a *subfolder* of notifications-admin). This will start the container in a new window, replacing the current one.
1. Wait a few minutes while things happen 🍵
1. Open a VS Code terminal and run the Flask application:
`make run-flask`
1. Go to http://localhost:6012
NOTE: when you change .env in the future, you'll need to rebuild the devcontainer for the change to take effect. VS Code _should_ detect the change and prompt you with a toast notification during a cached build. If not, you can find a manual rebuild in command pallette or just `docker rm` the notifications-api container.
## To test the application
From a terminal within the running devcontainer:
@@ -59,7 +83,7 @@ Unlike most of the tests and scans, pa11y-ci cannot currently be run from within
1. Run `make run-flask` from within the devcontainer
2. Run `make a11y-scan` from your host computer.
## Further docs [STILL UK DOCS]
## Further docs from UK
- [Working with static assets](docs/static-assets.md)
- [JavaScript documentation](https://github.com/alphagov/notifications-manuals/wiki/JavaScript-Documentation)

View File

@@ -1,38 +0,0 @@
# Run `make freeze-requirements` to update requirements.txt
# with package version changes made in requirements-app.txt
ago==0.0.93
govuk-bank-holidays==0.11
humanize==4.1.0
Flask==2.1.2
Flask-WTF==1.0.1
wtforms==3.0.1
Flask-Login==0.6.1
Werkzeug==2.1.2
jinja2==3.1.2
Flask-BasicAuth==0.2.0
blinker==1.4
pyexcel==0.7.0
pyexcel-io==0.6.6
pyexcel-xls==0.7.0
pyexcel-xlsx==0.6.0
pyexcel-ods3==0.6.1
pytz==2022.1
# Should be pinned until a new gunicorn release greater than 20.1.0 comes out. (Due to eventlet v0.33 compatibility issues)
git+https://github.com/benoitc/gunicorn.git@1299ea9e967a61ae2edebe191082fd169b864c64#egg=gunicorn[eventlet]==20.1.0
notifications-python-client==6.3.0
rtreelib==0.2.0
fido2==0.9.3
pyproj==3.3.1
python-dotenv==0.20.0
# PaaS
awscli-cwlogs>=1.4,<1.5
itsdangerous==2.1.2
notifications-utils @ git+https://github.com/GSA/notifications-utils.git@s3-credentials
govuk-frontend-jinja @ git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.8-alpha
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
prometheus-client==0.14.1
git+https://github.com/alphagov/gds_metrics_python.git@6f1840a57b6fb1ee40b7e84f2f18ec229de8aa72

View File

@@ -1,248 +0,0 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
#
# pip-compile requirements.in
#
ago==0.0.93
# via -r requirements.in
async-timeout==4.0.2
# via redis
awscli==1.24.8
# via awscli-cwlogs
awscli-cwlogs==1.4.6
# via -r requirements.in
bleach==5.0.0
# via notifications-utils
blinker==1.4
# via
# -r requirements.in
# gds-metrics
boto3==1.23.8
# via notifications-utils
botocore==1.26.8
# via
# awscli
# boto3
# s3transfer
cachetools==5.1.0
# via notifications-utils
certifi==2022.5.18.1
# via
# pyproj
# requests
cffi==1.15.0
# via cryptography
chardet==4.0.0
# via pyexcel
charset-normalizer==2.0.12
# via requests
click==8.1.3
# via flask
colorama==0.4.4
# via awscli
cryptography==38.0.3
# via fido2
deprecated==1.2.13
# via redis
dnspython==2.2.1
# via eventlet
docopt==0.6.2
# via notifications-python-client
docutils==0.16
# via awscli
et-xmlfile==1.1.0
# via openpyxl
eventlet==0.33.1
# via gunicorn
fido2==0.9.3
# via -r requirements.in
flask==2.1.2
# via
# -r requirements.in
# flask-basicauth
# flask-login
# flask-redis
# flask-wtf
# gds-metrics
# notifications-utils
flask-basicauth==0.2.0
# via -r requirements.in
flask-login==0.6.1
# via -r requirements.in
flask-redis==0.4.0
# via notifications-utils
flask-wtf==1.0.1
# via -r requirements.in
gds-metrics @ git+https://github.com/alphagov/gds_metrics_python.git@6f1840a57b6fb1ee40b7e84f2f18ec229de8aa72
# via -r requirements.in
geojson==2.5.0
# via notifications-utils
govuk-bank-holidays==0.11
# via
# -r requirements.in
# notifications-utils
govuk-frontend-jinja @ git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.8-alpha
# via -r requirements.in
greenlet==1.1.2
# via eventlet
gunicorn @ git+https://github.com/benoitc/gunicorn.git@1299ea9e967a61ae2edebe191082fd169b864c64
# via -r requirements.in
humanize==4.1.0
# via -r requirements.in
idna==3.3
# via requests
importlib-metadata==4.12.0
# via flask
itsdangerous==2.1.2
# via
# -r requirements.in
# flask
# flask-wtf
# notifications-utils
jinja2==3.1.2
# via
# -r requirements.in
# flask
# govuk-frontend-jinja
# notifications-utils
jmespath==1.0.0
# via
# boto3
# botocore
lml==0.1.0
# via
# pyexcel
# pyexcel-io
lxml==4.9.1
# via
# pyexcel-ezodf
# pyexcel-ods3
markupsafe==2.1.1
# via
# jinja2
# wtforms
mistune==0.8.4
# via notifications-utils
notifications-python-client==6.3.0
# via -r requirements.in
notifications-utils @ git+https://github.com/GSA/notifications-utils.git@s3-credentials
# via -r requirements.in
openpyxl==3.0.10
# via pyexcel-xlsx
orderedset==2.0.3
# via notifications-utils
packaging==21.3
# via redis
phonenumbers==8.12.48
# via notifications-utils
prometheus-client==0.14.1
# via
# -r requirements.in
# gds-metrics
pyasn1==0.4.8
# via rsa
pycparser==2.21
# via cffi
pyexcel==0.7.0
# via -r requirements.in
pyexcel-ezodf==0.3.4
# via pyexcel-ods3
pyexcel-io==0.6.6
# via
# -r requirements.in
# pyexcel
# pyexcel-ods3
# pyexcel-xls
# pyexcel-xlsx
pyexcel-ods3==0.6.1
# via -r requirements.in
pyexcel-xls==0.7.0
# via -r requirements.in
pyexcel-xlsx==0.6.0
# via -r requirements.in
pyjwt==2.4.0
# via notifications-python-client
pyparsing==3.0.9
# via packaging
pypdf2==2.0.0
# via notifications-utils
pyproj==3.3.1
# via
# -r requirements.in
# notifications-utils
python-dateutil==2.8.2
# via
# awscli-cwlogs
# botocore
python-dotenv==0.20.0
# via -r requirements.in
python-json-logger==2.0.2
# via notifications-utils
pytz==2022.1
# via
# -r requirements.in
# notifications-utils
pyyaml==5.4.1
# via
# awscli
# notifications-utils
redis==4.3.1
# via flask-redis
requests==2.27.1
# via
# awscli-cwlogs
# govuk-bank-holidays
# notifications-python-client
# notifications-utils
rsa==4.7.2
# via awscli
rtreelib==0.2.0
# via -r requirements.in
s3transfer==0.5.2
# via
# awscli
# boto3
shapely==1.8.2
# via notifications-utils
six==1.16.0
# via
# awscli-cwlogs
# bleach
# eventlet
# fido2
# python-dateutil
smartypants==2.0.1
# via notifications-utils
statsd==3.3.0
# via notifications-utils
texttable==1.6.4
# via pyexcel
typing-extensions==4.3.0
# via pypdf2
urllib3==1.26.9
# via
# botocore
# requests
webencodings==0.5.1
# via bleach
werkzeug==2.1.2
# via
# -r requirements.in
# flask
# flask-login
wrapt==1.14.1
# via deprecated
wtforms==3.0.1
# via
# -r requirements.in
# flask-wtf
xlrd==2.0.1
# via pyexcel-xls
xlwt==1.3.0
# via pyexcel-xls
zipp==3.8.1
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
# setuptools

View File

@@ -1,15 +0,0 @@
-r requirements.txt
isort==5.10.1
pytest==7.1.2
pytest-env==0.6.2
pytest-mock==3.7.0
pytest-xdist==2.5.0
beautifulsoup4==4.11.1
freezegun==1.2.1
flake8==4.0.1
flake8-bugbear==22.4.25
flake8-print==5.0.0
moto==3.1.7
requests-mock==1.9.3
# used for creating manifest file locally
jinja2-cli[yaml]==0.8.2