From 43056e3327ff1be67a12b9eac10b1ba274bb7de1 Mon Sep 17 00:00:00 2001 From: Felipe Martin Date: Tue, 18 Mar 2014 13:48:12 +0100 Subject: [PATCH] Initial commit --- .gitignore | 12 ++ config/local/requirements.txt | 1 + config/requirements.txt | 3 + fabfile.py | 246 ++++++++++++++++++++++++++++++++ gruntfile.coffee | 84 +++++++++++ manage.py | 17 +++ package.json | 13 ++ shelfzilla/__init__.py | 0 shelfzilla/settings/__init__.py | 0 shelfzilla/settings/base.py | 85 +++++++++++ shelfzilla/settings/local.py | 4 + shelfzilla/urls.py | 12 ++ shelfzilla/wsgi.py | 24 ++++ 13 files changed, 501 insertions(+) create mode 100644 .gitignore create mode 100644 config/local/requirements.txt create mode 100644 config/requirements.txt create mode 100644 fabfile.py create mode 100644 gruntfile.coffee create mode 100644 manage.py create mode 100644 package.json create mode 100644 shelfzilla/__init__.py create mode 100644 shelfzilla/settings/__init__.py create mode 100644 shelfzilla/settings/base.py create mode 100644 shelfzilla/settings/local.py create mode 100644 shelfzilla/urls.py create mode 100644 shelfzilla/wsgi.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18e285c --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Front +node_modules + +# Python +*.pyc +.virtualenv + +# OS X +.DS_Store + +# Local +db.sqlite3 diff --git a/config/local/requirements.txt b/config/local/requirements.txt new file mode 100644 index 0000000..3c8d7e7 --- /dev/null +++ b/config/local/requirements.txt @@ -0,0 +1 @@ +-r ../requirements.txt diff --git a/config/requirements.txt b/config/requirements.txt new file mode 100644 index 0000000..160789c --- /dev/null +++ b/config/requirements.txt @@ -0,0 +1,3 @@ +Django==1.6.2 +South==0.8.4 +django-suit==0.2.6 diff --git a/fabfile.py b/fabfile.py new file mode 100644 index 0000000..9a0b610 --- /dev/null +++ b/fabfile.py @@ -0,0 +1,246 @@ +from __future__ import with_statement, print_function +from os.path import dirname, abspath, join + +from fabric.api import * +from fabric.context_managers import settings +from fabric.contrib.files import exists +from fabric.colors import yellow, red, white, green + + +# +# GLOBALS +# +env.LOCAL_PATH = dirname(abspath(__file__)) + +# +# HOSTS +# +HOSTS = { + 'local': { + 'host': '127.0.0.1', + 'path': env.LOCAL_PATH, + }, + 'dev': { + 'host': 'dev', + 'path': '~', + 'user': 'app', + } +} + +if not env.hosts: + env.hosts = ['local'] + +# Doctor checkups +DOCTOR = { + 'apps': ['virtualenv', 'python', 'npm', 'grunt'] +} + + +# +# HELPERS +# +def get_host_string(host_config): + host_string = '' + if 'user' in host_config: + host_string += '{}@'.format(host_config['user']) + + host_string += host_config['host'] + + if 'port' in host_config: + host_string += ':{}'.format(host_config['port']) + + return host_string + + +def get_host_app_environment(): + """ + Get remote $ENVIRONMENT variable value. + Default: local + """ + # In case we're setting up a new host we need this defined + app_environment = 'local' + try: + ssh_io = run('echo -e "\n$ENVIRONMENT"', quiet=True).split()[1] + except IndexError: + ssh_io = 'local' + if ssh_io and exists(join(env.LOCAL_PATH, 'config', ssh_io)): + app_environment = ssh_io + + return app_environment + + +# +# CONTEXT MANAGERS +# +def virtualenv(): + """ + Activates virtualenv first + """ + return prefix('source .virtualenv/bin/activate') + + +# +# DECORATORS +# +def task_environment(method): + """ + Retrieves host based configuration and app_environment from the host + and automatically CDs into the specified path + """ + def wrapper(*args, **kwargs): + env.host_config = HOSTS[env.host] + with settings(host_string=get_host_string(env.host_config)): + env.appenv = get_host_app_environment() + + with cd(env.host_config['path']): + return method(*args, **kwargs) + return wrapper + + +# +# TASKS +# +@task_environment +@task +def setup_environment(): + """ + Prepares environment for the application + """ + execute(setup_virtualenv) + execute(setup_tools) + execute(setup_database) + + +@task_environment +@task +def setup_virtualenv(): + """ + Creates or updates a virtualenv + """ + if not exists('.virtualenv'): + print(yellow('Create virtualenv')) + run('virtualenv-2.7 .virtualenv') + + with virtualenv(): + print(yellow('Installing requirements')) + run('pip install -r config/{}/requirements.txt --use-mirrors'.format( + env.appenv)) + + +@task_environment +@task +def setup_tools(): + # Setup frontend tools + print(yellow('Installing npm dependencies')) + run('npm install') + + +@task_environment +@task +def setup_database(): + """ + Create or update the database + """ + with virtualenv(): + print(yellow('SyncDB')) + run('python manage.py syncdb') + print(yellow('Migrate')) + run('python manage.py migrate') + + +@task_environment +@task +def set_environment(): + env_type = prompt('Environment type?') + bashrc = run('cat $HOME/.bashrc', quiet=True) + if 'export ENVIRONMENT=`cat $HOME/.environment`' not in bashrc: + print(red('Error: .bashrc is not properly configured!')) + run("echo export ENVIRONMENT=\$\(cat $HOME/.environment\) " + ">> .bash_profile") + run('echo {} > .environment'.format(env_type)) + + +@task_environment +@task +def shell(): + """ + Opens a shell to the given host + """ + open_shell('cd {}'.format(env.host_config['path'])) + + +@task_environment +@task +def doctor(): + print(yellow('Checking for software:')) + for app in DOCTOR['apps']: + print(white('{}'.format(app)), end=': ') + check = run('which {}'.format(app), quiet=True) + if check.succeeded: + print(green('present')) + else: + print(red('not present')) + + +# +# LOCAL ONLY +# +@task_environment +@task +@hosts(['local']) +def runserver(): + """ + Executes local development server + """ + with virtualenv(): + run('python manage.py runserver 0.0.0.0:8000') + + +@task_environment +@task +def clean_pyc(): + run('find . -name "*.pyc" -exec rm -rf {} \;') + + +@task_environment +@task +@hosts(['local']) +def rungrunt(): + """ + Executes grunt + """ + run('grunt watch') + + +# +# SETUP +# +@task_environment +@task +@hosts(['local']) +def setup(): + execute(setup_virtualenv) + print(yellow('Creating project based on template')) + project_name = prompt('Project name? (lowercase, a-z or _)') + with virtualenv(): + run('django-admin.py startproject ' + '--template=$PWD/template {} .'.format(project_name) + ) + + # Find and replace {{ project_name }} inside gruntfile + run( + "sed -i -e 's/{{ project_name }}/%s/g' ./gruntfile.coffee" % + project_name + ) + # Find and replace {{ project_name }} inside package.json + run( + "sed -i -e 's/{{ project_name }}/%s/g' ./package.json" % + project_name + ) + + # Remove sed backup files + run("rm *-e") + + print(yellow('Finished!')) + + print('If youre ready to work, run fab doctor & fab setup_environment') diff --git a/gruntfile.coffee b/gruntfile.coffee new file mode 100644 index 0000000..65cf816 --- /dev/null +++ b/gruntfile.coffee @@ -0,0 +1,84 @@ +module.exports = (grunt) -> + # Project + grunt.initConfig + pkg: grunt.file.readJSON 'package.json' + + less: + options: + ieCompat: true + compress: true + development: + files: + "shelfzilla/themes/default/static/css/style.css": "shelfzilla/themes/default/static/less/style.less" + + coffee: + development: + files: + 'shelfzilla/themes/default/static/js/main.full.js': 'shelfzilla/themes/default/static/coffee/main.coffee' + + + concat: + options: + separator: ';' + base: + src: [ + "shelfzilla/themes/default/static/js/main.full.js", + ] + dest: "shelfzilla/themes/default/static/js/site.js" + + uglify: + development: + files: + 'shelfzilla/themes/default/static/js/site.js': 'shelfzilla/themes/default/static/js/site.js' + + clean: + development: + src: [ + "shelfzilla/themes/default/static/js/*.full.js", + ] + production: + src: [ + "shelfzilla/themes/default/static/js/*.full.js", + ] + release: + src: [ + "shelfzilla/themes/default/static/less", + "shelfzilla/themes/default/static/coffee", + "shelfzilla/themes/default/static/libs/kube*", + ] + + watch: + options: + livereload: true + layout: + files: ['shelfzilla/themes/default/templates/**/*.html', 'shelfzilla/themes/default/templates/**/*.jinja'] + tasks: [] + less: + files: ['shelfzilla/themes/default/static/less/*.less'] + tasks: ['less'] + coffee: + files: ['shelfzilla/themes/default/static/coffee/*.coffee'] + tasks: ['coffee', 'concat', 'clean:development'] + + + # Modules + grunt.loadNpmTasks 'grunt-contrib-less' + grunt.loadNpmTasks 'grunt-contrib-coffee' + grunt.loadNpmTasks 'grunt-contrib-uglify' + grunt.loadNpmTasks 'grunt-contrib-watch' + grunt.loadNpmTasks 'grunt-contrib-concat' + grunt.loadNpmTasks 'grunt-contrib-clean' + + # Tasks + grunt.registerTask 'default', [ + "less", "coffee", "concat", "clean:development", + "watch" + ] + + grunt.registerTask 'compile', [ + "less", "coffee", "concat", 'uglify', "clean:development" + ] + + grunt.registerTask 'build', [ + "less", "coffee", "concat", "uglify", 'clean:production' + ] diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..b2410af --- /dev/null +++ b/manage.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +import os +import sys + +SETTINGS_FILE = 'local' +if 'ENVIRONMENT' in os.environ: + SETTINGS_FILE = os.environ['ENVIRONMENT'] + +if __name__ == "__main__": + os.environ.setdefault( + "DJANGO_SETTINGS_MODULE", + "shelfzilla.settings.{}".format(SETTINGS_FILE) + ) + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/package.json b/package.json new file mode 100644 index 0000000..6f38091 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "shelfzilla", + "version": "0.0.0", + "devDependencies": { + "grunt": ">=0.4.1", + "grunt-contrib-coffee": ">=0.7.0", + "grunt-contrib-less": ">=0.5.2", + "grunt-contrib-uglify": ">=0.2.2", + "grunt-contrib-watch": ">=0.4.0", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-clean": "~0.5.0" + } +} diff --git a/shelfzilla/__init__.py b/shelfzilla/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/shelfzilla/settings/__init__.py b/shelfzilla/settings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/shelfzilla/settings/base.py b/shelfzilla/settings/base.py new file mode 100644 index 0000000..0d68ab7 --- /dev/null +++ b/shelfzilla/settings/base.py @@ -0,0 +1,85 @@ +""" +Django settings for shelfzilla project. + +For more information on this file, see +https://docs.djangoproject.com/en/1.6/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.6/ref/settings/ +""" + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os +BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'byceao!)=3(+ipvd+oh8t3zlhm3^ed-d3xh^#y=8xzz4%kfqv_' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +TEMPLATE_DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = ( + 'suit', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'south', +) + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'shelfzilla.urls' + +WSGI_APPLICATION = 'shelfzilla.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.6/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +# Internationalization +# https://docs.djangoproject.com/en/1.6/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.6/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/shelfzilla/settings/local.py b/shelfzilla/settings/local.py new file mode 100644 index 0000000..710706a --- /dev/null +++ b/shelfzilla/settings/local.py @@ -0,0 +1,4 @@ +from .base import * + +DEBUG = True +TEMPLATE_DEBUG = True diff --git a/shelfzilla/urls.py b/shelfzilla/urls.py new file mode 100644 index 0000000..e0ba923 --- /dev/null +++ b/shelfzilla/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import patterns, include, url + +from django.contrib import admin +admin.autodiscover() + +urlpatterns = patterns('', + # Examples: + # url(r'^$', 'shelfzilla.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +) diff --git a/shelfzilla/wsgi.py b/shelfzilla/wsgi.py new file mode 100644 index 0000000..a737b48 --- /dev/null +++ b/shelfzilla/wsgi.py @@ -0,0 +1,24 @@ +""" +WSGI config for shelfzilla project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ +""" + +import os + + +SETTINGS_FILE = 'local' +if 'ENVIRONMENT' in os.environ: + SETTINGS_FILE = os.environ['ENVIRONMENT'] + + +os.environ.setdefault( + "DJANGO_SETTINGS_MODULE", + "shelfzilla.settings.{}".format(SETTINGS_FILE) +) + +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application()