Commit 83ad5de6 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'master' into fl-eslint-vue-house-keeping

* master: (47 commits)
  Bumping gitlab-gollum-lib and gitlab-gollum-rugged_adapter
  i18n: document how to use links without splitting sentences
  Resolve "[Rails5] `ActionView::MissingTemplate` in spec/features/projects/wiki/user_views_wiki_page_spec.rb"
  Add CI job to check Gemfile.rails5.lock
  Add navigation theme documentation
  Move Gitaly branch/tag/ref RPC's to opt-out
  Add CI_{PIPELINE,JOB}_URL
  Resolve "Update docs as GKE cluster creation label has changed from "project ID" to "project""
  fixed/enhanced command-line documentation
  Use nip.io instead of xip.io
  [Rails5] Update Gitlab.rails5.lock
  Fix typo in doc/development/README.md
  Update import screenshot without LFS warning
  Hide overflow on hr
  Resolve "Milestone and labels dropdowns are misplaced with collapsed sidebar"
  Fix collapse sidebar button color
  Remove .row and .col-sm-12
  Relax expectation in spec/models/project_spec.rb
  fix padding in commit info
  GitHub Rake importer: Fail with a clearer explanation if GitLab username is wrong
  ...
parents 7f570348 d94b1621
......@@ -415,6 +415,7 @@ setup-test-env:
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here
- BUNDLE_GEMFILE=Gemfile.rails5 bundle install $BUNDLE_INSTALL_FLAGS
artifacts:
expire_in: 7d
paths:
......@@ -590,6 +591,12 @@ downtime_check:
- /(^docs[\/-].*|.*-docs$)/
- /(^qa[\/-].*|.*-qa$)/
rails5_gemfile_lock_check:
<<: *dedicated-no-docs-no-db-pull-cache-job
<<: *except-docs-and-qa
script:
- scripts/rails5-gemfile-lock-check
ee_compat_check:
<<: *rake-exec
except:
......
......@@ -296,7 +296,7 @@ GEM
flowdock (~> 0.7)
gitlab-grit (>= 2.4.1)
multi_json
gitlab-gollum-lib (4.2.7.2)
gitlab-gollum-lib (4.2.7.4)
gemojione (~> 3.2)
github-markup (~> 1.6)
gollum-grit_adapter (~> 1.0)
......@@ -304,7 +304,7 @@ GEM
rouge (~> 3.1)
sanitize (~> 2.1)
stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4)
gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15)
rugged (~> 0.25)
gitlab-grit (2.8.2)
......
......@@ -315,7 +315,7 @@ GEM
diff-lcs (~> 1.1)
mime-types (>= 1.16)
posix-spawn (~> 0.3)
gitlab-markup (1.6.3)
gitlab-markup (1.6.4)
gitlab-styles (2.3.2)
rubocop (~> 0.51)
rubocop-gitlab-security (~> 0.1.0)
......@@ -751,36 +751,36 @@ GEM
chunky_png
rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2)
rspec (3.6.0)
rspec-core (~> 3.6.0)
rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.6.0)
rspec-core (3.6.0)
rspec-support (~> 3.6.0)
rspec-expectations (3.6.0)
rspec (3.7.0)
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-core (3.7.1)
rspec-support (~> 3.7.0)
rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0)
rspec-mocks (3.6.0)
rspec-support (~> 3.7.0)
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0)
rspec-support (~> 3.7.0)
rspec-parameterized (0.4.0)
binding_of_caller
parser
proc_to_ast
rspec (>= 2.13, < 4)
unparser
rspec-rails (3.6.0)
rspec-rails (3.7.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.6.0)
rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.6.0)
rspec-support (~> 3.6.0)
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-support (~> 3.7.0)
rspec-retry (0.4.5)
rspec-core
rspec-set (0.1.3)
rspec-support (3.6.0)
rspec-support (3.7.1)
rspec_profiling (0.0.5)
activerecord
pg
......@@ -1054,7 +1054,7 @@ DEPENDENCIES
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2)
gitlab-gollum-rugged_adapter (~> 0.4.4)
gitlab-markup (~> 1.6.2)
gitlab-markup (~> 1.6.4)
gitlab-styles (~> 2.3)
gitlab_omniauth-ldap (~> 2.0.4)
gon (~> 6.2)
......@@ -1152,7 +1152,7 @@ DEPENDENCIES
rouge (~> 3.1)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
rspec-rails (~> 3.6.0)
rspec-rails (~> 3.7.0)
rspec-retry (~> 0.4.5)
rspec-set (~> 0.1.3)
rspec_profiling (~> 0.0.5)
......
......@@ -185,11 +185,7 @@ next patch release.
If a merge request is to be picked into more than one release it will need one
`Pick into X.Y` label per release where the merge request should be back-ported
to.
For example, if the current patch release is `10.1.1` and a regression fix needs
to be backported down to the `9.5` release, you will need to assign it the
`10.1` milestone and the following labels:
to. For example:
- `Pick into 10.1`
- `Pick into 10.0`
......
......@@ -8,4 +8,5 @@ export default {
OK: 200,
MULTIPLE_CHOICES: 300,
BAD_REQUEST: 400,
NOT_FOUND: 404,
};
......@@ -89,6 +89,10 @@ a {
color: $gl-link-color;
}
hr {
overflow: hidden;
}
.form-group.row .col-form-label {
// Bootstrap 4 aligns labels to the left
// for horizontal forms
......@@ -209,6 +213,10 @@ table {
border-bottom: 1px solid $well-inner-border;
}
}
.badge.badge-gray {
background-color: $well-expand-item;
}
}
.card {
......@@ -258,9 +266,17 @@ pre code {
.alert-danger {
background-color: $red-500;
border-color: $red-500;
}
.alert-warning,
.alert-danger,
.flash-notice {
border-radius: 0;
color: $white-light;
h4 {
h4,
a,
.alert-link {
color: $white-light;
}
}
......@@ -268,3 +284,11 @@ pre code {
input[type=color].form-control {
height: $input-height;
}
.toggle-sidebar-button {
.collapse-text,
.icon-angle-double-left,
.icon-angle-double-right {
color: $gl-text-color-secondary;
}
}
......@@ -305,14 +305,6 @@ img.emoji {
margin-bottom: 10px;
}
.btn-sign-in {
text-shadow: none;
@include media-breakpoint-up(sm) {
margin-top: 8px;
}
}
.side-filters {
fieldset {
margin-bottom: 15px;
......
......@@ -170,7 +170,7 @@ label {
}
.form-control::-webkit-input-placeholder {
color: $gl-text-color-secondary;
color: $placeholder-text-color;
}
.input-group {
......
......@@ -447,12 +447,16 @@
.btn-sign-in {
background-color: $indigo-100;
color: $indigo-900;
margin-top: 3px;
font-weight: $gl-font-weight-bold;
line-height: 18px;
&:hover {
background-color: $white-light;
}
@include media-breakpoint-down(xs) {
margin-top: $gl-padding-4;
}
}
.navbar-nav {
......
......@@ -4,3 +4,11 @@
text-decoration: none;
}
}
.page-item {
&.active {
.page-link {
z-index: 3;
}
}
}
......@@ -4,7 +4,7 @@
padding: 0;
&::before {
@include notes-media('max', map-get($grid-breakpoints, xs)) {
@include notes-media('max', map-get($grid-breakpoints, sm)) {
background: none;
}
}
......@@ -34,7 +34,7 @@
.timeline-entry-inner {
position: relative;
@include notes-media('max', map-get($grid-breakpoints, xs)) {
@include notes-media('max', map-get($grid-breakpoints, sm)) {
.timeline-icon {
display: none;
}
......
......@@ -99,7 +99,7 @@ $theme-gray-200: #dfdfdf;
$theme-gray-300: #cccccc;
$theme-gray-400: #bababa;
$theme-gray-500: #a7a7a7;
$theme-gray-600: #949494;
$theme-gray-600: #919191;
$theme-gray-700: #707070;
$theme-gray-800: #4f4f4f;
$theme-gray-900: #2e2e2e;
......@@ -191,7 +191,7 @@ $gl-font-weight-normal: 400;
$gl-font-weight-bold: 600;
$gl-text-color: #2e2e2e;
$gl-text-color-secondary: #707070;
$gl-text-color-tertiary: #949494;
$gl-text-color-tertiary: #919191;
$gl-text-color-quaternary: #d6d6d6;
$gl-text-color-inverted: rgba(255, 255, 255, 1);
$gl-text-color-secondary-inverted: rgba(255, 255, 255, 0.85);
......@@ -434,6 +434,22 @@ $gl-btn-horz-padding: 12px;
$badge-bg: rgba(0, 0, 0, 0.07);
$badge-color: $gl-text-color-secondary;
/*
* Pagination
*/
$pagination-padding-y: 6px;
$pagination-padding-x: 16px;
$pagination-line-height: 20px;
$pagination-border-color: $border-color;
$pagination-active-bg: $blue-600;
$pagination-active-border-color: $blue-600;
$pagination-hover-bg: $blue-50;
$pagination-hover-border-color: $border-color;
$pagination-hover-color: $gl-text-color;
$pagination-disabled-color: #cdcdcd;
$pagination-disabled-bg: $gray-light;
$pagination-disabled-border-color: $border-color;
/*
* Status icons
*/
......
......@@ -1129,7 +1129,7 @@
.ide-context-header {
.avatar {
flex: 0 0 40px;
flex: 0 0 38px;
}
.ide-merge-requests-dropdown.dropdown-menu {
......
......@@ -29,7 +29,7 @@ input[type="checkbox"]:hover {
}
.search {
margin: 4px 8px 0;
margin: 0 8px;
form {
@extend .form-control;
......
......@@ -611,6 +611,7 @@ module Ci
variables
.concat(pipeline.persisted_variables)
.append(key: 'CI_JOB_ID', value: id.to_s)
.append(key: 'CI_JOB_URL', value: Gitlab::Routing.url_helpers.project_job_url(project, self))
.append(key: 'CI_JOB_TOKEN', value: token, public: false)
.append(key: 'CI_BUILD_ID', value: id.to_s)
.append(key: 'CI_BUILD_TOKEN', value: token, public: false)
......
......@@ -549,7 +549,10 @@ module Ci
def persisted_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_PIPELINE_ID', value: id.to_s) if persisted?
break variables unless persisted?
variables.append(key: 'CI_PIPELINE_ID', value: id.to_s)
variables.append(key: 'CI_PIPELINE_URL', value: Gitlab::Routing.url_helpers.project_pipeline_url(project, self))
end
end
......
......@@ -1616,6 +1616,7 @@ class Project < ActiveRecord::Base
def after_import
repository.after_import
wiki.repository.after_import
import_finish
remove_import_jid
update_project_counter_caches
......@@ -2139,10 +2140,14 @@ class Project < ActiveRecord::Base
check_access = -> do
next false if empty_repo?
merge_request = source_of_merge_requests.opened
merge_requests = source_of_merge_requests.opened
.where(allow_collaboration: true)
.find_by(source_branch: branch_name)
merge_request&.can_be_merged_by?(user)
if branch_name
merge_requests.find_by(source_branch: branch_name)&.can_be_merged_by?(user)
else
merge_requests.any? { |merge_request| merge_request.can_be_merged_by?(user) }
end
end
if RequestStore.active?
......
......@@ -22,10 +22,10 @@ module ObjectStorage
module RecordsUploads
extend ActiveSupport::Concern
def prepended(base)
prepended do |base|
raise "#{base} must include ObjectStorage::Concern to use extensions." unless base < Concern
base.include(RecordsUploads::Concern)
base.include(::RecordsUploads::Concern)
end
def retrieve_from_store!(identifier)
......
......@@ -43,5 +43,6 @@
%span.toggle-icon
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
= render_if_exists 'ci/variables/environment_scope', form_field: form_field, variable: variable
%button.js-row-remove-button.ci-variable-row-remove-button{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
= icon('minus-circle')
......@@ -37,6 +37,6 @@
.form-group
= file_field_tag :file, class: ''
.row
.form-actions
.form-actions.col-sm-12
= submit_tag 'Import project', class: 'btn btn-create'
= link_to 'Cancel', new_project_path, class: 'btn btn-cancel'
......@@ -61,7 +61,7 @@
- if header_link?(:sign_in)
%li.nav-item
%div
= link_to "Sign in / Register", new_session_path(:user, redirect_to_referer: 'yes'), class: 'nav-link btn btn-sign-in'
= link_to "Sign in / Register", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in'
%button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
%span.sr-only Toggle navigation
......
......@@ -20,11 +20,11 @@
%span{ "aria-hidden": true } &times;
.modal-body
- if description
%p.append-bottom-20= description
%p= description
= form_tag [type.underscore, @project.namespace.becomes(Namespace), @project, commit], method: :post, remote: false, class: "js-#{type}-form js-requires-input" do
.form-group.row.branch
= label_tag 'start_branch', branch_label, class: 'col-form-label col-sm-2'
.col-sm-10
.form-group.branch
= label_tag 'start_branch', branch_label, class: 'label-light'
= hidden_field_tag :start_branch, @project.default_branch, id: 'start_branch'
= dropdown_tag(@project.default_branch, options: { title: s_("BranchSwitcherTitle|Switch branch"), filter: true, placeholder: s_("BranchSwitcherPlaceholder|Search branches"), toggle_class: 'js-project-refs-dropdown dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "start_branch", selected: @project.default_branch, start_branch: @project.default_branch, refs_url: project_branches_path(@project), submit_form_on_click: false } })
......
......@@ -6,7 +6,7 @@
- if @branches.any? || @tags.any? || @tags_limit_exceeded
%span
= link_to "#", class: "js-details-expand label label-gray ref-name" do
= link_to "#", class: "js-details-expand badge badge-gray ref-name" do
= sprite_icon('ellipsis_h', size: 12, css_class: 'vertical-align-middle')
%span.js-details-content.hide
= commit_branches_links(@project, @branches)
......
......@@ -13,7 +13,7 @@
= form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name), html: { class: 'common-note-form release-form js-quick-submit' }) do |f|
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here..."
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here"
= render 'shared/notes/hints'
.error-alert
.prepend-top-default
......
......@@ -36,7 +36,7 @@
= label_tag :release_description, s_('TagsPage|Release notes'), class: 'col-form-label col-sm-2'
.col-sm-10
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
= render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here...'), current_text: @release_description
= render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here'), current_text: @release_description
= render 'shared/notes/hints'
.form-text.text-muted
= s_('TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page.')
......
......@@ -25,7 +25,7 @@
.col-sm-12= f.label :content, class: 'control-label-full-width'
.col-sm-12
= render layout: 'projects/md_preview', locals: { url: project_wiki_preview_markdown_path(@project, @page.slug) } do
= render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: s_("WikiPage|Write your content or drag files here...")
= render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: s_("WikiPage|Write your content or drag files here")
= render 'shared/notes/hints'
.clearfix
......
.form-check
.form-check.prepend-top-8
- nonce = SecureRandom.hex
= check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request form-check-input', id: "create_merge_request-#{nonce}"
= label_tag "create_merge_request-#{nonce}", class: 'form-check-label' do
......
......@@ -16,7 +16,7 @@
= render layout: 'projects/md_preview', locals: { url: preview_url, referenced_users: true } do
= render 'projects/zen', f: form, attr: :description,
classes: 'note-textarea qa-issuable-form-description',
placeholder: "Write a comment or drag your files here...",
placeholder: "Write a comment or drag your files here",
supports_quick_actions: supports_quick_actions
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
.clearfix
......
......@@ -43,7 +43,7 @@
.selectbox.hide-collapsed
= f.hidden_field 'milestone_id', value: issuable.milestone_id, id: nil
= dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable.to_ability_name}[milestone_id]", project_id: @project.id, issuable_id: issuable.id, milestones: project_milestones_path(@project, :json), ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), use_id: true, default_no: true, selected: (issuable.milestone.name if issuable.milestone), null_default: true }})
= dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable.to_ability_name}[milestone_id]", project_id: @project.id, issuable_id: issuable.id, milestones: project_milestones_path(@project, :json), ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), use_id: true, default_no: true, selected: (issuable.milestone.name if issuable.milestone), null_default: true, display: 'static' }})
- if issuable.has_attribute?(:time_estimate)
#issuable-time-tracker.block
// Fallback while content is loading
......@@ -77,7 +77,7 @@
.selectbox.hide-collapsed
= f.hidden_field :due_date, value: issuable.due_date.try(:strftime, 'yy-mm-dd')
.dropdown
%button.dropdown-menu-toggle.js-due-date-select{ type: 'button', data: { toggle: 'dropdown', field_name: "#{issuable.to_ability_name}[due_date]", ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable) } }
%button.dropdown-menu-toggle.js-due-date-select{ type: 'button', data: { toggle: 'dropdown', field_name: "#{issuable.to_ability_name}[due_date]", ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), display: 'static' } }
%span.dropdown-toggle-text
= _('Due date')
= icon('chevron-down', 'aria-hidden': 'true')
......@@ -109,7 +109,7 @@
- selected_labels.each do |label|
= hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil
.dropdown
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path(false) if @project) } }
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path(false) if @project), display: 'static' } }
%span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
= multi_label_name(selected_labels, "Labels")
= icon('chevron-down', 'aria-hidden': 'true')
......
......@@ -37,7 +37,7 @@
- issuable.assignees.each do |assignee|
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }
- options = { toggle_class: 'js-user-search js-author-search', title: _('Assign to'), filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: _('Search users'), data: { first_user: current_user&.username, current_user: true, project_id: @project&.id, author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } }
- options = { toggle_class: 'js-user-search js-author-search', title: _('Assign to'), filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: _('Search users'), data: { first_user: current_user&.username, current_user: true, project_id: @project&.id, author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true, display: 'static' } }
- title = _('Select assignee')
- if issuable.is_a?(Issue)
......
......@@ -7,11 +7,11 @@
%hr
.form-group
.col-form-label
.form-group.row
%label.col-form-label.col-sm-2
= _('Contribution')
.col-sm-10
.form-check
.form-check.prepend-top-5
= form.check_box :allow_collaboration, disabled: !issuable.can_allow_collaboration?(current_user), class: 'form-check-input'
= form.label :allow_collaboration, class: 'form-check-label' do
= _('Allow commits from members who can merge to the target branch.')
......
......@@ -3,7 +3,7 @@
= hidden_field_tag :target_id, '', class: 'js-form-target-id'
= hidden_field_tag :target_type, '', class: 'js-form-target-type'
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(project), referenced_users: true } do
= render 'projects/zen', attr: 'note[note]', classes: 'note-textarea js-note-text js-task-list-field', placeholder: "Write a comment or drag your files here..."
= render 'projects/zen', attr: 'note[note]', classes: 'note-textarea js-note-text js-task-list-field', placeholder: "Write a comment or drag your files here"
= render 'shared/notes/hints'
.note-form-actions.clearfix
......
......@@ -29,7 +29,7 @@
= render 'projects/zen', f: f,
attr: :note,
classes: 'note-textarea js-note-text',
placeholder: "Write a comment or drag your files here...",
placeholder: "Write a comment or drag your files here",
supports_quick_actions: supports_quick_actions,
supports_autocomplete: supports_autocomplete
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
......
---
title: Make avatars/icons hidden on mobile
merge_request: 19585
author: Takuya Noguchi
type: fixed
---
title: Add CI job to check Gemfile.rails5.lock
merge_request: 19605
author: "@blackst0ne"
type: other
---
title: Fix bug where maintainer would not be allowed to push to forks with merge requests
that have `Allow maintainer edits` enabled.
merge_request: 18968
author:
type: fixed
---
title: Add Gitlab::SQL:CTE for easily building CTE statements
merge_request:
author:
type: added
---
title: Add CI_PIPELINE_URL and CI_JOB_URL
merge_request: 19618
author:
type: added
---
title: Fixed bug that allowed to remove other wiki pages if the title had wildcard characters
merge_request:
author:
type: fixed
---
title: Move Gitaly branch/tag/ref RPC's to opt-out
merge_request: 19644
author:
type: other
---
title: Expire Wiki content cache after importing a repository
merge_request:
author:
type: fixed
......@@ -6,7 +6,7 @@ scope(controller: :wikis) do
post '/', to: 'wikis#create'
end
scope(path: 'wikis/*id', as: :wiki, format: false) do
scope(path: 'wikis/*id', as: :wiki, format: false, defaults: { format: :html }) do
get :edit
get :history
post :preview_markdown
......
......@@ -100,14 +100,14 @@ As it's pointed out before, you will need public access to this machine that
you've installed Koding and GitLab on. Better to use a domain but a static IP
is also fine.
For IP based installation you can use [xip.io](https://xip.io) service which is
For IP based installation you can use [nip.io](https://nip.io) service which is
free and provides DNS resolution to IP based requests like following;
- 127.0.0.1.xip.io -> resolves to 127.0.0.1
- foo.bar.baz.127.0.0.1.xip.io -> resolves to 127.0.0.1
- 127.0.0.1.nip.io -> resolves to 127.0.0.1
- foo.bar.baz.127.0.0.1.nip.io -> resolves to 127.0.0.1
- and so on...
As Koding needs subdomains for team names; `foo.127.0.0.1.xip.io` requests for
As Koding needs subdomains for team names; `foo.127.0.0.1.nip.io` requests for
a running koding instance on `127.0.0.1` server will be handled as `foo` team
requests.
......@@ -127,8 +127,8 @@ your Koding installation. Team called `gitlab` has integration on Koding out
of the box, so if you didn't change anything your team on Koding should be
`gitlab`.
So, if your Koding is running on `http://1.2.3.4.xip.io:8090` your URL needs
to be `http://gitlab.1.2.3.4.xip.io:8090`. You need to provide the same host
So, if your Koding is running on `http://1.2.3.4.nip.io:8090` your URL needs
to be `http://gitlab.1.2.3.4.nip.io:8090`. You need to provide the same host
with your Koding installation here.
......@@ -192,7 +192,7 @@ cd koding
docker-compose run \
--service-ports backend \
/opt/koding/scripts/bootstrap-container build \
--host=**YOUR_IP**.xip.io \
--host=**YOUR_IP**.nip.io \
--gitlabHost=**GITLAB_IP** \
--gitlabPort=**GITLAB_PORT** \
--gitlabToken=**SECRET_TOKEN** \
......@@ -224,7 +224,7 @@ cd koding
docker-compose run \
--service-ports backend \
/opt/koding/scripts/bootstrap-container build \
--host=**YOUR_IP**.xip.io \
--host=**YOUR_IP**.nip.io \
```
#### Enable Single Sign On
......@@ -233,7 +233,7 @@ Once you restarted your Koding and logged in with your username and password
you need to activate oauth authentication for your user. To do that
- Navigate to Dashboard on Koding from;
`http://gitlab.**YOUR_IP**.xip.io:8090/Home/my-account`
`http://gitlab.**YOUR_IP**.nip.io:8090/Home/my-account`
- Scroll down to Integrations section
- Click on toggle to turn On integration in GitLab integration section
......
......@@ -64,6 +64,7 @@ future GitLab releases.**
| **CI_JOB_NAME** | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
| **CI_JOB_STAGE** | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_JOB_TOKEN** | 9.0 | 1.2 | Token used for authenticating with the GitLab Container Registry |
| **CI_JOB_URL** | 11.0 | 0.5 | Job details URL |
| **CI_REPOSITORY_URL** | 9.0 | all | The URL to clone the Git repository |
| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
| **CI_RUNNER_ID** | 8.10 | 0.5 | The unique id of runner being used |
......@@ -81,6 +82,7 @@ future GitLab releases.**
| **CI_PROJECT_NAMESPACE** | 8.10 | 0.5 | The project namespace (username or groupname) that is currently being built |
| **CI_PROJECT_PATH** | 8.10 | 0.5 | The namespace with project name |
| **CI_PROJECT_PATH_SLUG** | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
| **CI_PIPELINE_URL** | 11.0 | 0.5 | Pipeline details URL |
| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP address to access project |
| **CI_PROJECT_VISIBILITY** | 10.3 | all | The project visibility (internal, private, public) |
| **CI_REGISTRY** | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
......
......@@ -32,7 +32,7 @@ description: 'Learn how to contribute to GitLab.'
- [GitLab utilities](utilities.md)
- [API styleguide](api_styleguide.md) Use this styleguide if you are
contributing to the API.
- [GrapQL API styleguide](api_graphql_styleguide.md) Use this
- [GraphQL API styleguide](api_graphql_styleguide.md) Use this
styleguide if you are contribution to the [GraphQL API](../api/graphql/index.md)
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
- [Working with Gitaly](gitaly.md)
......
......@@ -233,7 +233,7 @@ This makes use of [`Intl.DateTimeFormat`].
Please never split a sentence as that would assume the sentence grammar and
structure is the same in all languages.
For instance, the following
For instance, the following:
```js
{{ s__("mrWidget|Set by") }}
......@@ -247,6 +247,27 @@ should be externalized as follows:
{{ sprintf(s__("mrWidget|Set by %{author} to be merged automatically when the pipeline succeeds"), { author: author.name }) }}
```
#### Avoid splitting sentences when adding links
This also applies when using links in between translated sentences, otherwise these texts are not translatable in certain languages.
Instead of:
```haml
- zones_link = link_to(s_('ClusterIntegration|zones'), 'https://cloud.google.com/compute/docs/regions-zones/regions-zones', target: '_blank', rel: 'noopener noreferrer')
= s_('ClusterIntegration|Learn more about %{zones_link}').html_safe % { zones_link: zones_link }
```
Set the link starting and ending HTML fragments as variables like so:
```haml
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- zones_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: zones_link_url }
= s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}').html_safe % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe }
```
The reasoning behind this is that in some languages words change depending on context. For example in Japanese は is added to the subject of a sentence and を to the object. This is impossible to translate correctly if we extract individual words from the sentence.
When in doubt, try to follow the best practices described in this [Mozilla
Developer documentation][mdn].
......
......@@ -7,17 +7,19 @@ In Git, when you copy a project you say you "clone" it. To work on a git project
When you are on your Dashboard, click on the project that you'd like to clone.
To work in the project, you can copy a link to the Git repository through a SSH
or a HTTPS protocol. SSH is easier to use after it's been
[setup](create-your-ssh-keys.md). While you are at the **Project** tab, select
HTTPS or SSH from the dropdown menu and copy the link using the 'Copy to clipboard'
[set up](create-your-ssh-keys.md). While you are at the **Project** tab, select
HTTPS or SSH from the dropdown menu and copy the link using the _Copy URL to clipboard_
button (you'll have to paste it on your shell in the next step).
![Copy the HTTPS or SSH](img/project_clone_url.png)
## On the command line
This section has examples of some basic shell commands that you might find useful. For more information, search the web for _bash commands_.
### Clone your project
Go to your computer's shell and type the following command:
Go to your computer's shell and type the following command with your SSH or HTTPS URL:
```
git clone PASTE HTTPS OR SSH HERE
......@@ -25,33 +27,45 @@ git clone PASTE HTTPS OR SSH HERE
A clone of the project will be created in your computer.
>**Note:** If you clone your project via an URL that contains special characters, make sure that they are URL-encoded.
>**Note:** If you clone your project via a URL that contains special characters, make sure that characters are URL-encoded.
### Go into a project, directory or file to work in it
### Go into a project directory to work in it
```
cd NAME-OF-PROJECT-OR-FILE
cd NAME-OF-PROJECT
```
### Go back one directory or file
### Go back one directory
```
cd ../
cd ..
```
### View what’s in the directory that you are in
### List what’s in the current directory
```
ls
```
### Create a directory
### List what’s in the current directory that starts with `a`
```
ls a*
```
### List what’s in the current directory that ends with `.md`
```
ls *.md
```
### Create a new directory
```
mkdir NAME-OF-YOUR-DIRECTORY
```
### Create a README.md or file in directory
### Create a README.md file in the current directory
```
touch README.md
......@@ -62,6 +76,12 @@ nano README.md
#### Press: enter
```
### Show the contents of the README.md file
```
cat README.md
```
### Remove a file
```
......@@ -74,12 +94,18 @@ rm NAME-OF-FILE
rm -r NAME-OF-DIRECTORY
```
### View history in the command line
### View command history
```
history
```
### Execute command 123 from history
```
!123
```
### Carry out commands for which the account you are using lacks authority
You will be asked for an administrator’s password.
......@@ -88,8 +114,14 @@ You will be asked for an administrator’s password.
sudo
```
### Tell where you are
### Show which directory I am in
```
pwd
```
### Clear the shell window
```
clear
```
......@@ -120,7 +120,7 @@ gitlabConfigStorageSize: 1Gi
Ingress routing and SSL are automatically configured within this Chart. An NGINX ingress is provisioned and configured, and will route traffic to any service. SSL certificates are automatically created and configured by [kube-lego](https://github.com/kubernetes/charts/tree/master/stable/kube-lego).
> **Note:**
Let's Encrypt limits a single TLD to five certificate requests within a single week. This means that common DNS wildcard services like [xip.io](http://xip.io) and [nip.io](http://nip.io) are unlikely to work.
Let's Encrypt limits a single TLD to five certificate requests within a single week. This means that common DNS wildcard services like [nip.io](http://nip.io) and [nip.io](http://nip.io) are unlikely to work.
## Installing GitLab using the Helm Chart
> **Note:**
......
......@@ -307,10 +307,10 @@ hostname** and use greater values for the volume sizes. If you don't provide a
password for PostgreSQL, it will be created automatically.
>**Note:**
The `gitlab.apps.10.2.2.2.xip.io` hostname that is used by default will
The `gitlab.apps.10.2.2.2.nip.io` hostname that is used by default will
resolve to the host with IP `10.2.2.2` which is the IP our VM uses. It is a
trick to have distinct FQDNs pointing to services that are on our local network.
Read more on how this works in <http://xip.io>.
Read more on how this works in <http://nip.io>.
Now that we configured this, let's see how to manage and scale GitLab.
......@@ -347,7 +347,7 @@ Navigate back to the **Overview** and hopefully all pods will be up and running.
![GitLab running](img/gitlab-running.png)
Congratulations! You can now navigate to your new shinny GitLab instance by
visiting <http://gitlab.apps.10.2.2.2.xip.io> where you will be asked to
visiting <http://gitlab.apps.10.2.2.2.nip.io> where you will be asked to
change the root user password. Login using `root` as username and providing the
password you just set, and start using GitLab!
......
......@@ -135,9 +135,9 @@ and `1.2.3.4` is the IP address of your load balancer; generally NGINX
([see requirements](#requirements)). How to set up the DNS record is beyond
the scope of this document; you should check with your DNS provider.
Alternatively you can use free public services like [xip.io](http://xip.io) or
Alternatively you can use free public services like [nip.io](http://nip.io) or
[nip.io](http://nip.io) which provide automatic wildcard DNS without any
configuration. Just set the Auto DevOps base domain to `1.2.3.4.xip.io` or
configuration. Just set the Auto DevOps base domain to `1.2.3.4.nip.io` or
`1.2.3.4.nip.io`.
Once set up, all requests will hit the load balancer, which in turn will route
......
......@@ -7,6 +7,34 @@ To navigate to your profile's preferences, click your avatar icon in the top
right corner and select **Settings**. From there on, choose the **Preferences**
tab.
![Profile preferences settings](img/profile_settings_dropdown.png)
## Navigation theme
>**Note:**
Navigation themes have been re-introduced with [GitLab 10.0](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/).
The GitLab navigation theme setting allows you to personalize your GitLab experience.
You can choose from several color themes that add unique colors to the top navigation
and left side navigation.
Using individual color themes might help you differentiate between your different
GitLab instances.
The default palette is Indigo. You can choose between 10 different themes:
- Indigo
- Light Indigo
- Blue
- Light Blue
- Green
- Light Green
- Red
- Light Red
- Dark
- Light
![Profile preferences syntax highlighting themes](img/profile-preferences-syntax-themes.png)
## Syntax highlighting theme
>**Note:**
......@@ -16,7 +44,7 @@ list of supported languages visit the rouge website.
Changing this setting allows you to customize the color theme when viewing any
syntax highlighted code on GitLab.
The default one is **White**, and you can choose among 5 different colors:
The default syntax theme is White, and you can choose among 5 different colors:
- White
- Dark
......@@ -24,6 +52,8 @@ The default one is **White**, and you can choose among 5 different colors:
- Solarized dark
- Monokai
![Profile preferences navigation themes](img/profil-preferences-navigation-theme.png)
## Behavior
The following settings allow you to customize the behavior of GitLab's layout
......@@ -52,16 +82,16 @@ You have 8 options here that you can use for your default dashboard view:
- Assigned Issues
- Assigned Merge Requests
### Project home page content
### Project overview content
The project home page content setting allows you to choose what content you want to
The project overview content setting allows you to choose what content you want to
see on a project’s home page.
You can choose between 3 options:
- Show the files and the readme (default)
- Show the readme
- Show the project’s activity
- Files and Readme (default)
- Readme
- Activity
[rouge]: http://rouge.jneen.net/ "Rouge website"
[todos]: ../../workflow/todos.md
......@@ -41,20 +41,20 @@ new Kubernetes cluster that will be hosted on GKE to your project:
1. Navigate to your project's **Operations > Kubernetes** page.
1. Click on **Add Kubernetes cluster**.
1. Click on **Create with GKE**.
1. Click on **Create with Google Kubernetes Engine**.
1. Connect your Google account if you haven't done already by clicking the
**Sign in with Google** button.
1. Fill in the requested values:
- **Cluster name** (required) - The name you wish to give the cluster.
- **GCP project ID** (required) - The ID of the project you created in your GCP
- **Kubernetes cluster name** - The name you wish to give the cluster.
- **Environment scope** - The [associated environment](#setting-the-environment-scope) to this cluster.
- **Google Cloud Platform project** - The project you created in your GCP
console that will host the Kubernetes cluster. This must **not** be confused
with the project name. Learn more about [Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
with the project ID. Learn more about [Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
- **Zone** - The [zone](https://cloud.google.com/compute/docs/regions-zones/)
under which the cluster will be created.
- **Number of nodes** - The number of nodes you wish the cluster to have.
- **Machine type** - The [machine type](https://cloud.google.com/compute/docs/machine-types)
of the Virtual Machine instance that the cluster will be based on.
- **Environment scope** - The [associated environment](#setting-the-environment-scope) to this cluster.
1. Finally, click the **Create Kubernetes cluster** button.
After a few moments, your cluster should be created. If something goes wrong,
......
......@@ -120,7 +120,7 @@ module Gitlab
# Default branch in the repository
def root_ref
@root_ref ||= gitaly_migrate(:root_ref) do |is_enabled|
@root_ref ||= gitaly_migrate(:root_ref, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_client.default_branch_name
else
......@@ -152,7 +152,7 @@ module Gitlab
# Returns an Array of branch names
# sorted by name ASC
def branch_names
gitaly_migrate(:branch_names) do |is_enabled|
gitaly_migrate(:branch_names, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_client.branch_names
else
......@@ -163,7 +163,7 @@ module Gitlab
# Returns an Array of Branches
def branches
gitaly_migrate(:branches) do |is_enabled|
gitaly_migrate(:branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_client.branches
else
......@@ -200,7 +200,7 @@ module Gitlab
end
def local_branches(sort_by: nil)
gitaly_migrate(:local_branches) do |is_enabled|
gitaly_migrate(:local_branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_client.local_branches(sort_by: sort_by)
else
......@@ -270,7 +270,7 @@ module Gitlab
# Returns an Array of tag names
def tag_names
gitaly_migrate(:tag_names) do |is_enabled|
gitaly_migrate(:tag_names, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_client.tag_names
else
......@@ -283,7 +283,7 @@ module Gitlab
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/390
def tags
gitaly_migrate(:tags) do |is_enabled|
gitaly_migrate(:tags, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
tags_from_gitaly
else
......@@ -310,7 +310,7 @@ module Gitlab
#
# name - The name of the tag as a String.
def tag_exists?(name)
gitaly_migrate(:ref_exists_tags) do |is_enabled|
gitaly_migrate(:ref_exists_tags, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_exists?("refs/tags/#{name}")
else
......@@ -323,7 +323,7 @@ module Gitlab
#
# name - The name of the branch as a String.
def branch_exists?(name)
gitaly_migrate(:ref_exists_branches) do |is_enabled|
gitaly_migrate(:ref_exists_branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_ref_exists?("refs/heads/#{name}")
else
......
......@@ -42,8 +42,6 @@ module Gitlab
klass.new(project, client, parallel: false).execute
end
project.repository.after_import
true
end
end
......
module Gitlab
module SQL
# Class for easily building CTE statements.
#
# Example:
#
# cte = CTE.new(:my_cte_name)
# ns = Arel::Table.new(:namespaces)
#
# cte << Namespace.
# where(ns[:parent_id].eq(some_namespace_id))
#
# Namespace
# with(cte.to_arel).
# from(cte.alias_to(ns))
class CTE
attr_reader :table, :query
# name - The name of the CTE as a String or Symbol.
def initialize(name, query)
@table = Arel::Table.new(name)
@query = query
end
# Returns the Arel relation for this CTE.
def to_arel
sql = Arel::Nodes::SqlLiteral.new("(#{query.to_sql})")
Arel::Nodes::As.new(table, sql)
end
# Returns an "AS" statement that aliases the CTE name as the given table
# name. This allows one to trick ActiveRecord into thinking it's selecting
# from an actual table, when in reality it's selecting from a CTE.
#
# alias_table - The Arel table to use as the alias.
def alias_to(alias_table)
Arel::Nodes::As.new(table, alias_table)
end
# Applies the CTE to the given relation, returning a new one that will
# query from it.
def apply_to(relation)
relation.except(:where)
.with(to_arel)
.from(alias_to(relation.model.arel_table))
end
end
end
end
......@@ -9,7 +9,10 @@ class GithubImport
def initialize(token, gitlab_username, project_path, extras)
@options = { token: token }
@project_path = project_path
@current_user = User.find_by_username(gitlab_username)
@current_user = User.find_by(username: gitlab_username)
raise "GitLab user #{gitlab_username} not found. Please specify a valid username." unless @current_user
@github_repo = extras.empty? ? nil : extras.first
end
......@@ -50,7 +53,7 @@ class GithubImport
end
if import_success
@project.import_finish
@project.after_import
puts "Import finished. Timings: #{timings}".color(:green)
else
puts "Import was not successful. Errors were as follows:"
......
......@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-06-08 18:19+0200\n"
"PO-Revision-Date: 2018-06-08 18:19+0200\n"
"POT-Creation-Date: 2018-06-11 09:18+0200\n"
"PO-Revision-Date: 2018-06-11 09:18+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
......@@ -4109,7 +4109,7 @@ msgstr ""
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
msgid "TagsPage|Write your release notes or drag files here..."
msgid "TagsPage|Write your release notes or drag files here"
msgstr ""
msgid "TagsPage|protected"
......@@ -4806,7 +4806,7 @@ msgstr ""
msgid "WikiPage|Page slug"
msgstr ""
msgid "WikiPage|Write your content or drag files here..."
msgid "WikiPage|Write your content or drag files here"
msgstr ""
msgid "Wiki|Create Page"
......
require 'pathname'
module QA
module Factory
module Repository
......
......@@ -46,6 +46,18 @@ module QA
def sandbox_name
ENV['GITLAB_SANDBOX_NAME']
end
def gcloud_account_key
ENV.fetch("GCLOUD_ACCOUNT_KEY")
end
def gcloud_account_email
ENV.fetch("GCLOUD_ACCOUNT_EMAIL")
end
def gcloud_zone
ENV.fetch('GCLOUD_ZONE')
end
end
end
end
......@@ -20,9 +20,11 @@ module QA
gcloud container clusters
create #{cluster_name}
--enable-legacy-authorization
--zone us-central1-a
--zone #{Runtime::Env.gcloud_zone}
&& gcloud container clusters
get-credentials #{cluster_name}
get-credentials
--zone #{Runtime::Env.gcloud_zone}
#{cluster_name}
CMD
@api_url = `kubectl config view --minify -o jsonpath='{.clusters[].cluster.server}'`
......@@ -32,7 +34,12 @@ module QA
end
def remove!
shell("gcloud container clusters delete #{cluster_name} --quiet --async")
shell <<~CMD.tr("\n", ' ')
gcloud container clusters delete
--zone #{Runtime::Env.gcloud_zone}
#{cluster_name}
--quiet --async
CMD
end
private
......@@ -54,9 +61,9 @@ module QA
def attempt_login_with_env_vars
puts "No gcloud account. Attempting to login from env vars GCLOUD_ACCOUNT_EMAIL and GCLOUD_ACCOUNT_KEY."
gcloud_account_key = Tempfile.new('gcloud-account-key')
gcloud_account_key.write(ENV.fetch("GCLOUD_ACCOUNT_KEY"))
gcloud_account_key.write(Runtime::Env.gcloud_account_key)
gcloud_account_key.close
gcloud_account_email = ENV.fetch("GCLOUD_ACCOUNT_EMAIL")
gcloud_account_email = Runtime::Env.gcloud_account_email
shell("gcloud auth activate-service-account #{gcloud_account_email} --key-file #{gcloud_account_key.path}")
ensure
gcloud_account_key && gcloud_account_key.unlink
......
require 'pathname'
module QA
feature 'Auto Devops', :kubernetes do
after do
......
#!/usr/bin/env bash
echo -e "=> Checking if Gemfile.rails5.lock is up-to-date...\\n"
cp Gemfile.rails5.lock Gemfile.rails5.lock.orig
BUNDLE_GEMFILE=Gemfile.rails5 bundle install "$BUNDLE_INSTALL_FLAGS"
diff -u Gemfile.rails5.lock.orig Gemfile.rails5.lock >/dev/null 2>&1
if [ $? == 1 ]
then
diff -u Gemfile.rails5.lock.orig Gemfile.rails5.lock
echo -e "\\n✖ ERROR: Gemfile.rails5.lock is not up-to-date!
Please run 'BUNDLE_GEMFILE=Gemfile.rails5 bundle install'\\n" >&2
exit 1
fi
echo "✔ Gemfile.rails5.lock is up-to-date"
exit 0
......@@ -84,7 +84,7 @@ describe('issue_comment_form component', () => {
it('should render textarea with placeholder', () => {
expect(
vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
).toEqual('Write a comment or drag your files here...');
).toEqual('Write a comment or drag your files here');
});
it('should make textarea disabled while requesting', (done) => {
......
......@@ -106,7 +106,7 @@ describe('note_app', () => {
expect(vm.$el.querySelector('.js-main-target-form').tagName).toEqual('FORM');
expect(
vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
).toEqual('Write a comment or drag your files here...');
).toEqual('Write a comment or drag your files here');
});
it('should render form comment button as disabled', () => {
......@@ -129,7 +129,7 @@ describe('note_app', () => {
expect(vm.$el.querySelector('.js-main-target-form').tagName).toEqual('FORM');
expect(
vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
).toEqual('Write a comment or drag your files here...');
).toEqual('Write a comment or drag your files here');
});
});
......
......@@ -49,7 +49,7 @@ describe('issue_note_form component', () => {
it('should render text area with placeholder', () => {
expect(
vm.$el.querySelector('textarea').getAttribute('placeholder'),
).toEqual('Write a comment or drag your files here...');
).toEqual('Write a comment or drag your files here');
});
it('should link to markdown docs', () => {
......
......@@ -25,6 +25,22 @@ describe Gitlab::Git::Wiki do
end
end
describe '#delete_page', :skip_gitaly_mock do
after do
destroy_page('page1')
end
it 'only removes the page with the same path' do
create_page('page1', 'content')
create_page('*', 'content')
subject.delete_page('*', commit_details('whatever'))
expect(subject.pages.count).to eq 1
expect(subject.pages.first.title).to eq 'page1'
end
end
def create_page(name, content)
subject.write_page(name, :markdown, content, commit_details(name))
end
......
......@@ -30,7 +30,6 @@ describe Gitlab::GithubImport::SequentialImporter do
expect(instance).to receive(:execute)
end
expect(repository).to receive(:after_import)
expect(importer.execute).to eq(true)
end
end
......
require 'spec_helper'
describe Gitlab::SQL::CTE, :postgresql do
describe '#to_arel' do
it 'generates an Arel relation for the CTE body' do
relation = User.where(id: 1)
cte = described_class.new(:cte_name, relation)
sql = cte.to_arel.to_sql
name = ActiveRecord::Base.connection.quote_table_name(:cte_name)
sql1 = ActiveRecord::Base.connection.unprepared_statement do
relation.except(:order).to_sql
end
expect(sql).to eq("#{name} AS (#{sql1})")
end
end
describe '#alias_to' do
it 'returns an alias for the CTE' do
cte = described_class.new(:cte_name, nil)
table = Arel::Table.new(:kittens)
source_name = ActiveRecord::Base.connection.quote_table_name(:cte_name)
alias_name = ActiveRecord::Base.connection.quote_table_name(:kittens)
expect(cte.alias_to(table).to_sql).to eq("#{source_name} AS #{alias_name}")
end
end
describe '#apply_to' do
it 'applies a CTE to an ActiveRecord::Relation' do
user = create(:user)
cte = described_class.new(:cte_name, User.where(id: user.id))
relation = cte.apply_to(User.all)
expect(relation.to_sql).to match(/WITH .+cte_name/)
expect(relation.to_a).to eq(User.where(id: user.id).to_a)
end
end
end
......@@ -1548,7 +1548,9 @@ describe Ci::Build do
let(:predefined_variables) do
[
{ key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
{ key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true },
{ key: 'CI_JOB_ID', value: build.id.to_s, public: true },
{ key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true },
{ key: 'CI_JOB_TOKEN', value: build.token, public: false },
{ key: 'CI_BUILD_ID', value: build.id.to_s, public: true },
{ key: 'CI_BUILD_TOKEN', value: build.token, public: false },
......@@ -2171,6 +2173,7 @@ describe Ci::Build do
it 'does not return prohibited variables' do
keys = %w[CI_JOB_ID
CI_JOB_URL
CI_JOB_TOKEN
CI_BUILD_ID
CI_BUILD_TOKEN
......
......@@ -194,7 +194,7 @@ describe Ci::Pipeline, :mailer do
it 'does contains persisted variables' do
keys = subject.map { |variable| variable[:key] }
expect(keys).to eq %w[CI_PIPELINE_ID]
expect(keys).to eq %w[CI_PIPELINE_ID CI_PIPELINE_URL]
end
end
end
......
......@@ -1733,7 +1733,11 @@ describe Project do
.with(project.repository_storage, project.disk_path, project.import_url)
.and_return(true)
expect_any_instance_of(Repository).to receive(:after_import)
# Works around https://github.com/rspec/rspec-mocks/issues/910
allow(described_class).to receive(:find).with(project.id).and_return(project)
expect(project.repository).to receive(:after_import)
.and_call_original
expect(project.wiki.repository).to receive(:after_import)
.and_call_original
end
......@@ -3398,10 +3402,11 @@ describe Project do
end
describe '#after_import' do
let(:project) { build(:project) }
let(:project) { create(:project) }
it 'runs the correct hooks' do
expect(project.repository).to receive(:after_import)
expect(project.wiki.repository).to receive(:after_import)
expect(project).to receive(:import_finish)
expect(project).to receive(:update_project_counter_caches)
expect(project).to receive(:remove_import_jid)
......@@ -3658,6 +3663,11 @@ describe Project do
.to be_truthy
end
it 'allows access when there are merge requests open but no branch name is given' do
expect(project.branch_allows_collaboration?(user, nil))
.to be_truthy
end
it 'does not allow guest users access' do
guest = create(:user)
target_project.add_guest(guest)
......
require "spec_helper"
describe 'Git HTTP requests' do
include ProjectForksHelper
include TermsHelper
include GitHttpHelpers
include WorkhorseHelpers
......@@ -305,6 +306,22 @@ describe 'Git HTTP requests' do
expect(response.body).to eq(change_access_error(:push_code))
end
end
context 'when merge requests are open that allow maintainer access' do
let(:canonical_project) { create(:project, :public, :repository) }
let(:project) { fork_project(canonical_project, nil, repository: true) }
before do
canonical_project.add_master(user)
create(:merge_request,
source_project: project,
target_project: canonical_project,
source_branch: 'fixes',
allow_collaboration: true)
end
it_behaves_like 'pushes are allowed'
end
end
end
......
......@@ -36,33 +36,36 @@ describe 'project routing' do
shared_examples 'RESTful project resources' do
let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
let(:controller_path) { controller }
let(:id) { { id: '1' } }
let(:format) { {} } # response format, e.g. { format: :html }
let(:params) { { namespace_id: 'gitlab', project_id: 'gitlabhq' } }
it 'to #index' do
expect(get("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#index", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:index)
expect(get("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#index", params) if actions.include?(:index)
end
it 'to #create' do
expect(post("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#create", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:create)
expect(post("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#create", params) if actions.include?(:create)
end
it 'to #new' do
expect(get("/gitlab/gitlabhq/#{controller_path}/new")).to route_to("projects/#{controller}#new", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:new)
expect(get("/gitlab/gitlabhq/#{controller_path}/new")).to route_to("projects/#{controller}#new", params) if actions.include?(:new)
end
it 'to #edit' do
expect(get("/gitlab/gitlabhq/#{controller_path}/1/edit")).to route_to("projects/#{controller}#edit", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
expect(get("/gitlab/gitlabhq/#{controller_path}/1/edit")).to route_to("projects/#{controller}#edit", params.merge(**id, **format)) if actions.include?(:edit)
end
it 'to #show' do
expect(get("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#show", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:show)
expect(get("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#show", params.merge(**id, **format)) if actions.include?(:show)
end
it 'to #update' do
expect(put("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#update", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:update)
expect(put("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#update", params.merge(id)) if actions.include?(:update)
end
it 'to #destroy' do
expect(delete("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#destroy", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
expect(delete("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#destroy", params.merge(**id, **format)) if actions.include?(:destroy)
end
end
......@@ -150,12 +153,13 @@ describe 'project routing' do
end
it 'to #history' do
expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: :html)
end
it_behaves_like 'RESTful project resources' do
let(:actions) { [:create, :edit, :show, :destroy] }
let(:controller) { 'wikis' }
let(:format) { { format: :html } }
end
end
......
......@@ -55,10 +55,15 @@ describe RepositoryForkWorker do
it 'flushes various caches' do
expect_fork_repository.and_return(true)
expect_any_instance_of(Repository).to receive(:expire_emptiness_caches)
# Works around https://github.com/rspec/rspec-mocks/issues/910
expect(Project).to receive(:find).with(fork_project.id).and_return(fork_project)
expect(fork_project.repository).to receive(:expire_emptiness_caches)
.and_call_original
expect_any_instance_of(Repository).to receive(:expire_exists_cache)
expect(fork_project.repository).to receive(:expire_exists_cache)
.and_call_original
expect(fork_project.wiki.repository).to receive(:expire_emptiness_caches)
.and_call_original
expect(fork_project.wiki.repository).to receive(:expire_exists_cache)
.and_call_original
perform!
......
......@@ -22,8 +22,11 @@ describe RepositoryImportWorker do
expect_any_instance_of(Projects::ImportService).to receive(:execute)
.and_return({ status: :ok })
expect_any_instance_of(Repository).to receive(:expire_emptiness_caches)
expect_any_instance_of(Project).to receive(:import_finish)
# Works around https://github.com/rspec/rspec-mocks/issues/910
expect(Project).to receive(:find).with(project.id).and_return(project)
expect(project.repository).to receive(:expire_emptiness_caches)
expect(project.wiki.repository).to receive(:expire_emptiness_caches)
expect(project).to receive(:import_finish)
subject.perform(project.id)
end
......@@ -34,9 +37,11 @@ describe RepositoryImportWorker do
expect_any_instance_of(Projects::ImportService).to receive(:execute)
.and_return({ status: :ok })
expect_any_instance_of(Project).to receive(:after_import).and_call_original
expect_any_instance_of(Repository).to receive(:expire_emptiness_caches)
expect_any_instance_of(Project).to receive(:import_finish)
# Works around https://github.com/rspec/rspec-mocks/issues/910
expect(Project).to receive(:find).with(project.id).and_return(project)
expect(project.repository).to receive(:expire_emptiness_caches)
expect(project.wiki.repository).to receive(:expire_emptiness_caches)
expect(project).to receive(:import_finish)
subject.perform(project.id)
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