Commit c73d0ff7 authored by Mayra Cabrera's avatar Mayra Cabrera 0️⃣
Browse files

Fixes invalid external locations

- Ensures every location, whether local or remote is a valid yml file
- Dry up files by creating a base class
- Adjust specs

Closes #4874
Closes #4873
parent 5ceb0c6d
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
module Gitlab
  module Ci
    module External
      module File
        class Base
          YAML_WHITELIST_EXTENSION = /(yml|yaml)$/i.freeze

          def initialize(location, opts = {})
            @location = location
          end

          def valid?
            location.match(YAML_WHITELIST_EXTENSION) && content
          end

          def content
            raise NotImplementedError, 'content must be implemented and return a string or nil'
          end

          def error_message
            raise NotImplementedError, 'error_message must be implemented and return a string'
          end
        end
      end
    end
  end
end
+9 −8
Original line number Diff line number Diff line
@@ -2,27 +2,28 @@ module Gitlab
  module Ci
    module External
      module File
        class Local
        class Local < Base
          attr_reader :location, :project, :sha

          def initialize(location, opts = {})
            @location = location
            super

            @project = opts.fetch(:project)
            @sha = opts.fetch(:sha)
          end

          def valid?
            local_file_content
          def content
            @content ||= fetch_local_content
          end

          def content
            local_file_content
          def error_message
            "Local file '#{location}' is not valid."
          end

          private

          def local_file_content
            @local_file_content ||= project.repository.blob_data_at(sha, location)
          def fetch_local_content
            project.repository.blob_data_at(sha, location)
          end
        end
      end
+7 −11
Original line number Diff line number Diff line
@@ -2,28 +2,24 @@ module Gitlab
  module Ci
    module External
      module File
        class Remote
        class Remote < Base
          include Gitlab::Utils::StrongMemoize
          attr_reader :location

          def initialize(location, opts = {})
            @location = location
          end

          def valid?
            ::Gitlab::UrlSanitizer.valid?(location) && content
          end

          def content
            return @content if defined?(@content)

            @content = strong_memoize(:content) do
              begin
                HTTParty.get(location)
              rescue HTTParty::Error, Timeout::Error
                false
              rescue HTTParty::Error, Timeout::Error, SocketError
                nil
              end
            end
          end

          def error_message
            "Remote file '#{location}' is not valid."
          end
        end
      end
+2 −4
Original line number Diff line number Diff line
@@ -17,10 +17,8 @@ def process
        attr_reader :locations, :project, :sha

        def build_external_file(location)
          remote_file = Gitlab::Ci::External::File::Remote.new(location)

          if remote_file.valid?
            remote_file
          if ::Gitlab::UrlSanitizer.valid?(location)
            Gitlab::Ci::External::File::Remote.new(location)
          else
            options = { project: project, sha: sha }
            Gitlab::Ci::External::File::Local.new(location, options)
+1 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ def perform

        def validate_external_file(external_file)
          unless external_file.valid?
            raise FileError, "External file: '#{external_file.location}' should be a valid local or remote file"
            raise FileError, external_file.error_message
          end
        end

Loading