diff --git a/.env b/.env index 92375a8..0cff0a0 100644 --- a/.env +++ b/.env @@ -1,7 +1,6 @@ ################## #### HTTP -DJANGO_BIND_ADDRESS=0.0.0.0 -DJANGO_BIND_PORT=8000 +PORT=8000 ################## #### Database engine diff --git a/Dockerfile b/Dockerfile index d4382cd..9eee549 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,18 @@ FROM python:3.7.3-slim-stretch +# In order to have OUTPUT from Heroku +RUN apt-get update && apt-get install curl -y + +RUN groupadd --system app-user && adduser --system --ingroup app-user app-user + WORKDIR /app -COPY . /app +COPY --chown=app-user:app-user . /app RUN python -m pip install --upgrade pip && \ pip install pipenv && \ pipenv install --system --deploy --ignore-pipfile + +USER app-user + +CMD gunicorn -cfile:gunicorn_config.ini -b 0.0.0.0:${PORT} django_graphql_playground.wsgi diff --git a/Pipfile b/Pipfile index 454ed34..3dde30f 100644 --- a/Pipfile +++ b/Pipfile @@ -27,6 +27,9 @@ drf-extensions = "*" graphene-django = "*" # Database driver psycopg2-binary = "*" +### WSGI +gunicorn = "*" +gevent = "*" ### GraphQL clients graphqlclient = "*" gql = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 5515ed3..101bb8a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f546cba5dab4bbe5e02c55104db03258a6b726fdb39bbb127b7f675bb5d5cbe9" + "sha256": "f75fe4bfdaedc0ed85b532624100cdd2e2f81488aef57bfcd055e65e84a6eefa" }, "pipfile-spec": 6, "requires": { @@ -18,17 +18,17 @@ "default": { "aniso8601": { "hashes": [ - "sha256:7849749cf00ae0680ad2bdfe4419c7a662bef19c03691a19e008c8b9a5267802", - "sha256:94f90871fcd314a458a3d4eca1c84448efbd200e86f55fe4c733c7a40149ef50" + "sha256:b8a6a9b24611fc50cf2d9b45d371bfdc4fd0581d1cc52254f5502130a776d4af", + "sha256:bb167645c79f7a438f9dfab6161af9bed75508c645b1f07d1158240841d22673" ], - "version": "==3.0.2" + "version": "==6.0.0" }, "certifi": { "hashes": [ - "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", - "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" + "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", + "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" ], - "version": "==2019.3.9" + "version": "==2019.6.16" }, "chardet": { "hashes": [ @@ -39,11 +39,11 @@ }, "django": { "hashes": [ - "sha256:6fcc3cbd55b16f9a01f37de8bcbe286e0ea22e87096557f1511051780338eaea", - "sha256:bb407d0bb46395ca1241f829f5bd03f7e482f97f7d1936e26e98dacb201ed4ec" + "sha256:753d30d3eb078064d2ddadfea65083c9848074a7f93d7b4dc7fa6b1380d278f5", + "sha256:7cb67e8b934fab23b6daed7144da52e8a25a47eba7f360ca43d2b448506b01ad" ], "index": "pypi", - "version": "==2.2.1" + "version": "==2.2.2" }, "django-filter": { "hashes": [ @@ -69,6 +69,32 @@ "index": "pypi", "version": "==0.5.0" }, + "gevent": { + "hashes": [ + "sha256:018677cd18b9e8f20d118fc425ffde9b7ce281aa39d66a9b689153bfaa40661d", + "sha256:0835990d528f1b613df99816b409d4916dee487e87289837375a49772e748a29", + "sha256:09120f9c75af384f8ac65b8459e033fd99ab5fd665b3c01e3a2470c39c3cf60b", + "sha256:0bd38a07e723f5a7feea267a3cf7a19db65583552b5d2960050df1208e396f2b", + "sha256:1141c62acee22328436cb09a7e1bcc6f652e88cf913d5de1066b38b6af7e221d", + "sha256:17a9686ed963c7f0d370bc096b0c91e19d99f2e04f65a5de2695577e1071d887", + "sha256:1acf2cb1b8c3c34f53397d7e5a1f883b1697fc5fd49789887583c3121332bdca", + "sha256:34d2d1dfade0f83f8938f69c981f1b281a8756d6cabcc60daa1ee3f3f1f1e5f2", + "sha256:63d9deb376144836e760207c2d7cd009b3b6a2e01f3634dcfc07d9d3b396cfe4", + "sha256:66f87af4894de2f2a739776737b47088770554003ddcf706ce8567d2e48a1c78", + "sha256:6c08d260cae5b28d6a8d3a26e2a8759e65b1585877ce218f5140f465b0c6f846", + "sha256:76d3a9575c86c3f6d865d2688adb6bf6eb43bb9dd90136224c746535137133eb", + "sha256:80a6da1437e3b6afe197477bbf80c7d0a6efa3265f99c3064e2a17d811485a9f", + "sha256:8fa234dadacf8e1920c088bd7ee2220a2a5e45f098b6f603995bb3e4bb27877a", + "sha256:9b324d004229e438f8c0cbe7617c06acaf6c9d9df400615249f39704d0fbb5c7", + "sha256:b3b17b3e41d7f531d30d1461deccb346bba7a54f09a7f4a1686abf6c2731acb6", + "sha256:c3afebb579423081b29a800d65838fe79292f7adf85e72f0734bd628bffbf624", + "sha256:c59a7e837023db0b1c69a22820732d49f52cdb9a18c2d828cfce09f8dacd9f7d", + "sha256:de2bed77aca19ad915293a916c67cff8eb36e3616828d91e2ed4cc16f1d9f967", + "sha256:df9c99c4e23e795f342b9bb489f209f569fb549095b7b3ca1b31bd2c6a2106d7" + ], + "index": "pypi", + "version": "==1.5a1" + }, "gql": { "hashes": [ "sha256:d20cf1eb1c6d54558174a3dcc3cf1ca0e07678cb1123804c2e165838238350f4" @@ -78,25 +104,25 @@ }, "graphene": { "hashes": [ - "sha256:b8ec446d17fa68721636eaad3d6adc1a378cb6323e219814c8f98c9928fc9642", - "sha256:faa26573b598b22ffd274e2fd7a4c52efa405dcca96e01a62239482246248aa3" + "sha256:2ac16d6bb3bdba4da3daa0f6d15b74ac585ed6a016980f502c77c3e687c763bb", + "sha256:fcbcb24ee960b2c768de4285fbd025aa98eed4ecb6a679bbd41985b05b4008c5" ], - "version": "==2.1.3" + "version": "==2.1.6" }, "graphene-django": { "hashes": [ - "sha256:3afd81d47c8b702650e05cc1179fac1cfceae991d241bb164d51f28bed9ec95c", - "sha256:760a18068feb5457e2ec00d2447c09b2fbac2a6b8c32cc8be2abce3752107ad3" + "sha256:7720a459da5bc99fba251f697c4d41858612bf1a36096326af86739dd31705f3", + "sha256:f155cfbd9d201604c3f681ef6b824cc693263946cfdf9ba140880994285016d4" ], "index": "pypi", - "version": "==2.2.0" + "version": "==2.3.2" }, "graphql-core": { "hashes": [ - "sha256:889e869be5574d02af77baf1f30b5db9ca2959f1c9f5be7b2863ead5a3ec6181", - "sha256:9462e22e32c7f03b667373ec0a84d95fba10e8ce2ead08f29fbddc63b671b0c1" + "sha256:60ef8277b82aaad49e87154a0288a9542a82a63909568375712f826b1c280ef5", + "sha256:6288fe97c32d2f868a2dfe62e766dc85d48c96c1d085294edf44714190f2e4f3" ], - "version": "==2.1" + "version": "==2.2" }, "graphql-relay": { "hashes": [ @@ -111,6 +137,39 @@ "index": "pypi", "version": "==0.2.4" }, + "greenlet": { + "hashes": [ + "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0", + "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28", + "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8", + "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304", + "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0", + "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214", + "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043", + "sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6", + "sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625", + "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc", + "sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638", + "sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163", + "sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4", + "sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490", + "sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248", + "sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939", + "sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87", + "sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720", + "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656" + ], + "markers": "platform_python_implementation == 'CPython'", + "version": "==0.4.15" + }, + "gunicorn": { + "hashes": [ + "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471", + "sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3" + ], + "index": "pypi", + "version": "==19.9.0" + }, "idna": { "hashes": [ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", @@ -127,37 +186,37 @@ }, "psycopg2-binary": { "hashes": [ - "sha256:007ca0df127b1862fc010125bc4100b7a630efc6841047bd11afceadb4754611", - "sha256:03c49e02adf0b4d68f422fdbd98f7a7c547beb27e99a75ed02298f85cb48406a", - "sha256:0a1232cdd314e08848825edda06600455ad2a7adaa463ebfb12ece2d09f3370e", - "sha256:131c80d0958c89273d9720b9adf9df1d7600bb3120e16019a7389ab15b079af5", - "sha256:2de34cc3b775724623f86617d2601308083176a495f5b2efc2bbb0da154f483a", - "sha256:2eddc31500f73544a2a54123d4c4b249c3c711d31e64deddb0890982ea37397a", - "sha256:484f6c62bdc166ee0e5be3aa831120423bf399786d1f3b0304526c86180fbc0b", - "sha256:4c2d9369ed40b4a44a8ccd6bc3a7db6272b8314812d2d1091f95c4c836d92e06", - "sha256:70f570b5fa44413b9f30dbc053d17ef3ce6a4100147a10822f8662e58d473656", - "sha256:7a2b5b095f3bd733aab101c89c0e1a3f0dfb4ebdc26f6374805c086ffe29d5b2", - "sha256:804914a669186e2843c1f7fbe12b55aad1b36d40a28274abe6027deffad9433d", - "sha256:8520c03172da18345d012949a53617a963e0191ccb3c666f23276d5326af27b5", - "sha256:90da901fc33ea393fc644607e4a3916b509387e9339ec6ebc7bfded45b7a0ae9", - "sha256:a582416ad123291a82c300d1d872bdc4136d69ad0b41d57dc5ca3df7ef8e3088", - "sha256:ac8c5e20309f4989c296d62cac20ee456b69c41fd1bc03829e27de23b6fa9dd0", - "sha256:b2cf82f55a619879f8557fdaae5cec7a294fac815e0087c4f67026fdf5259844", - "sha256:b59d6f8cfca2983d8fdbe457bf95d2192f7b7efdb2b483bf5fa4e8981b04e8b2", - "sha256:be08168197021d669b9964bd87628fa88f910b1be31e7010901070f2540c05fd", - "sha256:be0f952f1c365061041bad16e27e224e29615d4eb1fb5b7e7760a1d3d12b90b6", - "sha256:c1c9a33e46d7c12b9c96cf2d4349d783e3127163fd96254dcd44663cf0a1d438", - "sha256:d18c89957ac57dd2a2724ecfe9a759912d776f96ecabba23acb9ecbf5c731035", - "sha256:d7e7b0ff21f39433c50397e60bf0995d078802c591ca3b8d99857ea18a7496ee", - "sha256:da0929b2bf0d1f365345e5eb940d8713c1d516312e010135b14402e2a3d2404d", - "sha256:de24a4962e361c512d3e528ded6c7480eab24c655b8ca1f0b761d3b3650d2f07", - "sha256:e45f93ff3f7dae2202248cf413a87aeb330821bf76998b3cf374eda2fc893dd7", - "sha256:f046aeae1f7a845041b8661bb7a52449202b6c5d3fb59eb4724e7ca088811904", - "sha256:f1dc2b7b2748084b890f5d05b65a47cd03188824890e9a60818721fd492249fb", - "sha256:fcbe7cf3a786572b73d2cd5f34ed452a5f5fac47c9c9d1e0642c457a148f9f88" + "sha256:080c72714784989474f97be9ab0ddf7b2ad2984527e77f2909fcd04d4df53809", + "sha256:110457be80b63ff4915febb06faa7be002b93a76e5ba19bf3f27636a2ef58598", + "sha256:171352a03b22fc099f15103959b52ee77d9a27e028895d7e5fde127aa8e3bac5", + "sha256:19d013e7b0817087517a4b3cab39c084d78898369e5c46258aab7be4f233d6a1", + "sha256:249b6b21ae4eb0f7b8423b330aa80fab5f821b9ffc3f7561a5e2fd6bb142cf5d", + "sha256:2ac0731d2d84b05c7bb39e85b7e123c3a0acd4cda631d8d542802c88deb9e87e", + "sha256:2b6d561193f0dc3f50acfb22dd52ea8c8dfbc64bcafe3938b5f209cc17cb6f00", + "sha256:2bd23e242e954214944481124755cbefe7c2cf563b1a54cd8d196d502f2578bf", + "sha256:3e1239242ca60b3725e65ab2f13765fc199b03af9eaf1b5572f0e97bdcee5b43", + "sha256:3eb70bb697abbe86b1d2b1316370c02ba320bfd1e9e35cf3b9566a855ea8e4e5", + "sha256:51a2fc7e94b98bd1bb5d4570936f24fc2b0541b63eccadf8fdea266db8ad2f70", + "sha256:52f1bdafdc764b7447e393ed39bb263eccb12bfda25a4ac06d82e3a9056251f6", + "sha256:5b3581319a3951f1e866f4f6c5e42023db0fae0284273b82e97dfd32c51985cd", + "sha256:63c1b66e3b2a3a336288e4bcec499e0dc310cd1dceaed1c46fa7419764c68877", + "sha256:8123a99f24ecee469e5c1339427bcdb2a33920a18bb5c0d58b7c13f3b0298ba3", + "sha256:85e699fcabe7f817c0f0a412d4e7c6627e00c412b418da7666ff353f38e30f67", + "sha256:8dbff4557bbef963697583366400822387cccf794ccb001f1f2307ed21854c68", + "sha256:908d21d08d6b81f1b7e056bbf40b2f77f8c499ab29e64ec5113052819ef1c89b", + "sha256:af39d0237b17d0a5a5f638e9dffb34013ce2b1d41441fd30283e42b22d16858a", + "sha256:af51bb9f055a3f4af0187149a8f60c9d516cf7d5565b3dac53358796a8fb2a5b", + "sha256:b2ecac57eb49e461e86c092761e6b8e1fd9654dbaaddf71a076dcc869f7014e2", + "sha256:cd37cc170678a4609becb26b53a2bc1edea65177be70c48dd7b39a1149cabd6e", + "sha256:d17e3054b17e1a6cb8c1140f76310f6ede811e75b7a9d461922d2c72973f583e", + "sha256:d305313c5a9695f40c46294d4315ed3a07c7d2b55e48a9010dad7db7a66c8b7f", + "sha256:dd0ef0eb1f7dd18a3f4187226e226a7284bda6af5671937a221766e6ef1ee88f", + "sha256:e1adff53b56db9905db48a972fb89370ad5736e0450b96f91bcf99cadd96cfd7", + "sha256:f0d43828003c82dbc9269de87aa449e9896077a71954fbbb10a614c017e65737", + "sha256:f78e8b487de4d92640105c1389e5b90be3496b1d75c90a666edd8737cc2dbab7" ], "index": "pypi", - "version": "==2.8.2" + "version": "==2.8.3" }, "python-dateutil": { "hashes": [ @@ -184,10 +243,10 @@ }, "rx": { "hashes": [ - "sha256:283655a99696621c12680100baded358d2e4fa0e1a610bc1e824505f1ca523ac", - "sha256:496be2fade59e1be302264edee70667290a13b106543c94b63240747219d9301" + "sha256:30aacb634ee3ec16473cd38ff0725c28b5ee6fb61e39a24c1cccef5b4d7c4077", + "sha256:c3ca30ff6b4ad396e939ea3b1252e8854fdc00c36fecbe9b0d5763b7f39808b8" ], - "version": "==3.0.0b2" + "version": "==3.0.0b4" }, "singledispatch": { "hashes": [ @@ -340,18 +399,18 @@ }, "importlib-metadata": { "hashes": [ - "sha256:027cfc6524613de726789072f95d2e4cc64dd1dee8096d42d13f2ead5bd302f5", - "sha256:0d05199e1f0b1a8707a1b9c46476d4a49807fb56cb1b0737db1d37feb42fe31d" + "sha256:6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7", + "sha256:cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db" ], - "version": "==0.15" + "version": "==0.18" }, "isort": { "hashes": [ - "sha256:c40744b6bc5162bbb39c1257fe298b7a393861d50978b565f3ccd9cb9de0182a", - "sha256:f57abacd059dc3bd666258d1efb0377510a89777fda3e3274e3c01f7c03ae22d" + "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", + "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" ], "index": "pypi", - "version": "==4.3.20" + "version": "==4.3.21" }, "lazy-object-proxy": { "hashes": [ @@ -378,34 +437,32 @@ }, "lxml": { "hashes": [ - "sha256:03984196d00670b2ab14ae0ea83d5cc0cfa4f5a42558afa9ab5fa745995328f5", - "sha256:0815b0c9f897468de6a386dc15917a0becf48cc92425613aa8bbfc7f0f82951f", - "sha256:175f3825f075cf02d15099eb52658457cf0ff103dcf11512b5d2583e1d40f58b", - "sha256:30e14c62d88d1e01a26936ecd1c6e784d4afc9aa002bba4321c5897937112616", - "sha256:3210da6f36cf4b835ff1be853962b22cc354d506f493b67a4303c88bbb40d57b", - "sha256:40f60819fbd5bad6e191ba1329bfafa09ab7f3f174b3d034d413ef5266963294", - "sha256:43b26a865a61549919f8a42e094dfdb62847113cf776d84bd6b60e4e3fc20ea3", - "sha256:4a03dd682f8e35a10234904e0b9508d705ff98cf962c5851ed052e9340df3d90", - "sha256:62f382cddf3d2e52cf266e161aa522d54fd624b8cc567bc18f573d9d50d40e8e", - "sha256:7b98f0325be8450da70aa4a796c4f06852949fe031878b4aa1d6c417a412f314", - "sha256:846a0739e595871041385d86d12af4b6999f921359b38affb99cdd6b54219a8f", - "sha256:a3080470559938a09a5d0ec558c005282e99ac77bf8211fb7b9a5c66390acd8d", - "sha256:ad841b78a476623955da270ab8d207c3c694aa5eba71f4792f65926dc46c6ee8", - "sha256:afdd75d9735e44c639ffd6258ce04a2de3b208f148072c02478162d0944d9da3", - "sha256:b4fbf9b552faff54742bcd0791ab1da5863363fb19047e68f6592be1ac2dab33", - "sha256:b90c4e32d6ec089d3fa3518436bdf5ce4d902a0787dbd9bb09f37afe8b994317", - "sha256:b91cfe4438c741aeff662d413fd2808ac901cc6229c838236840d11de4586d63", - "sha256:bdb0593a42070b0a5f138b79b872289ee73c8e25b3f0bea6564e795b55b6bcdd", - "sha256:c4e4bca2bb68ce22320297dfa1a7bf070a5b20bcbaec4ee023f83d2f6e76496f", - "sha256:cec4ab14af9eae8501be3266ff50c3c2aecc017ba1e86c160209bb4f0423df6a", - "sha256:e83b4b2bf029f5104bc1227dbb7bf5ace6fd8fabaebffcd4f8106fafc69fc45f", - "sha256:e995b3734a46d41ae60b6097f7c51ba9958648c6d1e0935b7e0ee446ee4abe22", - "sha256:f679d93dec7f7210575c85379a31322df4c46496f184ef650d3aba1484b38a2d", - "sha256:fd213bb5166e46974f113c8228daaef1732abc47cb561ce9c4c8eaed4bd3b09b", - "sha256:fdcb57b906dbc1f80666e6290e794ab8fb959a2e17aa5aee1758a85d1da4533f", - "sha256:ff424b01d090ffe1947ec7432b07f536912e0300458f9a7f48ea217dd8362b86" - ], - "version": "==4.3.3" + "sha256:06c7616601430aa140a69f97e3116308fffe0848f543b639a5ec2e8920ae72fd", + "sha256:177202792f9842374a8077735c69c41a4282183f7851443d2beb8ee310720819", + "sha256:19317ad721ceb9e39847d11131903931e2794e447d4751ebb0d9236f1b349ff2", + "sha256:36d206e62f3e5dbaafd4ec692b67157e271f5da7fd925fda8515da675eace50d", + "sha256:387115b066c797c85f9861a9613abf50046a15aac16759bc92d04f94acfad082", + "sha256:3ce1c49d4b4a7bc75fb12acb3a6247bb7a91fe420542e6d671ba9187d12a12c2", + "sha256:4d2a5a7d6b0dbb8c37dab66a8ce09a8761409c044017721c21718659fa3365a1", + "sha256:58d0a1b33364d1253a88d18df6c0b2676a1746d27c969dc9e32d143a3701dda5", + "sha256:62a651c618b846b88fdcae0533ec23f185bb322d6c1845733f3123e8980c1d1b", + "sha256:69ff21064e7debc9b1b1e2eee8c2d686d042d4257186d70b338206a80c5bc5ea", + "sha256:7060453eba9ba59d821625c6af6a266bd68277dce6577f754d1eb9116c094266", + "sha256:7d26b36a9c4bce53b9cfe42e67849ae3c5c23558bc08363e53ffd6d94f4ff4d2", + "sha256:83b427ad2bfa0b9705e02a83d8d607d2c2f01889eb138168e462a3a052c42368", + "sha256:923d03c84534078386cf50193057aae98fa94cace8ea7580b74754493fda73ad", + "sha256:b773715609649a1a180025213f67ffdeb5a4878c784293ada300ee95a1f3257b", + "sha256:baff149c174e9108d4a2fee192c496711be85534eab63adb122f93e70aa35431", + "sha256:bca9d118b1014b4c2d19319b10a3ebed508ff649396ce1855e1c96528d9b2fa9", + "sha256:ce580c28845581535dc6000fc7c35fdadf8bea7ccb57d6321b044508e9ba0685", + "sha256:d34923a569e70224d88e6682490e24c842907ba2c948c5fd26185413cbe0cd96", + "sha256:dd9f0e531a049d8b35ec5e6c68a37f1ba6ec3a591415e6804cbdf652793d15d7", + "sha256:ecb805cbfe9102f3fd3d2ef16dfe5ae9e2d7a7dfbba92f4ff1e16ac9784dbfb0", + "sha256:ede9aad2197a0202caff35d417b671f5f91a3631477441076082a17c94edd846", + "sha256:ef2d1fc370400e0aa755aab0b20cf4f1d0e934e7fd5244f3dd4869078e4942b9", + "sha256:f2fec194a49bfaef42a548ee657362af5c7a640da757f6f452a35da7dd9f923c" + ], + "version": "==4.3.4" }, "mccabe": { "hashes": [ @@ -416,28 +473,27 @@ }, "more-itertools": { "hashes": [ - "sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7", - "sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a" + "sha256:3ad685ff8512bf6dc5a8b82ebf73543999b657eded8c11803d9ba6b648986f4d", + "sha256:8bb43d1f51ecef60d81854af61a3a880555a14643691cc4b64a6ee269c78f09a" ], - "markers": "python_version > '2.7'", - "version": "==7.0.0" + "version": "==7.1.0" }, "mypy": { "hashes": [ - "sha256:2afe51527b1f6cdc4a5f34fc90473109b22bf7f21086ba3e9451857cf11489e6", - "sha256:56a16df3e0abb145d8accd5dbb70eba6c4bd26e2f89042b491faa78c9635d1e2", - "sha256:5764f10d27b2e93c84f70af5778941b8f4aa1379b2430f85c827e0f5464e8714", - "sha256:5bbc86374f04a3aa817622f98e40375ccb28c4836f36b66706cf3c6ccce86eda", - "sha256:6a9343089f6377e71e20ca734cd8e7ac25d36478a9df580efabfe9059819bf82", - "sha256:6c9851bc4a23dc1d854d3f5dfd5f20a016f8da86bcdbb42687879bb5f86434b0", - "sha256:b8e85956af3fcf043d6f87c91cbe8705073fc67029ba6e22d3468bfee42c4823", - "sha256:b9a0af8fae490306bc112229000aa0c2ccc837b49d29a5c42e088c132a2334dd", - "sha256:bbf643528e2a55df2c1587008d6e3bda5c0445f1240dfa85129af22ae16d7a9a", - "sha256:c46ab3438bd21511db0f2c612d89d8344154c0c9494afc7fbc932de514cf8d15", - "sha256:f7a83d6bd805855ef83ec605eb01ab4fa42bcef254b13631e451cbb44914a9b0" + "sha256:12d18bd7fc642c5d54b1bb62dde813a7e2ab79b32ee11ff206ac387c68fc2ad4", + "sha256:23e24bc1683a36f39dee67d8ac74ea414654642eee26d420bada95b8ee8c9095", + "sha256:2b38e64c52a8968df4ebcae0ddba4a54eb94d184695dd4e54e14509a9389b78c", + "sha256:3d4f551466a76e278187ec3a5b26cfb50f72f6760b749aa00ac69a6f9c99898d", + "sha256:53d5dacb8d844e50be698830509aa592b093547e7ab90aee63eb23db61109007", + "sha256:56f981d246010ba21cac6b2455eaecfaf68fc8a5663d865b26c8e579c36f751d", + "sha256:8c57f6f59f1e8479d9fc6e1bf034353e54626ed64e32394c613afc493a441dc1", + "sha256:bbed4a593d87476b592d52867ef86da2155ccd0becf0c4c02e6567d842e43368", + "sha256:d6ff850e2ba18b2db7704897c8f2f1384478e3b75ad292ec06196bf7794f3a40", + "sha256:e13b1bb8785d7f785e0b88873f1c21cda58ceba9ce1153b58cbfa24b09a111d5", + "sha256:e2b9ee6f648ce72d6741925a47c88c2391168ef973b6f74f17969450c5b1ffdd" ], "index": "pypi", - "version": "==0.701" + "version": "==0.711" }, "mypy-extensions": { "hashes": [ @@ -446,6 +502,13 @@ ], "version": "==0.4.1" }, + "packaging": { + "hashes": [ + "sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", + "sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3" + ], + "version": "==19.0" + }, "parsel": { "hashes": [ "sha256:493a9214acbdcb4487a084d95344c25e85e90426a67311ea0425dc5df8dc24b9", @@ -498,13 +561,20 @@ "index": "pypi", "version": "==2.3.1" }, + "pyparsing": { + "hashes": [ + "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", + "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03" + ], + "version": "==2.4.0" + }, "pytest": { "hashes": [ - "sha256:1a8aa4fa958f8f451ac5441f3ac130d9fc86ea38780dd2715e6d5c5882700b24", - "sha256:b8bf138592384bd4e87338cb0f256bf5f615398a649d4bd83915f0e4047a5ca6" + "sha256:2878de8ae1c79a62c012da6186b88ff0562ea96ce29c4208d2a9b11d9f607df1", + "sha256:95b700cf21ed5b7e91bce7a6b5a573b2e3ef7b3643d00f681d8f9c4672f9fbdf" ], "index": "pypi", - "version": "==4.5.0" + "version": "==5.0.0" }, "pytest-cov": { "hashes": [ @@ -516,11 +586,11 @@ }, "pytest-django": { "hashes": [ - "sha256:30d773f1768e8f214a3106f1090e00300ce6edfcac8c55fd13b675fe1cbd1c85", - "sha256:4d3283e774fe1d40630ee58bf34929b83875e4751b525eeb07a7506996eb42ee" + "sha256:264fb4c506db5d48a6364c311a0b00b7b48a52715bad8839b2d8bee9b99ed6bb", + "sha256:4adfe5fb3ed47f0ba55506dd3daf688b1f74d5e69148c10ad2dd2f79f40c0d62" ], "index": "pypi", - "version": "==3.4.8" + "version": "==3.5.1" }, "pytest-env": { "hashes": [ @@ -553,43 +623,39 @@ }, "tox": { "hashes": [ - "sha256:f5c8e446b51edd2ea97df31d4ded8c8b72e7d6c619519da6bb6084b9dd5770f9", - "sha256:f87fd33892a2df0950e5e034def9468988b8d008c7e9416be665fcc0dd45b14f" + "sha256:45a265e953368fb372cca3eac33b69fdb1b1453e5b114be231c84fc3dfadceed", + "sha256:f5cb0b5b8d14f2100982b0981c750d840228180a348e6bad355aa38e949fbc3f" ], "index": "pypi", - "version": "==3.12.1" + "version": "==3.13.1" }, "typed-ast": { "hashes": [ - "sha256:132eae51d6ef3ff4a8c47c393a4ef5ebf0d1aecc96880eb5d6c8ceab7017cc9b", - "sha256:18141c1484ab8784006c839be8b985cfc82a2e9725837b0ecfa0203f71c4e39d", - "sha256:2baf617f5bbbfe73fd8846463f5aeafc912b5ee247f410700245d68525ec584a", - "sha256:3d90063f2cbbe39177e9b4d888e45777012652d6110156845b828908c51ae462", - "sha256:4304b2218b842d610aa1a1d87e1dc9559597969acc62ce717ee4dfeaa44d7eee", - "sha256:4983ede548ffc3541bae49a82675996497348e55bafd1554dc4e4a5d6eda541a", - "sha256:5315f4509c1476718a4825f45a203b82d7fdf2a6f5f0c8f166435975b1c9f7d4", - "sha256:6cdfb1b49d5345f7c2b90d638822d16ba62dc82f7616e9b4caa10b72f3f16649", - "sha256:7b325f12635598c604690efd7a0197d0b94b7d7778498e76e0710cd582fd1c7a", - "sha256:8d3b0e3b8626615826f9a626548057c5275a9733512b137984a68ba1598d3d2f", - "sha256:8f8631160c79f53081bd23446525db0bc4c5616f78d04021e6e434b286493fd7", - "sha256:912de10965f3dc89da23936f1cc4ed60764f712e5fa603a09dd904f88c996760", - "sha256:b010c07b975fe853c65d7bbe9d4ac62f1c69086750a574f6292597763781ba18", - "sha256:c908c10505904c48081a5415a1e295d8403e353e0c14c42b6d67f8f97fae6616", - "sha256:c94dd3807c0c0610f7c76f078119f4ea48235a953512752b9175f9f98f5ae2bd", - "sha256:ce65dee7594a84c466e79d7fb7d3303e7295d16a83c22c7c4037071b059e2c21", - "sha256:eaa9cfcb221a8a4c2889be6f93da141ac777eb8819f077e1d09fb12d00a09a93", - "sha256:f3376bc31bad66d46d44b4e6522c5c21976bf9bca4ef5987bb2bf727f4506cbb", - "sha256:f9202fa138544e13a4ec1a6792c35834250a85958fde1251b6a22e07d1260ae7" + "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", + "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", + "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", + "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", + "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", + "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", + "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", + "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", + "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", + "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", + "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", + "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", + "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", + "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", + "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" ], "markers": "implementation_name == 'cpython'", - "version": "==1.3.5" + "version": "==1.4.0" }, "virtualenv": { "hashes": [ - "sha256:99acaf1e35c7ccf9763db9ba2accbca2f4254d61d1912c5ee364f9cc4a8942a0", - "sha256:fe51cdbf04e5d8152af06c075404745a7419de27495a83f0d72518ad50be3ce8" + "sha256:b7335cddd9260a3dd214b73a2521ffc09647bde3e9457fcca31dc3be3999d04a", + "sha256:d28ca64c0f3f125f59cabf13e0a150e1c68e5eea60983cc4395d88c584495783" ], - "version": "==16.6.0" + "version": "==16.6.1" }, "w3lib": { "hashes": [ @@ -607,9 +673,9 @@ }, "wrapt": { "hashes": [ - "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533" + "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" ], - "version": "==1.11.1" + "version": "==1.11.2" }, "zipp": { "hashes": [ diff --git a/README.md b/README.md index 25153b3..498621a 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,9 @@ Useful links: - https://docs.graphene-python.org/en/latest/testing/#testing-tools - https://pytest-django.readthedocs.io/en/latest/helpers.html +- https://gist.github.com/JamesMGreene/cdd0ac49f90c987e45ac ## Issues - [Pipeline for Django fails with: No module named '_sqlite3'](https://developercommunity.visualstudio.com/content/problem/574733/pipeline-for-django-fails-with-no-module-named-sql.html) +- [GitHubInstallationTokenSignatureSecret](https://developercommunity.visualstudio.com/content/problem/564582/githubinstallationtokensignaturesecret-does-not-ex.html) diff --git a/django_graphql_playground/settings.py b/django_graphql_playground/settings.py index 19b2d43..164acb0 100644 --- a/django_graphql_playground/settings.py +++ b/django_graphql_playground/settings.py @@ -2,8 +2,9 @@ from enum import Enum from django_graphql_playground.support.utils import eval_env_as_boolean +from django_graphql_playground.support.utils import extract_db_properties_from_url -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ @@ -92,6 +93,23 @@ } } +# https://devcenter.heroku.com/changelog-items/438 +DATABASE_URL = os.getenv("DATABASE_URL") + +if DATABASE_URL: + properties = extract_db_properties_from_url(DATABASE_URL) + if properties.target == "postgres": + DATABASES["default"] = { + "ENGINE": "django.db.backends.postgresql", + "NAME": properties.database_name, + "USER": properties.user, + "HOST": properties.hostname, + "PORT": properties.port, + "PASSWORD": properties.password, + } + else: + raise NotImplementedError(f"The following DB is not supported: {properties.target}") + DATABASES["default"]["CONN_MAX_AGE"] = int(os.getenv("DB_CONN_MAX_AGE", 0)) # type: ignore # Password validation diff --git a/django_graphql_playground/support/utils.py b/django_graphql_playground/support/utils.py index 64ce355..a678539 100644 --- a/django_graphql_playground/support/utils.py +++ b/django_graphql_playground/support/utils.py @@ -1,10 +1,45 @@ import os +import re +from dataclasses import dataclass from datetime import date from datetime import timedelta from dateutil import relativedelta +@dataclass(frozen=True) +class _DatabaseProperties: + target: str + user: str + password: str + hostname: str + port: int + database_name: str + + +_TARGET = 1 +_USERNAME = 2 +_PASSWORD = 3 +_HOSTNAME = 4 +_PORT = 5 +_DB_NAME = 6 +_pattern = r"^([a-z]*):\/\/([a-zA-Z0-9]*):([a-zA-Z0-9]*)@([a-zA-Z0-9.-]*):([0-9]{4,5})\/([a-zA-Z0-9]*)" +_compiled_pattern = re.compile(_pattern, re.IGNORECASE) + + +def extract_db_properties_from_url(connection_url): + matches = _compiled_pattern.search(connection_url) + + return _DatabaseProperties( + matches.group(_TARGET), + matches.group(_USERNAME), + matches.group(_PASSWORD), + matches.group(_HOSTNAME), + matches.group(_PORT), + matches.group(_DB_NAME), + ) + + def retrieve_ip_address(request): """ Makes the best attempt to get the client's real IP or return the loopback diff --git a/docker-compose.yml b/docker-compose.yml index 719734d..bca8bd5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,7 @@ services: - db - broker ports: - - "8000:${DJANGO_BIND_PORT}" + - "8000:${PORT}" mem_limit: 256mb command: [ diff --git a/gunicorn_config.ini b/gunicorn_config.ini new file mode 100644 index 0000000..b47392a --- /dev/null +++ b/gunicorn_config.ini @@ -0,0 +1,16 @@ +############ +###### http://docs.gunicorn.org/en/stable/settings.html#worker-processes + +workers = 5 +worker_class = "gevent" +worker_connections = 1000 +timeout = 30 +keepalive = 2 + +############ +###### http://docs.gunicorn.org/en/stable/settings.html#logging + +errorlog = "-" +loglevel = "info" +accesslog = "-" +access_log_format = '{"message": "%(r)s", "http_status": %(s)s, "ip_address": "%(h)s", "response_length": "%(b)s", "referer": "%(f)s", "user_agent": "%(a)s", "request_time": %(L)s, "date": "%(t)s"}' diff --git a/heroku.yml b/heroku.yml new file mode 100644 index 0000000..8686484 --- /dev/null +++ b/heroku.yml @@ -0,0 +1,7 @@ +build: + docker: + web: Dockerfile +release: + image: web + command: + - ./release-task.sh diff --git a/release-task.sh b/release-task.sh new file mode 100755 index 0000000..cfe91db --- /dev/null +++ b/release-task.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +python manage.py makemigrations +python manage.py migrate +python manage.py seed_db --create-super-user diff --git a/start.sh b/start.sh index afe335a..4265134 100755 --- a/start.sh +++ b/start.sh @@ -3,11 +3,11 @@ python manage.py makemigrations python manage.py migrate python manage.py seed_db --create-super-user -if [[ ${DJANGO_BIND_ADDRESS+x} ]] && [[ ${DJANGO_BIND_PORT+x} ]]; +if [[ ${PORT+x} ]]; then - echo "OK! Using custom ADRESSS $DJANGO_BIND_ADDRESS and PORT $DJANGO_BIND_PORT to set Django runserver command" - python manage.py runserver ${DJANGO_BIND_ADDRESS}:${DJANGO_BIND_PORT} + echo "OK! Using custom PORT $PORT to set Django runserver command" + python manage.py runserver 0.0.0.0:${PORT} else - echo "Using 0.0.0.0:80 as parameter for Django runserver command" - python manage.py runserver 0.0.0.0:80 + echo "Using 0.0.0.0:8000 as parameter for Django runserver command" + python manage.py runserver 0.0.0.0:8000 fi diff --git a/tests/unit/support/test_utils.py b/tests/unit/support/test_utils.py new file mode 100644 index 0000000..3a023ce --- /dev/null +++ b/tests/unit/support/test_utils.py @@ -0,0 +1,21 @@ +import os +import re +from dataclasses import dataclass +from datetime import date +from datetime import timedelta + +from dateutil import relativedelta + +from django_graphql_playground.support import utils + + +def test_should_extract_db_properties_given_url(): + result = utils.extract_db_properties_from_url( + "postgres://czazgirubdxrxw:8d5d635df6f2a226b1a1f81541cfcd20fadf8617fff383f553e39330392de901@ec2-54-243-47-196.compute-1.amazonaws.com:5432/dau6saplk4ri6e" + ) + assert result.target == "postgres" + assert result.user == "czazgirubdxrxw" + assert result.password == "8d5d635df6f2a226b1a1f81541cfcd20fadf8617fff383f553e39330392de901" + assert result.hostname == "ec2-54-243-47-196.compute-1.amazonaws.com" + assert result.port == "5432" + assert result.database_name == "dau6saplk4ri6e"