diff --git a/.Dockerfile.swp b/.Dockerfile.swp deleted file mode 100644 index 139f124..0000000 Binary files a/.Dockerfile.swp and /dev/null differ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5aa4814..d8d150f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,38 +25,16 @@ jobs: docker-compose run -e APP_ENV=test --rm app bundle exec rspec build: - runs-on: ubuntu-latest + name: Publish image + runs-on: ubuntu-22.04 + needs: test steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Extract repo name - shell: bash - run: echo "##[set-output name=repo_name;]$(echo ${GITHUB_REPOSITORY} | sed "s/.*\///g" | sed "s/-docker$//")" - id: extract_repo_name - - name: Docker meta - id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 - with: - images: public.ecr.aws/citizensadvice/${{ steps.extract_repo_name.outputs.repo_name }} - tag-sha: true - - name: Login to AWS Elastic Container Registry - uses: docker/login-action@v1 - with: - registry: public.ecr.aws - username: ${{ secrets.PUBLIC_PUSH_ECR_AWS_KEY }} - password: ${{ secrets.PUBLIC_PUSH_ECR_AWS_SECRET }} - env: - AWS_REGION: us-east-1 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Build and push - id: docker_build - uses: docker/build-push-action@v3 - with: - context: . - push: true - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.docker_meta.outputs.labels }} + - name: Build and push to ECR + uses: citizensadvice/build-and-push-action@v1 + with: + aws_access_key: ${{ secrets.PUBLIC_PUSH_ECR_AWS_KEY }} + aws_secret_key: ${{ secrets.PUBLIC_PUSH_ECR_AWS_SECRET }} + dockerfile_context: '.' + repository_name: image-resizer + multiarch_build: 'enabled' + auth_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3c3629e..51a0fe7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules +*.swp +*.log diff --git a/.ruby-version b/.ruby-version index 944880f..e4604e3 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.0 +3.2.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b7e13..7b13737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## v2.2.0 _2023-02-13_ + +- Added a version endpoint +- New Relic now defaults to off +- Updated to Ruby 3.2.1 + ## v2.1.0 _2023-01-31_ - `mime_type` param is no longer required. The application will now determine the mime-type. diff --git a/Dockerfile b/Dockerfile index 0227057..9131d3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.2.0-alpine3.17 as builder +FROM ruby:3.2.1-alpine3.17 as builder ENV LANG C.UTF-8 WORKDIR /app @@ -17,7 +17,7 @@ RUN gem install bundler \ ################################################# -FROM ruby:3.2.0-alpine3.17 +FROM ruby:3.2.1-alpine3.17 WORKDIR /app ENV RACK_ENV=production diff --git a/Gemfile b/Gemfile index 97d7e5c..988a132 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby "3.2.0" +ruby "3.2.1" gem "image_processing" gem "puma" @@ -14,7 +14,7 @@ gem "svg_optimizer" gem "newrelic_rpm" group :development, :test do - gem "citizens-advice-style", github: "citizensadvice/citizens-advice-style-ruby", tag: "v9.0.0" + gem "citizens-advice-style", github: "citizensadvice/citizens-advice-style-ruby", tag: "v10.0.0" gem "debug" gem "rack-test" gem "rspec" diff --git a/Gemfile.lock b/Gemfile.lock index 05a88fa..7219501 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,32 +1,38 @@ GIT remote: https://github.com/citizensadvice/citizens-advice-style-ruby.git - revision: 1a0f7e2cdcfd455a1c4d757c03d1c45eb160551d - tag: v9.0.0 + revision: 399708d8878e96a811c99af041d12f9f9e58d4dc + tag: v10.0.0 specs: citizens-advice-style (9.0.0) - rubocop (~> 1.30.1) - rubocop-rspec (~> 2.11.1) + rubocop (~> 1.45) + rubocop-rails (~> 2.17) + rubocop-rspec (~> 2.18) GEM remote: https://rubygems.org/ specs: + activesupport (7.0.4.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) ast (2.4.2) + concurrent-ruby (1.2.0) debug (1.7.1) - irb (>= 1.5.0) - reline (>= 0.3.1) diff-lcs (1.5.0) ffi (1.15.5) + i18n (1.12.0) + concurrent-ruby (~> 1.0) image_processing (1.12.2) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) - io-console (0.6.0) - irb (1.6.2) - reline (>= 0.3.0) + json (2.6.3) mini_magick (4.12.0) + minitest (5.17.0) multi_json (1.15.0) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) - newrelic_rpm (8.15.0) + newrelic_rpm (8.16.0) nio4r (2.5.8) nokogiri (1.14.1-aarch64-linux) racc (~> 1.4) @@ -37,9 +43,9 @@ GEM nokogiri (1.14.1-x86_64-linux) racc (~> 1.4) parallel (1.22.1) - parser (3.2.0.0) + parser (3.2.1.0) ast (~> 2.4.1) - puma (6.0.2) + puma (6.1.0) nio4r (~> 2.0) racc (1.6.2) rack (2.2.6.2) @@ -48,9 +54,7 @@ GEM rack-test (2.0.2) rack (>= 1.3) rainbow (3.1.1) - regexp_parser (2.6.2) - reline (0.3.2) - io-console (~> 0.5) + regexp_parser (2.7.0) rexml (3.2.5) rspec (3.12.0) rspec-core (~> 3.12.0) @@ -65,19 +69,27 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-support (3.12.0) - rubocop (1.30.1) + rubocop (1.45.1) + json (~> 2.3) parallel (~> 1.10) - parser (>= 3.1.0.0) + parser (>= 3.2.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.18.0, < 2.0) + rubocop-ast (>= 1.24.1, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.24.1) - parser (>= 3.1.1.0) - rubocop-rspec (2.11.1) - rubocop (~> 1.19) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.26.0) + parser (>= 3.2.1.0) + rubocop-capybara (2.17.0) + rubocop (~> 1.41) + rubocop-rails (2.17.4) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-rspec (2.18.1) + rubocop (~> 1.33) + rubocop-capybara (~> 2.17) ruby-progressbar (1.11.0) ruby-vips (2.1.4) ffi (~> 1.12) @@ -96,6 +108,8 @@ GEM svg_optimizer (0.2.6) nokogiri tilt (2.0.11) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) PLATFORMS @@ -117,7 +131,7 @@ DEPENDENCIES svg_optimizer RUBY VERSION - ruby 3.2.0p0 + ruby 3.2.1p31 BUNDLED WITH - 2.4.5 + 2.4.6 diff --git a/app.rb b/app.rb index f09e549..f34396d 100644 --- a/app.rb +++ b/app.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require_relative "lib/version" require_relative "lib/image_resize_service" require "sinatra" require "newrelic_rpm" @@ -10,6 +11,10 @@ body "Image Resizer service is running" end +get "/version" do + VERSION +end + post "/image" do image_file = params[:image_file]&.[](:tempfile) halt 400, "no image file was provided" unless image_file.is_a?(Tempfile) diff --git a/config/newrelic.yml b/config/newrelic.yml new file mode 100644 index 0000000..f375d5b --- /dev/null +++ b/config/newrelic.yml @@ -0,0 +1,17 @@ +# https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration +common: &default_settings + app_name: Image resizer + agent_enabled: <%= ENV["NEW_RELIC_LICENSE_KEY"].to_s.strip.empty? ? false : true %> + browser_monitoring: + auto_instrument: false + +development: + <<: *default_settings + agent_enabled: false + +test: + <<: *default_settings + monitor_mode: false + +production: + <<: *default_settings diff --git a/lib/version.rb b/lib/version.rb new file mode 100644 index 0000000..4cbe73c --- /dev/null +++ b/lib/version.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +VERSION = "2.2.0" diff --git a/spec/app_spec.rb b/spec/app_spec.rb index eae682d..02424e9 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require_relative "../lib/version" + describe "image resizer app", type: :feature do let(:image_file) { Rack::Test::UploadedFile.new("spec/fixtures/image_files/#{test_image_file_name}") } let(:test_image_file_name) { "test-png-small-314x580px.png" } @@ -18,6 +20,14 @@ end end + describe "get /version" do + it "returns the version" do + get "/version" + expect(last_response.status).to eq 200 + expect(last_response.body).to eq VERSION + end + end + describe "post /image" do context "with missing image" do it "returns 400 status" do @@ -30,7 +40,7 @@ context "with invalid width" do it "returns 400 status" do - post "/image", image_file: image_file, width: 0 + post "/image", image_file:, width: 0 expect(last_response.status).to eq 400 expect(last_response.body).to eq "invalid width" @@ -39,7 +49,7 @@ context "with invalid height" do it "returns 400 status" do - post "/image", image_file: image_file, height: 0 + post "/image", image_file:, height: 0 expect(last_response.status).to eq 400 expect(last_response.body).to eq "invalid height" @@ -50,7 +60,7 @@ let(:test_image_file_name) { "test_csv.csv" } it "returns 500 status" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 500 expect(last_response.body).to include "magick convert" @@ -61,7 +71,7 @@ let(:test_image_file_name) { "test-png-small-314x580px.png" } it "returns the PNG image at its original size" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -73,7 +83,7 @@ let(:test_image_file_name) { "test-png-1102x1287px.png" } it "returns the PNG image resized to maximum dimensions of 800px" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -85,7 +95,7 @@ let(:test_image_file_name) { "test-jpg-1102x1287px.jpg" } it "returns the JPEG image resized to maximum dimensions of 800px" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "JPEG" @@ -97,7 +107,7 @@ let(:test_image_file_name) { "test-gif-1102x1287px.gif" } it "returns the GIF image resized to maximum dimensions of 800px" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "GIF" @@ -109,7 +119,7 @@ let(:test_image_file_name) { "test-bad-tif-800x1000px.tif" } it "returns the image converted to PNG and resized to maximum dimensions of 800px" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -121,7 +131,7 @@ let(:test_image_file_name) { "test-bmp.bmp" } it "returns the image converted to PNG and resized to maximum dimensions of 800px" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -133,7 +143,7 @@ let(:test_image_file_name) { "test-webp.webp" } it "returns the image converted to PNG and resized to maximum dimensions of 800px" do - post "/image", image_file: image_file + post("/image", image_file:) expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -145,7 +155,7 @@ let(:test_image_file_name) { "test-png-1102x1287px.png" } it "resizes to the custom width" do - post "/image", image_file: image_file, width: 200 + post "/image", image_file:, width: 200 expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -157,7 +167,7 @@ let(:test_image_file_name) { "test-png-1102x1287px.png" } it "resizes to the custom height" do - post "/image", image_file: image_file, height: 200 + post "/image", image_file:, height: 200 expect(last_response.status).to eq 200 expect(resized_image.type).to eq "PNG" @@ -169,7 +179,7 @@ let(:test_image_file_name) { "test-svg.svg" } it "optimises the image" do - post "/image", image_file: image_file + post("/image", image_file:) expect(`file --brief --mime-type #{resized_image_path}`.chomp).to eq "image/svg+xml" expect(last_response.body.size.to_f / File.open(image_file).size).to be_between(0.6, 0.8) diff --git a/spec/version_spec.rb b/spec/version_spec.rb new file mode 100644 index 0000000..32d9120 --- /dev/null +++ b/spec/version_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require_relative "../lib/version" + +describe VERSION do + it "matches the branch" do + # Only really works locally. Just to enforce updating the branch + branch = `git branch --show-current`.chomp + expect(VERSION).to eq branch.sub(/^v/, "") if branch.match?(/^v?\d+\.\d+\.\d+/) # rubocop:disable RSpec/DescribedClass + rescue Errno::ENOENT + # ignore + end +end