Makefile.mak

download

# Plik sterujący dla jednego z projektów
#
# Rozbudowaną architektura testującą, która sprawdza projekt po względem
# statycznym (cel "check_valid") i dynamicznym (cel "run_tests"). Te
# sprawdzenia są obligatoryjne przy fazie commit w systemie kontroli
# wersji (cel "ci").
# 
# W ten sposób automatycznie egzekwuję zasadę "projekt w systemie
# kontroli wersji przechodzi wszystkie zautomatyzowane testy". Inne
# automatycznie egzekwowane zasady tu zapisane:
# 
#   - nie można instalować na serwerze produkcyjnym z rozgałęzień
#     (cel "not_in_branch")
#   - obsługa pliku ze zmianami (cel "cvs_install")
#   - polityka tworzenia rozgałęzień (cele: "bcreate", "bmerge")
#   - zgłoszenie rozgałęzienie do kontroli jakości (cel "bverify") -
#     stosuję konwencję nazewniczą tagów w CVS-ie

# $Id: Makefile,v 1.130 2004/01/26 13:38:43 darek Exp $

######################################################################
# cel sprawdzający poprawność projektu (statyczną, dynamiczną)
# i instalujący wersję demo danych w bazie
test_rule: testIndexForm.py config.py rights check_valid run_tests demo

# uruchomienie testów statycznych
check_valid:
    sh check.sh

# uruchomienie testów dynamicznych
run_tests:
    # najpierw testujemy ostatnio modyfikowane moduły
    time -p python test.py ls -t \`grep -lr "^def test" *.py\``

######################################################################
DIST_TGZ=~/proj_name.tgz

# prawidłowy sposób zapisywania zmian w systemie CVS
# możliwy tylko kiedy przejdą wszystkie testy
ci: ready_for_commit test_rule py_compile cvs_commit

######################################################################
# obsługa serwera testowego
#
debian_all: debian_install debian_download debian_import 

