dev 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #!/bin/bash
  2. # devctl is an utility script for automating some development tasks and actions.
  3. # To find out what options are available, run it without any arguments.
  4. # Text styles
  5. RED='\033[0;31m'
  6. BOLD=$(tput bold)
  7. NORMAL=$(tput sgr0)
  8. # Define dev paths
  9. # Those are paths to dirs and files created for dev project
  10. dev_paths=(
  11. "./avatargallery"
  12. "./devproject"
  13. "./media"
  14. "./static"
  15. "./theme"
  16. "./userdata"
  17. "./cron.txt"
  18. "./manage.py"
  19. )
  20. # Required ports
  21. # Some tasks test for those ports before continuing
  22. port_django=8000
  23. port_postgresql=5432
  24. required_ports=($port_postgresql)
  25. # Default superuser
  26. username="Admin"
  27. password="password"
  28. # Some commond shorthands
  29. error() {
  30. echo -e "${RED}Error:${NORMAL} $1"
  31. }
  32. docker_stop() {
  33. docker-compose stop
  34. }
  35. docker_rebuild() {
  36. docker_stop
  37. docker-compose build --no-cache
  38. }
  39. docker_down() {
  40. docker_stop
  41. docker-compose down --remove-orphans
  42. }
  43. require_docker() {
  44. if [[ ! $IN_DOCKER = 1 ]]; then
  45. error "This command can only be ran inside the running Misago container."
  46. exit 1
  47. fi
  48. }
  49. wait_for_db() {
  50. require_docker
  51. export PGPASSWORD=$POSTGRES_PASSWORD
  52. RETRIES=10
  53. until psql -h $POSTGRES_HOST -U $POSTGRES_USER -d $POSTGRES_DB -c "select 1" > /dev/null 2>&1 || [ $RETRIES -eq 0 ]; do
  54. echo "Waiting for postgres server, $((RETRIES--)) remaining attempts..."
  55. sleep 3
  56. done
  57. }
  58. # Commands
  59. intro() {
  60. echo "Usage: ./dev [arg] ..."
  61. echo "Arguments grouped by type:"
  62. echo
  63. echo "Development project:"
  64. echo
  65. echo " ${BOLD}init${NORMAL} initialize new dev project for development, do nothing if project already exists."
  66. echo " ${BOLD}clear${NORMAL} if dev project exists, delete it's files and destroy docker containers."
  67. echo " ${BOLD}rebuild${NORMAL} rebuild docker containers (uses --no-cache)."
  68. echo
  69. echo "Testing:"
  70. echo
  71. echo " ${BOLD}test${NORMAL} run tests suite."
  72. echo " ${BOLD}test module${NORMAL} run tests suite in specified python module, eg. misago.users."
  73. echo
  74. echo "Translations:"
  75. echo
  76. echo " ${BOLD}makemessages${NORMAL} update translation files for \"en\" language."
  77. echo " ${BOLD}makemessages lang${NORMAL} update translation files for \"lang\" language."
  78. echo " ${BOLD}compilemessages${NORMAL} compile translation files to \"mo\" format."
  79. echo " ${BOLD}txpull${NORMAL} pull translations from Transifex."
  80. echo " ${BOLD}txpush${NORMAL} push new source files to Transifex."
  81. echo
  82. }
  83. # Handle invalid option message
  84. invalid_argument() {
  85. echo -e "Invalid argument: ${RED}$1${NORMAL}"
  86. echo "Please run this script without any arguments to see the list of available arguments."
  87. exit 1
  88. }
  89. # Initialize new dev project
  90. init() {
  91. for dev_path in "${dev_paths[@]}"; do
  92. if [ -e $dev_path ]; then
  93. error "Dev project already exists, or was not deleted completely."
  94. echo
  95. echo "Please use \"clear\" option to clear any pissible remaining files and try again."
  96. exit 1
  97. fi
  98. done
  99. for port in "${required_ports[@]}"; do
  100. nc "127.0.0.1" "$port" < /dev/null
  101. if [[ $? = "0" ]]; then
  102. if [[ $port = $port_django ]]; then
  103. error "Django application appears to already be running on http://127.0.0.1:8000"
  104. elif [[ $port = $port_postgresql ]]; then
  105. error "PostgreSQL appears to already be running on port $port."
  106. fi
  107. exit 1
  108. fi
  109. done
  110. docker_rebuild
  111. docker-compose run --rm misago ./dev init_in_docker
  112. }
  113. # Initialization step that has to occur inside docker
  114. init_in_docker() {
  115. require_docker
  116. wait_for_db
  117. # initialize django project
  118. python misago/bin/misago-start-devproject.py
  119. # move items of interest up one level
  120. mv devproject/devproject devproject_tmp
  121. mv devproject/avatargallery ./avatargallery
  122. mv devproject/media ./media
  123. mv devproject/userdata ./userdata
  124. mv devproject/manage.py ./manage.py
  125. rm -rf devproject
  126. mv devproject_tmp devproject
  127. # migrate the DB
  128. python manage.py migrate
  129. # create superuser Admin with password "password"
  130. python manage.py createsuperuser --username $username --email admin@example.com --password $password
  131. echo
  132. echo "================================================================================"
  133. echo
  134. echo "You can now start the development server using:"
  135. echo
  136. echo " docker-compose up"
  137. echo
  138. echo "Running server will be available in the browser under the http://127.0.0.1:8000 address."
  139. echo
  140. echo "Default superuser has been created with following credentials:"
  141. echo
  142. echo "Username: $username"
  143. echo "Password: $password"
  144. echo
  145. echo "For development project configuration see files in the \"devproject\" directory."
  146. echo
  147. }
  148. # Clear existing dev project
  149. clear() {
  150. echo -e "${RED}Warning:${NORMAL} You are going clear current development project."
  151. echo
  152. will_delete_files=false
  153. for dev_path in "${dev_paths[@]}"; do
  154. if [ -e $dev_path ]; then
  155. will_delete_files=true
  156. fi
  157. done
  158. if [[ $will_delete_files = true ]]; then
  159. echo "Following files and directories will be deleted:"
  160. for dev_path in "${dev_paths[@]}"; do
  161. if [ -e $dev_path ]; then
  162. echo " $dev_path"
  163. fi
  164. done
  165. echo
  166. fi
  167. echo "This will also stop and remove docker containers used by this project."
  168. echo
  169. echo "Enter \"y\" to confirm:"
  170. read confirmation
  171. if [[ $confirmation = "y" ]]; then
  172. for dev_path in "${dev_paths[@]}"; do
  173. if [ -e $dev_path ]; then
  174. echo "Removing $dev_path"
  175. rm -rf $dev_path
  176. fi
  177. done
  178. docker_down
  179. exit 0
  180. else
  181. echo "Operation canceled."
  182. exit 0
  183. fi
  184. }
  185. # Rebuild docker containers
  186. rebuild() {
  187. docker_rebuild
  188. exit 0
  189. }
  190. # Run tests suite
  191. test() {
  192. docker-compose run --rm misago runtests.py $1
  193. docker_stop
  194. exit 0
  195. }
  196. # Make messages
  197. makemessages() {
  198. docker-compose run --rm --no-deps misago ./dev makemessages_in_docker $1
  199. }
  200. # Docker part of makemessages
  201. makemessages_in_docker() {
  202. require_docker
  203. echo "Extracting messages for $1 language:"
  204. cd ./misago
  205. echo "Processing .py and .html files..."
  206. django-admin.py makemessages -l $1 -e html,txt,py > /dev/null
  207. echo "Processing .js files..."
  208. django-admin.py makemessages -l $1 -d djangojs > /dev/null
  209. }
  210. # Compile messages
  211. compilemessages() {
  212. docker-compose run --rm --no-deps misago ./dev compilemessages_in_docker
  213. }
  214. # Docker part of compile messages
  215. compilemessages_in_docker() {
  216. require_docker
  217. cd ./misago
  218. django-admin.py compilemessages
  219. }
  220. # Command dispatcher
  221. if [[ $1 ]]; then
  222. if [[ $1 = "init" ]]; then
  223. init
  224. elif [[ $1 = "init_in_docker" ]]; then
  225. init_in_docker
  226. elif [[ $1 = "clear" ]]; then
  227. clear
  228. elif [[ $1 = "rebuild" ]]; then
  229. rebuild
  230. elif [[ $1 = "test" ]]; then
  231. test $2
  232. elif [[ $1 = "makemessages" ]]; then
  233. makemessages ${2:-en}
  234. elif [[ $1 = "makemessages_in_docker" ]]; then
  235. makemessages_in_docker $2
  236. elif [[ $1 = "compilemessages" ]]; then
  237. compilemessages
  238. elif [[ $1 = "compilemessages_in_docker" ]]; then
  239. compilemessages_in_docker
  240. else
  241. invalid_argument $1
  242. fi
  243. else
  244. intro
  245. fi