summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2016-11-04 15:53:38 +0000
committerDouwe Maan <douwe@gitlab.com>2016-11-04 15:53:38 +0000
commit5a0a4506d2e27ce4da7bcd6122d519054b015ab0 (patch)
tree3dab4669053191d49165a7be825b7c178de8b3f1
parent5b220b38b436f409e87c3901db2b5a061c01b12e (diff)
parentb0a4635be395f0ce14e15e1671d7acfc2360d1ba (diff)
downloadgitlab-ce-5a0a4506d2e27ce4da7bcd6122d519054b015ab0.tar.gz
Merge branch 'feature/view-related-serializers' into 'master'
Add serializer for environments ## What does this MR do? This will make it possible to create a payload need in https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7015 for use with Vue. ## Why was this MR needed? Closes #23886 See merge request !7174
-rw-r--r--app/serializers/base_serializer.rb18
-rw-r--r--app/serializers/build_entity.rb24
-rw-r--r--app/serializers/commit_entity.rb12
-rw-r--r--app/serializers/deployment_entity.rb27
-rw-r--r--app/serializers/entity_request.rb12
-rw-r--r--app/serializers/environment_entity.rb20
-rw-r--r--app/serializers/environment_serializer.rb3
-rw-r--r--app/serializers/request_aware_entity.rb11
-rw-r--r--app/serializers/user_entity.rb2
-rw-r--r--spec/serializers/build_entity_spec.rb31
-rw-r--r--spec/serializers/commit_entity_spec.rb44
-rw-r--r--spec/serializers/deployment_entity_spec.rb20
-rw-r--r--spec/serializers/entity_request_spec.rb18
-rw-r--r--spec/serializers/environment_entity_spec.rb18
-rw-r--r--spec/serializers/environment_serializer_spec.rb60
-rw-r--r--spec/serializers/user_entity_spec.rb23
16 files changed, 343 insertions, 0 deletions
diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb
new file mode 100644
index 00000000000..de9a181db90
--- /dev/null
+++ b/app/serializers/base_serializer.rb
@@ -0,0 +1,18 @@
+class BaseSerializer
+ def initialize(parameters = {})
+ @request = EntityRequest.new(parameters)
+ end
+
+ def represent(resource, opts = {})
+ self.class.entity_class
+ .represent(resource, opts.merge(request: @request))
+ end
+
+ def self.entity(entity_class)
+ @entity_class ||= entity_class
+ end
+
+ def self.entity_class
+ @entity_class
+ end
+end
diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb
new file mode 100644
index 00000000000..3d9ac66de0e
--- /dev/null
+++ b/app/serializers/build_entity.rb
@@ -0,0 +1,24 @@
+class BuildEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :name
+
+ expose :build_url do |build|
+ url_to(:namespace_project_build, build)
+ end
+
+ expose :retry_url do |build|
+ url_to(:retry_namespace_project_build, build)
+ end
+
+ expose :play_url, if: ->(build, _) { build.manual? } do |build|
+ url_to(:play_namespace_project_build, build)
+ end
+
+ private
+
+ def url_to(route, build)
+ send("#{route}_url", build.project.namespace, build.project, build)
+ end
+end
diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb
new file mode 100644
index 00000000000..f7eba6fc1e3
--- /dev/null
+++ b/app/serializers/commit_entity.rb
@@ -0,0 +1,12 @@
+class CommitEntity < API::Entities::RepoCommit
+ include RequestAwareEntity
+
+ expose :author, using: UserEntity
+
+ expose :commit_url do |commit|
+ namespace_project_tree_url(
+ request.project.namespace,
+ request.project,
+ id: commit.id)
+ end
+end
diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
new file mode 100644
index 00000000000..ad6fc8d665b
--- /dev/null
+++ b/app/serializers/deployment_entity.rb
@@ -0,0 +1,27 @@
+class DeploymentEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :iid
+ expose :sha
+
+ expose :ref do
+ expose :name do |deployment|
+ deployment.ref
+ end
+
+ expose :ref_url do |deployment|
+ namespace_project_tree_url(
+ deployment.project.namespace,
+ deployment.project,
+ id: deployment.ref)
+ end
+ end
+
+ expose :tag
+ expose :last?
+ expose :user, using: UserEntity
+ expose :commit, using: CommitEntity
+ expose :deployable, using: BuildEntity
+ expose :manual_actions, using: BuildEntity
+end
diff --git a/app/serializers/entity_request.rb b/app/serializers/entity_request.rb
new file mode 100644
index 00000000000..456ba1174c0
--- /dev/null
+++ b/app/serializers/entity_request.rb
@@ -0,0 +1,12 @@
+class EntityRequest
+ # We use EntityRequest object to collect parameters and variables
+ # from the controller. Because options that are being passed to the entity
+ # do appear in each entity object in the chain, we need a way to pass data
+ # that is present in the controller (see #20045).
+ #
+ def initialize(parameters)
+ parameters.each do |key, value|
+ define_singleton_method(key) { value }
+ end
+ end
+end
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
new file mode 100644
index 00000000000..ee4392cc46d
--- /dev/null
+++ b/app/serializers/environment_entity.rb
@@ -0,0 +1,20 @@
+class EnvironmentEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :name
+ expose :state
+ expose :external_url
+ expose :environment_type
+ expose :last_deployment, using: DeploymentEntity
+ expose :stoppable?
+
+ expose :environment_url do |environment|
+ namespace_project_environment_url(
+ environment.project.namespace,
+ environment.project,
+ environment)
+ end
+
+ expose :created_at, :updated_at
+end
diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb
new file mode 100644
index 00000000000..91955542f25
--- /dev/null
+++ b/app/serializers/environment_serializer.rb
@@ -0,0 +1,3 @@
+class EnvironmentSerializer < BaseSerializer
+ entity EnvironmentEntity
+end
diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb
new file mode 100644
index 00000000000..ff8c1142abc
--- /dev/null
+++ b/app/serializers/request_aware_entity.rb
@@ -0,0 +1,11 @@
+module RequestAwareEntity
+ extend ActiveSupport::Concern
+
+ included do
+ include Gitlab::Routing.url_helpers
+ end
+
+ def request
+ @options.fetch(:request)
+ end
+end
diff --git a/app/serializers/user_entity.rb b/app/serializers/user_entity.rb
new file mode 100644
index 00000000000..43754ea94f7
--- /dev/null
+++ b/app/serializers/user_entity.rb
@@ -0,0 +1,2 @@
+class UserEntity < API::Entities::UserBasic
+end
diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb
new file mode 100644
index 00000000000..2734f5bedca
--- /dev/null
+++ b/spec/serializers/build_entity_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe BuildEntity do
+ let(:entity) do
+ described_class.new(build, request: double)
+ end
+
+ subject { entity.as_json }
+
+ context 'when build is a regular job' do
+ let(:build) { create(:ci_build) }
+
+ it 'contains url to build page and retry action' do
+ expect(subject).to include(:build_url, :retry_url)
+ expect(subject).not_to include(:play_url)
+ end
+
+ it 'does not contain sensitive information' do
+ expect(subject).not_to include(/token/)
+ expect(subject).not_to include(/variables/)
+ end
+ end
+
+ context 'when build is a manual action' do
+ let(:build) { create(:ci_build, :manual) }
+
+ it 'contains url to play action' do
+ expect(subject).to include(:play_url)
+ end
+ end
+end
diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb
new file mode 100644
index 00000000000..628e35c9a28
--- /dev/null
+++ b/spec/serializers/commit_entity_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe CommitEntity do
+ let(:entity) do
+ described_class.new(commit, request: request)
+ end
+
+ let(:request) { double('request') }
+ let(:project) { create(:project) }
+ let(:commit) { project.commit }
+
+ subject { entity.as_json }
+
+ before do
+ allow(request).to receive(:project).and_return(project)
+ end
+
+ context 'when commit author is a user' do
+ before do
+ create(:user, email: commit.author_email)
+ end
+
+ it 'contains information about user' do
+ expect(subject.fetch(:author)).not_to be_nil
+ end
+ end
+
+ context 'when commit author is not a user' do
+ it 'does not contain author details' do
+ expect(subject.fetch(:author)).to be_nil
+ end
+ end
+
+ it 'contains commit URL' do
+ expect(subject).to include(:commit_url)
+ end
+
+ it 'needs to receive project in the request' do
+ expect(request).to receive(:project)
+ .and_return(project)
+
+ subject
+ end
+end
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
new file mode 100644
index 00000000000..51b6de91571
--- /dev/null
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe DeploymentEntity do
+ let(:entity) do
+ described_class.new(deployment, request: double)
+ end
+
+ let(:deployment) { create(:deployment) }
+
+ subject { entity.as_json }
+
+ it 'exposes internal deployment id' do
+ expect(subject).to include(:iid)
+ end
+
+ it 'exposes nested information about branch' do
+ expect(subject[:ref][:name]).to eq 'master'
+ expect(subject[:ref][:ref_url]).not_to be_empty
+ end
+end
diff --git a/spec/serializers/entity_request_spec.rb b/spec/serializers/entity_request_spec.rb
new file mode 100644
index 00000000000..86654adfd54
--- /dev/null
+++ b/spec/serializers/entity_request_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe EntityRequest do
+ subject do
+ described_class.new(user: 'user', project: 'some project')
+ end
+
+ describe 'methods created' do
+ it 'defines accessible attributes' do
+ expect(subject.user).to eq 'user'
+ expect(subject.project).to eq 'some project'
+ end
+
+ it 'raises error when attribute is not defined' do
+ expect { subject.some_method }.to raise_error NoMethodError
+ end
+ end
+end
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
new file mode 100644
index 00000000000..4ca8c299147
--- /dev/null
+++ b/spec/serializers/environment_entity_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe EnvironmentEntity do
+ let(:entity) do
+ described_class.new(environment, request: double)
+ end
+
+ let(:environment) { create(:environment) }
+ subject { entity.as_json }
+
+ it 'exposes latest deployment' do
+ expect(subject).to include(:last_deployment)
+ end
+
+ it 'exposes core elements of environment' do
+ expect(subject).to include(:id, :name, :state, :environment_url)
+ end
+end
diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb
new file mode 100644
index 00000000000..37bc086826c
--- /dev/null
+++ b/spec/serializers/environment_serializer_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+describe EnvironmentSerializer do
+ let(:serializer) do
+ described_class
+ .new(user: user, project: project)
+ .represent(resource)
+ end
+
+ let(:json) { serializer.as_json }
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ context 'when there is a single object provided' do
+ before do
+ create(:ci_build, :manual, name: 'manual1',
+ pipeline: deployable.pipeline)
+ end
+
+ let(:deployment) do
+ create(:deployment, deployable: deployable,
+ user: user,
+ project: project,
+ sha: project.commit.id)
+ end
+
+ let(:deployable) { create(:ci_build) }
+ let(:resource) { deployment.environment }
+
+ it 'it generates payload for single object' do
+ expect(json).to be_an_instance_of Hash
+ end
+
+ it 'contains important elements of environment' do
+ expect(json)
+ .to include(:name, :external_url, :environment_url, :last_deployment)
+ end
+
+ it 'contains relevant information about last deployment' do
+ last_deployment = json.fetch(:last_deployment)
+
+ expect(last_deployment)
+ .to include(:ref, :user, :commit, :deployable, :manual_actions)
+ end
+ end
+
+ context 'when there is a collection of objects provided' do
+ let(:project) { create(:empty_project) }
+ let(:resource) { create_list(:environment, 2) }
+
+ it 'contains important elements of environment' do
+ expect(json.first)
+ .to include(:last_deployment, :name, :external_url)
+ end
+
+ it 'generates payload for collection' do
+ expect(json).to be_an_instance_of Array
+ end
+ end
+end
diff --git a/spec/serializers/user_entity_spec.rb b/spec/serializers/user_entity_spec.rb
new file mode 100644
index 00000000000..c5d11cbcf5e
--- /dev/null
+++ b/spec/serializers/user_entity_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe UserEntity do
+ let(:entity) { described_class.new(user) }
+ let(:user) { create(:user) }
+ subject { entity.as_json }
+
+ it 'exposes user name and login' do
+ expect(subject).to include(:username, :name)
+ end
+
+ it 'does not expose passwords' do
+ expect(subject).not_to include(/password/)
+ end
+
+ it 'does not expose tokens' do
+ expect(subject).not_to include(/token/)
+ end
+
+ it 'does not expose 2FA OTPs' do
+ expect(subject).not_to include(/otp/)
+ end
+end