# zainstalowanie nowej wersji oprogramowania na serwerze testowym
debian_install:
    tar zcf $(DIST_TGZ)\
        images/*.gif utils/* upgrade/* *.py *.html *.sql\
        *.cgi *.fcgi *.sh *.txt &&\
    scp proj_name-debian.sh $(DIST_TGZ) debian: &&\
    ssh debian 'sh -v proj_name-debian.sh'

# ściągnięcie aktualnej bazy danych z serwera produkcyjnego
debian_download:
    ssh debian '\
    set -x;\
    scp myapp@server.com:.htpasswd\* ~;\
    scp -r myapp@server.com:/var/www/proj_name/config .
    ssh myapp@server.com '\
    set -x;\
    cd /var/www/proj_name/ && python dump.py |\
        gzip -c > ~/tmp/proj_name.sql.gz &&\
        cat ~/tmp/proj_name.sql.gz &&\
        rm ~/tmp/proj_name.sql.gz' |\
    ssh debian 'cat > proj_name.sql.gz'

# załadowanie obrazu bazy danych i uruchomienie skruptów importujących
debian_import:
    ssh debian '\
        set -x;\
        cd public_html/proj_name;\
        sh utils/create-db.sh $$USER $$USER a;\
        zcat ~/proj_name.sql.gz | python mysql.py;\
        python upgrade.py | tee upgrade.log'

######################################################################
not_in_branch: 
    cvs st Makefile | awk '/branch/{exit 1}'

# instalacja na serwerze proukcyjnym - możliwa tylko z HEAD
oracle_install: not_in_branch delay
    tar zcf $(DIST_TGZ)\
        images/* utils/cgi-fcgi upgrade/* *.py *.html *.sql\
        *.cgi *.fcgi *.sh *.txt &&\
    scp proj_name-oracle.sh $(DIST_TGZ) myapp@server.com:tmp &&\
    ssh myapp@server.com 'cd ~/tmp && sh -v proj_name-oracle.sh';\
    now=date +%Y-%m-%d %H:%M';\
    branch_name=`cvs st Makefile | awk '/branch/{print "(" $$3 ")"};\
    info="$$now $$branch_name $$USER: INSTALL";\
    echo $$info >> versions.txt;\
    cvs ci -m "$$info"

    
######################################################################
# statystyki projektu (ilości linii)
stats:
    find . -name *.py' | sed '/CVS/d' | xargs sed '/^$$/d' | wc -l
    find . -name '*.sql' | sed '/CVS/d' | xargs sed '/^$$/d' | wc -l
    find . -name '*.html' | sed '/CVS/d' | xargs sed '/^$$/d' | wc -l

# generowanie charakterystyk pokrycia
pycover:
    rm -f coverage.dat
    python coverage.py ls -t \`grep -l "^def test" *.py\``
    ../pycover/pyviewc.py -e 'usr/lib|/test.py'

# statyczna weryfikacja poprawności kodu *.py
pycheck:
    pychecker\
        --tuple\
        --var\
        --allglobals\
        --initattr\
        --callattr\
        --blacklist xmllib\
        --maxlines 100\
        --maxbranches 20\
        --maxreturns 7\
        *.py > err

# stosunek kod / testy w poszczególnych modułach
test-ratio:
    utils/test-ratio *.py *.sql *.html

# wersja lokalna konfiguracji (stacja developerska)
# różni się od konfiguracji na serwerze produkcyjnym
config.py: workstation.sh install.sh
    . workstation.sh

######################################################################
# wyszukiwanie globalne
s:
    echo -n 'podaj szukany ciąg znaków: ;\
    read a;\
    echo "Szukam $$a";\
    fgrep -n "$$a" *

# usunięcie tymczasowych plików
clean:
    rm -f *.pyc *.pyo cache/* data/* *.cov coverage.dat err

rights:
    chmod 0755 *.cgi *.fcgi utils/* zmianaStanu.py

# dedykowany skrypt tworzy indeks projektu pozwalający po nazwie
# znaleźć definicję funkcji, klasy, zmiennej
tags: *.py *.sql *.html Makefile utils/dtags
    export LC_COLLATE=en_EN; utils/dtags *.py *.sql *.html | sort -k 1,1 > $@

######################################################################
# commit wraz z logowaniem
cvs_commit:
    read -p "enter log for this version: " description;\
    test -z "$$description" && exit 1;\
    now=date +%Y-%m-%d %H:%M';\
    branch_name=`cvs st Makefile | awk '/branch/{print "(" $$3 ")"};\
    info="$$now $$branch_name $$USER: $$description";\
    echo $$info >> versions.txt;\
    cvs ci -m "$$info";

# możemy instalować tylko jeśli wszystkie pliki zostały zapisane w CVS
ready_for_install:
    cvs -n up 2> /dev/null | awk \
        /^\?|^M/ { print "commit file:", $$0; result = 1; }\
        END { exit(result); }'

# od ostatniego update nie wprowadzano zmian na serwer
# wersja lokalna jest wersją aktualną
ready_for_commit:
    cvs -n up 2> /dev/null | awk '\
        /^P|^U|^\?|^C/ { print "update file:", $$0; result = 1; }\
        END { exit(result); }'

# sprawdzenie, czy wszystkie pliki się kompilują
py_compile:
    ls *.py | sed 's/\(.*\)\.py/import \1/' | python -OO
    rm -f *.pyo

# inicjalizacja bazy danych przykładowymi danymi
demo:
    python demo.py run_demo

delay:
    @echo "INSTALUJESZ NA SERWERZE PRODUKCYJNYM ZA 2 SEKUNDY"
    sleep 2

# zakończenie istniejących procesów FASTCGI
r: clean
    ps x | awk\
    '$$5 ~ /python/ && $$6 ~ /fcgi/ {print "kill", $$1}' | sh -v

# generowany dynamicznie kod testujący
testIndexForm.py: dispatch.py utils/testIndexForm.sh
    sh utils/testIndexForm.sh > $@

######################################################################
# status projektu - nazwa rozgałęzienia
st:
    cvs st Makefile

# lista istniejących tagów / rozgałęzień
blist:
    @cvs log -h Makefile |\
        sed 's/:.*//g' |\
        sed -n '/    /p' | sort

# utworzenie rozgałęzienia z kodu w podanej chwili czasowej
# razem z informacją o tym pozostawioną w HEAD
bcreate:
    @tail versions.txt;\
    read -p "date to start (yyyy-mm-dd HH:MM): " start_date;\
    read -p "name of new branch [a-z_0-9]+: " branch_name;\
    now=date +%Y-%m-%d %H:%M'