从CircleCi 2.0迁移后失败的规格

时间:2017-07-28 06:46:56

标签: ruby-on-rails ruby docker paperclip circleci

我已经通过Ruby on Rails项目进行迁移,以便在CircleCi 2.0上运行测试。执行此操作后,与文件上载相关的某些规范将失败。我有以下型号:

SlideAudio:

class SlideAudio < ApplicationRecord
  # == Extensions ============================================================
  Paperclip.interpolates :locale do |attachment, style|
    attachment.instance.locale
  end

  # Tell paperclip that :slide_id means SlideAudio#slide_id
  # This is used in the custom path and url below when we define the attachment
  Paperclip.interpolates :slide_id do |attachment, style|
    attachment.instance.slide_id
  end

  has_attached_file :audio,
    path: ":rails_root/public/slides/:attachment/:style/:locale/:slide_id.:extension",
    url: "/slides/:attachment/:style/:locale/:slide_id.:extension",
    processors: [:audio_compression],
    styles: {
      original: {},
      compressed_96k: {bitrate: '96k'}
    }
  # == Associations ==========================================================
  belongs_to :slide, optional: true

  # == Validations ===========================================================
  validates_attachment :audio, content_type: {
    content_type: [
      'audio/mpeg',
      'audio/x-mpeg',
      'audio/mp3',
      'audio/x-mp3',
      'audio/mpeg3',
      'audio/x-mpeg3',
      'audio/mpg',
      'audio/x-mpg',
      'audio/x-mpegaudio'
    ]
}
  # == Instance Methods ======================================================
  def has_a_valid_audio_file?
    return false if audio.blank?

    # Before a slide_audio is saved, the audio file lives in the tmp directory.
    if audio.queued_for_write.present? && audio.queued_for_write[:original].present?
      temporary_path = audio.queued_for_write[:original].path
      File.exists?(temporary_path)
    # After a slide is saved, Paperclip copies that file to "path".
    elsif audio.path.present?
      File.exists?(audio.path)
    else
      false
    end
  end
end

幻灯片:

class Slide < ApplicationRecord
  has_many :audios, class_name: 'SlideAudio'
end

我还有一个负责压缩音频的课程:

module Paperclip
  class AudioCompression < Processor

    def make
      original_filepath = @file.path

      if should_skip_compression?
        # If no compression is needed, we can't just return the original file (@file)
        # because Paperclip will remove it during cleanup.
        # That's why we need to copy it and return that copy.
        new_filepath = original_filepath.gsub('.mp3', '-copy.mp3')
        FileUtils.cp(original_filepath, new_filepath)
        return File.open(new_filepath)
      end

      desired_bitrate = options[:bitrate] # This is formatted as a string that ffmpeg accepts, e.g. "96k"

      Paperclip::AudioCompression.compress(original_filepath, desired_bitrate)
    end

    protected

    # This method is not required by Paperclip processors - it is our "helper" method.
    # If the original bitrate is not significantly higher than the desired bitrate,
    # we won't try to compress, because we would lose sound quality and wouldn't gain much.
    def should_skip_compression?
      return true if options[:style] == :original # Do not compress original files.

      desired_bitrate = options[:bitrate] # This is formatted as a string that ffmpeg accepts, e.g. "96k"
      desired_bitrate_in_kbs = desired_bitrate.to_i # This is a number, e.g. 96.

      original_audio_info = `ffmpeg -i #{@file.path} 2>&1`

      original_bitrate = original_audio_info.match(/(?:bitrate: )(\d+) (?:kb\/s)$/)&.captures&.first
      original_bitrate_in_kbs = original_bitrate.to_i

      upper_acceptable_bitrate_limit_in_kbs = desired_bitrate_in_kbs + 5

      original_bitrate_in_kbs < upper_acceptable_bitrate_limit_in_kbs
    end

    def self.compress(original_filepath, desired_bitrate)
      # This file doesn't exist yet, we're just constructing the filepath.
      compressed_filepath = original_filepath.gsub('.mp3', "-#{desired_bitrate}.mp3")

      # Use ffmpeg to compress the original file.
      # The files are usually uploaded to a temporary location, such as /var/folders.
      # The flags used:
      # -y: If there's a temporary file at compressed_filepath, overwrite it.
      # -i: Specifies the input filepath.
      # -ab: Specifies the desired bitrate.
      Paperclip.run('ffmpeg', "-y -i #{original_filepath} -ab #{desired_bitrate} #{compressed_filepath}")

      File.open(compressed_filepath)
    end
  end
end

我的测试看起来像这样:

require 'rails_helper'

RSpec.describe SlideAudio, type: :model do
  describe 'Instance Methods' do
    let(:slide) { create(:slide) }
    let(:audio) { slide.audios.create(locale: 'en') }

    let(:audio_file_128k) do
      Rack::Test::UploadedFile.new(
        'spec/fixtures/audios/test-128k.mp3',
        'audio/mpeg')
    end

    let(:audio_file_96k) do
      Rack::Test::UploadedFile.new(
        'spec/fixtures/audios/test-96k.mp3',
        'audio/mpeg')
    end

    describe '#audio=' do
      it 'should compress mp3 files to 96 kbps if their bitrate is too high' do
        audio.audio = audio_file_128k
        audio.save!

        audio_info = `ffmpeg -i #{audio.audio.path(:compressed_96k)} 2>&1`
        bitrate_info = audio_info[/bitrate:.*$/]

        expect(bitrate_info).to eq('bitrate: 96 kb/s')
      end
    end
  end
end

并且输出失败:

 Failure/Error: expect(bitrate_info).to eq('bitrate: 96 kb/s')

   expected: "bitrate: 96 kb/s"
        got: nil

   (compared using ==)

任何想法我该如何解决这个问题?这是我的circle.yml文件:

version: 2
environment:
  TZ: "/usr/share/zoneinfo/America/Los_Angeles"

jobs:
  build:
    parallelism: 2
    working_directory: ~/circleci-survey-builder
    docker:
      - image: circleci/ruby:2.3.4
        environment:
          PGHOST: 127.0.0.1
          PGUSER: ubuntu
          RAILS_ENV: test
      - image: circleci/postgres:9.6-alpine
        environment:
          POSTGRES_USER: ubuntu
          POSTGRES_DB: circle_test
          POSTGRES_PASSWORD: ''
    steps:
      - checkout

      - run:
          name: 'Install CircleCI dependencies'
          command: bash deploy/circle-dependencies.sh

      - type: cache-restore
        key: survey-builder-{{ checksum "Gemfile.lock" }}

      - run:
          name: 'Install dependencies'
          command: bundle install --path vendor/bundle

      - type: cache-save
        key: survey-builder-{{ checksum "Gemfile.lock" }}
        paths:
          - vendor/bundle

      - run:
          name: 'Create database.yml'
          command: mv config/database.ci.yml config/database.yml

      - run:
          name: Set up SurveyBuilder database
          command: bundle exec rake db:structure:load --trace

      - run:
          name: Set up Dashboard database
          command: |
            createdb dashboard_test
            psql -p 5432 dashboard_test < db/dashboard_test.sql

      - run:
          name: Set up foreign data wrapper
          command: psql -p 5432 circle_test < db/test_foreign_data_wrapper.sql

      - run:
          name: 'Run tests'
          command: |
            bundle exec rspec --format progress \
                              $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)

0 个答案:

没有答案