diff --git a/.env.integration-tests b/.env.integration-tests index 2ccfa48d6..8d9c2561d 100644 --- a/.env.integration-tests +++ b/.env.integration-tests @@ -28,7 +28,7 @@ KINTO_HOST=http://kinto:8888/v1 KINTO_PASS=experimenter KINTO_USER=experimenter KINTO_REVIEW_TIMEOUT=40 -LOGGING_CONSOLE_LEVEL=INFO +LOG_LEVEL=INFO LOGGING_USE_JSON=False NORMANDY_API_HOST= NORMANDY_DEVTOOLS_HOST=https://normandy-devtools.services.mozilla.com/#/local diff --git a/.env.sample b/.env.sample index 16e90ddca..165c09a91 100644 --- a/.env.sample +++ b/.env.sample @@ -30,7 +30,7 @@ KINTO_HOST=http://kinto:8888/v1 KINTO_PASS=experimenter KINTO_USER=experimenter KINTO_REVIEW_TIMEOUT=60 -LOGGING_CONSOLE_LEVEL=INFO +LOG_LEVEL=INFO LOGGING_USE_JSON=False NORMANDY_API_HOST= NORMANDY_DEVTOOLS_HOST=https://normandy-devtools.services.mozilla.com/#/local diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..fbafd9a49 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing + +First off, thanks for taking the time to contribute! ❤️ + +All types of contributions are encouraged and valued. + +Before doing so, here are a few guidelines: + +* You agree to license your contributions under the project [license](LICENSE). +* Use pull-requests early so it's open for discussion, even if your + contribution isn't ready yet. +* All pull requests should include tests, as they help us avoid regressions in + our code. +* A pull-request adding functionality should also update the documentation + accordingly. diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 000000000..0e9b29d1f --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +This code and its associated production web page are included in the Mozilla’s web and services [bug bounty program](https://www.mozilla.org/en-US/security/web-bug-bounty/). If you find a security vulnerability, please submit it via the process outlined in the program and [FAQ pages](https://www.mozilla.org/en-US/security/bug-bounty/faq-webapp/). Further technical details about this application are available from the [Bug Bounty Onramp page](https://wiki.mozilla.org/Security/BugBountyOnramp/). + +Please submit all security-related bugs through Bugzilla using the [web security bug form](https://bugzilla.mozilla.org/form.web.bounty). Never submit security-related bugs through a Github Issue or by email. diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 000000000..837739839 --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,5 @@ +# Support + +If you're looking for support for Experimenter, check out: + +* `#nimbus-dev` on mozilla.slack.com diff --git a/Makefile b/Makefile index 1f6cc6b92..8c67bfede 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,14 @@ CLI_DIR = experimenter/experimenter/features/manifests/application-services CLI_INSTALLER = $(CLI_DIR)/install-nimbus-cli.sh NIMBUS_CLI = $(CLI_DIR)/nimbus-cli -ssl: nginx/key.pem nginx/cert.pem +help: + @echo "Please use 'make ' where is one of the following commands." + @echo + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + @echo + @echo "Check the Makefile to know exactly what each target is doing." + +ssl: nginx/key.pem nginx/cert.pem ## Generate all SSL certificates nginx/key.pem: openssl genrsa -out nginx/key.pem 4096 @@ -66,10 +73,10 @@ nginx/cert.pem: nginx/key.pem -subj "/C=US/ST=California/L=Mountain View/O=Mozilla/CN=experiment_local" \ > nginx/cert.pem -secretkey: +secretkey: ## Generate random key openssl rand -hex 24 -auth_gcloud: +auth_gcloud: ## Login to GCloud gcloud auth login --update-adc jetstream_config: @@ -80,18 +87,18 @@ jetstream_config: feature_manifests: build_dev $(COMPOSE) run experimenter /experimenter/bin/manifest-tool.py fetch-latest -install_nimbus_cli: +install_nimbus_cli: ## Install Nimbus client mkdir -p $(CLI_DIR) curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/mozilla/application-services/main/install-nimbus-cli.sh > "$(CLI_INSTALLER)" $(SHELL) $(CLI_INSTALLER) --directory "$(CLI_DIR)" -fetch_external_resources: jetstream_config install_nimbus_cli feature_manifests +fetch_external_resources: jetstream_config install_nimbus_cli feature_manifests ## Fetch all external resources echo "External Resources Fetched" -update_kinto: +update_kinto: ## Update latest Kinto/Remote Settings container docker pull mozilla/kinto-dist:latest -compose_build: +compose_build: ## Build containers $(COMPOSE) build build_dev: ssl @@ -122,24 +129,27 @@ docker_prune: docker volume prune -f docker volume rm $$(docker volume ls -qf dangling=true) || true -static_rm: +static_rm: ## Remove statically generated files rm -Rf experimenter/node_modules rm -Rf experimenter/experimenter/legacy/legacy-ui/core/node_modules/ rm -Rf experimenter/experimenter/nimbus-ui/node_modules/ rm -Rf experimenter/experimenter/legacy/legacy-ui/assets/ rm -Rf experimenter/experimenter/nimbus-ui/build/ -kill: compose_stop compose_rm docker_prune +kill: compose_stop compose_rm docker_prune ## Stop, remove, and prune containers echo "All containers removed!" -check: build_test +lint: build_test ## Running linting on source code $(COMPOSE_TEST) run experimenter sh -c '$(WAIT_FOR_DB) (${PARALLEL} "$(NIMBUS_SCHEMA_CHECK)" "$(PYTHON_CHECK_MIGRATIONS)" "$(CHECK_DOCS)" "$(BLACK_CHECK)" "$(RUFF_CHECK)" "$(ESLINT_LEGACY)" "$(ESLINT_NIMBUS_UI)" "$(TYPECHECK_NIMBUS_UI)" "$(PYTHON_TYPECHECK)" "$(PYTHON_TEST)" "$(JS_TEST_LEGACY)" "$(JS_TEST_NIMBUS_UI)" "$(JS_TEST_REPORTING)") ${COLOR_CHECK}' +check: lint -pytest: build_test +test: build_test ## Run tests $(COMPOSE_TEST) run experimenter sh -c '$(WAIT_FOR_DB) $(PYTHON_TEST)' +pytest: test -up: build_dev +start: build_dev ## Start containers $(COMPOSE) up +up: start up_legacy: build_dev $(COMPOSE_LEGACY) up @@ -165,19 +175,20 @@ generate_docs: build_dev generate_types: build_dev $(COMPOSE) run experimenter sh -c "$(NIMBUS_TYPES_GENERATE)" -code_format: build_dev +format: build_dev ## Format source tree $(COMPOSE) run experimenter sh -c '${PARALLEL} "$(RUFF_FIX);$(BLACK_FIX)" "$(ESLINT_FIX_CORE)" "$(ESLINT_FIX_NIMBUS_UI)"' +code_format: format makemigrations: build_dev $(COMPOSE) run experimenter python manage.py makemigrations -migrate: build_dev +migrate: build_dev ## Run database migrations $(COMPOSE) run experimenter sh -c "$(WAIT_FOR_DB) $(PYTHON_MIGRATE)" bash: build_dev $(COMPOSE) run experimenter bash -refresh: kill build_dev compose_build +refresh: kill build_dev compose_build ## Rebuild all containers $(COMPOSE) run -e SKIP_DUMMY=$$SKIP_DUMMY experimenter bash -c '$(WAIT_FOR_DB) $(PYTHON_MIGRATE)&&$(LOAD_LOCALES)&&$(LOAD_COUNTRIES)&&$(LOAD_LANGUAGES)&&$(LOAD_FEATURES)&&$(LOAD_DUMMY_EXPERIMENTS)' dependabot_approve: @@ -270,17 +281,18 @@ SCHEMAS_DEPLOY_NPM = echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npm SCHEMAS_VERSION_PYPI = poetry version ${SCHEMAS_VERSION}; SCHEMAS_VERSION_NPM = npm version --allow-same-version ${SCHEMAS_VERSION}; -schemas_build: +schemas_build: ## Build schemas $(DOCKER_BUILD) --target dev -f schemas/Dockerfile -t schemas:dev schemas/ schemas_bash: schemas_build $(SCHEMAS_RUN) "bash" -schemas_format: schemas_build +schemas_format: schemas_build ## Format schemas source tree $(SCHEMAS_RUN) "$(SCHEMAS_FORMAT)" -schemas_check: schemas_build +schemas_lint: schemas_build ## Lint schemas source tree $(SCHEMAS_RUN) "$(SCHEMAS_BLACK)&&$(SCHEMAS_RUFF)&&$(SCHEMAS_DIFF_PYDANTIC)&&$(SCHEMAS_TEST)" +schemas_check: schemas_lint schemas_dist_pypi: schemas_build $(SCHEMAS_RUN) "$(SCHEMAS_DIST_PYPI)" diff --git a/README.md b/README.md index 50aed8d01..907e1c2fb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Mozilla Experimenter -[![CircleCI](https://circleci.com/gh/mozilla/experimenter.svg?style=svg)](https://circleci.com/gh/mozilla/experimenter) +[![CircleCI](https://circleci.com/gh/mozilla/experimenter.svg?style=svg)](https://circleci.com/gh/mozilla/experimenter) ![Status](https://img.shields.io/badge/Status-Invest-green) Experimenter is a platform for managing experiments in [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/?utm_medium=referral&utm_source=firefox-com). diff --git a/experimenter/experimenter/experiments/apps.py b/experimenter/experimenter/experiments/apps.py index ff9136b6b..383f087e3 100644 --- a/experimenter/experimenter/experiments/apps.py +++ b/experimenter/experimenter/experiments/apps.py @@ -1,6 +1,10 @@ import markus +import sentry_sdk from django.apps import AppConfig from django.conf import settings +from sentry_sdk.integrations.django import DjangoIntegration + +from experimenter.base import app_version class ExperimentsConfig(AppConfig): @@ -8,3 +12,18 @@ class ExperimentsConfig(AppConfig): def ready(self): markus.configure(settings.MARKUS_BACKEND) + + if settings.SENTRY_DSN: # pragma: no cover + sentry_sdk.init( + dsn=settings.SENTRY_DSN, + integrations=[DjangoIntegration()], + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for performance monitoring. + # We recommend adjusting this value in production. + traces_sample_rate=1.0, + # If you wish to associate users to errors (assuming you are using + # django.contrib.auth) you may enable sending PII data. + send_default_pii=False, + environment=settings.SENTRY_ENV, + release=app_version(), + ) diff --git a/experimenter/experimenter/settings.py b/experimenter/experimenter/settings.py index a29fc33c6..137c05990 100644 --- a/experimenter/experimenter/settings.py +++ b/experimenter/experimenter/settings.py @@ -14,11 +14,9 @@ import os from importlib import resources from urllib.parse import urljoin -import sentry_sdk from decouple import config from django.contrib.admin import ModelAdmin, StackedInline, TabularInline from django.db.models import DecimalField, ForeignKey, JSONField, ManyToManyField -from sentry_sdk.integrations.django import DjangoIntegration for cls in [ DecimalField, @@ -230,11 +228,13 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "media") MEDIA_URL = "/media/" -LOGGING_CONSOLE_LEVEL = config("LOGGING_CONSOLE_LEVEL", default="DEBUG") +LOGGING_CONSOLE_LEVEL = config("LOGGING_CONSOLE_LEVEL", default="DEBUG") # Legacy env var +LOG_LEVEL = config("LOG_LEVEL", default=LOGGING_CONSOLE_LEVEL) # Logging -LOGGING_USE_JSON = config("LOGGING_USE_JSON", cast=bool, default=True) +_logging_use_json = config("LOGGING_USE_JSON", cast=bool, default=True) # Legacy env var +LOG_FORMAT = config("LOG_FORMAT", default="mozlog" if _logging_use_json else "text") LOGGING = { "version": 1, @@ -244,13 +244,13 @@ LOGGING = { "()": "dockerflow.logging.JsonLogFormatter", "logger_name": "experimenter", }, - "verbose": {"format": "%(levelname)s %(asctime)s %(name)s %(message)s"}, + "text": {"format": "%(levelname)s %(asctime)s %(name)s %(message)s"}, }, "handlers": { "console": { - "level": LOGGING_CONSOLE_LEVEL, + "level": LOG_LEVEL, "class": "logging.StreamHandler", - "formatter": "mozlog" if LOGGING_USE_JSON else "verbose", + "formatter": LOG_FORMAT, } }, "loggers": { @@ -271,19 +271,8 @@ LOGGING = { # Sentry configuration SENTRY_DSN = config("SENTRY_DSN", default=None) +SENTRY_ENV = config("SENTRY_ENV", default=None) SENTRY_DSN_NIMBUS_UI = SENTRY_DSN -if SENTRY_DSN: # pragma: no cover - sentry_sdk.init( - dsn=SENTRY_DSN, - integrations=[DjangoIntegration()], - # Set traces_sample_rate to 1.0 to capture 100% - # of transactions for performance monitoring. - # We recommend adjusting this value in production. - traces_sample_rate=1.0, - # If you wish to associate users to errors (assuming you are using - # django.contrib.auth) you may enable sending PII data. - send_default_pii=False, - ) # Django Rest Framework Configuration