Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
33813f993b
commit
8db8e2a342
14 changed files with 150 additions and 22 deletions
|
@ -21,6 +21,8 @@ class MergeRequestDiffEntity < Grape::Entity
|
||||||
expose :latest?, as: :latest
|
expose :latest?, as: :latest
|
||||||
|
|
||||||
expose :short_commit_sha do |merge_request_diff|
|
expose :short_commit_sha do |merge_request_diff|
|
||||||
|
next unless merge_request_diff.head_commit_sha
|
||||||
|
|
||||||
short_sha(merge_request_diff.head_commit_sha)
|
short_sha(merge_request_diff.head_commit_sha)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
.input-group-text
|
.input-group-text
|
||||||
= s_("CompareBranches|Source")
|
= s_("CompareBranches|Source")
|
||||||
= hidden_field_tag :to, params[:to]
|
= hidden_field_tag :to, params[:to]
|
||||||
= button_tag type: 'button', title: params[:to], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip monospace", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do
|
= button_tag type: 'button', title: params[:to], class: "btn form-control compare-dropdown-toggle js-compare-dropdown has-tooltip", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do
|
||||||
.dropdown-toggle-text.str-truncated= params[:to] || _("Select branch/tag")
|
.dropdown-toggle-text.str-truncated.monospace.float-left= params[:to] || _("Select branch/tag")
|
||||||
|
= sprite_icon('arrow-down', size: 16, css_class: 'float-right')
|
||||||
= render 'shared/ref_dropdown'
|
= render 'shared/ref_dropdown'
|
||||||
.compare-ellipsis.inline ...
|
.compare-ellipsis.inline ...
|
||||||
.form-group.dropdown.compare-form-group.from.js-compare-from-dropdown
|
.form-group.dropdown.compare-form-group.from.js-compare-from-dropdown
|
||||||
|
@ -18,8 +19,9 @@
|
||||||
.input-group-text
|
.input-group-text
|
||||||
= s_("CompareBranches|Target")
|
= s_("CompareBranches|Target")
|
||||||
= hidden_field_tag :from, params[:from]
|
= hidden_field_tag :from, params[:from]
|
||||||
= button_tag type: 'button', title: params[:from], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip monospace", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
|
= button_tag type: 'button', title: params[:from], class: "btn form-control compare-dropdown-toggle js-compare-dropdown has-tooltip", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
|
||||||
.dropdown-toggle-text.str-truncated= params[:from] || _("Select branch/tag")
|
.dropdown-toggle-text.str-truncated.monospace.float-left= params[:from] || _("Select branch/tag")
|
||||||
|
= sprite_icon('arrow-down', size: 16, css_class: 'float-right')
|
||||||
= render 'shared/ref_dropdown'
|
= render 'shared/ref_dropdown'
|
||||||
|
|
||||||
= button_tag s_("CompareBranches|Compare"), class: "btn btn-success commits-compare-btn"
|
= button_tag s_("CompareBranches|Compare"), class: "btn btn-success commits-compare-btn"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Adding dropdown arrow icon and updated text alignment
|
||||||
|
merge_request:
|
||||||
|
author:
|
||||||
|
type: other
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Bump Auto-Deploy image to v0.3.0
|
||||||
|
merge_request: 18809
|
||||||
|
author:
|
||||||
|
type: added
|
5
changelogs/unreleased/id-nil-short-commit-sha.yml
Normal file
5
changelogs/unreleased/id-nil-short-commit-sha.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Serialize short sha as nil if head commit is blank
|
||||||
|
merge_request: 19014
|
||||||
|
author:
|
||||||
|
type: fixed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Support Enable/Disable operations in Feature Flag API
|
||||||
|
merge_request: 18368
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -924,6 +924,7 @@ applications.
|
||||||
| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | From GitLab 11.11, used to set the name of the Helm repository. Defaults to `gitlab`. |
|
| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | From GitLab 11.11, used to set the name of the Helm repository. Defaults to `gitlab`. |
|
||||||
| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | From GitLab 11.11, used to set a username to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD`. |
|
| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | From GitLab 11.11, used to set a username to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD`. |
|
||||||
| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | From GitLab 11.11, used to set a password to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME`. |
|
| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | From GitLab 11.11, used to set a password to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME`. |
|
||||||
|
| `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` | From GitLab 12.5, used in combination with [Modsecurity feature flag](../../user/clusters/applications.md#web-application-firewall-modsecurity) to toggle [Modsecurity's `SecRuleEngine`](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRuleEngine) behavior. Defaults to `DetectionOnly`. |
|
||||||
| `BUILDPACK_URL` | Buildpack's full URL. Can point to either Git repositories or a tarball URL. For Git repositories, it is possible to point to a specific `ref`. For example `https://github.com/heroku/heroku-buildpack-ruby.git#v142`. |
|
| `BUILDPACK_URL` | Buildpack's full URL. Can point to either Git repositories or a tarball URL. For Git repositories, it is possible to point to a specific `ref`. For example `https://github.com/heroku/heroku-buildpack-ruby.git#v142`. |
|
||||||
| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments-premium). |
|
| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments-premium). |
|
||||||
| `CANARY_PRODUCTION_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. Takes precedence over `CANARY_REPLICAS`. Defaults to 1. |
|
| `CANARY_PRODUCTION_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. Takes precedence over `CANARY_REPLICAS`. Defaults to 1. |
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.auto-deploy:
|
.auto-deploy:
|
||||||
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.1.0"
|
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.3.0"
|
||||||
|
|
||||||
review:
|
review:
|
||||||
extends: .auto-deploy
|
extends: .auto-deploy
|
||||||
|
|
|
@ -13,6 +13,15 @@ module Quality
|
||||||
end
|
end
|
||||||
|
|
||||||
def cleanup(release_name:)
|
def cleanup(release_name:)
|
||||||
|
selector = case release_name
|
||||||
|
when String
|
||||||
|
%(-l release="#{release_name}")
|
||||||
|
when Array
|
||||||
|
%(-l 'release in (#{release_name.join(', ')})')
|
||||||
|
else
|
||||||
|
raise ArgumentError, 'release_name must be a string or an array'
|
||||||
|
end
|
||||||
|
|
||||||
command = [
|
command = [
|
||||||
%(--namespace "#{namespace}"),
|
%(--namespace "#{namespace}"),
|
||||||
'delete',
|
'delete',
|
||||||
|
@ -20,7 +29,7 @@ module Quality
|
||||||
'--now',
|
'--now',
|
||||||
'--ignore-not-found',
|
'--ignore-not-found',
|
||||||
'--include-uninitialized',
|
'--include-uninitialized',
|
||||||
%(-l release="#{release_name}")
|
selector
|
||||||
]
|
]
|
||||||
|
|
||||||
run_command(command)
|
run_command(command)
|
||||||
|
|
|
@ -60,6 +60,8 @@ class AutomatedCleanup
|
||||||
stop_threshold = threshold_time(days: days_for_stop)
|
stop_threshold = threshold_time(days: days_for_stop)
|
||||||
deployments_look_back_threshold = threshold_time(days: days_for_delete * 5)
|
deployments_look_back_threshold = threshold_time(days: days_for_delete * 5)
|
||||||
|
|
||||||
|
releases_to_delete = []
|
||||||
|
|
||||||
gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc').auto_paginate do |deployment|
|
gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE, sort: 'desc').auto_paginate do |deployment|
|
||||||
break if Time.parse(deployment.created_at) < deployments_look_back_threshold
|
break if Time.parse(deployment.created_at) < deployments_look_back_threshold
|
||||||
|
|
||||||
|
@ -75,7 +77,7 @@ class AutomatedCleanup
|
||||||
if deployed_at < delete_threshold
|
if deployed_at < delete_threshold
|
||||||
delete_environment(environment, deployment)
|
delete_environment(environment, deployment)
|
||||||
release = Quality::HelmClient::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
|
release = Quality::HelmClient::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
|
||||||
delete_helm_release(release)
|
releases_to_delete << release
|
||||||
elsif deployed_at < stop_threshold
|
elsif deployed_at < stop_threshold
|
||||||
stop_environment(environment, deployment)
|
stop_environment(environment, deployment)
|
||||||
else
|
else
|
||||||
|
@ -84,6 +86,8 @@ class AutomatedCleanup
|
||||||
|
|
||||||
checked_environments << environment.slug
|
checked_environments << environment.slug
|
||||||
end
|
end
|
||||||
|
|
||||||
|
delete_helm_releases(releases_to_delete)
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_helm_releases_cleanup!(days:)
|
def perform_helm_releases_cleanup!(days:)
|
||||||
|
@ -91,16 +95,20 @@ class AutomatedCleanup
|
||||||
|
|
||||||
threshold_day = threshold_time(days: days)
|
threshold_day = threshold_time(days: days)
|
||||||
|
|
||||||
|
releases_to_delete = []
|
||||||
|
|
||||||
helm_releases.each do |release|
|
helm_releases.each do |release|
|
||||||
# Prevents deleting `dns-gitlab-review-app` releases or other unrelated releases
|
# Prevents deleting `dns-gitlab-review-app` releases or other unrelated releases
|
||||||
next unless release.name.start_with?('review-')
|
next unless release.name.start_with?('review-')
|
||||||
|
|
||||||
if release.status == 'FAILED' || release.last_update < threshold_day
|
if release.status == 'FAILED' || release.last_update < threshold_day
|
||||||
delete_helm_release(release)
|
releases_to_delete << release
|
||||||
else
|
else
|
||||||
print_release_state(subject: 'Release', release_name: release.name, release_date: release.last_update, action: 'leaving')
|
print_release_state(subject: 'Release', release_name: release.name, release_date: release.last_update, action: 'leaving')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
delete_helm_releases(releases_to_delete)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -121,10 +129,17 @@ class AutomatedCleanup
|
||||||
helm.releases(args: args)
|
helm.releases(args: args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_helm_release(release)
|
def delete_helm_releases(releases)
|
||||||
print_release_state(subject: 'Release', release_name: release.name, release_status: release.status, release_date: release.last_update, action: 'cleaning')
|
return if releases.empty?
|
||||||
helm.delete(release_name: release.name)
|
|
||||||
kubernetes.cleanup(release_name: release.name)
|
releases.each do |release|
|
||||||
|
print_release_state(subject: 'Release', release_name: release.name, release_status: release.status, release_date: release.last_update, action: 'cleaning')
|
||||||
|
end
|
||||||
|
|
||||||
|
releases_names = releases.map(&:name)
|
||||||
|
helm.delete(release_name: releases_names)
|
||||||
|
kubernetes.cleanup(release_name: releases_names)
|
||||||
|
|
||||||
rescue Quality::HelmClient::CommandFailedError => ex
|
rescue Quality::HelmClient::CommandFailedError => ex
|
||||||
raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
|
raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ module Trigger
|
||||||
end
|
end
|
||||||
|
|
||||||
class Base
|
class Base
|
||||||
def invoke!(post_comment: false)
|
def invoke!(post_comment: false, downstream_job_name: nil)
|
||||||
pipeline = Gitlab.run_trigger(
|
pipeline = Gitlab.run_trigger(
|
||||||
downstream_project_path,
|
downstream_project_path,
|
||||||
trigger_token,
|
trigger_token,
|
||||||
|
@ -28,7 +28,18 @@ module Trigger
|
||||||
puts "Waiting for downstream pipeline status"
|
puts "Waiting for downstream pipeline status"
|
||||||
|
|
||||||
Trigger::CommitComment.post!(pipeline, access_token) if post_comment
|
Trigger::CommitComment.post!(pipeline, access_token) if post_comment
|
||||||
Trigger::Pipeline.new(downstream_project_path, pipeline.id, access_token)
|
downstream_job =
|
||||||
|
if downstream_job_name
|
||||||
|
Gitlab.pipeline_jobs(downstream_project_path, pipeline.id).auto_paginate.find do |potential_job|
|
||||||
|
potential_job.name == downstream_job_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if downstream_job
|
||||||
|
Trigger::Job.new(downstream_project_path, downstream_job.id, access_token)
|
||||||
|
else
|
||||||
|
Trigger::Pipeline.new(downstream_project_path, pipeline.id, access_token)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -187,6 +198,14 @@ module Trigger
|
||||||
|
|
||||||
attr_reader :project, :id, :api_token
|
attr_reader :project, :id, :api_token
|
||||||
|
|
||||||
|
def self.unscoped_class_name
|
||||||
|
name.split('::').last
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.gitlab_api_method_name
|
||||||
|
unscoped_class_name.downcase
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(project, id, api_token)
|
def initialize(project, id, api_token)
|
||||||
@project = project
|
@project = project
|
||||||
@id = id
|
@id = id
|
||||||
|
@ -199,17 +218,17 @@ module Trigger
|
||||||
|
|
||||||
def wait!
|
def wait!
|
||||||
loop do
|
loop do
|
||||||
raise "Pipeline timed out after waiting for #{duration} minutes!" if timeout?
|
raise "#{self.class.unscoped_class_name} timed out after waiting for #{duration} minutes!" if timeout?
|
||||||
|
|
||||||
case status
|
case status
|
||||||
when :created, :pending, :running
|
when :created, :pending, :running
|
||||||
print "."
|
print "."
|
||||||
sleep INTERVAL
|
sleep INTERVAL
|
||||||
when :success
|
when :success
|
||||||
puts "Pipeline succeeded in #{duration} minutes!"
|
puts "#{self.class.unscoped_class_name} succeeded in #{duration} minutes!"
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
raise "Pipeline did not succeed!"
|
raise "#{self.class.unscoped_class_name} did not succeed!"
|
||||||
end
|
end
|
||||||
|
|
||||||
STDOUT.flush
|
STDOUT.flush
|
||||||
|
@ -225,7 +244,7 @@ module Trigger
|
||||||
end
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
Gitlab.pipeline(project, id).status.to_sym
|
Gitlab.public_send(self.class.gitlab_api_method_name, project, id).status.to_sym # rubocop:disable GitlabSecurity/PublicSend
|
||||||
rescue Gitlab::Error::Error => error
|
rescue Gitlab::Error::Error => error
|
||||||
puts "Ignoring the following error: #{error}"
|
puts "Ignoring the following error: #{error}"
|
||||||
# Ignore GitLab API hiccups. If GitLab is really down, we'll hit the job
|
# Ignore GitLab API hiccups. If GitLab is really down, we'll hit the job
|
||||||
|
@ -233,11 +252,13 @@ module Trigger
|
||||||
:running
|
:running
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Job = Class.new(Pipeline)
|
||||||
end
|
end
|
||||||
|
|
||||||
case ARGV[0]
|
case ARGV[0]
|
||||||
when 'omnibus'
|
when 'omnibus'
|
||||||
Trigger::Omnibus.new.invoke!(post_comment: true).wait!
|
Trigger::Omnibus.new.invoke!(post_comment: true, downstream_job_name: 'Trigger:qa-test').wait!
|
||||||
when 'cng'
|
when 'cng'
|
||||||
Trigger::CNG.new.invoke!.wait!
|
Trigger::CNG.new.invoke!.wait!
|
||||||
else
|
else
|
||||||
|
|
|
@ -107,5 +107,25 @@ RSpec.describe Quality::HelmClient do
|
||||||
|
|
||||||
expect(subject.delete(release_name: release_name)).to eq('')
|
expect(subject.delete(release_name: release_name)).to eq('')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with multiple release names' do
|
||||||
|
let(:release_name) { ['my-release', 'my-release-2'] }
|
||||||
|
|
||||||
|
it 'raises an error if the Helm command fails' do
|
||||||
|
expect(Gitlab::Popen).to receive(:popen_with_detail)
|
||||||
|
.with([%(helm delete --tiller-namespace "#{namespace}" --purge #{release_name.join(' ')})])
|
||||||
|
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
|
||||||
|
|
||||||
|
expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls helm delete with multiple release names' do
|
||||||
|
expect(Gitlab::Popen).to receive(:popen_with_detail)
|
||||||
|
.with([%(helm delete --tiller-namespace "#{namespace}" --purge #{release_name.join(' ')})])
|
||||||
|
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
|
||||||
|
|
||||||
|
expect(subject.delete(release_name: release_name)).to eq('')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,5 +29,30 @@ RSpec.describe Quality::KubernetesClient do
|
||||||
# We're not verifying the output here, just silencing it
|
# We're not verifying the output here, just silencing it
|
||||||
expect { subject.cleanup(release_name: release_name) }.to output.to_stdout
|
expect { subject.cleanup(release_name: release_name) }.to output.to_stdout
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with multiple releases' do
|
||||||
|
let(:release_name) { ['my-release', 'my-release-2'] }
|
||||||
|
|
||||||
|
it 'raises an error if the Kubernetes command fails' do
|
||||||
|
expect(Gitlab::Popen).to receive(:popen_with_detail)
|
||||||
|
.with([%(kubectl --namespace "#{namespace}" delete ) \
|
||||||
|
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \
|
||||||
|
"--now --ignore-not-found --include-uninitialized -l 'release in (#{release_name.join(', ')})'"])
|
||||||
|
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
|
||||||
|
|
||||||
|
expect { subject.cleanup(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls kubectl with the correct arguments' do
|
||||||
|
expect(Gitlab::Popen).to receive(:popen_with_detail)
|
||||||
|
.with([%(kubectl --namespace "#{namespace}" delete ) \
|
||||||
|
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \
|
||||||
|
"--now --ignore-not-found --include-uninitialized -l 'release in (#{release_name.join(', ')})'"])
|
||||||
|
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
|
||||||
|
|
||||||
|
# We're not verifying the output here, just silencing it
|
||||||
|
expect { subject.cleanup(release_name: release_name) }.to output.to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,14 +7,15 @@ describe MergeRequestDiffEntity do
|
||||||
let(:request) { EntityRequest.new(project: project) }
|
let(:request) { EntityRequest.new(project: project) }
|
||||||
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
|
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
|
||||||
let(:merge_request_diffs) { merge_request.merge_request_diffs }
|
let(:merge_request_diffs) { merge_request.merge_request_diffs }
|
||||||
|
let(:merge_request_diff) { merge_request_diffs.first }
|
||||||
|
|
||||||
let(:entity) do
|
let(:entity) do
|
||||||
described_class.new(merge_request_diffs.first, request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs)
|
described_class.new(merge_request_diff, request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'as json' do
|
subject { entity.as_json }
|
||||||
subject { entity.as_json }
|
|
||||||
|
|
||||||
|
context 'as json' do
|
||||||
it 'exposes needed attributes' do
|
it 'exposes needed attributes' do
|
||||||
expect(subject).to include(
|
expect(subject).to include(
|
||||||
:version_index, :created_at, :commits_count,
|
:version_index, :created_at, :commits_count,
|
||||||
|
@ -23,4 +24,16 @@ describe MergeRequestDiffEntity do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#short_commit_sha' do
|
||||||
|
it 'returns short sha' do
|
||||||
|
expect(subject[:short_commit_sha]).to eq('b83d6e39')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns nil if head_commit_sha does not exist' do
|
||||||
|
allow(merge_request_diff).to receive(:head_commit_sha).and_return(nil)
|
||||||
|
|
||||||
|
expect(subject[:short_commit_sha]).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue