From 822bb7b4f963551aabdac866e218a49a9aec3538 Mon Sep 17 00:00:00 2001 From: Michel Albert Date: Sun, 1 Apr 2018 13:38:01 +0200 Subject: [PATCH 01/20] Use gouge-logging on the CLI --- lost_tracker/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lost_tracker/main.py b/lost_tracker/main.py index 85eae2a..82cb9ea 100644 --- a/lost_tracker/main.py +++ b/lost_tracker/main.py @@ -226,6 +226,8 @@ def fake_login(): if __name__ == '__main__': from lost_tracker.colorize import colorize_werkzeug + from gouge.colourcli import Simple + Simple.basicConfig(level=0) colorize_werkzeug() myapp = make_app() myapp.add_url_rule('/fake_login', 'fake_login', fake_login) From d3fb856eda5b6bef8f6d9f921e1f6288d29a4002 Mon Sep 17 00:00:00 2001 From: Michel Albert Date: Sat, 6 Apr 2019 17:19:18 +0200 Subject: [PATCH 02/20] Move developemt tasks to "invoke" --- fabfile.py | 296 ----------------------------------------------------- tasks.py | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+), 296 deletions(-) delete mode 100644 fabfile.py create mode 100644 tasks.py diff --git a/fabfile.py b/fabfile.py deleted file mode 100644 index e8167a9..0000000 --- a/fabfile.py +++ /dev/null @@ -1,296 +0,0 @@ -from __future__ import print_function -from ConfigParser import SafeConfigParser -from getpass import getuser -from os.path import exists, dirname - -import fabric.api as fab -import fabric.colors as clr - -fab.env.roledefs = { - 'prod': ['178.62.219.167'], -} - - -REMOTE_FOLDER = '/var/www/lost.lu/www' -REMOTE_USER = 'lost_tracker' -DOCKER_PLOVR = 'exhuma/lost-tracker-closure' - - -@fab.task -@fab.roles('prod') -@fab.with_settings(user=REMOTE_USER) -def deploy(): - fab.execute(build) - fab.execute(babel_compile) - fab.execute(upload) - fab.execute(install) - fab.execute(clean) - - -@fab.task -@fab.with_settings(user=REMOTE_USER) -def upload(): - fab.local('python setup.py sdist') - name = fab.local('python setup.py --fullname', capture=True) - with fab.cd(REMOTE_FOLDER): - fab.put('dist/{0}.tar.gz'.format(name), '.') - fab.put('alembic.ini', '.') - fab.put('alembic', '.') - fab.put('requirements.txt', '.') - - -@fab.task -@fab.with_settings(user=REMOTE_USER) -def install(): - name = fab.local('python setup.py --fullname', capture=True) - with fab.cd(REMOTE_FOLDER): - fab.run('env/bin/pip install alembic') - fab.run('env/bin/pip install -r requirements.txt') - fab.run('env/bin/pip install {0}.tar.gz'.format(name)) - fab.run('env/bin/alembic upgrade head') - fab.run('touch wsgi/lost-tracker.wsgi') - - -@fab.task -def clean(): - name = fab.local('python setup.py --fullname', capture=True) - with fab.cd(REMOTE_FOLDER): - fab.run('rm {0}.tar.gz'.format(name)) - fab.run('rm requirements.txt') - - -@fab.task -@fab.with_settings(user=REMOTE_USER) -def redeploy(): - name = fab.local('python setup.py --name', capture=True) - with fab.cd(REMOTE_FOLDER): - fab.run('env/bin/pip uninstall %s' % name) - fab.execute(deploy) - - -@fab.task -@fab.with_settings(user=getuser()) -def bootstrap(): - fab.run('mkdir -p %s' % REMOTE_FOLDER) - fab.sudo('apt-get install aptitude') - fab.sudo('aptitude update') - fab.sudo('aptitude install -y ' - 'apache2 libapache2-mod-wsgi python3-venv libpq-dev ' - 'libffi-dev ' - 'python3-dev python-dev libjpeg-dev build-essential ' - 'postgresql') - with fab.cd(REMOTE_FOLDER): - fab.run('mkdir -p wsgi') - fab.put('wsgi/lost-tracker.wsgi', '/tmp') - fab.run('[ -f wsgi/lost-tracker.wsgi ] || mv /tmp/lost-tracker.wsgi', - 'wsgi') - fab.run('[ -f /tmp/lost-tracker.wsgi ] && rm -f /tmp/lost-tracker.wsgi') - fab.run('[ -d env ] || pyvenv env') - fab.run('./env/bin/pip install -U pip alembic') - fab.sudo('chown -R {0}:{0} {1}'.format(REMOTE_USER, REMOTE_FOLDER)) - - -@fab.task -def alembic(): - "Run DB Migrations" - with fab.settings(shell_env={'PYTHONWARNINGS': ''}): - fab.local('./env/bin/alembic upgrade head') - - -@fab.task -def develop(): - """ - Sets up a new development environment. Should be run right after cloning - the repo. - """ - l = fab.local - ini_file = '.mamerwiselen/lost-tracker/app.ini' - - l('[ -d env ] || virtualenv env') - l('./env/bin/pip install "setuptools>=0.8"') # needed by IMAPClient - # some packages are unavailable on pypi :( -> Use requirements.txt - l('./env/bin/pip install -r requirements.txt') - l('./env/bin/pip install -e .[dev,test]') - l('docker pull {}'.format(DOCKER_PLOVR)) - l('mkdir -p .mamerwiselen/lost-tracker') - - with fab.settings(warn_only=True): - ini_is_missing = l('[ -f ' + ini_file + ' ]').failed - - if ini_is_missing: - print(clr.green('No INI file found. Please fill in the following ' - 'values:')) - print('') - print(clr.green(' Look at "app.ini.dist" for documentation.')) - print('') - print(clr.yellow(' The file will be stored in {}'.format(ini_file))) - print(clr.yellow(' You can change this at any time. If you do, you ' - 'need to restart the application if it is still ' - 'running!')) - print('') - cfg = SafeConfigParser() - cfg.read('app.ini.dist') - for sect in cfg.sections(): - for opt in cfg.options(sect): - curval = cfg.get(sect, opt) - newval = fab.prompt('{}:{} = '.format( - clr.green(sect), - clr.blue(opt, bold=True)), default=curval) - cfg.set(sect, opt, newval) - cfg.write(open(ini_file, 'w')) - print(clr.green('>>> New config file created in ' + ini_file)) - else: - print(clr.white('=== Kept old config file from ' + ini_file, bold=True)) - fab.execute(babel_compile) - print(clr.green('Applying database migrations...')) - print(clr.yellow('NOTE: The DB must exist, and the URL in %r must be ' - 'correct. I will pause now to give you a chance to fix ' - 'that, if needed. Press ENTER when ready.' % ini_file)) - print(clr.yellow('This step can always be re-executed by running ' - '"fab alembic"')) - fab.prompt('Press ENTER when ready...') - fab.execute(alembic) - print(clr.green('Done!')) - - -@fab.task -def build(): - """ - Compile JS sources. - """ - from os import stat - from json import load - with open('plovr-config.js') as fp: - plovr_config = load(fp) - - input_file = plovr_config['inputs'] - output_file = plovr_config['output-file'] - - stat_in = stat(input_file) - - if exists(output_file): - stat_out = stat(output_file) - needs_build = stat_in.st_mtime > stat_out.st_mtime - else: - needs_build = True - - if not needs_build: - print(clr.blue(input_file), - clr.green('is older than'), - clr.blue(output_file), - clr.green('Assuming it has not changed and skipping ' - 'closure-build!')) - return - else: - print(clr.blue(input_file), - clr.green('has changed'), - clr.green('recompiling to'), - clr.blue(output_file)) - - fab.local('docker run -v {}:/app --rm {} build /app/plovr-config.js'.format( - dirname(__file__), - DOCKER_PLOVR, - )) - - -@fab.task -def extract_pot(): - fab.local('./env/bin/pybabel extract ' - '-F babel.cfg -o messages.pot lost_tracker') - - -@fab.task -def babel_init(locale): - """ - Initialise support for a new locale. - """ - fab.local('./env/bin/pybabel init ' - '-i messages.pot -d lost_tracker/translations -l {}'.format( - locale)) - - -@fab.task -def babel_compile(): - """ - Compile all translations into the application. - """ - fab.local('./env/bin/pybabel compile -f -d lost_tracker/translations') - - -@fab.task -def babel_update(): - """ - Extracts translations and updates the pot template. - """ - fab.execute(extract_pot) - fab.local('./env/bin/pybabel update ' - '-i messages.pot ' - '-d lost_tracker/translations') - - -def _get_psql_params(): - ''' - return a list of PostgreSQL parameters. These parameters are usable for - commands like ``psql`` or ``pg_dump``. It uses a config-file containing a - ``db.dsn`` option to determine those parameters. - ''' - from urlparse import urlparse - with fab.cd(REMOTE_FOLDER), fab.hide('stdout', 'running', 'stderr'): - dsn = fab.run( - './env/bin/python -c "' - 'from config_resolver import Config; ' - 'import logging; logging.basicConfig(level=logging.ERROR); ' - "config = Config('mamerwiselen', 'lost-tracker'); " - "print(config.get('db', 'dsn'))" - '"' - ).strip() - if not dsn: - fab.abort(clr.red('Unable to get DSN from config file!')) - - # psql does not support SQLAlchemy Style DSNs so we need to parse it and - # reconstruct a proper command - dsn_detail = urlparse(dsn) - psql_params = ['-U', dsn_detail.username] - if dsn_detail.port: - psql_params.extend(['-p', dsn_detail.port]) - if dsn_detail.hostname and dsn_detail.hostname != 'localhost': - psql_params.extend(['-h', dsn_detail.hostname]) - psql_params.append(dsn_detail.path[1:]) - return psql_params - - -@fab.task -def pull_db(): - psql_params = _get_psql_params() - with fab.cd(REMOTE_FOLDER): - tempfile = fab.run('mktemp --tmpdir=.') - full_cmd = ['pg_dump', '--clean', '-f', tempfile] + psql_params - fab.run(' '.join(full_cmd)) - retrieved_files = fab.get(tempfile) - fab.run('rm %s' % tempfile) - if len(retrieved_files) != 1: - fab.abort(clr.red('Expected to retrieve exactly one file. ' - 'But got %d!' % len(retrieved_files))) - local_file = next(iter(retrieved_files)) - fab.local('psql -X -q -f %s lost_tracker_2016' % local_file) - fab.local('rm %s' % local_file) - - -@fab.task -def serve_plovr(): - """ - Run JS development server. - """ - fab.local('docker run -p 9810:9810 -v {}:/app --rm {} ' - 'serve /app/plovr-config.js'.format( - dirname(__file__), - DOCKER_PLOVR, - )) - - -@fab.task -def serve_web(): - """ - Run development server. - """ - fab.local('./env/bin/python lost_tracker/main.py') diff --git a/tasks.py b/tasks.py new file mode 100644 index 0000000..89e38dc --- /dev/null +++ b/tasks.py @@ -0,0 +1,293 @@ +from configparser import SafeConfigParser +from getpass import getuser +from os.path import dirname, exists + +from fabric import Connection +from invoke import Context, task + +from blessings import Terminal + +ROLES = { + 'prod': '178.62.219.167', +} + + +REMOTE_FOLDER = '/var/www/lost.lu/www' +REMOTE_USER = 'lost_tracker' +DOCKER_PLOVR = 'exhuma/lost-tracker-closure' + + +@task +def deploy(ctx): # type: ignore + build(ctx) + babel_compile(ctx) + upload(ctx) + with Connection(ROLES['prod'], user=REMOTE_USER) as conn: + install(conn) + clean(conn) + + +@task +def publish(ctx): # type: ignore + ctx.run('docker build -t malbert/lost-tracker:2019 -t lost-tracker:latest .') + ctx.run('docker login') + ctx.run('docker push malbert/lost-tracker:latest') + + +# @task +# def install(): +# name = fab.local('python setup.py --fullname', capture=True) +# with fab.cd(REMOTE_FOLDER): +# fab.run('env/bin/pip install alembic') +# fab.run('env/bin/pip install -r requirements.txt') +# fab.run('env/bin/pip install {0}.tar.gz'.format(name)) +# fab.run('env/bin/alembic upgrade head') +# fab.run('touch wsgi/lost-tracker.wsgi') +# +# +# @fab.task +# def clean(): +# name = fab.local('python setup.py --fullname', capture=True) +# with fab.cd(REMOTE_FOLDER): +# fab.run('rm {0}.tar.gz'.format(name)) +# fab.run('rm requirements.txt') +# +# +# @fab.task +# @fab.with_settings(user=REMOTE_USER) +# def redeploy(): +# name = fab.local('python setup.py --name', capture=True) +# with fab.cd(REMOTE_FOLDER): +# fab.run('env/bin/pip uninstall %s' % name) +# fab.execute(deploy) +# +# +# @fab.task +# @fab.with_settings(user=getuser()) +# def bootstrap(): +# fab.run('mkdir -p %s' % REMOTE_FOLDER) +# fab.sudo('apt-get install aptitude') +# fab.sudo('aptitude update') +# fab.sudo('aptitude install -y ' +# 'apache2 libapache2-mod-wsgi python3-venv libpq-dev ' +# 'libffi-dev ' +# 'python3-dev python-dev libjpeg-dev build-essential ' +# 'postgresql') +# with fab.cd(REMOTE_FOLDER): +# fab.run('mkdir -p wsgi') +# fab.put('wsgi/lost-tracker.wsgi', '/tmp') +# fab.run('[ -f wsgi/lost-tracker.wsgi ] || mv /tmp/lost-tracker.wsgi', +# 'wsgi') +# fab.run('[ -f /tmp/lost-tracker.wsgi ] && rm -f /tmp/lost-tracker.wsgi') +# fab.run('[ -d env ] || pyvenv env') +# fab.run('./env/bin/pip install -U pip alembic') +# fab.sudo('chown -R {0}:{0} {1}'.format(REMOTE_USER, REMOTE_FOLDER)) + + +@task +def alembic(ctx): # type: ignore + "Run DB Migrations" + ctx.run('./env/bin/alembic upgrade head', env={'PYTHONWARNINGS': ''}) + + +@task +def develop(ctx): # type: ignore + """ + Sets up a new development environment. Should be run right after cloning + the repo. + """ + l = ctx.run + ini_file = '.mamerwiselen/lost-tracker/app.ini' + + l('[ -d env ] || virtualenv env') + l('./env/bin/pip install "setuptools>=0.8"') # needed by IMAPClient + # some packages are unavailable on pypi :( -> Use requirements.txt + l('./env/bin/pip install -r requirements.txt') + l('./env/bin/pip install -e .[dev,test]') + l('docker pull {}'.format(DOCKER_PLOVR)) + l('mkdir -p .mamerwiselen/lost-tracker') + + ini_is_missing = l('[ -f ' + ini_file + ' ]', run=True).failed + + if ini_is_missing: + term = Terminal() + print(term.green('No INI file found. Please fill in the following ' + 'values:')) + print('') + print(term.green(' Look at "app.ini.dist" for documentation.')) + print('') + print(term.yellow(' The file will be stored in {}'.format(ini_file))) + print(term.yellow(' You can change this at any time. If you do, you ' + 'need to restart the application if it is still ' + 'running!')) + print('') + cfg = SafeConfigParser() + cfg.read('app.ini.dist') + for sect in cfg.sections(): + for opt in cfg.options(sect): + curval = cfg.get(sect, opt) + newval = input('{}:{} = '.format( + term.green(sect), + term.bold_blue(opt))) + if not newval.strip(): + newval = curval + cfg.set(sect, opt, newval) + cfg.write(open(ini_file, 'w')) + print(term.green('>>> New config file created in ' + ini_file)) + else: + print(term.white('=== Kept old config file from ' + ini_file, + bold=True)) + babel_compile(ctx) + print(term.green('Applying database migrations...')) + print(term.yellow('NOTE: The DB must exist, and the URL in %r must be ' + 'correct. I will pause now to give you a chance to fix ' + 'that, if needed. Press ENTER when ready.' % ini_file)) + print(term.yellow('This step can always be re-executed by running ' + '"fab alembic"')) + input('Press ENTER when ready...') + alembic(ctx) + print(term.green('Done!')) + + +@task +def build(ctx): # type: ignore + """ + Compile JS sources. + """ + from os import stat + from json import load + with open('plovr-config.js') as fp: + plovr_config = load(fp) + + input_file = plovr_config['inputs'] + output_file = plovr_config['output-file'] + + stat_in = stat(input_file) + + if exists(output_file): + stat_out = stat(output_file) + needs_build = stat_in.st_mtime > stat_out.st_mtime + else: + needs_build = True + + term = Terminal() + if not needs_build: + print(term.blue(input_file), + term.green('is older than'), + term.blue(output_file), + term.green('Assuming it has not changed and skipping ' + 'closure-build!')) + return + else: + print(term.blue(input_file), + term.green('has changed'), + term.green('recompiling to'), + term.blue(output_file)) + + ctx.run('docker run -v {}:/app --rm {} build /app/plovr-config.js'.format( + dirname(__file__), + DOCKER_PLOVR, + )) + + +@task +def extract_pot(ctx): # type: ignore + ctx.run('./env/bin/pybabel extract ' + '-F babel.cfg -o messages.pot lost_tracker') + + +@task +def babel_init(ctx, locale): # type: ignore + """ + Initialise support for a new locale. + """ + ctx.run('./env/bin/pybabel init ' + '-i messages.pot -d lost_tracker/translations -l {}'.format( + locale)) + + +@task +def babel_compile(ctx): # type: ignore + """ + Compile all translations into the application. + """ + ctx.run('./env/bin/pybabel compile -f -d lost_tracker/translations') + + +@task +def babel_update(ctx): # type: ignore + """ + Extracts translations and updates the pot template. + """ + extract_pot(ctx) + ctx.run('./env/bin/pybabel update ' + '-i messages.pot ' + '-d lost_tracker/translations') + + +# def _get_psql_params(): +# ''' +# return a list of PostgreSQL parameters. These parameters are usable for +# commands like ``psql`` or ``pg_dump``. It uses a config-file containing a +# ``db.dsn`` option to determine those parameters. +# ''' +# from urlparse import urlparse +# with fab.cd(REMOTE_FOLDER), fab.hide('stdout', 'running', 'stderr'): +# dsn = fab.run( +# './env/bin/python -c "' +# 'from config_resolver import Config; ' +# 'import logging; logging.basicConfig(level=logging.ERROR); ' +# "config = Config('mamerwiselen', 'lost-tracker'); " +# "print(config.get('db', 'dsn'))" +# '"' +# ).strip() +# if not dsn: +# fab.abort(clr.red('Unable to get DSN from config file!')) +# +# # psql does not support SQLAlchemy Style DSNs so we need to parse it and +# # reconstruct a proper command +# dsn_detail = urlparse(dsn) +# psql_params = ['-U', dsn_detail.username] +# if dsn_detail.port: +# psql_params.extend(['-p', dsn_detail.port]) +# if dsn_detail.hostname and dsn_detail.hostname != 'localhost': +# psql_params.extend(['-h', dsn_detail.hostname]) +# psql_params.append(dsn_detail.path[1:]) +# return psql_params +# +# +# @fab.task +# def pull_db(): +# psql_params = _get_psql_params() +# with fab.cd(REMOTE_FOLDER): +# tempfile = fab.run('mktemp --tmpdir=.') +# full_cmd = ['pg_dump', '--clean', '-f', tempfile] + psql_params +# fab.run(' '.join(full_cmd)) +# retrieved_files = fab.get(tempfile) +# fab.run('rm %s' % tempfile) +# if len(retrieved_files) != 1: +# fab.abort(clr.red('Expected to retrieve exactly one file. ' +# 'But got %d!' % len(retrieved_files))) +# local_file = next(iter(retrieved_files)) +# fab.local('psql -X -q -f %s lost_tracker_2016' % local_file) +# fab.local('rm %s' % local_file) + + +@task +def serve_plovr(ctx): # type: ignore + """ + Run JS development server. + """ + ctx.run('docker run -p 9810:9810 -v {}:/app --rm {} ' + 'serve /app/plovr-config.js'.format( + dirname(__file__), + DOCKER_PLOVR, + )) + + +@task +def serve_web(ctx): # type: ignore + """ + Run development server. + """ + ctx.run('./env/bin/python lost_tracker/main.py') From 1b2c2af9e8f94d6b81e6e5e3b0204244a2a31733 Mon Sep 17 00:00:00 2001 From: Michel Albert Date: Sun, 7 Apr 2019 14:26:49 +0200 Subject: [PATCH 03/20] Remove login code (broken OAuth) --- lost_tracker/main.py | 52 ----------------------- lost_tracker/templates/master_framed.html | 10 ----- 2 files changed, 62 deletions(-) diff --git a/lost_tracker/main.py b/lost_tracker/main.py index 85eae2a..bb173f2 100644 --- a/lost_tracker/main.py +++ b/lost_tracker/main.py @@ -3,13 +3,6 @@ from config_resolver import Config from flask.ext.babel import Babel, gettext -from flask.ext.social import ( - SQLAlchemyConnectionDatastore, - Social, - login_failed, -) -from flask.ext.social.views import connect_handler -from flask.ext.social.utils import get_connection_values_from_oauth_response from flask.ext.security import ( SQLAlchemyUserDatastore, Security, @@ -80,54 +73,10 @@ def make_app(): babel = Babel() security = Security() - social = Social() user_datastore = SQLAlchemyUserDatastore(mdl.DB, mdl.User, mdl.Role) app = Flask(__name__) - @login_failed.connect_via(app) - def auto_add_user(sender, provider, oauth_response): - connection_values = get_connection_values_from_oauth_response( - provider, oauth_response) - email = connection_values['email'] - if not email or not email.strip(): - email = '' - - if provider.name.lower() == 'facebook': - fname = connection_values['full_name'] - email = fb.get_email(oauth_response) - elif provider.name.lower() == 'twitter': - fname = connection_values['display_name'][1:] # cut off leading @ - else: - fname = connection_values['display_name'] - - user = user_datastore.create_user( - email=email, - name=fname, - active=True, - confirmed_at=datetime.now(), - ) - - role_query = mdl.DB.session.query(mdl.Role).filter_by( - name='authenticated') - try: - role = role_query.one() - except NoResultFound: - role = mdl.Role(name='authenticated') - - user.roles.append(role) - user_datastore.commit() - connection_values['user_id'] = user.id - connect_handler(connection_values, provider) - login_user(user) - mdl.DB.session.commit() - flash(gettext( - 'Successfully linked login with {}. ' - 'Ignore the message saying: "{}"').format( - provider.name, '... account not associated with an existing user'), - 'info') - return redirect(url_for('root.profile')) - app.user_datastore = user_datastore app.localconf = lconf = Config('mamerwiselen', 'lost-tracker', version='2.0', require_load=True) @@ -147,7 +96,6 @@ def auto_add_user(sender, provider, oauth_response): app.config.update(social_connections) - social.init_app(app, SQLAlchemyConnectionDatastore(mdl.DB, mdl.Connection)) security.init_app(app, user_datastore) app.register_blueprint(COMMENT, url_prefix=COMMENT_PREFIX) diff --git a/lost_tracker/templates/master_framed.html b/lost_tracker/templates/master_framed.html index b6d1fc7..823e2b6 100644 --- a/lost_tracker/templates/master_framed.html +++ b/lost_tracker/templates/master_framed.html @@ -33,16 +33,6 @@   - - - {{_('Matrix')}} | - {% if current_user.is_authenticated %} - {{_('Logged in as:')}} {{avatar(current_user, 20)}} {{current_user.name}} | - {{_('Logout')}} - {% else %} - {{_('Login')}} - {% endif %} - {% endblock %} From 009ac5a0cf6e5e9095255df764b06f0703530dcc Mon Sep 17 00:00:00 2001 From: Michel Albert Date: Sun, 7 Apr 2019 14:42:34 +0200 Subject: [PATCH 04/20] Migrate from fabric to invoke, fix dependencies --- custom-requirements.txt | 3 +++ setup.py | 28 ++++++++++++---------------- tasks.py | 32 +++++++++++++++++++++++--------- 3 files changed, 38 insertions(+), 25 deletions(-) create mode 100644 custom-requirements.txt diff --git a/custom-requirements.txt b/custom-requirements.txt new file mode 100644 index 0000000..e346cbc --- /dev/null +++ b/custom-requirements.txt @@ -0,0 +1,3 @@ +git+https://github.com/exhuma/flask-social@711b21fd8#egg=flask-social +git+https://github.com/pythonforfacebook/facebook-sdk@master#egg=facebook-sdk +# git+https://github.com/bear/python-twitter diff --git a/setup.py b/setup.py index 9d566e9..c0d4cbe 100644 --- a/setup.py +++ b/setup.py @@ -7,24 +7,20 @@ packages=find_packages(), install_requires=[ 'config-resolver >= 4.2, <5.0', - 'envelopes==0.4', - 'facebook-sdk>=1.0.0a0', - 'flask-babel==0.9', - 'flask-security==1.7.5', - 'flask-social>=1.6.2', - 'flask-sqlalchemy==2.1', - 'flask==0.10.1', - 'google-api-python-client==1.5.0', + 'envelopes', + 'flask < 1.0', + 'flask-babel', + 'flask-security', + 'flask-sqlalchemy', 'gouge >= 1.1, <2.0', - 'imapclient==1.0.1', - 'markdown==2.6.5', - 'pillow==2.8.1', - 'psycopg2==2.5.2', - 'python-twitter>=3.0rc1', + 'imapclient', + 'markdown', + 'pillow', + 'psycopg2', 'pytz', - 'qrcode==5.2.2', - 'requests==2.6.0', - 'sqlalchemy==0.9.3', + 'qrcode', + 'requests', + 'sqlalchemy', ], extras_require={ 'dev': [ diff --git a/tasks.py b/tasks.py index 89e38dc..5cb7388 100644 --- a/tasks.py +++ b/tasks.py @@ -29,7 +29,6 @@ def deploy(ctx): # type: ignore @task def publish(ctx): # type: ignore - ctx.run('docker build -t malbert/lost-tracker:2019 -t lost-tracker:latest .') ctx.run('docker login') ctx.run('docker push malbert/lost-tracker:latest') @@ -99,18 +98,18 @@ def develop(ctx): # type: ignore l = ctx.run ini_file = '.mamerwiselen/lost-tracker/app.ini' - l('[ -d env ] || virtualenv env') + l('[ -d env ] || python3 -m venv env') l('./env/bin/pip install "setuptools>=0.8"') # needed by IMAPClient - # some packages are unavailable on pypi :( -> Use requirements.txt - l('./env/bin/pip install -r requirements.txt') + # some packages are unavailable on pypi :( -> Use custom-requirements.txt + l('./env/bin/pip install -r custom-requirements.txt') l('./env/bin/pip install -e .[dev,test]') l('docker pull {}'.format(DOCKER_PLOVR)) l('mkdir -p .mamerwiselen/lost-tracker') - ini_is_missing = l('[ -f ' + ini_file + ' ]', run=True).failed + ini_is_missing = l('[ -f ' + ini_file + ' ]').failed + term = Terminal() if ini_is_missing: - term = Terminal() print(term.green('No INI file found. Please fill in the following ' 'values:')) print('') @@ -135,8 +134,7 @@ def develop(ctx): # type: ignore cfg.write(open(ini_file, 'w')) print(term.green('>>> New config file created in ' + ini_file)) else: - print(term.white('=== Kept old config file from ' + ini_file, - bold=True)) + print(term.bold_white('=== Kept old config file from ' + ini_file)) babel_compile(ctx) print(term.green('Applying database migrations...')) print(term.yellow('NOTE: The DB must exist, and the URL in %r must be ' @@ -150,7 +148,7 @@ def develop(ctx): # type: ignore @task -def build(ctx): # type: ignore +def build_js(ctx): # type: ignore """ Compile JS sources. """ @@ -189,6 +187,22 @@ def build(ctx): # type: ignore DOCKER_PLOVR, )) +@task +def build(ctx): # type: ignore + """ + Compile JS sources. + """ + from os import listdir + build_js(ctx) + ctx.run('rm -rf dist') + ctx.run('python setup.py sdist') + files = [fname for fname in listdir('dist') if not fname.startswith('.')] + assert len(files) == 1 + ctx.run('mv dist/%s dist/docker.tar.gz' % files[0]) + ctx.run( + 'docker build -t malbert/lost-tracker:2019 -t malbert/lost-tracker:latest .') + + @task def extract_pot(ctx): # type: ignore From f7c1b6b6906a4e7cd1891cbd026b76bb343d83fe Mon Sep 17 00:00:00 2001 From: Michel Albert Date: Sun, 7 Apr 2019 14:43:47 +0200 Subject: [PATCH 05/20] Remove Vagrant (in favor of docker) --- Vagrantfile | 76 ----------------------------------------------------- 1 file changed, 76 deletions(-) delete mode 100755 Vagrantfile diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100755 index 209190c..0000000 --- a/Vagrantfile +++ /dev/null @@ -1,76 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -VAGRANTFILE_API_VERSION = "2" - -$script = <