diff --git a/.github/workflows/on_release.yml b/.github/workflows/on_release.yml index 529dbc2..2d918ee 100644 --- a/.github/workflows/on_release.yml +++ b/.github/workflows/on_release.yml @@ -6,67 +6,68 @@ on: - 'v*' jobs: - docker: + build: + name: Build the docker image runs-on: ubuntu-latest steps: - # - name: Build started - # uses: voxmedia/github-action-slack-notify-build@v1 - # if: success() - # with: - # channel: ci-notifications - # status: STARTED - # color: good - # env: - # SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - # - name: Checkout - # uses: actions/checkout@v1 - # with: - # fetch-depth: 1 - # - name: Log in to Docker Hub - # uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 - # with: - # username: ${{ secrets.DOCKER_HUB_USERNAME }} - # password: ${{ secrets.DOCKER_HUB_PASSWORD }} - # - name: Extract metadata (tags, labels) for Docker - # id: meta - # uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 - # with: - # images: redbeard/mines-backend - # - name: Build and push Docker image - # uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc - # env: - # SCOPE: production - # with: - # context: . - # push: true - # tags: ${{ steps.meta.outputs.tags }} - # labels: ${{ steps.meta.outputs.labels }} - - name: Create Sentry release - uses: distributhor/workflow-webhook@v2 + - name: Build started + uses: voxmedia/github-action-slack-notify-build@v1 + if: success() + with: + channel: ci-notifications + status: STARTED + color: good env: - webhook_type: 'json-extended' - webhook_url: ${{ secrets.SENTRY_WEBHOOK_URL }} - data: '{ "version": "${{ github.ref_name }}", "environment" : "production" }' - # - name: executing remote ssh commands using password - # uses: appleboy/ssh-action@master - # with: - # host: ${{ secrets.SSH_HOST }} - # username: ${{ secrets.SSH_USERNAME }} - # password: ${{ secrets.SSH_PASSWORD }} - # port: ${{ secrets.SSH_PORT }} - # script: | - # cd /media/data/apps/mines-backend - # docker pull redbeard/mines-backend:latest - # docker-compose up -d app0 - # docker-compose up -d app1 - # docker exec -t mines-be0 python manage.py migrate - # docker image prune -f - # - name: Build finished - # if: success() - # uses: voxmedia/github-action-slack-notify-build@v1 - # with: - # channel: ci-notifications - # status: SUCCESS - # color: good - # env: - # SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 1 + - name: Log in to Docker Hub + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: redbeard/mines-backend + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + env: + SCOPE: production + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + - name: Build finished + if: success() + uses: voxmedia/github-action-slack-notify-build@v1 + with: + channel: ci-notifications + status: SUCCESS + color: good + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + deploy: + name: Deploy + runs-on: ubuntu-latest + needs: + - build + steps: + - name: Deploy to production + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USERNAME }} + password: ${{ secrets.SSH_PASSWORD }} + port: ${{ secrets.SSH_PORT }} + script: | + cd /media/data/apps/mines-backend + docker pull redbeard/mines-backend:latest + docker-compose up -d app0 + docker-compose up -d app1 + docker exec -t mines-be0 python manage.py migrate + docker image prune -f diff --git a/app/settings.py b/app/settings.py index 5054821..d5ba35e 100644 --- a/app/settings.py +++ b/app/settings.py @@ -3,12 +3,16 @@ import os from pathlib import Path import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration +from .utils import get_op_config +op_config = get_op_config() -SCOPE = os.getenv("SCOPE", "production") +print(op_config) + +SCOPE = op_config['settings.SCOPE'] sentry_sdk.init( - dsn=os.getenv("SENTRY_DSN"), + dsn=op_config['settings.SENTRY_DSN'], integrations=[DjangoIntegration()], environment=SCOPE, send_default_pii=False, @@ -19,12 +23,12 @@ sentry_sdk.init( BASE_DIR = Path(__file__).resolve().parent.parent # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = os.getenv("SECRET_KEY", "changeme") +SECRET_KEY = op_config['settings.SECRET_KEY'] # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.getenv("DEBUG", "0") in ["1", "true"] +DEBUG = op_config.get("settings.DEBUG", "0") in ["1", "true"] -ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "127.0.0.1,localhost").split(",") +ALLOWED_HOSTS = op_config.get("settings.ALLOWED_HOSTS", "127.0.0.1,localhost").split(",") # Application definition INSTALLED_APPS = [ @@ -80,11 +84,11 @@ AUTH_USER_MODEL = "core.User" DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", - "NAME": os.getenv("DB_NAME"), - "USER": os.getenv("DB_USER"), - "PASSWORD": os.getenv("DB_PASS"), - "HOST": os.getenv("DB_HOST"), - "PORT": os.getenv("DB_PORT"), + "NAME": op_config['database.name'], + "USER": op_config['database.user'], + "PASSWORD": op_config['database.password'], + "HOST": op_config['database.host'], + "PORT": op_config['database.port'], "OPTIONS": {"charset": "utf8mb4"}, } } diff --git a/app/utils.py b/app/utils.py new file mode 100644 index 0000000..c845242 --- /dev/null +++ b/app/utils.py @@ -0,0 +1,27 @@ +import os + +import onepasswordconnectsdk +from onepasswordconnectsdk.client import Client, new_client_from_environment + + +def get_op_config(): + op_client: Client = new_client_from_environment() + + OP_DJANGO_SETTINGS_VARS = [ + 'database.host', + 'database.port', + 'database.name', + 'database.user', + 'database.password', + 'settings.ALLOWED_HOSTS', + 'settings.DEBUG', + 'settings.SCOPE', + 'settings.SENTRY_DSN', + 'settings.SECRET_KEY', + ] + + op_config_get = {} + for var in OP_DJANGO_SETTINGS_VARS: + op_config_get[var] = {"opitem": "mines", "opfield": var} + + return onepasswordconnectsdk.load_dict(op_client, op_config_get) diff --git a/poetry.lock b/poetry.lock index cd9cf08..c50c4c4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -69,6 +69,17 @@ category = "dev" optional = false python-versions = ">=3.6.1" +[[package]] +name = "charset-normalizer" +version = "2.1.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + [[package]] name = "click" version = "8.1.3" @@ -223,6 +234,14 @@ python-versions = ">=3.7" [package.extras] license = ["ukkonen"] +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + [[package]] name = "mccabe" version = "0.7.0" @@ -255,6 +274,19 @@ category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +[[package]] +name = "onepasswordconnectsdk" +version = "1.2.0" +description = "Python SDK for 1Password Connect" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +python-dateutil = ">=2.8.1,<3.0.0" +requests = ">=2.24.0,<3.0.0" +six = ">=1.10,<2.0" + [[package]] name = "pathspec" version = "0.9.0" @@ -362,6 +394,24 @@ category = "dev" optional = false python-versions = ">=3.6" +[[package]] +name = "requests" +version = "2.28.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] + [[package]] name = "sentry-sdk" version = "1.9.5" @@ -511,7 +561,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "1.1" python-versions = ">=3.8,<4" -content-hash = "2e14758a5488fc86d2bf9442a8bf63b8c3b4937e34a020f6c46dd4a90cafde01" +content-hash = "b69914f0572517fb0cac4578bc94c453cb0e436e5745b1b73f104253cb3f5544" [metadata.files] asgiref = [ @@ -570,6 +620,7 @@ cfgv = [ {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] +charset-normalizer = [] click = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, @@ -589,6 +640,10 @@ flake8 = [] gevent = [] greenlet = [] identify = [] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] mccabe = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -599,6 +654,7 @@ mypy-extensions = [ ] mysqlclient = [] nodeenv = [] +onepasswordconnectsdk = [] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, @@ -681,6 +737,10 @@ pyyaml = [ {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] +requests = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] sentry-sdk = [] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, diff --git a/pyproject.toml b/pyproject.toml index faf38ad..4b3553a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ pendulum = "^2.1.2" sentry-sdk = "^1.9.5" uWSGI = "^2.0.20" pytz = "^2022.2.1" +onepasswordconnectsdk = "^1.2.0" [tool.poetry.dev-dependencies] pre-commit = "^2.20.0"