diff options
| author | 2019-09-24 13:54:40 -0400 | |
|---|---|---|
| committer | 2019-09-24 13:54:40 -0400 | |
| commit | 20b19de0d22e33476ac082ea048476f9f8c1a5ed (patch) | |
| tree | f1541776183c3d3850693ad20d81fb530bed3a1d | |
| parent | Apply suggestions from code review (diff) | |
| parent | Swap out old discord shield for new one. (diff) | |
Merge branch 'master' into update-linting
| -rw-r--r-- | .coveragerc | 1 | ||||
| -rw-r--r-- | .dockerignore | 7 | ||||
| -rw-r--r-- | .gitattributes | 3 | ||||
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Pipfile | 8 | ||||
| -rw-r--r-- | Pipfile.lock | 122 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | azure-pipelines.yml | 171 | ||||
| -rw-r--r-- | docker-compose.yml | 6 | ||||
| -rw-r--r-- | docker/app/Dockerfile | 55 | ||||
| -rw-r--r-- | docker/app/Dockerfile.local | 49 | ||||
| -rw-r--r-- | docker/app/build-wiki.Dockerfile | 2 | ||||
| -rw-r--r-- | docker/app/local.Dockerfile | 28 | ||||
| -rw-r--r-- | docker/app/scripts/build-wiki.sh | 4 | ||||
| -rwxr-xr-x | docker/app/scripts/migrate_and_serve.sh | 3 | ||||
| -rw-r--r-- | docker/app/wheels/wiki-0.5.dev20190420204942-py3-none-any.whl | bin | 0 -> 1287002 bytes | |||
| -rw-r--r-- | pydis_site/apps/api/migrations/0042_infraction_add_default_ordering.py | 17 | ||||
| -rw-r--r-- | pydis_site/apps/api/models/bot/infraction.py | 5 | ||||
| -rw-r--r-- | pydis_site/apps/api/tests/test_infractions.py | 5 | ||||
| -rw-r--r-- | pydis_site/apps/api/tests/test_off_topic_channel_names.py | 18 | 
20 files changed, 301 insertions, 211 deletions
| diff --git a/.coveragerc b/.coveragerc index 68f8305a..a49af74e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -8,6 +8,7 @@ source =      pydis_site/apps/staff      pydis_site/apps/wiki  omit = +    */migrations/*      */admin.py      */apps.py      */urls.py diff --git a/.dockerignore b/.dockerignore index f2475d80..771913a3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,21 +11,16 @@  .venv  __pycache__  pydis_site/apps/admin/tests -pydis_site/apps/admin/tests.py  pydis_site/apps/api/tests -pydis_site/apps/api/tests.py  pydis_site/apps/home/tests -pydis_site/apps/home/tests.py  pydis_site/apps/staff/tests -pydis_site/apps/staff/tests.py  CHANGELOG.md  CONTRIBUTING.md  docker -!docker/app/scripts/migrate_and_boot.sh  !docker/app/scripts/migrate.sh  !docker/app/uwsgi.ini +!docker/app/wheels  docker-compose.yml -Dockerfile  Dockerfile.local  docs  htmlcov diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..a90a0a96 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Declare files that will always have LF line endings on checkout +# This prevents git on Windows from automatically inserting CRLF line endings +* text=auto eol=lf
\ No newline at end of file @@ -117,5 +117,7 @@ media/  pip-wheel-metadata/  staticfiles/ +!docker/app/wheels +  *.js.tmp  log.* @@ -17,7 +17,8 @@ django-crispy-bulma = ">=0.1.2,<2.0"  whitenoise = "==4.1.2"  requests = "~=2.21"  pygments = "~=2.3.1" -wiki = {git = "https://github.com/python-discord/django-wiki.git"} +#wiki = {git = "https://github.com/python-discord/django-wiki.git"} +wiki = {path = "./docker/app/wheels/wiki-0.5.dev20190420204942-py3-none-any.whl"}  pyyaml = "*"  [dev-packages] @@ -42,6 +43,7 @@ python_version = "3.7"  [scripts]  makemigrations = "python manage.py makemigrations"  django_shell = "python manage.py shell" -test = "python manage.py test" -lint = "flake8 pydis_site" +test = "coverage run manage.py test" +report = "coverage report -m" +lint = "flake8"  precommit = "pre-commit install" diff --git a/Pipfile.lock b/Pipfile.lock index c9cd758f..01345754 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@  {      "_meta": {          "hash": { -            "sha256": "db7c552ce1bfd18819d21f7c2832c19f007d210d292dbaac158e47f2a1e18295" +            "sha256": "d0e378fcea422eb28537a91e60e7faab8ae08a4ad9e3f1bd71fe89d377d36a8d"          },          "pipfile-spec": 6,          "requires": { @@ -16,6 +16,13 @@          ]      },      "default": { +        "bleach": { +            "hashes": [ +                "sha256:0ee95f6167129859c5dce9b1ca291ebdb5d8cd7e382ca0e237dfd0dad63f63d8", +                "sha256:24754b9a7d530bf30ce7cbc805bc6cce785660b4a10ff3a43633728438c105ab" +            ], +            "version": "==2.1.4" +        },          "certifi": {              "hashes": [                  "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", @@ -38,6 +45,12 @@              "index": "pypi",              "version": "==2.2.5"          }, +        "django-classy-tags": { +            "hashes": [ +                "sha256:38b4546a8053499e2fef7af679a58d7c868298717d645b8b8227acba5fd4bf2b" +            ], +            "version": "==0.9.0" +        },          "django-crispy-bulma": {              "hashes": [                  "sha256:0d982e217a95706e0bbecd9f43990c191b071a20287478c7847ff096567e6e64", @@ -78,6 +91,33 @@              "index": "pypi",              "version": "==3.0"          }, +        "django-js-asset": { +            "hashes": [ +                "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd", +                "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260" +            ], +            "version": "==1.2.2" +        }, +        "django-mptt": { +            "hashes": [ +                "sha256:18a41d1b56ca7c02a5b04d246e33ee2d18f6ee5459c02ed1d945f5abdef23a2e", +                "sha256:689a04cce0981671d6061a9928c33a16b47abb0d4cd43cf7dec31ae284fdae9d" +            ], +            "version": "==0.9.1" +        }, +        "django-nyt": { +            "hashes": [ +                "sha256:187f2aae5088c4cf79e7a7caa55c2a9c292722f50cf185c5a738636713ae67ea", +                "sha256:5556e2de47a7b710325a33c49314ee3eff7021d638492e957ef2de15c9360143" +            ], +            "version": "==1.1.3" +        }, +        "django-sekizai": { +            "hashes": [ +                "sha256:642a3356fe92fe9b5ccc97f320b64edd2cfcb3b2fbb113e8a26dad9a1f3b5e14" +            ], +            "version": "==1.0.0" +        },          "django-simple-bulma": {              "hashes": [                  "sha256:ca2e4dbda5cf2d697cef91701a9fd7e58cecec93a76897158c4d7e135aa13842", @@ -101,6 +141,13 @@              "index": "pypi",              "version": "==0.2.1"          }, +        "html5lib": { +            "hashes": [ +                "sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3", +                "sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736" +            ], +            "version": "==1.0.1" +        },          "idna": {              "hashes": [                  "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", @@ -128,6 +175,44 @@              ],              "version": "==0.19.2"          }, +        "markdown": { +            "hashes": [ +                "sha256:c00429bd503a47ec88d5e30a751e147dcb4c6889663cd3e2ba0afe858e009baa", +                "sha256:d02e0f9b04c500cde6637c11ad7c72671f359b87b9fe924b2383649d8841db7c" +            ], +            "version": "==3.0.1" +        }, +        "pillow": { +            "hashes": [ +                "sha256:0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", +                "sha256:0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f", +                "sha256:0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4", +                "sha256:365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed", +                "sha256:38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03", +                "sha256:3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992", +                "sha256:3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd", +                "sha256:45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68", +                "sha256:49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010", +                "sha256:571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555", +                "sha256:5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f", +                "sha256:6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad", +                "sha256:6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a", +                "sha256:70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826", +                "sha256:70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4", +                "sha256:76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686", +                "sha256:7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99", +                "sha256:7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff", +                "sha256:7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829", +                "sha256:b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0", +                "sha256:bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa", +                "sha256:cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c", +                "sha256:e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e", +                "sha256:e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616", +                "sha256:ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808", +                "sha256:f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b" +            ], +            "version": "==6.1.0" +        },          "psycopg2-binary": {              "hashes": [                  "sha256:080c72714784989474f97be9ab0ddf7b2ad2984527e77f2909fcd04d4df53809", @@ -211,6 +296,13 @@              ],              "version": "==1.12.0"          }, +        "sorl-thumbnail": { +            "hashes": [ +                "sha256:8dfe5fda91a5047d1d35a0b9effe7b000764a01d648e15ca076f44e9c34b6dbd", +                "sha256:d9e3f018d19293824803e4ffead96b19dfcd44fa7987cea392f50436817bef34" +            ], +            "version": "==12.5.0" +        },          "sqlparse": {              "hashes": [                  "sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177", @@ -220,10 +312,17 @@          },          "urllib3": {              "hashes": [ -                "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", -                "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" +                "sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", +                "sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"              ], -            "version": "==1.25.3" +            "version": "==1.25.6" +        }, +        "webencodings": { +            "hashes": [ +                "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", +                "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" +            ], +            "version": "==0.5.1"          },          "whitenoise": {              "hashes": [ @@ -234,8 +333,11 @@              "version": "==4.1.2"          },          "wiki": { -            "git": "https://github.com/python-discord/django-wiki.git", -            "ref": "66d443248279fb8decf23f68c5363ecf6362ee09" +            "hashes": [ +                "sha256:73a53bc770ce6b1d2ea6916d81ccefe40751d87b30556fa3b992c85b7fde8534" +            ], +            "path": "./docker/app/wheels/wiki-0.5.dev20190420204942-py3-none-any.whl", +            "version": "==0.5.dev20190420204942"          }      },      "develop": { @@ -267,6 +369,14 @@              ],              "version": "==2.0.1"          }, +        "colorama": { +            "hashes": [ +                "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", +                "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" +            ], +            "markers": "platform_system == 'Windows'", +            "version": "==0.4.1" +        },          "coverage": {              "hashes": [                  "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", @@ -1,4 +1,10 @@  # Python Discord: Site +[](https://discord.gg/2B963hn) +[](https://dev.azure.com/python-discord/Python%20Discord/_build/latest?definitionId=2&branchName=master) +[](https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Site?branchName=master) +[](https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Site?branchName=master) +[](LICENSE) +[](https://pythondiscord.com)  This is all of the code that is responsible for maintaining  [our website](https://pythondiscord.com), and all of its subdomains. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index de6237d8..b3d4e6da 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,97 +1,80 @@  # https://aka.ms/yaml  jobs: -- job: python_lint -  displayName: 'Lint Job' -  pool: -    vmImage: ubuntu-16.04 - -  variables: -    PIP_CACHE_DIR: .cache/pip - -  steps: -  - task: UsePythonVersion@0 -    displayName: 'Set Python Version' -    inputs: -      versionSpec: '3.7.x' -      addToPath: true - -  - script: python3 -m pip install pipenv && pipenv install --dev --system && python3 -m pip install flake8-formatter-junit-xml -    displayName: 'Install Project Environment' - -  - script: python3 -m flake8 --format junit-xml --output-file test-lint.xml -    displayName: 'Run Linter' - -  - task: PublishTestResults@2 -    condition: succeededOrFailed() -    inputs: -      testResultsFiles: '**/test-*.xml' -      testRunTitle: 'Site-Django Lint Results' - -- job: coverage_test -  displayName: 'Test Job' -  dependsOn: python_lint -  pool: -    vmImage: ubuntu-16.04 - -  steps: -    - task: UsePythonVersion@0 -      inputs: -        versionSpec: '3.7.x' -        architecture: x64 - -    - script: | -        curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - -        sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' -        sudo apt-get update -y -        sudo apt-get install -y postgresql-11 -      displayName: 'Install PostgreSQL' - -    - script: | -        echo "$USER_CREATE_COMMAND;" > pgscript.sql -        echo "CREATE DATABASE pysite OWNER pysite;" >> pgscript.sql -        sudo su postgres -c "psql < pgscript.sql" -      env: -        USER_CREATE_COMMAND: CREATE USER pysite WITH PASSWORD 'pysite' CREATEDB -      displayName: 'Setup Database' - -    - script: python3 -m pip install pipenv && pipenv install --dev --system -      displayName: 'Install Project Environment' - -    - script: | -        python manage.py makemigrations --check -        python manage.py migrate -        coverage run --branch manage.py test --testrunner xmlrunner.extra.djangotestrunner.XMLTestRunner --no-input -      env: -        CI: azure -        DATABASE_URL: postgres://pysite:pysite@localhost/pysite -      displayName: 'Run Test' - -    - script: coverage report -      displayName: 'Show Coverage Results' - -    - task: PublishTestResults@2 -      inputs: -        testResultsFiles: "**/TEST-*.xml" -        testRunTitle: 'Site-Django Test Results' - -- job: docker -  displayName: 'Build & Push Job' -  dependsOn: coverage_test -  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) -  pool: -    vmImage: ubuntu-16.04 - -  steps: -    - task: Docker@1 -      displayName: Login to Docker Hub - -      inputs: -        containerregistrytype: 'Container Registry' -        dockerRegistryEndpoint: 'DockerHub' -        command: 'login' - -    - script: | -        docker build -t pythondiscord/site:latest -f docker/app/Dockerfile . -        docker push pythondiscord/site:latest -      displayName: 'Build & Push Docker Image' +  - job: test +    displayName: 'Test & Lint' +    pool: +      vmImage: ubuntu-16.04 + +    variables: +      PIP_CACHE_DIR: .cache/pip + +    steps: +      - task: UsePythonVersion@0 +        displayName: 'Set Python Version' +        inputs: +          versionSpec: '3.7.x' +          addToPath: true + +      - task: DockerCompose@0 +        displayName: 'Setup Database' +        inputs: +          action: Run a specific service +          dockerComposeFile: docker-compose.yml +          projectName: pydis_web +          serviceName: postgres +          ports: '7777:5432' + +      - script: | +          pip install pipenv +          pipenv install --dev --system +          pip install flake8-formatter-junit-xml +        displayName: 'Install Project Environment' + +      - script: flake8 --format junit-xml --output-file TEST-lint.xml +        displayName: 'Run Linter' + +      - script: | +          python3 manage.py makemigrations --check +          python3 manage.py migrate +          coverage run \ +            manage.py test \ +              --testrunner xmlrunner.extra.djangotestrunner.XMLTestRunner \ +              --no-input +        env: +          CI: azure +          DATABASE_URL: postgres://pysite:pysite@localhost:7777/pysite +        displayName: 'Run Tests' + +      - script: coverage report -m && coverage xml +        displayName: 'Generate Coverage Reports' + +      - task: PublishTestResults@2 +        condition: succeededOrFailed() +        displayName: 'Publish Test & Linting Results' +        inputs: +          testResultsFiles: '**/TEST-*.xml' +          testRunTitle: 'Site Test Results' + +      - task: PublishCodeCoverageResults@1 +        displayName: 'Publish Coverage Results' +        condition: succeededOrFailed() +        inputs: +          codeCoverageTool: Cobertura +          summaryFileLocation: '**/coverage.xml' + +  - job: build +    displayName: 'Build & Push Container' +    dependsOn: test +    condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) + +    steps: +      - task: Docker@2 +        displayName: 'Build & Push Container' +        inputs: +          containerRegistry: 'DockerHub' +          repository: 'pythondiscord/site' +          command: 'buildAndPush' +          Dockerfile: 'docker/app/Dockerfile' +          buildContext: '.' +          tags: 'latest' diff --git a/docker-compose.yml b/docker-compose.yml index d415340b..4ea110c4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,13 +16,13 @@ services:        - "127.0.0.1:7777:5432"      environment:        POSTGRES_DB: pysite -      POSTGRES_PASSWORD: supersecretpassword +      POSTGRES_PASSWORD: pysite        POSTGRES_USER: pysite    web:      build:        context: . -      dockerfile: docker/app/Dockerfile.local +      dockerfile: docker/app/local.Dockerfile      command: docker/app/scripts/migrate_and_serve.sh      ports:        - "127.0.0.1:8000:8000" @@ -32,7 +32,7 @@ services:        - .:/app:ro        - staticfiles:/var/www/static      environment: -      DATABASE_URL: postgres://pysite:supersecretpassword@postgres:5432/pysite +      DATABASE_URL: postgres://pysite:pysite@postgres:5432/pysite        DEBUG: "true"        SECRET_KEY: suitable-for-development-only        STATIC_ROOT: /var/www/static diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile index 903e7dc6..a6986fb2 100644 --- a/docker/app/Dockerfile +++ b/docker/app/Dockerfile @@ -1,52 +1,27 @@ -FROM bitnami/python:3.7-prod +FROM python:3.7-slim -# I have no idea what this does. +# Allow service to handle stops gracefully  STOPSIGNAL SIGQUIT -ARG EXTRAS=deploy -# Create a user. -RUN adduser \ -    --disabled-login \ -    --no-create-home \ -    --uid 1500 \ -    pysite +# Set pip to have cleaner logs and no saved cache +ENV PIP_NO_CACHE_DIR=false \ +    PIPENV_HIDE_EMOJIS=1 \ +    PIPENV_NOSPIN=1 -# Install prerequisites needed to complete the dependency installation. -RUN apt-get update -y \ -    && \ -        apt-get install --no-install-recommends -y \ -                gcc \ -                libc-dev \ -                libpq-dev \ -                git \ -    && \ -        apt-get clean \ -    && \ -        rm -rf /var/lib/apt/lists/* +# Create non-root user. +RUN useradd --system --shell /bin/false --uid 1500 pysite -# Set up the working directory. -WORKDIR /app -COPY Pipfile Pipfile.lock /app/ - -# Pip install the stuff we'll need. -RUN rm -r /opt/bitnami/python/lib/python3.*/site-packages/setuptools* && \ -    pip install --no-cache-dir -U setuptools -RUN python3 -m pip install pipenv \ -    && python3 -m pipenv install --system --deploy \ -    && pip install uwsgi==2.0.18 +# Install pipenv & pyuwsgi +RUN pip install -U pipenv pyuwsgi -# Copy everything into the docker environment. +# Copy the project files into working directory +WORKDIR /app  COPY . . -# RUN SECRET_KEY=placeholder DATABASE_URL=sqlite:// python3 manage.py collectstatic --no-input --clear --verbosity 0 - -# Remove the prerequisites, dependency installation is now complete. -RUN apt-get purge -y \ -            gcc \ -            libc-dev \ -            libpq-dev +# Install project dependencies +RUN pipenv install --system --deploy -# Migrate, collect and start the app. +# Migrate, collect and start the app  RUN chmod +x /app/docker/app/scripts/migrate.sh  ENTRYPOINT ["/app/docker/app/scripts/migrate.sh"]  CMD ["uwsgi", "--ini", "docker/app/uwsgi.ini"] diff --git a/docker/app/Dockerfile.local b/docker/app/Dockerfile.local deleted file mode 100644 index c332c757..00000000 --- a/docker/app/Dockerfile.local +++ /dev/null @@ -1,49 +0,0 @@ -FROM bitnami/python:3.7-prod - -# I have no idea what this does. -STOPSIGNAL SIGQUIT -ARG EXTRAS=deploy - -# Create a user. -RUN adduser \ -    --disabled-login \ -    --no-create-home \ -    --uid 1500 \ -    pysite - -# Install prerequisites needed to complete the dependency installation. -RUN apt-get update -y \ -    && \ -        apt-get install --no-install-recommends -y \ -                gcc \ -                libc-dev \ -                libpq-dev \ -                git \ -    && \ -        apt-get clean \ -    && \ -        rm -rf /var/lib/apt/lists/* - -# Set up the working directory. -WORKDIR /app -COPY Pipfile Pipfile.lock /app/ - -# Pip install the stuff we'll need. -RUN rm -r /opt/bitnami/python/lib/python3.*/site-packages/setuptools* && \ -    pip install --no-cache-dir -U setuptools -RUN python3 -m pip install pipenv \ -    && python3 -m pipenv install --system --deploy \ -    && pip install uwsgi==2.0.18 - -# Copy everything into the docker environment. -COPY . . - -RUN SECRET_KEY=placeholder DATABASE_URL=sqlite:// python3 manage.py collectstatic --no-input --clear --verbosity 0 - -# Remove the prerequisites, dependency installation is now complete. -RUN apt-get purge -y \ -            gcc \ -            libc-dev \ -            libpq-dev - -CMD ["uwsgi", "--ini", "docker/app/uwsgi.ini"] diff --git a/docker/app/build-wiki.Dockerfile b/docker/app/build-wiki.Dockerfile new file mode 100644 index 00000000..92003377 --- /dev/null +++ b/docker/app/build-wiki.Dockerfile @@ -0,0 +1,2 @@ +FROM python:3.7 +RUN pip --no-cache-dir wheel --wheel-dir=/wheels "wiki @ git+https://github.com/python-discord/django-wiki.git" diff --git a/docker/app/local.Dockerfile b/docker/app/local.Dockerfile new file mode 100644 index 00000000..9e15c438 --- /dev/null +++ b/docker/app/local.Dockerfile @@ -0,0 +1,28 @@ +FROM python:3.7-slim + +# Allow service to handle stops gracefully +STOPSIGNAL SIGQUIT + +# Set pip to have cleaner logs and no saved cache +ENV PIP_NO_CACHE_DIR=false \ +    PIPENV_HIDE_EMOJIS=1 \ +    PIPENV_NOSPIN=1 + +# Create non-root user +RUN useradd --system --shell /bin/false --uid 1500 pysite + +# Install pipenv & pyuwsgi +RUN pip install -U pipenv pyuwsgi + +# Copy the project files into working directory +WORKDIR /app +COPY . . + +# Install project dependencies +RUN pipenv install --system --deploy + +# Prepare static files for site +RUN SECRET_KEY=placeholder DATABASE_URL=sqlite:// \ +    python3 manage.py collectstatic --no-input --clear --verbosity 0 + +CMD ["uwsgi", "--ini", "docker/app/uwsgi.ini"] diff --git a/docker/app/scripts/build-wiki.sh b/docker/app/scripts/build-wiki.sh new file mode 100644 index 00000000..07c54f66 --- /dev/null +++ b/docker/app/scripts/build-wiki.sh @@ -0,0 +1,4 @@ +docker build -t build_uwsgi -f docker/app/build-wiki.Dockerfile . +CONTAINER=$(docker run -itd build_uwsgi /bin/bash) +docker cp "$CONTAINER:/wheels" docker/app +docker stop "$CONTAINER" diff --git a/docker/app/scripts/migrate_and_serve.sh b/docker/app/scripts/migrate_and_serve.sh index 0b54a2e5..c30d7e04 100755 --- a/docker/app/scripts/migrate_and_serve.sh +++ b/docker/app/scripts/migrate_and_serve.sh @@ -1,4 +1,5 @@ -#!/bin/sh -eu +#!/bin/sh +set -eu  ### NOTE  # This file is intended to be used by local setups. diff --git a/docker/app/wheels/wiki-0.5.dev20190420204942-py3-none-any.whl b/docker/app/wheels/wiki-0.5.dev20190420204942-py3-none-any.whlBinary files differ new file mode 100644 index 00000000..b7637e76 --- /dev/null +++ b/docker/app/wheels/wiki-0.5.dev20190420204942-py3-none-any.whl diff --git a/pydis_site/apps/api/migrations/0042_infraction_add_default_ordering.py b/pydis_site/apps/api/migrations/0042_infraction_add_default_ordering.py new file mode 100644 index 00000000..1a0dbb34 --- /dev/null +++ b/pydis_site/apps/api/migrations/0042_infraction_add_default_ordering.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.3 on 2019-09-17 14:07 + +from django.db import migrations + + +class Migration(migrations.Migration): + +    dependencies = [ +        ('api', '0041_add_default_ordering_deleted_messages'), +    ] + +    operations = [ +        migrations.AlterModelOptions( +            name='infraction', +            options={'ordering': ['-inserted_at']}, +        ), +    ] diff --git a/pydis_site/apps/api/models/bot/infraction.py b/pydis_site/apps/api/models/bot/infraction.py index da91d6c2..dfb32a97 100644 --- a/pydis_site/apps/api/models/bot/infraction.py +++ b/pydis_site/apps/api/models/bot/infraction.py @@ -66,3 +66,8 @@ class Infraction(ModelReprMixin, models.Model):          if self.hidden:              s += " (hidden)"          return s + +    class Meta: +        """Defines the meta options for the infraction model.""" + +        ordering = ['-inserted_at'] diff --git a/pydis_site/apps/api/tests/test_infractions.py b/pydis_site/apps/api/tests/test_infractions.py index 7c370c17..0092d355 100644 --- a/pydis_site/apps/api/tests/test_infractions.py +++ b/pydis_site/apps/api/tests/test_infractions.py @@ -63,6 +63,7 @@ class InfractionTests(APISubdomainTestCase):          )      def test_list_all(self): +        """Tests the list-view, which should be ordered by inserted_at (newest first)."""          url = reverse('bot:infraction-list', host='api')          response = self.client.get(url) @@ -70,8 +71,8 @@ class InfractionTests(APISubdomainTestCase):          infractions = response.json()          self.assertEqual(len(infractions), 2) -        self.assertEqual(infractions[0]['id'], self.ban_hidden.id) -        self.assertEqual(infractions[1]['id'], self.ban_inactive.id) +        self.assertEqual(infractions[0]['id'], self.ban_inactive.id) +        self.assertEqual(infractions[1]['id'], self.ban_hidden.id)      def test_filter_search(self):          url = reverse('bot:infraction-list', host='api') diff --git a/pydis_site/apps/api/tests/test_off_topic_channel_names.py b/pydis_site/apps/api/tests/test_off_topic_channel_names.py index 60af1f62..9ab71409 100644 --- a/pydis_site/apps/api/tests/test_off_topic_channel_names.py +++ b/pydis_site/apps/api/tests/test_off_topic_channel_names.py @@ -88,16 +88,20 @@ class CreationTests(APISubdomainTestCase):          super().setUp()          url = reverse('bot:offtopicchannelname-list', host='api') -        self.name = "lemonade-shop" +        self.name = "abcdefghijklmnopqrstuvwxyz-0123456789"          response = self.client.post(f'{url}?name={self.name}')          self.assertEqual(response.status_code, 201) -    def test_name_in_full_list(self): +    def test_returns_201_for_unicode_chars(self):          url = reverse('bot:offtopicchannelname-list', host='api') -        response = self.client.get(url) +        names = ( +            '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹', +            'ǃ?’', +        ) -        self.assertEqual(response.status_code, 200) -        self.assertEqual(response.json(), [self.name]) +        for name in names: +            response = self.client.post(f'{url}?name={name}') +            self.assertEqual(response.status_code, 201)      def test_returns_400_for_missing_name_param(self):          url = reverse('bot:offtopicchannelname-list', host='api') @@ -111,8 +115,8 @@ class CreationTests(APISubdomainTestCase):          url = reverse('bot:offtopicchannelname-list', host='api')          invalid_names = (              'space between words', -            'UPPERCASE', -            '$$$$$$$$' +            'ABCDEFGHIJKLMNOPQRSTUVWXYZ', +            '!?\'@#$%^&*()',          )          for name in invalid_names: | 
