diff --git a/.gitignore b/.gitignore index 29cb72ad9..91226854d 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ latest.dump /node_modules yarn-debug.log* .yarn-integrity +.env # Ignore storybook static site generation app/javascript/storybook-static/ diff --git a/.gitpod.yml b/.gitpod.yml index 7365367ba..6376f0fcb 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -21,7 +21,7 @@ tasks: redis-server & /home/gitpod/elasticsearch-7.5.2/bin/elasticsearch & init: > - cp config/sample_application.yml config/application.yml && + cp config/.env_sample .env && gem install solargraph && bin/setup command: > diff --git a/.travis.yml b/.travis.yml index 4324b254b..1caee957b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,6 @@ env: # Dummy values needed to verify the app boots via "rails runner" - APP_PROTOCOL=http:// - APP_DOMAIN=localhost:3000 - - SENDGRID_USERNAME_ACCEL=dummy - - SENDGRID_PASSWORD_ACCEL=dummy - HEROKU_APP_URL=practicaldev.herokuapp.com - SECRET_KEY_BASE=dummydummydummy - GITHUB_KEY=dummy @@ -45,6 +43,7 @@ install: true script: - date --rfc-3339=seconds - nvm install + - cp config/.env_sample .env - pkill -9 -f elasticsearch || true - curl -s -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.5.2-amd64.deb - sudo dpkg -i --force-confnew elasticsearch-7.5.2-amd64.deb diff --git a/Envfile b/Envfile deleted file mode 100644 index 92bc254cd..000000000 --- a/Envfile +++ /dev/null @@ -1,177 +0,0 @@ -# Most of the things are optional. If you need to use a -# custom key, please create an application.yml for it - -enable_defaults! { ENV["RACK_ENV"] != "production" } - -################################################ -############## Basic configuration ############# -################################################ - -# App domain + Protocol setting for development -variable :APP_DOMAIN, :String, default: "localhost:3000" -variable :APP_PROTOCOL, :String, default: "http://" - -# Community Related Variables -variable :COMMUNITY_COPYRIGHT_START_YEAR, :String, default: "2016" -variable :COMMUNITY_NAME, :String, default: "DEV(local)" - -# Email related variables -variable :DEFAULT_EMAIL, :String, default: "yo@dev.to" - -# Service timeout length -variable :RACK_TIMEOUT_WAIT_TIMEOUT, :Integer, default: 100_000 -variable :RACK_TIMEOUT_SERVICE_TIMEOUT, :Integer, default: 100_000 - -# Heroku release slug used to bust caches on deploys -variable :HEROKU_SLUG_COMMIT, :String, default: "Optional" - -# Redis caching storage -variable :REDIS_URL, :String, default: "redis://localhost:6379" - -# Redis sessions storage -variable :REDIS_SESSIONS_URL, :String, default: "redis://localhost:6379" -variable :SESSION_KEY, :String, default: "_Dev_Community_Session" -variable :SESSION_EXPIRY_SECONDS, :Integer, default: 1209600 # two weeks in seconds - -# Redis Sidekiq storage -variable :REDIS_SIDEKIQ_URL, :String, default: "redis://localhost:6379" - -# Elasticsearch -variable :ELASTICSEARCH_URL, :String, default: "http://localhost:9200" - -# SSL config -variable :FORCE_SSL_IN_RAILS, :String, default: "not applicable in dev" - -################################################ -############## 3rd Party Services ############## -################################################ - -# It's best if you have the following configured -# for more development experience - -# GitHub -# (https://developer.github.com/v3/guides/basics-of-authentication/) -variable :GITHUB_KEY, :String, default: "" -variable :GITHUB_SECRET, :String, default: "" - -# Twitter -# (https://developer.twitter.com/en/docs/basics/authentication/oauth-2-0/application-only) -variable :TWITTER_KEY, :String, default: "" -variable :TWITTER_SECRET, :String, default: "" - -################################################ -######### Optional 3rd Party Services ########## -################################################ - -# Honeybadger for error tracking -# (https://docs.honeybadger.io/lib/ruby/getting-started/introduction.html) -variable :HONEYBADGER_API_KEY, :String, default: "Optional" -variable :HONEYBADGER_JS_API_KEY, :String, default: "Optional" - -# AWS for images storages -variable :AWS_ID, :String, default: "Optional" -variable :AWS_SECRET, :String, default: "Optional" -variable :AWS_BUCKET_NAME, :String, default: "Optional" -variable :AWS_UPLOAD_REGION, :String, default: "" - -# AWS SDK -# (https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html) -variable :AWS_DEFAULT_REGION, :String, default: "us-east-1" -variable :AWS_SDK_KEY, :String, default: "Optional" -variable :AWS_SDK_SECRET, :String, default: "Optional" - -# AWS for video storage -variable :AWS_S3_INPUT_BUCKET, :String, default: "Optional" -variable :AWS_S3_VIDEO_ID, :String, default: "Optional" -variable :AWS_S3_VIDEO_KEY, :String, default: "Optional" - -# Buffer for sending to buffer -# (https://buffer.com/developers/api) -variable :BUFFER_ACCESS_TOKEN, :String, default: "Optional" -variable :BUFFER_FACEBOOK_ID, :String, default: "Optional" -variable :BUFFER_LINKEDIN_ID, :String, default: "Optional" -variable :BUFFER_PROFILE_ID, :Integer, default: 0 -variable :BUFFER_TWITTER_ID, :String, default: "Optional" -variable :BUFFER_LISTINGS_PROFILE, :String, default: "Optional" - -# Cloudinary for image resizing and cache?? -# (https://cloudinary.com/documentation/rails_integration) -variable :CLOUDINARY_API_KEY, :String, default: "Optional" -variable :CLOUDINARY_API_SECRET, :String, default: "Optional" -variable :CLOUDINARY_CLOUD_NAME, :String, default: "Optional" -variable :CLOUDINARY_SECURE, :String, default: "Optional" - -# HTML/CSS to Image for generating social preview images -# (https://docs.htmlcsstoimage.com/example-code/ruby) -variable :HCTI_API_USER_ID, :String, default: "Optional" -variable :HCTI_API_KEY, :String, default: "Optional" - -# Fastly for edge caching -# (https://docs.fastly.com/api/) -variable :FASTLY_API_KEY, :String, default: "" -variable :FASTLY_SERVICE_ID, :String, default: "" - -# Honeycomb for monitoring and observability -# (https://www.honeycomb.io/) -variable :HONEYCOMB_API_KEY, :String, default: "" - -# Google analytic -# (https://developers.google.com/analytics/devguides/reporting/core/v4) -variable :GA_TRACKING_ID, :String, default: "Optional" - -# Mailchimp for mails -# (https://mailchimp.com/developer/) -variable :MAILCHIMP_API_KEY, :String, default: "Optional-valid" - -# Pusher for DEV Connect/notfications -# (https://pusher.com/docs) -variable :PUSHER_APP_ID, :String, default: "Optional" -variable :PUSHER_CLUSTER, :String, default: "Optional" -variable :PUSHER_KEY, :String, default: "Optional" -variable :PUSHER_SECRET, :String, default: "Optional" -variable :PUSHER_BEAMS_ID, :String, default: "Optional" -variable :PUSHER_BEAMS_KEY, :String, default: "Optional" - -# Google recaptcha -# (https://developers.google.com/recaptcha/intro) -variable :RECAPTCHA_SECRET, :String, default: "Optional" -variable :RECAPTCHA_SITE, :String, default: "Optional" - -# Slack for customer alerts -# (https://api.slack.com/) -variable :SLACK_CHANNEL, :String, default: "" -variable :SLACK_DEPLOY_CHANNEL, :String, default: "" -variable :SLACK_WEBHOOK_URL, :String, default: "" - -# Stripe for payment system -# (https://stripe.com/docs/api) -variable :STRIPE_PUBLISHABLE_KEY, :String, default: "Optional" -variable :STRIPE_SECRET_KEY, :String, default: "Optional" - -# For video calling in DEV Connect -# (https://www.twilio.com/docs/video) -variable :TWILIO_ACCOUNT_SID, :String, default: "Optional" -variable :TWILIO_VIDEO_API_KEY, :String, default: "Optional" -variable :TWILIO_VIDEO_API_SECRET, :String, default: "Optional" - -# For Twitch live stream integration -# (https://dev.twitch.tv/docs) -variable :TWITCH_CLIENT_ID, :String, default: "Optional" -variable :TWITCH_CLIENT_SECRET, :String, default: "Optional" -variable :TWITCH_WEBHOOK_SECRET, :String, default: "Optional" - -# For calling the Stack Exchange API -# (https://api.stackexchange.com/docs) -variable :STACK_EXCHANGE_APP_KEY, :String, default: "" - -group :production do - variable :SECRET_KEY_BASE, :String - - # Sendgrid - # (https://sendgrid.com/docs/API_Reference/api_v3.html) - variable :SENDGRID_USERNAME_ACCEL, :String - variable :SENDGRID_PASSWORD_ACCEL, :String - - # Heroku - variable :HEROKU_APP_URL, :String # practicaldev.herokuapp.com -end diff --git a/Gemfile b/Gemfile index d13d6a840..f96607e65 100644 --- a/Gemfile +++ b/Gemfile @@ -36,7 +36,6 @@ gem "doorkeeper", "~> 5.4" # Oauth 2 provider gem "elasticsearch", "~> 7.8" # Powers DEVs core search functionality gem "email_validator", "~> 2.0" # Email validator for Rails and ActiveModel gem "emoji_regex", "~> 3.0" # A pair of Ruby regular expressions for matching Unicode Emoji symbols -gem "envied", "~> 0.9" # Ensure presence and type of your app's ENV-variables gem "faraday-http-cache", "~> 2.2" # Middleware to handle HTTP caching gem "fastly", "~> 2.5" # Client library for the Fastly acceleration system gem "feedjira", "~> 3.1" # A feed fetching and parsing library @@ -134,6 +133,7 @@ group :development, :test do gem "amazing_print", "~> 1.2" # Great Ruby debugging companion: pretty print Ruby objects to visualize their structure gem "bullet", "~> 6.1" # help to kill N+1 queries and unused eager loading gem "capybara", "~> 3.33" # Capybara is an integration testing tool for rack based web applications + gem "dotenv-rails", "~> 2.7.6" # For loading ENV variables locally gem "faker", "~> 2.13" # A library for generating fake data such as names, addresses, and phone numbers gem "knapsack_pro", "~> 2.1.1" # Help parallelize Ruby spec builds gem "pry-byebug", "~> 3.8" # Combine 'pry' with 'byebug'. Adds 'step', 'next', 'finish', 'continue' and 'break' commands to control execution diff --git a/Gemfile.lock b/Gemfile.lock index b6a03439f..3ea670838 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -252,6 +252,10 @@ GEM unf (>= 0.0.5, < 1.0.0) doorkeeper (5.4.0) railties (>= 5) + dotenv (2.7.6) + dotenv-rails (2.7.6) + dotenv (= 2.7.6) + railties (>= 3.2) elasticsearch (7.8.1) elasticsearch-api (= 7.8.1) elasticsearch-transport (= 7.8.1) @@ -267,8 +271,6 @@ GEM activemodel emoji_regex (3.0.0) enumerable-statistics (2.0.1) - envied (0.9.3) - thor (~> 0.15) environs (1.1.0) equalizer (0.0.11) erb_lint (0.0.35) @@ -878,10 +880,10 @@ DEPENDENCIES devise_invitable (~> 2.0.0) dogstatsd-ruby (~> 4.8) doorkeeper (~> 5.4) + dotenv-rails (~> 2.7.6) elasticsearch (~> 7.8) email_validator (~> 2.0) emoji_regex (~> 3.0) - envied (~> 0.9) erb_lint (~> 0.0.34) exifr (>= 1.3.6) factory_bot_rails (~> 6.1) diff --git a/app/views/admin/configs/show.html.erb b/app/views/admin/configs/show.html.erb index 967e2fdec..8ccdd51d5 100644 --- a/app/views/admin/configs/show.html.erb +++ b/app/views/admin/configs/show.html.erb @@ -884,13 +884,11 @@ - <% ENVied.config.variables.each do |v| %> - <% if v.group.in?(ENVied.required_groups) %> - - <%= v.name %> - <%= ApplicationConfig[v.name] %> - - <% end %> + <% ENV.sort.each do |key, value| %> + + <%= key %> + <%= value %> + <% end %> diff --git a/bin/setup b/bin/setup index 384ca0121..a4286a6fb 100755 --- a/bin/setup +++ b/bin/setup @@ -25,6 +25,10 @@ chdir APP_ROOT do # Install JavaScript dependencies if using Yarn system("bin/yarn") + # TEMPORARY @sre will remove before Sept 1, 2020 + puts "\n== Create .env File from application.yml ==" + system!("bin/rails create_dot_env_file") + puts "\n== Copying sample files ==" unless File.exist?("config/database.yml") cp "config/database.yml.sample", "config/database.yml" diff --git a/config/.env_sample b/config/.env_sample new file mode 100644 index 000000000..3f100f258 --- /dev/null +++ b/config/.env_sample @@ -0,0 +1,156 @@ +# App domain + Protocol setting for development +export APP_DOMAIN="localhost:3000" +export APP_PROTOCOL="http://" + +# Community Related Variables +export COMMUNITY_COPYRIGHT_START_YEAR="2016" +export COMMUNITY_NAME="DEV(local)" + +# Email related variables +export DEFAULT_EMAIL="yo@dev.to" + +# Service timeout length +export RACK_TIMEOUT_WAIT_TIMEOUT=100_000 +export RACK_TIMEOUT_SERVICE_TIMEOUT=100_000 + +# Heroku release slug used to bust caches on deploys +export HEROKU_SLUG_COMMIT="Optional" + +# Redis caching storage +export REDIS_URL="redis://localhost:6379" + +# Redis sessions storage +export REDIS_SESSIONS_URL="redis://localhost:6379" +export SESSION_KEY="_Dev_Community_Session" +export SESSION_EXPIRY_SECONDS=1209600 # two weeks in seconds + +# Redis Sidekiq storage +export REDIS_SIDEKIQ_URL="redis://localhost:6379" + +# Elasticsearch +export ELASTICSEARCH_URL="http://localhost:9200" + +# SSL config +export FORCE_SSL_IN_RAILS="not applicable in dev" + +################################################ +############## 3rd Party Services ############## +################################################ + +# It's best if you have the following configured +# for more development experience + +# GitHub +# (https://developer.github.com/v3/guides/basics-of-authentication/) +export GITHUB_KEY="" +export GITHUB_SECRET="" + +# Twitter +# (https://developer.twitter.com/en/docs/basics/authentication/oauth-2-0/application-only) +export TWITTER_KEY="" +export TWITTER_SECRET="" + +################################################ +######### Optional 3rd Party Services ########## +################################################ + +# Honeybadger for error tracking +# (https://docs.honeybadger.io/lib/ruby/getting-started/introduction.html) +export HONEYBADGER_API_KEY="Optional" +export HONEYBADGER_JS_API_KEY="Optional" + +# AWS for images storages +export AWS_ID="Optional" +export AWS_SECRET="Optional" +export AWS_BUCKET_NAME="Optional" +export AWS_UPLOAD_REGION="" + +# AWS SDK +# (https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html) +export AWS_DEFAULT_REGION="us-east-1" +export AWS_SDK_KEY="Optional" +export AWS_SDK_SECRET="Optional" + +# AWS for video storage +export AWS_S3_INPUT_BUCKET="Optional" +export AWS_S3_VIDEO_ID="Optional" +export AWS_S3_VIDEO_KEY="Optional" + +# Buffer for sending to buffer +# (https://buffer.com/developers/api) +export BUFFER_ACCESS_TOKEN="Optional" +export BUFFER_FACEBOOK_ID="Optional" +export BUFFER_LINKEDIN_ID="Optional" +export BUFFER_PROFILE_ID=0 +export BUFFER_TWITTER_ID="Optional" +export BUFFER_LISTINGS_PROFILE="Optional" + +# Cloudinary for image resizing and cache?? +# (https://cloudinary.com/documentation/rails_integration) +export CLOUDINARY_API_KEY="Optional" +export CLOUDINARY_API_SECRET="Optional" +export CLOUDINARY_CLOUD_NAME="Optional" +export CLOUDINARY_SECURE="Optional" + +# HTML/CSS to Image for generating social preview images +# (https://docs.htmlcsstoimage.com/example-code/ruby) +export HCTI_API_USER_ID="Optional" +export HCTI_API_KEY="Optional" + +# Fastly for edge caching +# (https://docs.fastly.com/api/) +export FASTLY_API_KEY="" +export FASTLY_SERVICE_ID="" + +# Honeycomb for monitoring and observability +# (https://www.honeycomb.io/) +export HONEYCOMB_API_KEY="" + +# Google analytic +# (https://developers.google.com/analytics/devguides/reporting/core/v4) +export GA_TRACKING_ID="Optional" + +# Mailchimp for mails +# (https://mailchimp.com/developer/) +export MAILCHIMP_API_KEY="Optional-valid" + +# Pusher for DEV Connect/notfications +# (https://pusher.com/docs) +export PUSHER_APP_ID= +export PUSHER_CLUSTER= +export PUSHER_KEY= +export PUSHER_SECRET= +export PUSHER_BEAMS_ID= +export PUSHER_BEAMS_KEY= + +# Google recaptcha +# (https://developers.google.com/recaptcha/intro) +export RECAPTCHA_SECRET="Optional" +export RECAPTCHA_SITE="Optional" + +# Slack for customer alerts +# (https://api.slack.com/) +export SLACK_CHANNEL="" +export SLACK_DEPLOY_CHANNEL="" +export SLACK_WEBHOOK_URL="" + +# Stripe for payment system +# (https://stripe.com/docs/api) +export STRIPE_PUBLISHABLE_KEY="Optional" +export STRIPE_SECRET_KEY="Optional" + +# For video calling in DEV Connect +# (https://www.twilio.com/docs/video) +export TWILIO_ACCOUNT_SID="Optional" +export TWILIO_VIDEO_API_KEY="Optional" +export TWILIO_VIDEO_API_SECRET="Optional" + +# For Twitch live stream integration +# (https://dev.twitch.tv/docs) +export TWITCH_CLIENT_ID="Optional" +export TWITCH_CLIENT_SECRET="Optional" +export TWITCH_WEBHOOK_SECRET="Optional" + +# For calling the Stack Exchange API +# (https://api.stackexchange.com/docs) +export STACK_EXCHANGE_APP_KEY="" diff --git a/config/application.rb b/config/application.rb index 6cfa51c4f..19bfdd8ae 100644 --- a/config/application.rb +++ b/config/application.rb @@ -17,6 +17,8 @@ require "sprockets/railtie" # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) +Dotenv::Railtie.load if Rails.env.test? || Rails.env.development? + module PracticalDeveloper class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. diff --git a/config/environments/production.rb b/config/environments/production.rb index 828346228..dacaf4b37 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -110,11 +110,12 @@ Rails.application.configure do # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - config.app_domain = ENV["APP_DOMAIN"] + config.app_domain = ENV["APP_DOMAIN"] || "localhost:3000" + protocol = ENV["APP_PROTOCOL"] || "http://" config.action_mailer.delivery_method = :smtp config.action_mailer.perform_deliveries = true - config.action_mailer.default_url_options = { host: ENV["APP_PROTOCOL"] + ENV["APP_DOMAIN"] } + config.action_mailer.default_url_options = { host: protocol + config.app_domain } ActionMailer::Base.smtp_settings = { address: "smtp.sendgrid.net", port: "587", @@ -125,14 +126,14 @@ Rails.application.configure do enable_starttls_auto: true } - if ENV["HEROKU_APP_URL"] != ENV["APP_DOMAIN"] + if ENV["HEROKU_APP_URL"] != config.app_domain config.middleware.use Rack::HostRedirect, - ENV["HEROKU_APP_URL"] => ENV["APP_DOMAIN"] + ENV["HEROKU_APP_URL"] => config.app_domain end end # rubocop:enable Metrics/BlockLength Rails.application.routes.default_url_options = { host: Rails.application.config.app_domain, - protocol: ENV["APP_PROTOCOL"].delete_suffix("://") + protocol: (ENV["APP_PROTOCOL"] || "http://").delete_suffix("://") } diff --git a/config/initializers/0_application_config.rb b/config/initializers/0_application_config.rb index 154af296f..d7e5d698e 100644 --- a/config/initializers/0_application_config.rb +++ b/config/initializers/0_application_config.rb @@ -1,15 +1,19 @@ -ENVied.require(*ENV["ENVIED_GROUPS"] || Rails.groups) - class ApplicationConfig URI_REGEXP = %r{(?https?://)?(?.+?)(?:\d+)?$}.freeze def self.[](key) - ENVied.public_send(key) + if ENV.key?(key) + ENV[key] + else + Rails.logger.warn("Unset ENV variable: #{key}.") + nil + end end def self.app_domain_no_port app_domain = self["APP_DOMAIN"] - match = app_domain.match(URI_REGEXP) - match[:host] + return unless app_domain + + app_domain.match(URI_REGEXP)[:host] end end diff --git a/config/initializers/aws_sdk.rb b/config/initializers/aws_sdk.rb index 4460eb360..05218d72f 100644 --- a/config/initializers/aws_sdk.rb +++ b/config/initializers/aws_sdk.rb @@ -1,5 +1,5 @@ Rails.application.reloader.to_prepare do - AWS_LAMBDA = if Rails.env.production? + AWS_LAMBDA = if Rails.env.production? && ApplicationConfig["AWS_SDK_KEY"].present? Aws::Lambda::Client.new( region: ApplicationConfig["AWS_DEFAULT_REGION"], access_key_id: ApplicationConfig["AWS_SDK_KEY"], diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index ec320e910..132f71daa 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -27,7 +27,7 @@ CarrierWave.configure do |config| } config.asset_host = "https://#{ApplicationConfig['APP_DOMAIN']}/images" config.fog_public = false - else + elsif ApplicationConfig["AWS_ID"].present? region = ApplicationConfig["AWS_UPLOAD_REGION"].presence || ApplicationConfig["AWS_DEFAULT_REGION"] config.fog_credentials = { provider: "AWS", @@ -35,6 +35,10 @@ CarrierWave.configure do |config| aws_secret_access_key: ApplicationConfig["AWS_SECRET"], region: region } + else + # Fallback on file storage if AWS creds are not present + config.asset_host = "https://#{ApplicationConfig['APP_DOMAIN']}/images" + config.storage = :file end config.fog_directory = ApplicationConfig["AWS_BUCKET_NAME"] config.storage = :fog diff --git a/config/initializers/pusher.rb b/config/initializers/pusher.rb index 47a2e7858..7b0dfbf9a 100644 --- a/config/initializers/pusher.rb +++ b/config/initializers/pusher.rb @@ -1,13 +1,15 @@ require "pusher/push_notifications" -Pusher.app_id = ApplicationConfig["PUSHER_APP_ID"] -Pusher.key = ApplicationConfig["PUSHER_KEY"] -Pusher.secret = ApplicationConfig["PUSHER_SECRET"] -Pusher.cluster = ApplicationConfig["PUSHER_CLUSTER"] -Pusher.logger = Rails.logger -Pusher.encrypted = true +if ApplicationConfig["PUSHER_APP_ID"].present? + Pusher.app_id = ApplicationConfig["PUSHER_APP_ID"] + Pusher.key = ApplicationConfig["PUSHER_KEY"] + Pusher.secret = ApplicationConfig["PUSHER_SECRET"] + Pusher.cluster = ApplicationConfig["PUSHER_CLUSTER"] + Pusher.logger = Rails.logger + Pusher.encrypted = true -Pusher::PushNotifications.configure do |config| - config.instance_id = ApplicationConfig["PUSHER_BEAMS_ID"] - config.secret_key = ApplicationConfig["PUSHER_BEAMS_KEY"] + Pusher::PushNotifications.configure do |config| + config.instance_id = ApplicationConfig["PUSHER_BEAMS_ID"] + config.secret_key = ApplicationConfig["PUSHER_BEAMS_KEY"] + end end diff --git a/config/initializers/slack_notifier.rb b/config/initializers/slack_notifier.rb index 7bda893d0..be6a289f8 100644 --- a/config/initializers/slack_notifier.rb +++ b/config/initializers/slack_notifier.rb @@ -4,14 +4,6 @@ class NoOpHTTPClient end end -def create_normal_notifier - Slack::Notifier.new( - ApplicationConfig["SLACK_WEBHOOK_URL"], - channel: ApplicationConfig["SLACK_CHANNEL"], - username: "activity_bot", - ) -end - def create_test_channel_notifier return create_stubbed_notifier if ApplicationConfig["SLACK_WEBHOOK_URL"].blank? @@ -41,7 +33,7 @@ def init_slack_client } end - webhook_url = ApplicationConfig["SLACK_WEBHOOK_URL"] + webhook_url = ApplicationConfig["SLACK_WEBHOOK_URL"] || "" use_no_op_client = Rails.env.test? || webhook_url.blank? Slack::Notifier.new(webhook_url) do diff --git a/config/sample_application.yml b/config/sample_application.yml index 32b00715e..c94c2f6ce 100644 --- a/config/sample_application.yml +++ b/config/sample_application.yml @@ -1,14 +1,156 @@ -GITHUB_KEY: -GITHUB_SECRET: +# App domain + Protocol setting for development +APP_DOMAIN: "localhost:3000" +APP_PROTOCOL: "http://" -TWITTER_KEY: -TWITTER_SECRET: +# Community Related Variables +COMMUNITY_COPYRIGHT_START_YEAR: "2016" +COMMUNITY_NAME: "DEV(local)" -PUSHER_APP_ID: -PUSHER_KEY: -PUSHER_SECRET: -PUSHER_CLUSTER: +# Email related variables +DEFAULT_EMAIL: "yo@dev.to" -TWITCH_CLIENT_ID: -TWITCH_CLIENT_SECRET: -TWITCH_WEBHOOK_SECRET: +# Service timeout length +RACK_TIMEOUT_WAIT_TIMEOUT: 100_000 +RACK_TIMEOUT_SERVICE_TIMEOUT: 100_000 + +# Heroku release slug used to bust caches on deploys +HEROKU_SLUG_COMMIT: "Optional" + +# Redis caching storage +REDIS_URL: "redis://localhost:6379" + +# Redis sessions storage +REDIS_SESSIONS_URL: "redis://localhost:6379" +SESSION_KEY: "_Dev_Community_Session" +SESSION_EXPIRY_SECONDS: 1209600 # two weeks in seconds + +# Redis Sidekiq storage +REDIS_SIDEKIQ_URL: "redis://localhost:6379" + +# Elasticsearch +ELASTICSEARCH_URL: "http://localhost:9200" + +# SSL config +FORCE_SSL_IN_RAILS: "not applicable in dev" + +################################################ +############## 3rd Party Services ############## +################################################ + +# It's best if you have the following configured +# for more development experience + +# GitHub +# (https://developer.github.com/v3/guides/basics-of-authentication/) +GITHUB_KEY: "" +GITHUB_SECRET: "" + +# Twitter +# (https://developer.twitter.com/en/docs/basics/authentication/oauth-2-0/application-only) +TWITTER_KEY: "" +TWITTER_SECRET: "" + +################################################ +######### Optional 3rd Party Services ########## +################################################ + +# Honeybadger for error tracking +# (https://docs.honeybadger.io/lib/ruby/getting-started/introduction.html) +HONEYBADGER_API_KEY: "Optional" +HONEYBADGER_JS_API_KEY: "Optional" + +# AWS for images storages +AWS_ID: "Optional" +AWS_SECRET: "Optional" +AWS_BUCKET_NAME: "Optional" +AWS_UPLOAD_REGION: "" + +# AWS SDK +# (https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html) +AWS_DEFAULT_REGION: "us-east-1" +AWS_SDK_KEY: "Optional" +AWS_SDK_SECRET: "Optional" + +# AWS for video storage +AWS_S3_INPUT_BUCKET: "Optional" +AWS_S3_VIDEO_ID: "Optional" +AWS_S3_VIDEO_KEY: "Optional" + +# Buffer for sending to buffer +# (https://buffer.com/developers/api) +BUFFER_ACCESS_TOKEN: "Optional" +BUFFER_FACEBOOK_ID: "Optional" +BUFFER_LINKEDIN_ID: "Optional" +BUFFER_PROFILE_ID: 0 +BUFFER_TWITTER_ID: "Optional" +BUFFER_LISTINGS_PROFILE: "Optional" + +# Cloudinary for image resizing and cache?? +# (https://cloudinary.com/documentation/rails_integration) +CLOUDINARY_API_KEY: "Optional" +CLOUDINARY_API_SECRET: "Optional" +CLOUDINARY_CLOUD_NAME: "Optional" +CLOUDINARY_SECURE: "Optional" + +# HTML/CSS to Image for generating social preview images +# (https://docs.htmlcsstoimage.com/example-code/ruby) +HCTI_API_USER_ID: "Optional" +HCTI_API_KEY: "Optional" + +# Fastly for edge caching +# (https://docs.fastly.com/api/) +FASTLY_API_KEY: "" +FASTLY_SERVICE_ID: "" + +# Honeycomb for monitoring and observability +# (https://www.honeycomb.io/) +HONEYCOMB_API_KEY: "" + +# Google analytic +# (https://developers.google.com/analytics/devguides/reporting/core/v4) +GA_TRACKING_ID: "Optional" + +# Mailchimp for mails +# (https://mailchimp.com/developer/) +MAILCHIMP_API_KEY: "Optional-valid" + +# Pusher for DEV Connect/notfications +# (https://pusher.com/docs) +PUSHER_APP_ID: "Optional" +PUSHER_CLUSTER: "Optional" +PUSHER_KEY: "Optional" +PUSHER_SECRET: "Optional" +PUSHER_BEAMS_ID: "Optional" +PUSHER_BEAMS_KEY: "Optional" + +# Google recaptcha +# (https://developers.google.com/recaptcha/intro) +RECAPTCHA_SECRET: "Optional" +RECAPTCHA_SITE: "Optional" + +# Slack for customer alerts +# (https://api.slack.com/) +SLACK_CHANNEL: "" +SLACK_DEPLOY_CHANNEL: "" +SLACK_WEBHOOK_URL: "" + +# Stripe for payment system +# (https://stripe.com/docs/api) +STRIPE_PUBLISHABLE_KEY: "Optional" +STRIPE_SECRET_KEY: "Optional" + +# For video calling in DEV Connect +# (https://www.twilio.com/docs/video) +TWILIO_ACCOUNT_SID: "Optional" +TWILIO_VIDEO_API_KEY: "Optional" +TWILIO_VIDEO_API_SECRET: "Optional" + +# For Twitch live stream integration +# (https://dev.twitch.tv/docs) +TWITCH_CLIENT_ID: "Optional" +TWITCH_CLIENT_SECRET: "Optional" +TWITCH_WEBHOOK_SECRET: "Optional" + +# For calling the Stack Exchange API +# (https://api.stackexchange.com/docs) +STACK_EXCHANGE_APP_KEY: "" diff --git a/docs/backend/configuration.md b/docs/backend/configuration.md index 4d15fcc42..5f25d802b 100644 --- a/docs/backend/configuration.md +++ b/docs/backend/configuration.md @@ -6,21 +6,20 @@ title: Configuration We currently use the following gems for configuring the application: -- [ENVied](https://github.com/eval/envied) +- [dotenv](https://github.com/bkeepers/dotenv) - [rails-settings-cached](https://github.com/huacnlee/rails-settings-cached) - [vault](https://github.com/hashicorp/vault-ruby) -## ENVied +## dotenv -This gem is primarily used for configuring environment variables related to -credentials and third party services. Examples: +This gem is used for configuring environment variables for test and development +environments. Examples: - `REDIS_URL` - `FASTLY_API_KEY` - `STRIPE_SECRET_KEY` -Settings managed via ENVied can be found in -[`Envfile`](https://github.com/forem/forem/blob/master/Envfile) (see +Settings managed via your ENV can be found in [Configuring Environment Variables](../getting-started/config-env.md)) and viewed at `/admin/config` (see [the Admin guide](../admin/readme.md)): diff --git a/docs/faqs.md b/docs/faqs.md index bb19ce99f..f65c2e099 100644 --- a/docs/faqs.md +++ b/docs/faqs.md @@ -20,8 +20,8 @@ By default Rails logs to `log.development.log`. If, instead, you wish to log to `STDOUT` you can add the variable: -```yaml -RAILS_LOG_TO_STDOUT: true +```shell +export RAILS_LOG_TO_STDOUT=true ``` -to your own `config/application.yml` file. +to your own `.env` file. diff --git a/docs/getting-started/config-env.md b/docs/getting-started/config-env.md index 2a2027e14..d7e34ec6b 100644 --- a/docs/getting-started/config-env.md +++ b/docs/getting-started/config-env.md @@ -10,27 +10,27 @@ provides a fake default for any missing keys. The [backend guide][backend_guide] will show you how to get free API keys for additional services that may be required to run certain parts of the app. -To set up keys for your local instance of Forem, you'll need to create an -`application.yml` file. You can do this by copying the file called -`sample_application.yml` in the `config` directory: +To set up keys for your local instance of Forem, you'll need to create an `.env` +file. You can do this by copying the file called `.env_sample` in the `config` +directory: ```shell -cp config/sample_application.yml config/application.yml +cp config/.env_sample .env ``` -Then, add each key you need to the `application.yml` file. For example, if -you're setting up GitHub authentication: +Then, add each key you need to the `.env` file. For example, if you're setting +up GitHub authentication: ```shell -GITHUB_KEY: "SOME_REAL_SECURE_KEY_HERE" -GITHUB_SECRET: "ANOTHER_REAL_SECURE_KEY_HERE" +export GITHUB_KEY="SOME_REAL_SECURE_KEY_HERE" +export GITHUB_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" ``` -(Don't worry, your `application.yml` file is ignored by git) +(Don't worry, your `.env` file is ignored by git) -If you are missing `ENV` variables on bootup, the [envied][envied] gem will -alert you with messages similar to -`'error_on_missing_variables!': The following environment variables should be set: A_MISSING_KEY.`. +If you are missing `ENV` variables when you boot your application you will see a +warning message in your logs when you try to access that variable +`Unset ENV variable: xyz`. Only certain features require "real" keys, so you may be able to add them as you work on different areas of the application. diff --git a/docs/installation/containers.md b/docs/installation/containers.md index 36f8defd4..5ca6283ff 100644 --- a/docs/installation/containers.md +++ b/docs/installation/containers.md @@ -67,16 +67,15 @@ with Podman. You can install it by following these additional services that may be required to run certain parts of the app. - For any key that you wish to enter/replace: - 1. Create `config/application.yml` by copying from the provided template - (i.e. with bash: - `cp config/sample_application.yml config/application.yml`). This is a - personal file that is ignored in git. + 1. Create `.env` by copying from the provided template (i.e. with bash: + `cp config/.env_sample .env`). This is a personal file that is ignored + in git. 1. Obtain the development variable and apply the key you wish to enter/replace. i.e.: ```shell - GITHUB_KEY: "SOME_REAL_SECURE_KEY_HERE" - GITHUB_SECRET: "ANOTHER_REAL_SECURE_KEY_HERE" + export GITHUB_KEY="SOME_REAL_SECURE_KEY_HERE" + export GITHUB_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" ``` - You do not need "real" keys for basic development. Some features require diff --git a/docs/installation/linux.md b/docs/installation/linux.md index 357f0539e..171e37466 100644 --- a/docs/installation/linux.md +++ b/docs/installation/linux.md @@ -97,16 +97,15 @@ NOTE: Make sure to download **the OSS version**, `elasticsearch-oss`. additional services that may be required to run certain parts of the app. - For any key that you wish to enter/replace: - 1. Create `config/application.yml` by copying from the provided template - (i.e. with bash: - `cp config/sample_application.yml config/application.yml`). This is a - personal file that is ignored in git. + 1. Create `.env` by copying from the provided template (i.e. with bash: + `cp config/.env_sample .env`). This is a personal file that is ignored + in git. 1. Obtain the development variable and apply the key you wish to enter/replace. i.e.: ```shell - GITHUB_KEY: "SOME_REAL_SECURE_KEY_HERE" - GITHUB_SECRET: "ANOTHER_REAL_SECURE_KEY_HERE" + export GITHUB_KEY="SOME_REAL_SECURE_KEY_HERE" + export GITHUB_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" ``` - If you are missing `ENV` variables on bootup, the diff --git a/docs/installation/mac.md b/docs/installation/mac.md index 9d1abce07..b3442abeb 100644 --- a/docs/installation/mac.md +++ b/docs/installation/mac.md @@ -217,16 +217,15 @@ your local Elasticsearch installation, for example: additional services that may be required to run certain parts of the app. - For any key that you wish to enter/replace, follow the steps below. - 1. Create `config/application.yml` by copying from the provided template - (i.e. with bash: - `cp config/sample_application.yml config/application.yml`). This is a - personal file that is ignored in git. + 1. Create `.env` by copying from the provided template (i.e. with bash: + `cp config/.env_sample .env`). This is a personal file that is ignored + in git. 2. Obtain the development variable and apply the key you wish to enter/replace. i.e.: ```shell - GITHUB_KEY: "SOME_REAL_SECURE_KEY_HERE" - GITHUB_SECRET: "ANOTHER_REAL_SECURE_KEY_HERE" + export GITHUB_KEY="SOME_REAL_SECURE_KEY_HERE" + export GITHUB_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" ``` - If you are missing `ENV` variables on bootup, the diff --git a/docs/installation/postgresql.md b/docs/installation/postgresql.md index 8a475107b..2bd9ccce2 100644 --- a/docs/installation/postgresql.md +++ b/docs/installation/postgresql.md @@ -32,17 +32,17 @@ The go into depth on how Rails merges the existing `database.yml` with the connection string. -### Setup `DATABASE_URL` in application.yml +### Setup `DATABASE_URL` in .env -1. Open your `config/application.yml` +1. Open your `.env` 1. Add the following: -```yml -DATABASE_URL: postgresql://USERNAME:PASSWORD@localhost +```shell +export DATABASE_URL=postgresql://USERNAME:PASSWORD@localhost # Optional: If your test database is in a different url, be sure to set this. -DATABASE_URL_TEST: postgresql://USERNAME:PASSWORD@localhost +export DATABASE_URL_TEST=postgresql://USERNAME:PASSWORD@localhost ``` 1. Replace `USERNAME` with your database username, `PASSWORD` with your database diff --git a/docs/installation/vault.md b/docs/installation/vault.md index 6e0f34e30..7a565af3b 100644 --- a/docs/installation/vault.md +++ b/docs/installation/vault.md @@ -99,11 +99,11 @@ The final command will give you the following output: The `token` output from above is what you will use in your application to access Vault. All that is left to do is set the appropriate ENV variables in your -`application.yml` file. +`.env` file. -```yml -VAULT_TOKEN: important-policy-token -VAULT_SECRET_NAMESPACE: +```shell +export VAULT_TOKEN=important-policy-token export VAULT_SECRET_NAMESPACE= ``` Restart your application to start using Vault. One easy way to see it in action diff --git a/docs/installation/windows.md b/docs/installation/windows.md index 5e6bb4749..d6c0b7b2f 100644 --- a/docs/installation/windows.md +++ b/docs/installation/windows.md @@ -254,16 +254,15 @@ To install Elasticsearch perform the following steps: additional services that may be required to run certain parts of the app. - For any key that you wish to enter/replace: - 1. Create `config/application.yml` by copying from the provided template - (ie. with bash: - `cp config/sample_application.yml config/application.yml`). This is a - personal file that is ignored in git. + 1. Create `.env` by copying from the provided template (ie. with bash: + `cp config/.env_sample .env`). This is a personal file that is ignored + in git. 1. Obtain the development variable and apply the key you wish to enter/replace. ie: ```shell - GITHUB_KEY: "SOME_REAL_SECURE_KEY_HERE" - GITHUB_SECRET: "ANOTHER_REAL_SECURE_KEY_HERE" + export GITHUB_KEY="SOME_REAL_SECURE_KEY_HERE" + export GITHUB_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" ``` - If you are missing `ENV` variables on bootup, the @@ -329,8 +328,7 @@ There are currently two work-arounds. 1. `docker run -d --name selenium-hub -p 4444:4444 selenium/hub:3.141.59-20200409` 2. `CH=$(docker run --rm --name=ch --link selenium-hub:hub -v /dev/shm:/dev/shm selenium/node-chrome:3.141.59-20200409)` - 3. Add `SELENIUM_URL: "http://localhost:4444/wd/hub"` to your - `application.yml` + 3. Add `export SELENIUM_URL="http://localhost:4444/wd/hub"` to your `.env` 4. Run your System test! 2. Port forward with `socats` (more info needed). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 49c4829c3..60c1700cb 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -96,8 +96,8 @@ refer to ## CORS If you are experiencing CORS issues locally or need to display more information -about the CORS headers, add the following variable to your `application.yml`: +about the CORS headers, add the following variable to your `.env`: -```yml -DEBUG_CORS: true +```shell +export DEBUG_CORS=true ``` diff --git a/lib/tasks/temporary/env_variables.rake b/lib/tasks/temporary/env_variables.rake new file mode 100644 index 000000000..d14dfcc83 --- /dev/null +++ b/lib/tasks/temporary/env_variables.rake @@ -0,0 +1,18 @@ +# Create a .env file from your application.yml file +task create_dot_env_file: :environment do + exit unless File.file?("config/application.yml") + + File.open(".env", "w") do |env_file| + File.open("config/application.yml", 'r') do |file| + file.each_line do |line| + new_line = line.gsub(": ", "=") + unless new_line.blank? || new_line.starts_with?("#") + new_line.prepend("export ") + end + env_file.write(new_line) + end + end + end + + File.delete("config/application.yml") +end diff --git a/spec/initializers/application_config_spec.rb b/spec/initializers/application_config_spec.rb index 6a7829d5f..3c216b61c 100644 --- a/spec/initializers/application_config_spec.rb +++ b/spec/initializers/application_config_spec.rb @@ -1,6 +1,12 @@ require "rails_helper" describe ApplicationConfig do + it "logs warning if key is not found" do + allow(Rails.logger).to receive(:warn) + described_class["missing"] + expect(Rails.logger).to have_received(:warn).with("Unset ENV variable: missing.") + end + describe ".app_domain_no_port" do it "handles plain subdomain only name" do setup_app_domain("renner") diff --git a/vendor/cache/dotenv-2.7.6.gem b/vendor/cache/dotenv-2.7.6.gem new file mode 100644 index 000000000..c3a414727 Binary files /dev/null and b/vendor/cache/dotenv-2.7.6.gem differ diff --git a/vendor/cache/dotenv-rails-2.7.6.gem b/vendor/cache/dotenv-rails-2.7.6.gem new file mode 100644 index 000000000..8f292af2b Binary files /dev/null and b/vendor/cache/dotenv-rails-2.7.6.gem differ diff --git a/vendor/cache/envied-0.9.3.gem b/vendor/cache/envied-0.9.3.gem deleted file mode 100644 index 6e33088ae..000000000 Binary files a/vendor/cache/envied-0.9.3.gem and /dev/null differ