diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..b047734a954209a53e7896d2d0fc47829ebf8cdf --- /dev/null +++ b/.dockerignore @@ -0,0 +1,330 @@ +# Created by https://www.gitignore.io/api/node,python,pycharm+all,visualstudiocode +# Edit at https://www.gitignore.io/?templates=node,python,pycharm+all,visualstudiocode + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +### PyCharm+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/node,python,pycharm+all,visualstudiocode + +# Project-specific ignored files +.bash_history +webpack-stats.json +assets/bundles/* +test/* +.tmp/ + +# Docker-specific ignored files +.devcontainer +.tmp +.vscode +Dockerfile +docker-compose.yml +LICENSE +README.md \ No newline at end of file diff --git a/.gitignore b/.gitignore index e52ab6277ed4e707ea668f8df9b55d465f6e0bfb..2c6cae6466efa0b98f94cfdcec948ab8ae135093 100755 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,321 @@ -node_modules -*.pyc -.pyc -venv -assets/bundles/* -.idea -webpack-stats.json -.npm -.bash_history -.cache -test/* -.coverage -.tmp/ -npm-debug.log -debug.log +# Created by https://www.gitignore.io/api/node,python,pycharm+all,visualstudiocode +# Edit at https://www.gitignore.io/?templates=node,python,pycharm+all,visualstudiocode + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +### PyCharm+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/node,python,pycharm+all,visualstudiocode + +# Project-specific ignored files +.bash_history +webpack-stats.json +assets/bundles/* +test/* +.tmp/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d1e008c30cfc7fd5c06d894fed1f237c57abc7d9..040e750df5706268df1aca69ac51240efc58fb7f 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,30 +1,46 @@ +--- +image: python:2-jessie + +stages: + - build + - test + - deploy + test: + services: + - postgres:9.6-alpine + variables: + POSTGRES_DB: kape + POSTGRES_USER: kape + POSTGRES_PASSWORD: kape + stage: test script: - - apt-get install -f - - apt-get update -qy - - apt-get install -y python-dev python-pip sudo postgresql postgresql-client libpq-dev libxss1 libappindicator1 libindicator7 - - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' - - apt-get update - - apt-get install -y google-chrome-stable - - export CHROME_BIN=/usr/bin/google-chrome - - curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - - - sudo apt-get install -y nodejs - - sudo apt-get install -y build-essential - - npm install npm -g - - npm install - - npm run build-production - - service postgresql start - - sudo -u postgres psql -c "CREATE USER kape WITH PASSWORD 'kape' CREATEDB" - - sudo -u postgres psql -c "CREATE DATABASE kape OWNER kape" - - pip install -r requirements.txt - - python manage.py migrate - - python manage.py test - - npm run karma + - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - + - sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' + - apt-get update && apt-get install -y google-chrome-stable libappindicator1 libindicator7 libpq-dev libxss1 python-dev python-pip sudo + - export CHROME_BIN=/usr/bin/google-chrome + - curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - + - apt-get install -y build-essential nodejs + - npm install + - npm run build-production + - pip install -r requirements.txt + - python manage.py migrate + - python manage.py test + - npm run karma artifacts: paths: - test/ +SonarScanner Analysis: + image: addianto/sonar-scanner-cli:latest + stage: test + script: + - sonar-scanner + -Dsonar.host.url=$SONARQUBE_HOST + -Dsonar.login=$SONARQUBE_TOKEN + only: + - master + pages: stage: deploy dependencies: @@ -39,31 +55,61 @@ pages: staging: type: deploy script: - - apt-get update -qy - - apt-get install sshpass - - git clone https://gitlab.com/PPL2017csui/PPLA1.git - - cd PPLA1 - - git checkout develop - - git pull - - git remote add deployment ssh://kape@bot.recruit.id:8023/home/kape.git - - mkdir ~/.ssh - - echo -e "Host bot.recruit.id\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - - sshpass -p yukcarikape git push deployment develop:master --force + - apt-get update -qy + - apt-get install sshpass + - git clone https://gitlab.com/PPL2017csui/PPLA1.git + - cd PPLA1 + - git checkout develop + - git pull + - git remote add deployment ssh://kape@bot.recruit.id:8023/home/kape.git + - mkdir ~/.ssh + - echo -e "Host bot.recruit.id\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + - sshpass -p yukcarikape git push deployment develop:master --force only: - - develop + - develop production: type: deploy script: - - apt-get update -qy - - apt-get install sshpass - - git clone https://gitlab.com/PPL2017csui/PPLA1.git - - cd PPLA1 - - git checkout master - - git pull - - git remote add deployment ssh://kape@bot.recruit.id:8022/home/kape.git - - mkdir ~/.ssh - - echo -e "Host bot.recruit.id\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - - sshpass -p yukcarikape git push deployment master:master --force + - apt-get update -qy + - apt-get install sshpass + - git clone https://gitlab.com/PPL2017csui/PPLA1.git + - cd PPLA1 + - git checkout master + - git pull + - git remote add deployment ssh://kape@bot.recruit.id:8022/home/kape.git + - mkdir ~/.ssh + - echo -e "Host bot.recruit.id\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + - sshpass -p yukcarikape git push deployment master:master --force + when: manual + only: + - master + +Publish Container Image: + image: docker:19-git + stage: deploy + services: + # Workaround from https://forum.gitlab.com/t/docker-dind-stops-working-after-12-1-0-update/28664/2 + - name: docker:19-dind + entrypoint: ["env", "-u", "DOCKER_HOST"] + command: ["dockerd-entrypoint.sh"] + variables: + DOCKER_HOST: tcp://docker:2375/ + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" + before_script: + - docker info + - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD + script: + - docker build + --build-arg=NPM_PROXY=$NPM_PROXY + --build-arg=IMAGE_CREATED="$(date --utc -Iseconds)" + --build-arg=IMAGE_REVISION="$(git show --pretty=oneline | tac | tail -n 1 | awk '{print $1}')" + --tag $IMAGE_NAMESPACE/kape:latest . + - docker push $IMAGE_NAMESPACE/kape:latest + tags: + - docker + retry: 1 + allow_failure: true only: - - master \ No newline at end of file + - master diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..f2c6d104e0a78dee7246ef4f596bdc9b38ec75ea --- /dev/null +++ b/Dockerfile @@ -0,0 +1,84 @@ +FROM node:4 AS frontend-builder + +WORKDIR /home/kape/app +COPY . . +ARG NPM_PROXY="" +RUN npm config set proxy ${NPM_PROXY} \ + && npm install \ + && npm run build-production + +FROM python:2-jessie AS app + +# Avoid warnings by switching to noninteractive +ENV DEBIAN_FRONTEND=noninteractive +ENV PYTHONUNBUFFERED 1 + +ARG USERNAME=kape +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +COPY requirements.txt /tmp/pip-tmp/ + +# Install system packages +RUN pip --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ + && rm -rf /tmp/pip-tmp + +# Setup user +RUN groupadd --gid ${USER_GID} ${USERNAME} \ + && useradd -s /bin/bash --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} + +# Build the app +USER kape +WORKDIR /home/kape/app +COPY . . +COPY --chown=${USERNAME} --from=frontend-builder /home/kape/app/assets/bundles ./assets/bundles +COPY --chown=${USERNAME} --from=frontend-builder /home/kape/app/webpack-stats.json ./ +RUN mkdir -p /home/kape/assets \ + && mkdir -p /home/kape/files \ + && python manage.py collectstatic --noinput + +# Switch back to dialog for any ad-hoc use of apt-get +ENV DEBIAN_FRONTEND= + +# Set environment variables +ENV KAPE_DB_NAME=kape +ENV KAPE_DB_USER=kape +ENV KAPE_DB_PASSWORD=kape +ENV KAPE_DB_HOST=db +ENV KAPE_DB_PORT=5432 + +# Run the app as non-root user +EXPOSE 8001 +VOLUME ["/home/kape/assets", "/home/kape/files"] +CMD ["gunicorn", "--bind", "0.0.0.0:8001", "kape.wsgi:application", "--reload"] + +# Container image metadata +## Note to editors: metadata values for `created`, `version`, and `revision` +## keys must be provided during build process, i.e. `docker build` invocation. +## It is also possible to pass other metadata values via build arguments. +ARG IMAGE_CREATED="" +ARG IMAGE_AUTHORS="PPLA1 Team & Faculty of Computer Science Universitas Indonesia" +ARG IMAGE_SOURCE="https://gitlab.cs.ui.ac.id/foss/kape" +ARG IMAGE_VERSION="" +ARG IMAGE_REVISION="" +ARG IMAGE_VENDOR="Faculty of Computer Science Universitas Indonesia" +ARG IMAGE_TITLE="Kape" +ARG IMAGE_DESCRIPTION="Fork of https://gitlab.com/PPL2017csui/PPLA1" +LABEL org.opencontainers.image.created=${IMAGE_CREATED} \ + org.opencontainers.image.authors=${IMAGE_AUTHORS} \ + org.opencontainers.image.source=${IMAGE_SOURCE} \ + org.opencontainers.image.version=${IMAGE_VERSION} \ + org.opencontainers.image.revision=${IMAGE_REVISION} \ + org.opencontainers.image.vendor=${IMAGE_VENDOR} \ + org.opencontainers.image.licenses="ISC" \ + org.opencontainers.image.title=${IMAGE_TITLE} \ + org.opencontainers.image.description=${IMAGE_DESCRIPTION} + +## Note to editors: The following label assignments are to ensure backward +## compatibility with Label Schema standard +LABEL org.label-schema.build-date=${IMAGE_CREATED} \ + org.label-schema.vcs-url=${IMAGE_SOURCE} \ + org.label-schema.version=${IMAGE_VERSION} \ + org.label-schema.vendor=${IMAGE_VENDOR} \ + org.label-schema.title=${IMAGE_TITLE} \ + org.label-schema.description=${IMAGE_DESCRIPTION} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..47c70f83a05904a62b16e060765b67a9947da33f --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ +ISC License + +Copyright (c) 2017 PPLA1 Team & Faculty of Computer Science Universitas +Indonesia + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/README.md b/README.md index 76cb0ca8612978a161d4541514edde114ca4b148..3020546098563953b463aa84d24bb2958f22f589 100755 --- a/README.md +++ b/README.md @@ -1,71 +1,161 @@ -# How To Deploy to Production Server - -## Deployment -* Clone this repository -* Install docker, you can do this manually or using command `bash /provision/setup-docker.sh` -* Deploy using command `bash /provision/run-docker.sh DOCKERNAME APP_PORT SSH_PORT` for example `bash /provision/run-docker.sh staging 8000 8022` -* Profit :) - -## HTTPS Server and Domain Name -* Add your domain name on the `ALLOWED_HOSTS` field on `kape/settings.py` -* Add these server blocks on yout NGINX setting (change `DOMAIN_NAME` and `APP_PORT`) - ``` - server { - listen 80; - listen [::]:80; - server_name your.DOMAIN_NAME.com; - return 301 https://$server_name$request_uri; - } - - server { - listen 443 ssl default_server; - listen [::]:443 ssl default_server; - include snippets/ssl-your.DOMAIN_NAME.sslconfiguration.conf; - server_name your.DOMAIN_NAME.com; - location / { - proxy_pass http://localhost:APP_PORT; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; - } - } - ``` - -## Git push on the production server -* You can push directly to production git if SSH port is not blocked -* In the repo directory, run `git remote add production ssh://kape@DOMAIN_NAME:SSH_PORT/home/kape.git` -* To push to production server, run `git push production master` (default docker ssh password : yukcarikape) - - -# How To Build for Development Environment - -## Requirements - -* NodeJS + Npm Package Manager -* Python + Pip Package Manager -* PostgreSQL - -## Installation - -* `git clone https://gitlab.com/PPL2017csui/PPLA1.git kape` -* `cd kape` -* `npm install` -* `pip install -r requirements.txt` -* `psql` insert these queries: - * `create user kape password 'kape';` to create user. - * `create database kape;` to create database. - * if you want to create another database user, please update the setting file `kape/settings.py` -* `python manage.py migrate` To migrate all the database - -## Run Development Mode App - -* `npm run webpack` to run webpack server. (if you don't want live update run `npm run build`, if you want the uglified+zipped+production ready version run `npm run build-production`) -* on a different terminal window, run `python manage.py runserver` to run API server - -### Now go to localhost:8000 and you'll see the App running! - - -## Run Unit Test - -* Frontend test, run `npm run webpack` -* Backend test, run `python manage.py test` +# Kanal Akses Pendaftaran KP Elektronik _(kape)_ + +> Internship matchmaking platform for students and companies. + +## Table of Contents + +- [Install](#install) +- [Running Development Mode (Classic)](#running-development-mode-classic) +- [Running Development Mode (Containerised)](#running-development-mode-containerised) +- [References](#references) +- [License](#license) + +## Install + +This project uses Python 2 and Node.js v4 for building the backend and frontend, +respectively. The backend uses Django Framework and PostgreSQL database, while +the frontend is developed using React. You need to install the required +dependencies prior to building and contributing to the project. + +- [Node.js v4.9.1](https://nodejs.org/en/download/releases/) and `npm` package + manager. + > Note: We recommend `nvm` (Node Version Manager) for installing Node.js. You + > can find `nvm` for your OS at the following links: + > - [nvm for macOS or GNU/Linux-based OS](https://github.com/creationix/nvm) + > - [nvm for Windows](https://github.com/coreybutler/nvm-windows) + > + > Once `nvm` has been installed, install Node.js and activate it by executing + > `nvm install 4.9.1` followed by `nvm activate 4.9.1`. +- [Python 2.7.16](https://www.python.org/downloads/release/) and `pip` package + manager. + > Note: We recommend using _virtual environment_ to isolate project-specific + > Python packages from system-level packages. You can install and use + > [`virtualenv`](https://virtualenv.pypa.io/en/stable/) package to create the + > virtual environment for this project. +- [PostgreSQL 9.6](https://www.postgresql.org/download/) and any database + client that can interface with PostgreSQL, e.g. `psql`, pgAdmin. + > Note: We recommend running the database as container or virtual machine to + > avoid cluttering your local development environment. Please consult the + > documentation for your container engine (e.g. Docker) or virtualization + > platform (e.g. VirtualBox or Hyper-V) on how to provision PostgreSQL + > database. If you had to use locally-installed database, make sure your + > own data will not interleave with the data generated by this project. + +Verify that Node.js and Python 2 have been successfully installed. Make sure +the interpreter for both platforms can be invoked from the shell. For example, +in `bash` shell (macOS or GNU/Linux-based OS): + +```bash +# Assuming there is a Python virtual environment directory named `env` in +# current path +$ source env/bin/activate +$ python --version # or: python2 --version +Python 2.7.16 +$ node --version +v4.9.1 +``` + +Now install the packages required by Node.js and Python 2: + +```bash +npm install +pip install -r requirements.txt +``` + +If you are cloning the project for the first time into your local development +environment, you need to create a new database user named `kape` and create a +new database with the same name for this project. Do not forget to set the +ownership of the new database to `kape` user. Once you have finished setting up +the database, perform database migration and seeding: + +```bash +python manage.py migrate +python manage.py loaddata seeder.json +``` + +> Note: Can't connect to the database? Adjust the database connection settings +> at [`settings.py`](kape/settings.py). + +Finally, verify that the test suites pass: + +```bash +# Run the test suite for backend +python manage.py test +``` + +To run the test suite for frontend, you need to build the frontend first before +running the test suite: + +```bash +npm run build-production +npm run karma +``` + +## Running Development Mode (Classic) + +To run the API (backend) server: + +```bash +python manage.py runserver +``` + +To serve the frontend: + +```bash +npm run webpack +# If you don't want live update, run: npm run build +# If you want the uglified, zipped, production-ready version, run: npm run build-production +``` + +You can see the app running by going to `localhost:8080` via your favourite +Web browser. + +## Running Development Mode (Containerised) + +If you have installed Docker and Docker Compose, you can build the app +into a container image and run it with container-based database and +Web server: + +```bash +docker-compose up --build --detach +docker-compose run --rm app python manage.py migrate +docker-compose run --rm app python manage.py loaddata seeder.json +``` + +> Explanation: +> 1. Rebuild the application (the frontend + backend), then start it along with +> the database (`postgres`) and Web server (`nginx`). +> 1. Perform database migration +> 1. Perform database seeding + +Before you can see the app, you need to know the port in the host that mapped +to the port in the Web server container: + +```bash +# The following is just an example. The output may vary in your environment. +$ docker-compose ps + Name Command State Ports +--------------------------------------------------------------------------- +kape_app_1 gunicorn --bind 0.0.0.0:80 ... Up 8001/tcp +kape_db_1 docker-entrypoint.sh postgres Up 5432/tcp +kape_web_1 nginx -g daemon off; Up 0.0.0.0:32770->80/tcp +``` + +In the above example, port 32770 is mapped to port 80 in the Web server +container. Thus, you can see the app via Web browser by opening +`http://localhost:32770`. + +> Note: Running the app and its dependencies as containers are convenient, but +> you will not be able to see any changes to the codebase in real-time. If +> you want to see changes in the codebase reflected in real-time, follow the +> classical approach for running the development mode. + +## References + +- [The original README file](README.old.md). +- [The original (_upstream_) GitLab project repository](https://gitlab.com/PPL2017csui/PPLA1). + +## License + +Copyright (c) 2017 PPLA1 Team & Faculty of Computer Science Universitas +Indonesia. This project is licensed under [ISC](LICENSE) license. diff --git a/README.old.md b/README.old.md new file mode 100644 index 0000000000000000000000000000000000000000..d60f4bc920e766054da8147d32fd422425a69714 --- /dev/null +++ b/README.old.md @@ -0,0 +1,71 @@ +# How To Deploy to Production Server + +## Deployment + +* Clone this repository +* Install docker, you can do this manually or using command `bash /provision/setup-docker.sh` +* Deploy using command `bash /provision/run-docker.sh DOCKERNAME APP_PORT SSH_PORT` for example `bash /provision/run-docker.sh staging 8000 8022` +* Profit :) + +## HTTPS Server and Domain Name +* Add your domain name on the `ALLOWED_HOSTS` field on `kape/settings.py` +* Add these server blocks on yout NGINX setting (change `DOMAIN_NAME` and `APP_PORT`) + ``` + server { + listen 80; + listen [::]:80; + server_name your.DOMAIN_NAME.com; + return 301 https://$server_name$request_uri; + } + + server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + include snippets/ssl-your.DOMAIN_NAME.sslconfiguration.conf; + server_name your.DOMAIN_NAME.com; + location / { + proxy_pass http://localhost:APP_PORT; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + } + ``` + +## Git push on the production server +* You can push directly to production git if SSH port is not blocked +* In the repo directory, run `git remote add production ssh://kape@DOMAIN_NAME:SSH_PORT/home/kape.git` +* To push to production server, run `git push production master` (default docker ssh password : yukcarikape) + + +# How To Build for Development Environment + +## Requirements + +* NodeJS + Npm Package Manager +* Python + Pip Package Manager +* PostgreSQL + +## Installation + +* `git clone https://gitlab.com/PPL2017csui/PPLA1.git kape` +* `cd kape` +* `npm install` +* `pip install -r requirements.txt` +* `psql` insert these queries: + * `create user kape password 'kape';` to create user. + * `create database kape;` to create database. + * if you want to create another database user, please update the setting file `kape/settings.py` +* `python manage.py migrate` To migrate all the database + +## Run Development Mode App + +* `npm run webpack` to run webpack server. (if you don't want live update run `npm run build`, if you want the uglified+zipped+production ready version run `npm run build-production`) +* on a different terminal window, run `python manage.py runserver` to run API server + +### Now go to localhost:8000 and you'll see the App running! + +## Run Unit Test + +* Frontend test, run `npm run webpack` +* Backend test, run `python manage.py test` diff --git a/debug.log b/debug.log deleted file mode 100644 index 622e4f65f6a8de84c8fe8143a99307f5459826fd..0000000000000000000000000000000000000000 --- a/debug.log +++ /dev/null @@ -1,6 +0,0 @@ -[0419/113046.282:ERROR:process_info.cc(625)] range at 0x953e621000000000, size 0x202 fully unreadable -[0419/113046.284:ERROR:process_info.cc(625)] range at 0x953e623000000000, size 0x202 fully unreadable -[0419/113046.284:ERROR:process_info.cc(625)] range at 0x0, size 0x202 fully unreadable -[0419/113046.299:ERROR:file_io_win.cc(145)] CreateFile C:\Users\baisa\AppData\Local\Temp\karma-28613191\Crashpad\settings.dat: The system cannot find the path specified. (0x3) -[0419/113046.299:ERROR:file_io_win.cc(154)] CreateFile C:\Users\baisa\AppData\Local\Temp\karma-28613191\Crashpad\reports\a859f38f-0a5a-4ff9-939d-aac920dec0cd.dmp: The system cannot find the path specified. (0x3) -[0419/113046.299:ERROR:crash_report_exception_handler.cc(95)] PrepareNewCrashReport failed diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..481a95bb60236c0f21fc48f69fca83dbe3178a58 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,42 @@ +--- +version: '3' + +services: + db: + image: postgres:9.6-alpine + expose: + - "5432" + environment: + POSTGRES_DB: ${KAPE_DB_NAME:-kape} + POSTGRES_USER: ${KAPE_DB_USER:-kape} + POSTGRES_PASSWORD: ${KAPE_DB_PASSWORD:-kape} + + app: + build: + context: . + environment: + KAPE_DB_HOST: ${KAPE_DB_HOST:-db} + expose: + - "8001" + user: kape + volumes: + - assetsdata:/home/kape/assets:ro + - mediadata:/home/kape/files + depends_on: + - db + + web: + image: nginx:1.16-alpine + ports: + - "80" + volumes: + - ./provision/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./provision/nginx/conf.d/:/etc/nginx/conf.d/:ro + - assetsdata:/var/www/assets:ro + - mediadata:/var/www/files:ro + depends_on: + - app + +volumes: + assetsdata: + mediadata: diff --git a/kape/settings.py b/kape/settings.py index 9b1643d07b5b4211cc4eabf296083b08d93f882d..7529209fcc26179972d10cd9895de5eaabf98988 100755 --- a/kape/settings.py +++ b/kape/settings.py @@ -20,7 +20,8 @@ SECRET_KEY = 'gz!k*@!n8h$yny1)zp!e5#w8!s4%*wqnur5$qnr@$*xx_o+aij' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = (len(sys.argv) > 1 and sys.argv[1] == 'runserver') -ALLOWED_HOSTS = [u'bot.recruit.id',u'kape.recruit.id',u'104.236.76.161',u'localhost',u'127.0.0.1'] +ALLOWED_HOSTS = [u'bot.recruit.id', u'kape.recruit.id', u'104.236.76.161', + u'localhost', u'127.0.0.1', u'pmpl.cs.ui.ac.id'] # Application definition @@ -91,14 +92,37 @@ WSGI_APPLICATION = 'kape.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'kape', - 'USER': 'kape', - 'PASSWORD': 'kape', - 'HOST': 'localhost', - 'PORT': '', + 'NAME': os.getenv('KAPE_DB_NAME', 'kape'), + 'USER': os.getenv('KAPE_DB_USER', 'kape'), + 'PASSWORD': os.getenv('KAPE_DB_PASSWORD', 'kape'), + 'HOST': os.getenv('KAPE_DB_HOST', 'localhost'), + 'PORT': os.getenv('KAPE_DB_PORT', ''), } } +TEST_DATABASE = { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'kape', + 'USER': 'kape', + 'PASSWORD': 'kape', + 'HOST': 'localhost', + 'PORT': '5432', +} + +CI_DATABASE = { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'kape', + 'USER': 'kape', + 'PASSWORD': 'kape', + 'HOST': 'postgres', + 'PORT': '5432', +} + +if DEBUG: + DATABASES['default'] = TEST_DATABASE + +if os.getenv('CI_SERVER') == 'yes': + DATABASES['default'] = CI_DATABASE # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators @@ -123,13 +147,9 @@ AUTH_PASSWORD_VALIDATORS = [ # https://docs.djangoproject.com/en/1.10/topics/i18n/ LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - +TIME_ZONE = 'Asia/Jakarta' USE_I18N = True - USE_L10N = True - USE_TZ = True @@ -137,9 +157,9 @@ USE_TZ = True # https://docs.djangoproject.com/en/1.10/howto/static-files/ STATIC_URL = '/assets/' -STATIC_ROOT = '/home/assets' +STATIC_ROOT = '/home/kape/assets' MEDIA_URL = '/files/' -MEDIA_ROOT = '/home/files' +MEDIA_ROOT = '/home/kape/files' REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, diff --git a/npm-debug.log.1735884061 b/npm-debug.log.1735884061 deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/provision/nginx/conf.d/app.conf b/provision/nginx/conf.d/app.conf new file mode 100644 index 0000000000000000000000000000000000000000..24a63c24177a08e40b446407cd63a88a53f071dc --- /dev/null +++ b/provision/nginx/conf.d/app.conf @@ -0,0 +1,27 @@ +# nginx configuration for the app based on Gunicorn recommended settings. +upstream app_server { + server app:8001 fail_timeout=0; +} + +server { + listen 80 deferred; + listen [::]:80 deferred; + server_name localhost; + keepalive_timeout 5; + root /var/www; + + location / { + # Checks for static file, if not found proxy to app + try_files $uri @proxy_to_app; + } + + location @proxy_to_app { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + # We don't want nginx trying to do something clever with redirects, + # we set the Host: header above already + proxy_redirect off; + proxy_pass http://app_server; + } +} \ No newline at end of file diff --git a/provision/nginx/nginx.conf b/provision/nginx/nginx.conf new file mode 100644 index 0000000000000000000000000000000000000000..bbff48cb46ffe772efe11340ba26f445f57b7bed --- /dev/null +++ b/provision/nginx/nginx.conf @@ -0,0 +1,33 @@ +# Custom nginx configuration based on nginx:alpine and Gunicorn recommended +# settings. +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; # Increase if you have lots of clients + accept_mutex on; # Set to 'on' if nginx worker_processes > 1 + use epoll; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index aeac0dc7d6a4d7bdb0f3b35c75025e2f3046e78a..46dd30dcda09b8658ee3208d6e3a69bcc001d640 100755 --- a/requirements.txt +++ b/requirements.txt @@ -7,10 +7,10 @@ psycopg2==2.6.2 pyparsing==2.1.10 six==1.10.0 gunicorn -django-nose +django-nose==1.4.4 coverage django-rest-swagger -django-silk +django-silk==1.0.0 requests -requests-mock -django-filter \ No newline at end of file +requests-mock==1.3.0 +django-filter==1.1.0 diff --git a/seeder.json b/seeder.json index fb24bedccd3ab7f1eb1492a84405c1890a49f50d..0b34318ec4576a507b1e752aee83a32331d2a58d 100644 --- a/seeder.json +++ b/seeder.json @@ -191,7 +191,6 @@ "company1" ], "description": "Ini Company nomor satu", - "verified": true, "logo": "", "address": "Alamat company 1" } @@ -206,7 +205,6 @@ "company2" ], "description": "Ini Company nomor dua", - "verified": true, "logo": "", "address": "Ini alamat Company duar" } @@ -221,7 +219,6 @@ "Tutuplapak" ], "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla aliquet semper neque a fermentum. Duis ac tellus vitae augue iaculis ultrices. Curabitur commodo et neque nec feugiat. Morbi ac diam vel nunc commodo cursus. Phasellus nulla sapien, hendrerit vitae bibendum at, sollicitudin eu ante. Maecenas maximus, ante eu sollicitudin convallis, mauris nunc posuere risus, eu porttitor diam lacus vitae enim. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse at lectus a elit sollicitudin tempor. Nullam condimentum, justo nec tincidunt maximus, neque mi vulputate leo, sit amet lacinia massa ex eget sem. Duis ac erat facilisis, fringilla mauris in, consequat neque. In et neque consequat, vehicula magna at, efficitur ante. Mauris ac lacinia nibh.\r\n\r\nProin sagittis, lectus quis maximus varius, libero justo sollicitudin augue, non lacinia risus orci a enim. Curabitur iaculis enim quis ullamcorper commodo. Vivamus id nisi rhoncus, dignissim tellus quis, interdum est. Fusce sollicitudin eu libero ac feugiat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas semper posuere ex, sed accumsan libero iaculis faucibus. Fusce laoreet ac ligula ut consectetur. Donec tortor mauris, rutrum at sodales et, viverra in dolor. Sed bibendum elit et maximus volutpat. Phasellus justo ipsum, laoreet sit amet faucibus eu, ultricies suscipit mauris. Nullam aliquam libero eu ante ultrices mattis. Donec non justo hendrerit neque volutpat placerat. Ut euismod est nec sem mollis, sit amet porttitor massa rhoncus. Aenean id erat sit amet nunc ultrices scelerisque non in ipsum. Curabitur sollicitudin nulla id mi accumsan venenatis.", - "verified": true, "logo": "company-logo/8a258a48-3bce-4873-b5d1-538b360d0059.png", "address": "Jl. Kebayoran Baru nomor 13, Jakarta Barat" } diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000000000000000000000000000000000000..48a6c493c8cf0d1ead4cb49babe175535621ae67 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,13 @@ +# SonarQube Scanner Properties + +## Server +### sonar.host.url=[pass URL via CLI/CI] + +## Project Configuration +sonar.projectKey=id.ac.ui.cs.foss:kape +sonar.exclusions=/.devcontainer/,/.gitlab/,*.config.js,/.tmp/, +sonar.scm.provider=git + +## Authentication +### sonar.login=[pass token via CLI/CI] +