diff --git a/README.md b/README.md index 82c95f1..0478e68 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ config.middleware.use Shimmer::CloudflareProxy Can't reproduce an issue with your local test data and just want the production or staging data on your development machine? Here you go: ```bash -rails db:pull +rails shimmer:db:pull ``` This will drop your local database and pull in the database of your connected Heroku app (make sure you executed `heroku git:remote -a your_app` before to have the git remote). But what about assets you might ask? Easy - assets are pulled from S3 as well via the AWS CLI automatically (make sure your environment variables in Heroku are correctly named as `AWS_REGION`, `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`) and the database is updated to use your local filesystem instead. @@ -256,8 +256,8 @@ This will drop your local database and pull in the database of your connected He If you don't want the asset support, you can also only pull the database or only the assets: ```bash -rails db:pull_data -rails db:pull_assets +rails shimmer:db:pull_data +rails shimmer:db:pull_assets ``` ### Localizable Routes with Browser Locale Support diff --git a/lib/shimmer/tasks/auth.rake b/lib/shimmer/tasks/auth.rake index 80d14b7..7e98134 100644 --- a/lib/shimmer/tasks/auth.rake +++ b/lib/shimmer/tasks/auth.rake @@ -1,19 +1,21 @@ # frozen_string_literal: true -namespace :auth do - desc "Generates a Sign in with Apple Token" - task :apple_token do - ecdsa_key = OpenSSL::PKey::EC.new IO.read ".apple-key.p8" - headers = { - "kid" => Shimmer::Config.instance.apple_key_id! - } - claims = { - "iss" => Shimmer::Config.instance.apple_team_id!, - "iat" => Time.now.to_i, - "exp" => 180.days.from_now.to_i, - "aud" => "https://appleid.apple.com", - "sub" => Shimmer::Config.instance.apple_bundle_id! - } - puts JWT.encode claims, ecdsa_key, "ES256", headers +namespace :shimmer do + namespace :auth do + desc "Generates a Sign in with Apple Token" + task :apple_token do + ecdsa_key = OpenSSL::PKey::EC.new IO.read ".apple-key.p8" + headers = { + "kid" => Shimmer::Config.instance.apple_key_id! + } + claims = { + "iss" => Shimmer::Config.instance.apple_team_id!, + "iat" => Time.now.to_i, + "exp" => 180.days.from_now.to_i, + "aud" => "https://appleid.apple.com", + "sub" => Shimmer::Config.instance.apple_bundle_id! + } + puts JWT.encode claims, ecdsa_key, "ES256", headers + end end end diff --git a/lib/shimmer/tasks/db.rake b/lib/shimmer/tasks/db.rake index b5e862f..279a517 100644 --- a/lib/shimmer/tasks/db.rake +++ b/lib/shimmer/tasks/db.rake @@ -1,55 +1,57 @@ # frozen_string_literal: true -namespace :db do - desc "Downloads the app database from Heroku and imports it to the local database" - task pull_data: :environment do - config = if Rails.version.to_f >= 7 - ActiveRecord::Base.connection_db_config.configuration_hash.with_indifferent_access - else - ActiveRecord::Base.connection_db_config.config +namespace :shimmer do + namespace :db do + desc "Downloads the app database from Heroku and imports it to the local database" + task pull_data: :environment do + config = if Rails.version.to_f >= 7 + ActiveRecord::Base.connection_db_config.configuration_hash.with_indifferent_access + else + ActiveRecord::Base.connection_db_config.config + end + ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] = "1" + Rake::Task["db:drop"].invoke + ENV["PGUSER"] = config["username"] + ENV["PGHOST"] = config["host"] + ENV["PGPORT"] = config["port"].to_s + sh "heroku pg:pull DATABASE_URL #{config["database"]}" + sh "rails db:environment:set" + sh "RAILS_ENV=test rails db:create" end - ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] = "1" - Rake::Task["db:drop"].invoke - ENV["PGUSER"] = config["username"] - ENV["PGHOST"] = config["host"] - ENV["PGPORT"] = config["port"].to_s - sh "heroku pg:pull DATABASE_URL #{config["database"]}" - sh "rails db:environment:set" - sh "RAILS_ENV=test rails db:create" - end - desc "Downloads the app assets from Heroku to directory `storage`." - task pull_assets: :environment do - config = JSON.parse(`heroku config --json`) - ENV["AWS_DEFAULT_REGION"] = config.fetch("AWS_REGION") - bucket = config.fetch("AWS_BUCKET") - ENV["AWS_ACCESS_KEY_ID"] = config.fetch("AWS_ACCESS_KEY_ID") - ENV["AWS_SECRET_ACCESS_KEY"] = config.fetch("AWS_SECRET_ACCESS_KEY") - storage_folder = Rails.root.join("storage") - download_folder = storage_folder.join("downloads") - FileUtils.mkdir_p download_folder - sh "aws s3 sync s3://#{bucket} #{storage_folder}/downloads" - download_folder.each_child do |file| - next if file.directory? + desc "Downloads the app assets from Heroku to directory `storage`." + task pull_assets: :environment do + config = JSON.parse(`heroku config --json`) + ENV["AWS_DEFAULT_REGION"] = config.fetch("AWS_REGION") + bucket = config.fetch("AWS_BUCKET") + ENV["AWS_ACCESS_KEY_ID"] = config.fetch("AWS_ACCESS_KEY_ID") + ENV["AWS_SECRET_ACCESS_KEY"] = config.fetch("AWS_SECRET_ACCESS_KEY") + storage_folder = Rails.root.join("storage") + download_folder = storage_folder.join("downloads") + FileUtils.mkdir_p download_folder + sh "aws s3 sync s3://#{bucket} #{storage_folder}/downloads" + download_folder.each_child do |file| + next if file.directory? - new_path = storage_folder.join file.basename.to_s.then { |e| [e[0..1], e[2..3], e] }.join("/") - FileUtils.mkdir_p(new_path.dirname) - FileUtils.cp(file, new_path) + new_path = storage_folder.join file.basename.to_s.then { |e| [e[0..1], e[2..3], e] }.join("/") + FileUtils.mkdir_p(new_path.dirname) + FileUtils.cp(file, new_path) + end + # purge variants + ActiveStorage::VariantRecord.delete_all + ActiveStorage::Blob.update_all(service_name: :local) end - # purge variants - ActiveStorage::VariantRecord.delete_all - ActiveStorage::Blob.update_all(service_name: :local) - end - desc "Download all app data, including assets" - task pull: [:pull_data, :pull_assets] + desc "Download all app data, including assets" + task pull: [:pull_data, :pull_assets] - desc "Migrates if the database has any tables." - task migrate_if_tables: :environment do - if ActiveRecord::Base.connection.tables.any? - Rake::Task["db:migrate"].invoke - else - puts "No tables in database yet, skipping migration" + desc "Migrates if the database has any tables." + task migrate_if_tables: :environment do + if ActiveRecord::Base.connection.tables.any? + Rake::Task["db:migrate"].invoke + else + puts "No tables in database yet, skipping migration" + end end end end diff --git a/lib/shimmer/tasks/lint.rake b/lib/shimmer/tasks/lint.rake index fe66d28..ffb503e 100644 --- a/lib/shimmer/tasks/lint.rake +++ b/lib/shimmer/tasks/lint.rake @@ -1,9 +1,11 @@ # frozen_string_literal: true desc "Executes all linters and tests" -task :lint do - sh "bundle exec standardrb --fix" - sh "yarn lint" - sh "i18n-tasks health" - sh "bin/rspec" +namespace :shimmer do + task :lint do + sh "bundle exec standardrb --fix" + sh "yarn lint" + sh "i18n-tasks health" + sh "bin/rspec" + end end diff --git a/lib/shimmer/tasks/s3.rake b/lib/shimmer/tasks/s3.rake index 5e6b6c8..cd6797f 100644 --- a/lib/shimmer/tasks/s3.rake +++ b/lib/shimmer/tasks/s3.rake @@ -1,46 +1,48 @@ # frozen_string_literal: true -namespace :s3 do - desc "Creates a new S3 bucket and outputs or uploads the credentials." - task :create_bucket do - puts "Please enter the name for your new bucket" - name = $stdin.gets.strip - region = "eu-central-1" - sh "aws s3 mb s3://#{name} --region #{region}" - sh "aws iam create-user --user-name #{name}" - policy = <<~JSON - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:CreateBucket", - "s3:DeleteObject", - "s3:Put*", - "s3:Get*", - "s3:List*" - ], - "Resource": [ - "arn:aws:s3:::#{name}", - "arn:aws:s3:::#{name}/*" - ] - } - ] - } - JSON - File.write("policy.json", policy) - sh "aws iam put-user-policy --user-name #{name} --policy-name #{name} --policy-document file://policy.json" - File.delete("policy.json") - content = JSON.parse `aws iam create-access-key --user-name #{name}` - id = content.dig("AccessKey", "AccessKeyId") - secret = content.dig("AccessKey", "SecretAccessKey") - puts "Credentials and bucket were generated. Automatically assign them to the associated Heroku project? This will override and delete all current keys on Heroku. (y/n)" - vars = {AWS_REGION: region, AWS_BUCKET: name, AWS_ACCESS_KEY_ID: id, AWS_SECRET_ACCESS_KEY: secret} - if $stdin.gets.strip == "y" - sh "heroku config:set #{vars.map { |k, v| "#{k}=#{v}" }.join(" ")}" - else - vars.each { |k, v| puts "#{k}=#{v}" } +namespace :shimmer do + namespace :s3 do + desc "Creates a new S3 bucket and outputs or uploads the credentials." + task :create_bucket do + puts "Please enter the name for your new bucket" + name = $stdin.gets.strip + region = "eu-central-1" + sh "aws s3 mb s3://#{name} --region #{region}" + sh "aws iam create-user --user-name #{name}" + policy = <<~JSON + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:CreateBucket", + "s3:DeleteObject", + "s3:Put*", + "s3:Get*", + "s3:List*" + ], + "Resource": [ + "arn:aws:s3:::#{name}", + "arn:aws:s3:::#{name}/*" + ] + } + ] + } + JSON + File.write("policy.json", policy) + sh "aws iam put-user-policy --user-name #{name} --policy-name #{name} --policy-document file://policy.json" + File.delete("policy.json") + content = JSON.parse `aws iam create-access-key --user-name #{name}` + id = content.dig("AccessKey", "AccessKeyId") + secret = content.dig("AccessKey", "SecretAccessKey") + puts "Credentials and bucket were generated. Automatically assign them to the associated Heroku project? This will override and delete all current keys on Heroku. (y/n)" + vars = {AWS_REGION: region, AWS_BUCKET: name, AWS_ACCESS_KEY_ID: id, AWS_SECRET_ACCESS_KEY: secret} + if $stdin.gets.strip == "y" + sh "heroku config:set #{vars.map { |k, v| "#{k}=#{v}" }.join(" ")}" + else + vars.each { |k, v| puts "#{k}=#{v}" } + end end end end