Commit e0665e66 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ce_upstream' into 'master'

CE upstream

See merge request !996
parents cdb51842 0e569f2c
......@@ -4,8 +4,7 @@ entry.
## 8.15.0 (2017-01-22)
- Add shortcuts for adding users to a project team with a specific role. (Nikolay Ponomarev and Dino M)
- Ensure nil User-Agent doesn't break the CI API.
- Whitelist next project names: notes, services.
- Use Grape's new Route methods.
- Fixed issue boards scrolling with a lot of lists & issues.
- Remove unnecessary sentences for status codes in the API documentation. (Luis Alonso Chavez Armendariz)
......@@ -28,11 +27,11 @@ entry.
- Use authorized projects in ProjectTeam.
- Destroy a user's session when they delete their own account.
- Edit help text to clarify annotated tag creation. (Liz Lam)
- Fixed file template dropdown for the "New File" editor for smaller/zoomed screens.
- Fix Route#rename_children behavior.
- Add nested groups support on data level.
- Fixed file template dropdown for the "New File" editor for smaller/zoomed screens.
- Allow projects with 'dashboard' as path.
- Whitelist next project names: notes, services.
- Disabled emoji buttons when user is not logged in.
- Remove unused and void services from the database.
- Add issue search slash command.
- Accept issue new as command to create an issue.
......@@ -46,7 +45,7 @@ entry.
- Fixed timeago re-rendering every timeago.
- Enable ColorVariable in scss-lint. (Sam Rose)
- Various small emoji positioning adjustments.
- Disabled emoji buttons when user is not logged in.
- Add shortcuts for adding users to a project team with a specific role. (Nikolay Ponomarev and Dino M)
- Additional rounded label fixes.
- Remove unnecessary database indices.
- 24726 Remove Across GitLab from side navigation.
......@@ -85,7 +84,7 @@ entry.
- 25617 Fix placeholder color of todo filters.
- Made the padding on the plus button in the breadcrumb menu even. (Ryan Harris)
- Allow to delete tag release note.
- Don't delete branches/tags that contains changes only in the remote mirror. !968
- Ensure nil User-Agent doesn't break the CI API.
- Replace Rack::Multipart with GitLab-Workhorse based solution. !5867
- Add scopes for personal access tokens and OAuth tokens. !5951
- API: Endpoint to expose personal snippets as /snippets. !6373 (Bernard Guyzmo Pratz)
......@@ -182,7 +181,7 @@ entry.
- Allow all alphanumeric characters in file names. !8002 (winniehell)
- Added support for math rendering, using KaTeX, in Markdown and asciidoc. !8003 (Munken)
- Remove unnecessary commits order message. !8004
- API: Memoize the current_user so that the sudo can work properly. !8017
- API: Memoize the current_user so that sudo can work properly. !8017
- group authors in contribution graph with case insensitive email handle comparison. !8021
- Move admin active tab spinach tests to rspec. !8037 (Semyon Pupkov)
- Add Authentiq as Oauth provider. !8038 (Alexandros Keramidas)
......
8.14.0-ee-pre
8.16.0-ee-pre
......@@ -143,11 +143,6 @@
case 'projects:merge_requests:commits':
new MergedButtons();
break;
case 'projects:merge_requests:pipelines':
new gl.MiniPipelineGraph({
container: '.js-pipeline-table',
});
break;
case "projects:merge_requests:diffs":
new gl.Diff();
new ZenMode();
......
......@@ -74,15 +74,16 @@
// The below is taken from At.js source
// Tweaked to commands to start without a space only if char before is a non-word character
// https://github.com/ichord/At.js
var _a, _y, regexp, match, atSymbols;
atSymbols = Object.keys(this.app.controllers).join('|');
var _a, _y, regexp, match, atSymbolsWithBar, atSymbolsWithoutBar;
atSymbolsWithBar = Object.keys(this.app.controllers).join('|');
atSymbolsWithoutBar = Object.keys(this.app.controllers).join('');
subtext = subtext.split(' ').pop();
flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
_a = decodeURI("%C3%80");
_y = decodeURI("%C3%BF");
regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?![" + atSymbols + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
match = regexp.exec(subtext);
......
......@@ -259,6 +259,10 @@
gl.utils.localTimeAgo($('.js-timeago', '#pipelines'));
this.pipelinesLoaded = true;
this.scrollToElement('#pipelines');
new gl.MiniPipelineGraph({
container: '.js-pipeline-table',
});
},
});
}
......
......@@ -98,7 +98,7 @@
}
.label {
padding: 8px 9px 9px;
padding: 8px 9px 9px $gl-padding;
font-size: 14px;
}
}
......
......@@ -25,12 +25,6 @@
}
.issuable-row {
.color-label {
border-radius: 2px;
padding: 3px !important;
margin-right: 7px;
}
span a {
color: $gl-text-color;
word-wrap: break-word;
......
......@@ -52,6 +52,10 @@
}
}
.content-list.pipelines .table-holder {
min-height: 300px;
}
.pipeline-holder {
width: 100%;
overflow: auto;
......@@ -593,6 +597,27 @@
}
}
}
.grouped-pipeline-dropdown {
.dropdown-build {
.build-content {
width: 100%;
&:hover {
background-color: $stage-hover-bg;
color: $gl-text-color;
}
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
position: absolute;
top: 1px;
right: 8px;
}
}
}
}
.dropdown-counter-badge {
......@@ -603,9 +628,11 @@
margin-right: 2px;
}
.grouped-pipeline-dropdown {
padding: 0;
width: 191px;
min-width: 191px;
left: auto;
right: -195px;
top: -4px;
......@@ -615,11 +642,22 @@
display: inline-block;
}
.dropdown-build {
.build-content {
width: 138px;
width: 100%;
&:hover {
background-color: $stage-hover-bg;
color: $gl-text-color;
}
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
position: absolute;
margin-top: 3px;
right: 7px;
}
}
......@@ -629,12 +667,10 @@
margin: 3px 0;
li {
padding-top: 2px;
margin: 4px 7px;
padding: 0 3px;
padding-left: 0;
padding-bottom: 0;
line-height: 0;
margin: 4px 8px 4px 9px;
padding: 0;
line-height: 1.1;
position: relative;
.ci-action-icon-container:hover {
background-color: transparent;
......@@ -648,6 +684,11 @@
}
}
.pipeline-graph .dropdown-build .ci-status-icon svg {
width: 18px;
height: 18px;
}
.ci-status-text {
max-width: 110px;
white-space: nowrap;
......@@ -656,7 +697,7 @@
vertical-align: bottom;
display: inline-block;
position: relative;
font-weight: 100;
font-weight: 200;
}
// Action Icons
......@@ -693,7 +734,7 @@
color: $gl-text-color-light;
.build-content {
padding: 3px 7px 6px;
padding: 4px 7px 8px;
}
.ci-action-icon-container {
......
......@@ -105,8 +105,8 @@ module IssuablesHelper
if issuable.tasks?
output << "&ensp;".html_safe
output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs")
output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-sm hidden-md hidden-lg")
output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs hidden-sm")
output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-md hidden-lg")
end
output
......
......@@ -35,7 +35,7 @@ module TodosHelper
else
path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target]
path.unshift(:builds) if todo.build_failed?
path.unshift(:pipelines) if todo.build_failed?
polymorphic_path(path, anchor: anchor)
end
......
......@@ -46,6 +46,6 @@ class MattermostSlashCommandsService < ChatSlashCommandsService
description: "Perform common operations on: #{pretty_project_name}",
display_name: "GitLab / #{pretty_project_name}",
method: 'P',
user_name: 'GitLab')
username: 'GitLab')
end
end
......@@ -16,7 +16,7 @@ class SlackSlashCommandsService < ChatSlashCommandsService
def trigger(params)
# Format messages to be Slack-compatible
super.tap do |result|
result[:text] = format(result[:text])
result[:text] = format(result[:text]) if result.is_a?(Hash)
end
end
......
......@@ -710,8 +710,7 @@ class Repository
end
def last_commit_for_path(sha, path)
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
sha = last_commit_id_for_path(sha, path)
commit(sha)
end
......@@ -724,6 +723,15 @@ class Repository
end
end
def last_commit_id_for_path(sha, path)
key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}"
cache.fetch(key) do
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
Gitlab::Popen.popen(args, path_to_repo).first.strip
end
end
def next_branch(name, opts = {})
branch_ids = self.branch_names.map do |n|
next 1 if n == name
......
%ul
- @stage.statuses.each do |status|
- @stage.statuses.latest.each do |status|
%li.dropdown-build
= render 'ci/status/graph_badge', subject: status
- group_status = CommitStatus.where(id: subject).status
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown'} }
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown', title: "#{name} - #{group_status}" } }
%span{class: "ci-status-icon ci-status-icon-#{group_status}"}
= ci_icon_for_status(group_status)
%span.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{name} - #{group_status}" }
%span.ci-status-text
= name
%span.dropdown-counter-badge= subject.size
.dropdown-menu.grouped-pipeline-dropdown
......
---
title: Change earlier to task_status_short to avoid titlebar line wraps
merge_request:
author:
---
title: Fix Pipeline builds list blank on MR
merge_request: 8255
author:
---
title: Do not show retried builds in pipeline stage dropdown
merge_request: 8260
author:
---
title: Fix Mattermost command creation by specifying username
merge_request:
author:
---
title: Add Gitaly to the architecture documentation
merge_request: 8264
author: Pablo Carranza <pablo@gitlab.com>
......@@ -20,9 +20,10 @@ The list of supported autodeploy templates is available [here][autodeploy-templa
## Configuration
1. Enable a deployment [project service][project-services] to store your
credentials. For example, if you want to deploy to a Kubernetes cluster
you have to enable [Kubernetes service][kubernetes-service].
1. Configure GitLab Runner to use [docker-in-docker executor][docker-in-docker].
credentials. For example, if you want to deploy to OpenShift you have to
enable [Kubernetes service][kubernetes-service].
1. Configure GitLab Runner to use Docker or Kubernetes executor with
[privileged mode enabled][docker-in-docker].
1. Navigate to the "Project" tab and click "Set up autodeploy" button.
![Autodeploy button](img/autodeploy_button.png)
1. Select a template.
......
......@@ -34,7 +34,7 @@ production:
This project has three jobs:
1. `test` - used to test Rails application,
2. `staging` - used to automatically deploy staging environment every push to `master` branch
3. `production` - used to automatically deploy production environmnet for every created tag
3. `production` - used to automatically deploy production environment for every created tag
### Store API keys
You'll need to create two variables in `Project > Variables`:
......
......@@ -6,7 +6,7 @@ There are two editions of GitLab: [Enterprise Edition](https://about.gitlab.com/
EE releases are available not long after CE releases. To obtain GitLab EE there is a [repository at gitlab.com](https://gitlab.com/gitlab-org/gitlab-ee). For more information about the release process see the section 'New versions and upgrading' in the readme.
Both EE and CE require an add-on component called gitlab-shell. It is obtained from the [gitlab-shell repository](https://gitlab.com/gitlab-org/gitlab-shell/tree/master). New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
Both EE and CE require some add-on components called gitlab-shell and Gitaly. These components are available from the [gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell/tree/master) and [gitaly](https://gitlab.com/gitlab-org/gitaly/tree/master) repositories respectively. New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
## Physical office analogy
......@@ -35,8 +35,10 @@ Their job description:
- make tasks for Sidekiq;
- fetch stuff from the warehouse or move things around in there;
**Gitlab-shell** is a third kind of worker that takes orders from a fax machine (SSH) instead of the front desk (HTTP).
Gitlab-shell communicates with Sidekiq via the “communication board” (Redis), and asks quick questions of the Unicorn workers either directly or via the front desk.
**GitLab-shell** is a third kind of worker that takes orders from a fax machine (SSH) instead of the front desk (HTTP).
GitLab-shell communicates with Sidekiq via the “communication board” (Redis), and asks quick questions of the Unicorn workers either directly or via the front desk.
**Gitaly** is a back desk that is specialized on reaching the disks to perform git operations efficiently and keep a copy of the result of costly operations. All git operations go through Gitaly.
**GitLab Enterprise Edition (the application)** is the collection of processes and business practices that the office is run by.
......@@ -62,7 +64,9 @@ The GitLab web app uses MySQL or PostgreSQL for persistent database information
When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects.
The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories directly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access.
The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories through Gitaly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access.
Gitaly executes git operations from gitlab-shell and Workhorse, and provides an API to the GitLab web app to get attributes from git (e.g. title, branches, tags, other meta data), and to get blobs (e.g. diffs, commits, files)
### Installation Folder Summary
......
# Chat Commands
Chat commands allow user to perform common operations on GitLab right from there chat client.
Right now both Mattermost and Slack are supported.
## Available commands
The trigger is configurable, but for the sake of this example, we'll use `/trigger`
* `/trigger help` - Displays all available commands for this user
* `/trigger issue new <title> <shift+return> <description>` - creates a new issue on the project
* `/trigger issue show <id>` - Shows the issue with the given ID, if you've got access
* `/trigger issue search <query>` - Shows a maximum of 5 items matching the query
* `/trigger deploy <from> to <to>` - Deploy from an environment to another
......@@ -14,12 +14,18 @@ If you have the Omnibus GitLab package installed, Mattermost is already bundled
in it. All you have to do is configure it. Read more in the
[Omnibus GitLab Mattermost documentation][omnimmdocs].
## Configuration
## Automated Configuration
If Mattermost is installed on the same server as GitLab, the configuration process can be
done for you by GitLab.
Go to the Mattermost Slash Command service on your project and click the 'Add to Mattermost' button.
## Manual Configuration
The configuration consists of two parts. First you need to enable the slash
commands in Mattermost and then enable the service in GitLab.
### Step 1. Enable custom slash commands in Mattermost
This step is only required when using a source install, omnibus installs will be
......
# Slack slash commands
> Introduced in GitLab 8.15
Slack commands give users an extra interface to perform common operations
from the chat environment. This allows one to, for example, create an issue as
soon as the idea was discussed in chat.
For all available commands try the help subcommand, for example: `/gitlab help`,
all review the [full list of commands](../integrations/chat_commands.md).
## Prerequisites
A [team](https://get.slack.help/hc/en-us/articles/217608418-Creating-a-team) in Slack should be created beforehand, GitLab cannot create it for you.
## Configuration
First, navigate to the Slack Slash commands service page, found at your project's
**Settings** > **Services**, and you find the instructions there:
![Slack setup instructions](img/slack_setup.png)
Once you've followed the instructions, mark the service as active and insert the token
you've received from Slack. After saving the service you are good to go!
......@@ -51,13 +51,15 @@ are resolved.
![Only allow merge if all the discussions are resolved message](img/only_allow_merge_if_all_discussions_are_resolved_msg.png)
### Move all unresolved discussions in a merge request to an issue
## Move all unresolved discussions in a merge request to an issue
> [Introduced][ce-7180] (Currently on Backlog)
> [Introduced][ce-7180] in GitLab 8.15.
To delegate unresolved discussions to a new issue you can click the link **open
an issue to resolve them later**.
![Open new issue from unresolved discussions](img/resolve_discussion_open_issue.png)
This will prepare an issue with content referring to the merge request and
discussions.
......@@ -66,6 +68,8 @@ discussions.
Hitting **Submit issue** will cause all discussions to be marked as resolved and
add a note referring to the newly created issue.
![Mark discussions as resolved notice](img/resolve_discussion_issue_notice.png)
You can now proceed to merge the merge request from the UI.
[ce-5022]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5022
......
......@@ -68,7 +68,7 @@ module API
ref: params[:ref],
blob_id: blob.id,
commit_id: commit.id,
last_commit_id: repo.last_commit_for_path(commit.sha, params[:file_path]).id
last_commit_id: repo.last_commit_id_for_path(commit.sha, params[:file_path])
}
end
......
......@@ -37,8 +37,6 @@ module API
optional :labels, type: String, desc: 'Comma-separated list of label names'
optional :due_date, type: String, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :confidential, type: Boolean, desc: 'Boolean parameter if the issue should be confidential'
optional :state_event, type: String, values: %w[open close],
desc: 'State of the issue'
end
end
......@@ -172,6 +170,7 @@ module API
optional :title, type: String, desc: 'The title of an issue'
optional :updated_at, type: DateTime,
desc: 'Date time when the issue was updated. Available only for admins and project owners.'
optional :state_event, type: String, values: %w[reopen close], desc: 'State of the issue'
use :issue_params
at_least_one_of :title, :description, :assignee_id, :milestone_id,
:labels, :created_at, :due_date, :confidential, :state_event
......
......@@ -5,12 +5,6 @@ module Banzai
# HTML filter that adds class="code math" and removes the dollar sign in $`2+2`$.
#
class MathFilter < HTML::Pipeline::Filter
# This picks out <code>...</code>.
INLINE_MATH = 'descendant-or-self::code'.freeze
# Pick out a code block which is declared math
DISPLAY_MATH = "descendant-or-self::pre[contains(@class, 'math') and contains(@class, 'code')]".freeze
# Attribute indicating inline or display math.
STYLE_ATTRIBUTE = 'data-math-style'.freeze
......@@ -22,13 +16,14 @@ module Banzai
DOLLAR_SIGN = '$'.freeze
def call
doc.xpath(INLINE_MATH).each do |code|
doc.css('code').each do |code|
closing = code.next
opening = code.previous
# We need a sibling before and after.
# They should end and start with $ respectively.
if closing && opening &&
closing.text? && opening.text? &&
closing.content.first == DOLLAR_SIGN &&
opening.content.last == DOLLAR_SIGN
......@@ -39,7 +34,7 @@ module Banzai
end
end
doc.xpath(DISPLAY_MATH).each do |el|
doc.css('pre.code.math').each do |el|
el[STYLE_ATTRIBUTE] = 'display'
el[:class] += " #{TAG_CLASS}"
end
......
......@@ -21,6 +21,7 @@ FactoryGirl.define do
trait :build_failed do
action { Todo::BUILD_FAILED }
target factory: :merge_request
end
trait :approval_required do
......
......@@ -47,6 +47,24 @@ feature 'GFM autocomplete', feature: true, js: true do
expect_to_wrap(true, label_item, note, label.title)
end
it "does not show drpdown when preceded with a special character" do
note = find('#note_note')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys("@")
note.click
end
expect(page).to have_selector('.atwho-container')
page.within '.timeline-content-form' do
note.native.send_keys("@")
note.click
end
expect(page).to have_selector('.atwho-container', visible: false)
end
it 'doesn\'t wrap for assignee values' do
note = find('#note_note')
page.within '.timeline-content-form' do
......
......@@ -155,5 +155,24 @@ describe 'Dashboard Todos', feature: true do
expect(page).to have_selector('.todos-all-done', count: 1)
end
end
context 'User has a Build Failed todo' do
let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) }
before do
login_as user
visit dashboard_todos_path
end
it 'shows the todo' do
expect(page).to have_content 'The build failed for your merge request'
end
it 'links to the pipelines for the merge request' do
href = pipelines_namespace_project_merge_request_path(project.namespace, project, todo.target)
expect(page).to have_link "merge request #{todo.target.to_reference}", href
end
end
end
end
......@@ -79,6 +79,13 @@ describe Banzai::Filter::MathFilter, lib: true do
expect(doc.to_s).to eq input
end
it 'ignores dollar signs if they are inside another element' do
input = '<p>We check strictly <em>$</em><code>2+2</code><em>$</em></p>'
doc = filter(input)
expect(doc.to_s).to eq input
end
# Display math
it 'adds data-math-style display attribute to display math' do
......
......@@ -36,7 +36,7 @@ describe MattermostSlashCommandsService, :models do
description: "Perform common operations on: #{project.name_with_namespace}",
display_name: "GitLab / #{project.name_with_namespace}",
method: 'P',
user_name: 'GitLab' }.to_json).
username: 'GitLab' }.to_json).
to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
......
......@@ -18,7 +18,8 @@ describe SlackSlashCommandsService, :models do
let(:service) do
project.create_slack_slash_commands_service(
properties: { token: 'token' }
properties: { token: 'token' },
active: true
)
end
......
......@@ -139,6 +139,22 @@ describe Repository, models: true do
it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
end
describe '#last_commit_id_for_path' do
subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') }
it "returns last commit id for a given path" do
is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8')
end
it "caches last commit id for a given path" do
cache = repository.send(:cache)
key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}"
expect(cache).to receive(:fetch).with(key).and_return('c1acaa5')
is_expected.to eq('c1acaa5')
end
end
describe '#find_commits_by_message' do
it 'returns commits with messages containing a given string' do
commit_ids = repository.find_commits_by_message('submodule').map(&:id)
......
......@@ -932,6 +932,13 @@ describe API::Issues, api: true do
expect(json_response['state']).to eq "closed"
end
it 'reopens a project isssue' do
put api("/projects/#{project.id}/issues/#{closed_issue.id}", user), state_event: 'reopen'
expect(response).to have_http_status(200)
expect(json_response['state']).to eq 'reopened'
end
context 'when an admin or owner makes the request' do
it 'accepts the update date to be set' do
update_time = 2.weeks.ago
......
......@@ -7,7 +7,10 @@ describe 'projects/pipelines/_stage', :view do
before do
assign :stage, stage
end
context 'when there are only latest builds present' do
before do
create(:ci_build, name: 'test:build',
stage: stage.name,
pipeline: pipeline)
......@@ -18,4 +21,33 @@ describe 'projects/pipelines/_stage', :view do
expect(rendered).to have_text 'test:build'
end
end
context 'when build belongs to different stage' do
before do
create(:ci_build, name: 'test:build',
stage: 'other:stage',
pipeline: pipeline)
end
it 'does not render build' do
render
expect(rendered).not_to have_text 'test:build'
end
end
context 'when there are retried builds present' do
before do
create_list(:ci_build, 2, name: 'test:build',
stage: stage.name,
pipeline: pipeline)
end
it 'shows only latest builds' do
render
expect(rendered).to have_text 'test:build', count: 1
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment