Commit 47ec3266 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-10-09

# Conflicts:
#	doc/user/project/issues/create_new_issue.md

[ci skip]
parents 1aaf30a1 e0429111
......@@ -826,7 +826,7 @@ GEM
rubyzip (1.2.2)
rufus-scheduler (3.4.0)
et-orbi (~> 1.0)
rugged (0.27.4)
rugged (0.27.5)
safe_yaml (1.0.4)
sanitize (4.6.6)
crass (~> 1.0.2)
......
......@@ -834,7 +834,7 @@ GEM
rubyzip (1.2.2)
rufus-scheduler (3.4.0)
et-orbi (~> 1.0)
rugged (0.27.4)
rugged (0.27.5)
safe_yaml (1.0.4)
sanitize (4.6.6)
crass (~> 1.0.2)
......
......@@ -395,7 +395,7 @@ Please check your network connection and try again.`;
role="group">
<button
type="button"
class="btn btn-default mr-2"
class="btn btn-default"
@click="resolveHandler()"
>
<i
......
......@@ -59,7 +59,7 @@
vertical-align: middle;
.stage-cell .stage-container {
margin: 3px 3px 3px 0;
margin: 0 3px 3px 0;
}
.stage-container:last-child {
......
......@@ -67,7 +67,6 @@ class ApplicationController < ActionController::Base
end
rescue_from Gitlab::Git::Storage::Inaccessible, GRPC::Unavailable, Gitlab::Git::CommandError do |exception|
Raven.capture_exception(exception) if sentry_enabled?
log_exception(exception)
headers['Retry-After'] = exception.retry_after if exception.respond_to?(:retry_after)
......
......@@ -2,6 +2,7 @@
class Projects::JobsController < Projects::ApplicationController
include SendFileUpload
include ContinueParams
before_action :build, except: [:index, :cancel_all]
before_action :authorize_read_build!
......@@ -107,7 +108,12 @@ class Projects::JobsController < Projects::ApplicationController
return respond_422 unless @build.cancelable?
@build.cancel
redirect_to build_path(@build)
if continue_params
redirect_to continue_params[:to]
else
redirect_to builds_project_pipeline_path(@project, @build.pipeline.id)
end
end
def unschedule
......
......@@ -47,12 +47,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@noteable = @merge_request
@commits_count = @merge_request.commits_count
# TODO cleanup- Fatih Simon Create an issue to remove these after the refactoring
# we no longer render notes here. I see it will require a small frontend refactoring,
# since we gather some data from this collection.
@discussions = @merge_request.discussions
@notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes), @noteable)
labels
set_pipeline_variables
......
# frozen_string_literal: true
# Finder for retrieving the pending todos of a user, optionally filtered using
# various fields.
#
# While this finder is a bit more verbose compared to use
# `where(params.slice(...))`, it allows us to decouple the input parameters from
# the actual column names. For example, if we ever decide to use separate
# columns for target types (e.g. `issue_id`, `merge_request_id`, etc), we no
# longer need to change _everything_ that uses this finder. Instead, we just
# change the various `by_*` methods in this finder, without having to touch
# everything that uses it.
class PendingTodosFinder
attr_reader :current_user, :params
# current_user - The user to retrieve the todos for.
# params - A Hash containing columns and values to use for filtering todos.
def initialize(current_user, params = {})
@current_user = current_user
@params = params
end
def execute
todos = current_user.todos.pending
todos = by_project(todos)
todos = by_target_id(todos)
todos = by_target_type(todos)
todos = by_commit_id(todos)
todos
end
def by_project(todos)
if (id = params[:project_id])
todos.for_project(id)
else
todos
end
end
def by_target_id(todos)
if (id = params[:target_id])
todos.for_target(id)
else
todos
end
end
def by_target_type(todos)
if (type = params[:target_type])
todos.for_type(type)
else
todos
end
end
def by_commit_id(todos)
if (id = params[:commit_id])
todos.for_commit(id)
else
todos
end
end
end
......@@ -23,6 +23,8 @@ class TodosFinder
NONE = '0'.freeze
TODO_TYPES = Set.new(%w(Issue MergeRequest Epic)).freeze
attr_accessor :current_user, :params
def initialize(current_user, params = {})
......@@ -45,6 +47,13 @@ class TodosFinder
sort(items)
end
# Returns `true` if the current user has any todos for the given target.
#
# target - The value of the `target_type` column, such as `Issue`.
def any_for_target?(target)
current_user.todos.any_for_target?(target)
end
private
def action_id?
......@@ -72,14 +81,11 @@ class TodosFinder
end
def author
return @author if defined?(@author)
@author =
strong_memoize(:author) do
if author? && params[:author_id] != NONE
User.find(params[:author_id])
else
nil
end
end
end
def project?
......@@ -91,17 +97,9 @@ class TodosFinder
end
def project
return @project if defined?(@project)
if project?
@project = Project.find(params[:project_id])
@project = nil if @project.pending_delete?
else
@project = nil
strong_memoize(:project) do
Project.find_without_deleted(params[:project_id]) if project?
end
@project
end
def group
......@@ -111,7 +109,7 @@ class TodosFinder
end
def type?
type.present? && %w(Issue MergeRequest Epic).include?(type)
type.present? && TODO_TYPES.include?(type)
end
def type
......@@ -119,77 +117,66 @@ class TodosFinder
end
def sort(items)
params[:sort] ? items.sort_by_attribute(params[:sort]) : items.order_id_desc
if params[:sort]
items.sort_by_attribute(params[:sort])
else
items.order_id_desc
end
end
# rubocop: disable CodeReuse/ActiveRecord
def by_action(items)
if action?
items = items.where(action: to_action_id)
items.for_action(to_action_id)
else
items
end
items
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def by_action_id(items)
if action_id?
items = items.where(action: action_id)
items.for_action(action_id)
else
items
end
items
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def by_author(items)
if author?
items = items.where(author_id: author.try(:id))
items.for_author(author)
else
items
end
items
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def by_project(items)
if project?
items = items.where(project: project)
items.for_project(project)
else
items
end
items
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def by_group(items)
return items unless group?
groups = group.self_and_descendants
project_todos = items.where(project_id: Project.where(group: groups).select(:id))
group_todos = items.where(group_id: groups.select(:id))
Todo.from_union([project_todos, group_todos])
if group?
items.for_group_and_descendants(group)
else
items
end
end
# rubocop: enable CodeReuse/ActiveRecord
def by_state(items)
case params[:state].to_s
when 'done'
if params[:state].to_s == 'done'
items.done
else
items.pending
end
end
# rubocop: disable CodeReuse/ActiveRecord
def by_type(items)
if type?
items = items.where(target_type: type)
items.for_type(type)
else
items
end
items
end
# rubocop: enable CodeReuse/ActiveRecord
end
# frozen_string_literal: true
# Finder that given a target (e.g. an issue) finds all the users that have
# pending todos for said target.
class UsersWithPendingTodosFinder
attr_reader :target
# target - The target, such as an Issue or MergeRequest.
def initialize(target)
@target = target
end
def execute
User.for_todos(target.todos.pending)
end
end
......@@ -144,7 +144,7 @@ module NotesHelper
def initial_notes_data(autocomplete)
{
notesUrl: notes_url,
notesIds: @notes.map(&:id),
notesIds: @noteable.notes.pluck(:id), # rubocop: disable CodeReuse/ActiveRecord
now: Time.now.to_i,
diffView: diff_view,
enableGFM: {
......
......@@ -391,6 +391,13 @@ class Project < ActiveRecord::Base
only_integer: true,
message: 'needs to be beetween 10 minutes and 1 month' }
# Returns a project, if it is not about to be removed.
#
# id - The ID of the project to retrieve.
def self.find_without_deleted(id)
without_deleted.find_by_id(id)
end
# Paginates a collection using a `WHERE id < ?` condition.
#
# before - A project ID to use for filtering out projects with an equal or
......@@ -455,6 +462,7 @@ class Project < ActiveRecord::Base
scope :joins_import_state, -> { joins("LEFT JOIN project_mirror_data import_state ON import_state.project_id = projects.id") }
scope :import_started, -> { joins_import_state.where("import_state.status = 'started' OR projects.import_status = 'started'") }
scope :for_group, -> (group) { where(group: group) }
class << self
# Searches for a list of projects based on the query given in `query`.
......
......@@ -41,6 +41,13 @@ class Todo < ActiveRecord::Base
scope :pending, -> { with_state(:pending) }
scope :done, -> { with_state(:done) }
scope :for_action, -> (action) { where(action: action) }
scope :for_author, -> (author) { where(author: author) }
scope :for_project, -> (project) { where(project: project) }
scope :for_group, -> (group) { where(group: group) }
scope :for_type, -> (type) { where(target_type: type) }
scope :for_target, -> (id) { where(target_id: id) }
scope :for_commit, -> (id) { where(commit_id: id) }
state_machine :state, initial: :pending do
event :done do
......@@ -54,6 +61,42 @@ class Todo < ActiveRecord::Base
after_save :keep_around_commit, if: :commit_id
class << self
# Returns all todos for the given group and its descendants.
#
# group - A `Group` to retrieve todos for.
#
# Returns an `ActiveRecord::Relation`.
def for_group_and_descendants(group)
groups = group.self_and_descendants
from_union([
for_project(Project.for_group(groups)),
for_group(groups)
])
end
# Returns `true` if the current user has any todos for the given target.
#
# target - The value of the `target_type` column, such as `Issue`.
def any_for_target?(target)
exists?(target: target)
end
# Updates the state of a relation of todos to the new state.
#
# new_state - The new state of the todos.
#
# Returns an `Array` containing the IDs of the updated todos.
def update_state(new_state)
# Only update those that are not really on that state
base = where.not(state: new_state).except(:order)
ids = base.pluck(:id)
base.update_all(state: new_state)
ids
end
# Priority sorting isn't displayed in the dropdown, because we don't show
# milestones, but still show something if the user has a URL with that
# selected.
......
......@@ -274,6 +274,7 @@ class User < ActiveRecord::Base
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :by_username, -> (usernames) { iwhere(username: usernames) }
scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) }
# Limits the users to those that have TODOs, optionally in the given state.
#
......@@ -1388,6 +1389,10 @@ class User < ActiveRecord::Base
!consented_usage_stats? && 7.days.ago > self.created_at && !has_current_license? && User.single_user?
end
def todos_limited_to(ids)
todos.where(id: ids)
end
# @deprecated
alias_method :owned_or_masters_groups, :owned_or_maintainers_groups
......
......@@ -43,15 +43,13 @@ class TodoService
# collects the todo users before the todos themselves are deleted, then
# updates the todo counts for those users.
#
# rubocop: disable CodeReuse/ActiveRecord
def destroy_target(target)
todo_users = User.where(id: target.todos.pending.select(:user_id)).to_a
todo_users = UsersWithPendingTodosFinder.new(target).execute.to_a
yield target
todo_users.each(&:update_todos_count_cache)
end
# rubocop: enable CodeReuse/ActiveRecord
# When we reassign an issue we should:
#
......@@ -202,30 +200,23 @@ class TodoService
create_todos(current_user, attributes)
end
# rubocop: disable CodeReuse/ActiveRecord
def todo_exist?(issuable, current_user)
TodosFinder.new(current_user).execute.exists?(target: issuable)
TodosFinder.new(current_user).any_for_target?(issuable)
end
# rubocop: enable CodeReuse/ActiveRecord
private
# rubocop: disable CodeReuse/ActiveRecord
def todos_by_ids(ids, current_user)
current_user.todos.where(id: Array(ids))
current_user.todos_limited_to(Array(ids))
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def update_todos_state(todos, current_user, state)
# Only update those that are not really on that state
todos = todos.where.not(state: state)
todos_ids = todos.pluck(:id)
todos.unscope(:order).update_all(state: state)
todos_ids = todos.update_state(state)
current_user.update_todos_count_cache
todos_ids
end
# rubocop: enable CodeReuse/ActiveRecord
def create_todos(users, attributes)
Array(users).map do |user|
......@@ -350,10 +341,7 @@ class TodoService
end
end
# rubocop: disable CodeReuse/ActiveRecord
def pending_todos(user, criteria = {})
valid_keys = [:project_id, :target_id, :target_type, :commit_id]
user.todos.pending.where(criteria.slice(*valid_keys))
PendingTodosFinder.new(user, criteria).execute
end
# rubocop: enable CodeReuse/ActiveRecord
end
......@@ -26,8 +26,7 @@
= markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "* ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a bullet list") })
= markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a numbered list") })
= markdown_toolbar_button({ icon: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a task list") })
= markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header 1 | header 2 |\n| -------- | -------- |\n| cell 1 | cell 2 |\n| cell 3 | cell 4 |", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a table") })
= markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: _('Add a table') })
= markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a table") })
%button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: s_("MarkdownToolbar|Go full screen"), data: { container: "body" } }
= sprite_icon("screen-full")
......
......@@ -33,7 +33,7 @@
.form-group.project-path.col-sm-6
= f.label :path, class: 'label-bold' do
%span= _("Project slug")
= f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, required: true
= f.text_field :path, placeholder: "my-awesome-project", class: "form-control", required: true
- if current_user.can_create_group?
.form-text.text-muted
Want to house several dependent projects under the same namespace?
......@@ -61,5 +61,5 @@
.option-description
Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.
= f.submit 'Create project', class: "btn btn-success project-submit", tabindex: 4, data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
= f.submit 'Create project', class: "btn btn-success project-submit", data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "cancel" }
......@@ -101,7 +101,7 @@
= sprite_icon('download')
- if can?(current_user, :update_build, job)
- if job.active?
= link_to cancel_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
= link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: 'Cancel', class: 'btn btn-build' do
= icon('remove', class: 'cred')
- elsif job.scheduled?
.btn-group
......
......@@ -6,14 +6,13 @@ class PruneOldEventsWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform
# Contribution calendar shows maximum 12 months of events.
# Double nested query is used because MySQL doesn't allow DELETE subqueries
# on the same table.
# Contribution calendar shows maximum 12 months of events, we retain 2 years for data integrity.
# Double nested query is used because MySQL doesn't allow DELETE subqueries on the same table.
Event.unscoped.where(
'(id IN (SELECT id FROM (?) ids_to_remove))',
Event.unscoped.where(
'created_at < ?',
(12.months + 1.day).ago)
(2.years + 1.day).ago)
.select(:id)
.limit(10_000))
.delete_all
......
---
title: Fix incorrect spacing between buttons when commenting on a MR.
merge_request: 22135
author:
type: fixed
---
title: Vertical align Pipeline Graph in Commit Page
merge_request: 22173
author: Johann Hubert Sonntagbauer
type: fixed
---
title: Focus project slug on tab navigation
merge_request: 22198
author:
type: other
---
title: Redirect to the pipeline builds page when a build is canceled
merge_request:
author: Eva Kadlecova
type: fixed
---
title: Increased retained event data by extending events pruner timeframe to 2 years
merge_request: 22145
author:
type: changed
---
title: Remove duplicate button from the markdown header toolbar
merge_request: 22192
author: George Tsiolis
type: changed
---
title: Enable more frozen string in lib/**/*.rb
merge_request:
author: gfyoung
type: performance
---
title: Removes expensive dead code on main MR page request
merge_request: 22153
author:
type: performance
---
title: 'Rails 5: fix mysql milliseconds problems in scheduled build specs'
merge_request: 22170
author: Jasper Maes
type: other
......@@ -52,6 +52,9 @@ Hooks can be also placed in `hooks/<hook_name>.d` (global) or
`custom_hooks/<hook_name>.d` (per project) directories supporting chained
execution of the hooks.
NOTE: **Note:** `<hook_name>.d` would need to be either `pre-receive.d`,
`post-receive.d`, or `update.d` to work properly. Any other names will be ignored.
To look in a different directory for the global custom hooks (those in
`hooks/<hook_name.d>`), set `custom_hooks_dir` in gitlab-shell config. For
Omnibus installations, this can be set in `gitlab.rb`; and in source
......
......@@ -44,7 +44,7 @@ YYYY-MM-DD
### Event Time Period Limit
GitLab removes events older than 1 year from the events table for performance reasons. The range of 1 year was chosen because user contribution calendars only show contributions of the past year.
GitLab removes events older than 2 years from the events table for performance reasons.
## List currently authenticated user's events
......
......@@ -461,25 +461,25 @@ that runner.
> - If the repository is private you need to authenticate your GitLab Runner in the
> registry. Learn more about how [GitLab Runner works in this case][runner-priv-reg].
As an example, let's assume that you want to use the `registry.example.com/private/image:latest`
As an example, let's assume that you want to use the `registry.example.com:5000/private/image:latest`
image which is private and requires you to login into a private container registry.
Let's also assume that these are the login credentials:
| Key | Value |
|----------|----------------------|
| registry | registry.example.com |
| username | my_username |
| password | my_password |
| Key | Value |
|----------|---------------------------|
| registry | registry.example.com:5000 |
| username | my_username |
| password | my_password |
To configure access for `registry.example.com`, follow these steps:
To configure access for `registry.example.com:5000`, follow these steps:
1. Find what the value of `DOCKER_AUTH_CONFIG` should be. There are two ways to
accomplish this:
- **First way -** Do a `docker login` on your local machine:
```bash
docker login registry.example.com --username my_username --password my_password
docker login registry.example.com:5000 --username my_username --password my_password
```
Then copy the content of `~/.docker/config.json`.
......@@ -503,7 +503,7 @@ To configure access for `registry.example.com`, follow these steps:
```json
{
"auths": {
"registry.example.com": {
"registry.example.com:5000": {
"auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
}
}
......@@ -515,22 +515,28 @@ To configure access for `registry.example.com`, follow these steps:
registry from it:
```bash
docker logout registry.example.com
docker logout registry.example.com:5000
```
1. You can now use any private image from `registry.example.com` defined in
1. You can now use any private image from `registry.example.com:5000` defined in
`image` and/or `services` in your `.gitlab-ci.yml` file:
```yaml
image: my.registry.tld:5000/namespace/image:tag
image: registry.example.com:5000/namespace/image:tag
```
In the example above, GitLab Runner will look at `my.registry.tld:5000` for the
In the example above, GitLab Runner will look at `registry.example.com:5000` for the
image `namespace/image:tag`.
You can add configuration for as many registries as you want, adding more
registries to the `"auths"` hash as described above.
NOTE: **Note:** The full `hostname:port` combination is required everywhere
for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if
`registry.example.com:5000/namespace/image:tag` is specified in `.gitlab-ci.yml`,
then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
Specifying only `registry.example.com` will not work.
## Configuring services
Many services accept environment variables which allow you to easily change
......
......@@ -25,6 +25,12 @@ Two things need to be configured for the interactive web terminal to work:
NOTE: **Note:** Not all executors are
[supported](https://docs.gitlab.com/runner/executors/#compatibility-chart).
NOTE: **Note:** The `docker` executor does not keep running
after the build script is finished. At that point, the terminal will automatically
disconnect and will not wait for the user to finish. Please follow [this
issue](https://gitlab.com/gitlab-org/gitlab-runner/issues/3605) for updates on
improving this behavior.
Sometimes, when a job is running, things don't go as you would expect, and it
would be helpful if one can have a shell to aid debugging. When a job is
running, on the right panel you can see a button `debug` that will open the terminal
......
......@@ -200,7 +200,7 @@ Likewise, group-level variables can be added by going to your group's
**Settings > CI/CD**, then finding the section called **Variables**.
Any variables of [subgroups] will be inherited recursively.
![Variables](img/secret_variables.png)
![Variables](img/variables.png)
Once you set them, they will be available for all subsequent pipelines. You can also
[protect your variables](#protected-variables).
......
......@@ -102,10 +102,13 @@ rspec:
- $RSPEC
```
In the example above, the `rspec` job is going to inherit from the `.tests`
template job. GitLab will perform a reverse deep merge, which means that it will
merge the `rspec` contents into `.tests` recursively, and this is going to result in
the following `rspec` job:
In the example above, the `rspec` job inherits from the `.tests` template job.
GitLab will perform a reverse deep merge based on the keys. GitLab will:
- Merge the `rspec` contents into `.tests` recursively.
- Not merge the values of the keys.
This results in the following `rspec` job:
```yaml
rspec:
......@@ -118,6 +121,11 @@ rspec:
- $RSPEC
```
NOTE: **Note:**
Note that `script: rake test` has been overwritten by `script: rake rspec`.
If you do want to include the `rake test`, have a look at [before_script-and-after_script](#before_script-and-after_script).
`.tests` in this example is a [hidden key](#hidden-keys-jobs), but it's
possible to inherit from regular jobs as well.
......
# Merge Request Checklist
When creating a merge request that performs database related changes (schema
changes, adjusting queries to optimise performance, etc) you should use the
merge request template called "Database Changes". This template contains a
changes, adjusting queries to optimize performance, etc) you should use the
merge request template called "Database changes". This template contains a
checklist of steps to follow to make sure the changes are up to snuff.
To use the checklist, create a new merge request and click on the "Choose a
template" dropdown, then click "Database Changes".
template" dropdown, then click "Database changes".
An example of this checklist can be found at
https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12463.
<https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12463>.
The source code of the checklist can be found in at
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Database%20Changes.md
<https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Database%20changes.md>
......@@ -12,7 +12,7 @@ Since installations from source don't have Runit, Sidekiq can't be terminated an
## Select Version to Install
Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-3-stable`).
Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-4-stable`).
You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar).
If the highest number stable branch is unclear please check the [GitLab Blog](https://about.gitlab.com/blog/) for installation guide links by version.
......@@ -300,9 +300,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-3-stable gitlab
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-4-stable gitlab
**Note:** You can change `11-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `11-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
......
......@@ -23,7 +23,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [How to Configure LDAP with GitLab CE](../../administration/auth/how_to_configure_ldap_gitlab_ce/index.md)
- [How to Configure LDAP with GitLab EE](../../administration/auth/how_to_configure_ldap_gitlab_ee/index.md)
- [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/)
- [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/ldap/debugging_ldap.html)
- [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/support-engineering/ldap/debugging_ldap.html)
- **Integrations:**
- [OmniAuth](../../integration/omniauth.md)
- [Authentiq OmniAuth Provider](../../administration/auth/authentiq.md#authentiq-omniauth-provider)
......@@ -42,7 +42,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
## Third-party resources
- [Kanboard Plugin GitLab Authentication](https://kanboard.net/plugin/gitlab-auth)
- [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth)
- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins-ci.org/display/JENKINS/GitLab+OAuth+Plugin)
- [Set up Gitlab CE with Active Directory authentication](https://www.caseylabs.com/setup-gitlab-ce-with-active-directory-authentication/)
- [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/)
......
......@@ -15,7 +15,7 @@ need to ensure your own [Runners are configured](../../ci/runners/README.md) and
Before creating and connecting your Kubernetes cluster to your GitLab project,
you need a Google Cloud Platform account. If you don't already have one,
sign up at https://console.cloud.google.com. You'll need to either sign in with an existing
sign up at <https://console.cloud.google.com>. You'll need to either sign in with an existing
Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one.
1. Follow the steps as outlined in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)
......@@ -205,7 +205,7 @@ applications. In the rightmost column for the production environment, you can ma
application is running.
Right below, there is the
[Deploy Board](https://docs.gitlab.com/ee/user/project/deploy_boards.md).
[Deploy Board](https://docs.gitlab.com/ee/user/project/deploy_boards.html).
The squares represent pods in your Kubernetes cluster that are associated with
the given environment. Hovering above each square you can see the state of a
deployment and clicking a square will take you to the pod's logs page.
......@@ -264,8 +264,8 @@ Let's fix that:
to stage the changes.
1. Write a commit message and click **Commit**.
Now, if you go back to the merge request you should not only see the test passing,
but also the application deployed as a [review app](index.md#auto-review-apps). You
Now, if you go back to the merge request you should not only see the test passing, but
also the application deployed as a [review app](index.md#auto-review-apps). You
can visit it by following the URL in the merge request. The changes that we
previously made should be there.
......
---
comments: false
---
# From 11.3 to 11.4
Make sure you view this update guide from the branch (version) of GitLab you would
like to install (e.g., `11-4-stable`. You can select the branch in the version
dropdown at the top left corner of GitLab (below the menu bar).
If the highest number stable branch is unclear please check the
[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
guide links by version.
### 1. Stop server
```bash
sudo service gitlab stop
```
### 2. Backup
NOTE: If you installed GitLab from source, make sure `rsync` is installed.
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 3. Update Ruby
NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
sure to upgrade your interpreter if necessary.
You can check which version you are running with `ruby -v`.
Download Ruby and compile it:
```bash
mkdir /tmp/ruby && cd /tmp/ruby
curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
cd ruby-2.4.4
./configure --disable-install-rdoc
make
sudo make install
```
Install Bundler:
```bash
sudo gem install bundler --no-ri --no-rdoc
```
### 4. Update Node
GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
This requires a minimum version of node v6.0.0.
You can check which version you are running with `node -v`. If you are running
a version older than `v6.0.0` you will need to update to a newer version. You
can find instructions to install from community maintained packages or compile
from source at the nodejs.org website.
<https://nodejs.org/en/download/>
GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
dependencies.
```bash
curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo apt-get install yarn
```
More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
### 5. Update Go
NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
You can check which version you are running with `go version`.
Download and install Go:
```bash
# Remove former Go installation folder
sudo rm -rf /usr/local/go
curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
rm go1.10.3.linux-amd64.tar.gz
```
### 6. Get latest code
```bash
cd /home/git/gitlab
sudo -u git -H git fetch --all --prune
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
sudo -u git -H git checkout -- locale
```
For GitLab Community Edition:
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 11-4-stable
```
OR
For GitLab Enterprise Edition:
```bash
cd /home/git/gitlab
sudo -u git -H git checkout 11-4-stable-ee
```
### 7. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch --all --tags --prune
sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
sudo -u git -H bin/compile
```
### 8. Update gitlab-workhorse
Install and compile gitlab-workhorse. GitLab-Workhorse uses
[GNU Make](https://www.gnu.org/software/make/).
If you are not using Linux you may have to run `gmake` instead of
`make` below.
```bash
cd /home/git/gitlab-workhorse
sudo -u git -H git fetch --all --tags --prune
sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
sudo -u git -H make
```
### 9. Update Gitaly
#### New Gitaly configuration options required
In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
```shell
echo '
[gitaly-ruby]
dir = "/home/git/gitaly/ruby"
[gitlab-shell]
dir = "/home/git/gitlab-shell"
' | sudo -u git tee -a /home/git/gitaly/config.toml
```
#### Check Gitaly configuration
Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
configuration file may contain syntax errors. The block name
`[[storages]]`, which may occur more than once in your `config.toml`
file, should be `[[storage]]` instead.
```shell
sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
```
#### Compile Gitaly
```shell
cd /home/git/gitaly
sudo -u git -H git fetch --all --tags --prune
sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
sudo -u git -H make
```
### 10. Update gitlab-pages
#### Only needed if you use GitLab Pages.
Install and compile gitlab-pages. GitLab-Pages uses
[GNU Make](https://www.gnu.org/software/make/).
If you are not using Linux you may have to run `gmake` instead of
`make` below.
```bash
cd /home/git/gitlab-pages
sudo -u git -H git fetch --all --tags --prune
sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
sudo -u git -H make
```
### 11. Update MySQL permissions
If you are using MySQL you need to grant the GitLab user the necessary
permissions on the database:
```bash
mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
```
If you use MySQL with replication, or just have MySQL configured with binary logging,
you will need to also run the following on all of your MySQL servers:
```bash
mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
```
You can make this setting permanent by adding it to your `my.cnf`:
```
log_bin_trust_function_creators=1
```
### 12. Update configuration files
#### New configuration options for `gitlab.yml`
There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
cd /home/git/gitlab
git diff origin/11-1-stable:config/gitlab.yml.example origin/11-4-stable:config/gitlab.yml.example
```
#### Nginx configuration
Ensure you're still up-to-date with the latest NGINX configuration changes:
```sh
cd /home/git/gitlab
# For HTTPS configurations
git diff origin/11-1-stable:lib/support/nginx/gitlab-ssl origin/11-4-stable:lib/support/nginx/gitlab-ssl
# For HTTP configurations
git diff origin/11-1-stable:lib/support/nginx/gitlab origin/11-4-stable:lib/support/nginx/gitlab
```
If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
configuration as GitLab application no longer handles setting it.
If you are using Apache instead of NGINX please see the updated [Apache templates].
Also note that because Apache does not support upstreams behind Unix sockets you
will need to let gitlab-workhorse listen on a TCP port. You can do this
via [/etc/default/gitlab].
[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/lib/support/init.d/gitlab.default.example#L38
#### SMTP configuration
If you're installing from source and use SMTP to deliver mail, you will need to add the following line
to config/initializers/smtp_settings.rb:
```ruby
ActionMailer::Base.delivery_method = :smtp
```
See [smtp_settings.rb.sample] as an example.
[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/config/initializers/smtp_settings.rb.sample#L13
#### Init script
There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
```sh
cd /home/git/gitlab
git diff origin/11-1-stable:lib/support/init.d/gitlab.default.example origin/11-4-stable:lib/support/init.d/gitlab.default.example
```
Ensure you're still up-to-date with the latest init script changes:
```bash
cd /home/git/gitlab
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
For Ubuntu 16.04.1 LTS:
```bash
sudo systemctl daemon-reload
```
### 13. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL installations (note: the line below states '--without postgres')
sudo -u git -H bundle install --without postgres development test --deployment
# PostgreSQL installations (note: the line below states '--without mysql')
sudo -u git -H bundle install --without mysql development test --deployment
# Optional: clean up old gems
sudo -u git -H bundle clean
# Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Compile GetText PO files
sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
# Update node dependencies and recompile assets
sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
# Clean up cache
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
```
**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
### 14. Start application
```bash
sudo service gitlab start
sudo service nginx restart
```
### 15. Check application status
Check if GitLab and its environment are configured correctly:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
```
To make sure you didn't miss anything run a more thorough check:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
```
If all items are green, then congratulations, the upgrade is complete!
## Things went south? Revert to previous version (11.3)
### 1. Revert the code to the previous version
Follow the [upgrade guide from 11.2 to 11.3](11.2-to-11.3.md), except for the
database migration (the backup is already migrated to the previous version).
### 2. Restore from the backup
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/config/gitlab.yml.example
[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/lib/support/init.d/gitlab.default.example
......@@ -35,17 +35,17 @@ continue their registration afterwards.
## Accepting terms
When this feature was enabled, the users that have not accepted the
When this feature is enabled, the users that have not accepted the
terms of service will be presented with a screen where they can either
accept or decline the terms.
![Respond to terms](img/respond_to_terms.png)
When the user accepts the terms, they will be directed to where they
If the user accepts the terms, they will be directed to where they
were going. After a sign-in or sign-up this will most likely be the
dashboard.
When the user was already logged in when the feature was turned on,
If the user was already logged in when the feature was turned on,
they will be asked to accept the terms on their next interaction.
When a user declines the terms, they will be signed out.
If a user declines the terms, they will be signed out.
......@@ -59,6 +59,7 @@ supported.
![Bottom of a project issues page](img/new_issue_from_email.png)
<<<<<<< HEAD
## New issue via Service Desk **[PREMIUM]**
Enable [Service Desk](../service_desk.md) to your project and offer email support.
......@@ -79,6 +80,8 @@ create issues for the same project.
![Create issue from group-level issue tracker](img/create_issue_from_group_level_issue_tracker.png)
=======
>>>>>>> upstream/master
## New issue via URL with prefilled fields
You can link directly to the new issue page for a given project, with prefilled
......@@ -96,6 +99,9 @@ Follow these examples to form your new issue URL with prefilled fields.
and a pre-entered description, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea`
- For a new issue in the GitLab Community Edition project with a pre-entered title
and a pre-entered description template, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Research%20proposal`
<<<<<<< HEAD
[Markdown]: ../../markdown.md
[quick actions]: ../quick_actions.md
=======
>>>>>>> upstream/master
......@@ -57,7 +57,7 @@ started:
gpg --full-gen-key
```
_NOTE: In some cases like Gpg4win on Windows and other Mac OS versions the command here may be ` gpg --gen-key`_
_NOTE: In some cases like Gpg4win on Windows and other Mac OS versions the command here may be ` gpg --gen-key`_
This will spawn a series of questions.
......
# frozen_string_literal: true
module AfterCommitQueue
extend ActiveSupport::Concern
......
# frozen_string_literal: true
module Backup
Error = Class.new(StandardError)
end
# frozen_string_literal: true
module Banzai
# if you need to render markdown, then you probably need to post_process as well,
# such as removing references that the current user doesn't have
......
# frozen_string_literal: true
module Banzai
module ColorParser
ALPHA = /0(?:\.\d+)?|\.\d+|1(?:\.0+)?/ # 0.0..1.0
......
# frozen_string_literal: true
module Banzai
module CommitRenderer
ATTRIBUTES = [:description, :title].freeze
......
# frozen_string_literal: true
module Banzai
# Common methods for ReferenceFilters that support an optional cross-project
# reference.
......
# frozen_string_literal: true
module Banzai
module Filter
def self.[](name)
......
# frozen_string_literal: true
# `CommonMark` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `commonmarker` which is a ruby wrapper for libcmark (CommonMark parser)
......
# frozen_string_literal: true
# `Redcarpet` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `redcarpet` which is a ruby library for markdown processing.
......
# frozen_string_literal: true
module Banzai
module Filter
class WikiLinkFilter < HTML::Pipeline::Filter
......
# frozen_string_literal: true
module Banzai
class FilterArray < Array
# Insert a value immediately after another value
......
# frozen_string_literal: true
module Banzai
# Extract references to issuables from multiple documents
......
# frozen_string_literal: true
module Banzai
# Class for rendering multiple objects (e.g. Note instances) in a single pass,
# using +render_field+ to benefit from caching in the database. Rendering and
......
# frozen_string_literal: true
module Banzai
module Pipeline
def self.[](name)
......
# frozen_string_literal: true
module Banzai
module Pipeline
class AsciiDocPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class AtomPipeline < FullPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class BroadcastMessagePipeline < DescriptionPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
module CombinedPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class CommitDescriptionPipeline < SingleLinePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class DescriptionPipeline < FullPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class EmailPipeline < FullPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class FullPipeline < CombinedPipeline.new(PlainMarkdownPipeline, GfmPipeline)
......
# frozen_string_literal: true
module Banzai
module Pipeline
class GfmPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class MarkupPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class NotePipeline < FullPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class PlainMarkdownPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class PostProcessPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class PreProcessPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class RelativeLinkPipeline < BasePipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class SingleLinePipeline < GfmPipeline
......
# frozen_string_literal: true
module Banzai
module Pipeline
class WikiPipeline < FullPipeline
......
# frozen_string_literal: true
module Banzai
module Querying
module_function
......
# frozen_string_literal: true
module Banzai
# Class for removing Markdown references a certain user is not allowed to
# view.
......
# frozen_string_literal: true
module Banzai
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
# Returns the reference parser class for the given type
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
# Base class for reference parsing classes.
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class CommitParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class CommitRangeParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class DirectlyAddressedUserParser < UserParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
# The actual parser is implemented in the EE mixin
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class ExternalIssueParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class IssuableParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class IssueParser < IssuableParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class LabelParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class MergeRequestParser < IssuableParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class MilestoneParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class SnippetParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module ReferenceParser
class UserParser < BaseParser
......
# frozen_string_literal: true
module Banzai
module Renderer
# Convert a Markdown String into an HTML-safe String of HTML
......
# frozen_string_literal: true
module Banzai
module Renderer
module CommonMark
......
# frozen_string_literal: true
module Banzai
module Renderer
module Redcarpet
......
# frozen_string_literal: true
module Banzai
module RequestStoreReferenceCache
def cached_call(request_store_key, cache_key, path: [])
......
# frozen_string_literal: true
module Bitbucket
class Client
attr_reader :connection
......
# frozen_string_literal: true
module Bitbucket
class Collection < Enumerator
def initialize(paginator)
......
# frozen_string_literal: true
module Bitbucket
class Connection
DEFAULT_API_VERSION = '2.0'.freeze
......
# frozen_string_literal: true
module Bitbucket
module Error
Unauthorized = Class.new(StandardError)
......
# frozen_string_literal: true
module Bitbucket
class Page
attr_reader :attrs, :items
......
# frozen_string_literal: true
module Bitbucket
class Paginator
PAGE_LENGTH = 50 # The minimum length is 10 and the maximum is 100.
......
# frozen_string_literal: true
module Bitbucket
module Representation
class Base
......
# frozen_string_literal: true
module Bitbucket
module Representation
class Comment < Representation::Base
......
# frozen_string_literal: true
module Bitbucket
module Representation
class Issue < Representation::Base
......
# frozen_string_literal: true
module Bitbucket
module Representation
class PullRequest < Representation::Base
......
# frozen_string_literal: true
module Bitbucket
module Representation
class PullRequestComment < Comment
......
# frozen_string_literal: true
module Bitbucket
module Representation
class Repo < Representation::Base
......
# frozen_string_literal: true
module Bitbucket
module Representation
class User < Representation::Base
......
# frozen_string_literal: true
class CarrierWaveStringFile < StringIO
def original_filename
""
......
# frozen_string_literal: true
module Constraints
class FeatureConstrainer
attr_reader :feature
......
# frozen_string_literal: true
module Constraints
class GroupUrlConstrainer
def matches?(request)
......
# frozen_string_literal: true
module Constraints
class ProjectUrlConstrainer
def matches?(request)
......
# frozen_string_literal: true
module Constraints
class UserUrlConstrainer
def matches?(request)
......
# frozen_string_literal: true
module ContainerRegistry
class Blob
attr_reader :repository, :config
......
# frozen_string_literal: true
require 'faraday'
require 'faraday_middleware'
......
# frozen_string_literal: true
module ContainerRegistry
class Config
attr_reader :tag, :blob, :data
......
# frozen_string_literal: true
module ContainerRegistry
##
# Class responsible for extracting project and repository name from
......
# frozen_string_literal: true
module ContainerRegistry
class Registry
attr_reader :uri, :client, :path
......
# frozen_string_literal: true
module ContainerRegistry
class Tag
attr_reader :repository, :name
......
# frozen_string_literal: true
require_dependency 'declarative_policy/cache'
require_dependency 'declarative_policy/condition'
require_dependency 'declarative_policy/delegate_dsl'
......
# frozen_string_literal: true
module DeclarativePolicy
class Base
# A map of ability => list of rules together with :enable
......
# frozen_string_literal: true
module DeclarativePolicy
module Cache
class << self
......
# frozen_string_literal: true
module DeclarativePolicy
# A Condition is the data structure that is created by the
# `condition` declaration on DeclarativePolicy::Base. It is
......
# frozen_string_literal: true
module DeclarativePolicy
# Used when the name of a delegate is mentioned in
# the rule DSL.
......
# frozen_string_literal: true
module DeclarativePolicy
# The return value of a rule { ... } declaration.
# Can call back to register rules with the containing
......
module DeclarativePolicy # rubocop:disable Naming/FileName
# rubocop:disable Naming/FileName
# frozen_string_literal: true
module DeclarativePolicy
PREFERRED_SCOPE_KEY = :"DeclarativePolicy.preferred_scope"
class << self
......
# frozen_string_literal: true
module DeclarativePolicy
module Rule
# A Rule is the object that results from the `rule` declaration,
......
# frozen_string_literal: true
module DeclarativePolicy
# The DSL evaluation context inside rule { ... } blocks.
# Responsible for creating and combining Rule objects.
......
# frozen_string_literal: true
module DeclarativePolicy
class Runner
class State
......
# frozen_string_literal: true
module DeclarativePolicy
# This object represents one step in the runtime decision of whether
# an ability is allowed. It contains a Rule and a context (instance
......
# frozen_string_literal: true
module ExpandVariables
class << self
def expand(value, variables)
......
# frozen_string_literal: true
# Module providing methods for dealing with separating a tree-ish string and a
# file path string when combined in a request parameter
module ExtractsPath
......@@ -50,7 +52,9 @@ module ExtractsPath
# branches and tags
# Append a trailing slash if we only get a ref and no file path
id += '/' unless id.ends_with?('/')
unless id.ends_with?('/')
id = [id, '/'].join
end
valid_refs = ref_names.select { |v| id.start_with?("#{v}/") }
......@@ -151,9 +155,9 @@ module ExtractsPath
# overriden in subclasses, do not remove
def get_id
id = params[:id] || params[:ref]
id += "/" + params[:path] unless params[:path].blank?
id
id = [params[:id] || params[:ref]]
id << "/" + params[:path] unless params[:path].blank?
id.join
end
def ref_names
......
# frozen_string_literal: true
require 'flipper/adapters/active_record'
require 'flipper/adapters/active_support_cache_store'
......
# frozen_string_literal: true
class FileSizeValidator < ActiveModel::EachValidator
MESSAGES = { is: :wrong_size, minimum: :size_too_small, maximum: :size_too_big }.freeze
CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze
......
# frozen_string_literal: true
class Forever
POSTGRESQL_DATE = DateTime.new(3000, 1, 1)
MYSQL_DATE = DateTime.new(2038, 01, 19)
......
# frozen_string_literal: true
require_dependency 'gitlab/popen'
module Gitlab
......
# frozen_string_literal: true
class GtOneCoercion < Virtus::Attribute
def coerce(value)
[1, value.to_i].max
......
# frozen_string_literal: true
module MilestoneArray
class << self
def sort(array, sort_method)
......
# frozen_string_literal: true
# Disable NO_ZERO_DATE mode for mysql in rails 5.
# We use zero date as a default value
# (config/initializers/active_record_mysql_timestamp.rb), in
......
# frozen_string_literal: true
# Provides an ActiveRecord-like interface to a model whose data is not persisted to a database.
module StaticModel
extend ActiveSupport::Concern
......
# frozen_string_literal: true
# Library to perform System Checks
#
# Every Check is implemented as its own class inherited from SystemCheck::BaseCheck
......
# frozen_string_literal: true
require_relative 'gt_one_coercion'
class UnfoldForm
......
# frozen_string_literal: true
require "tempfile"
require "tmpdir"
require "fileutils"
......
# frozen_string_literal: true
require "base64"
# This class is used to build image URL to
......
......@@ -86,8 +86,12 @@ module Page
end
```
It is possible to use `element` DSL method without value, with a String value
or with a Regexp.
The `view` DSL method declares the filename of the view where an
`element` is implmented.
The `element` DSL method in turn declares an element and defines a value
to match to the actual view code. It is possible to use `element` with value,
with a String value or with a Regexp.
```ruby
view 'app/views/my/view.html.haml' do
......
......@@ -7,7 +7,7 @@ module QA
# set to 'false' to have Chrome run visibly instead of headless
def chrome_headless?
(ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i) != 0
enabled?(ENV['CHROME_HEADLESS'])
end
def accept_insecure_certs?
......@@ -18,6 +18,10 @@ module QA
ENV['CI'] || ENV['CI_SERVER']
end
def signup_disabled?
enabled?(ENV['SIGNUP_DISABLED'], default: false)
end
# specifies token that can be used for the api
def personal_access_token
ENV['PERSONAL_ACCESS_TOKEN']
......@@ -89,6 +93,14 @@ module QA
raise ArgumentError, "Please provide GITHUB_ACCESS_TOKEN"
end
private
def enabled?(value, default: true)
return default if value.nil?
(value =~ /^(false|no|0)$/i) != 0
end
end
end
end
......@@ -16,13 +16,13 @@ module QA
end
end
context :manage do
context :manage, :skip_signup_disabled do
describe 'standard' do
it_behaves_like 'registration and login'
end
end
context :manage, :orchestrated, :ldap do
context :manage, :orchestrated, :ldap, :skip_signup_disabled do
describe 'while LDAP is enabled' do
it_behaves_like 'registration and login'
end
......
......@@ -23,6 +23,8 @@ module QA
args.push(%w[--tag ~orchestrated]) unless (%w[-t --tag] & options).any?
end
args.push(%w[--tag ~skip_signup_disabled]) if QA::Runtime::Env.signup_disabled?
args.push(options)
args.push(DEFAULT_TEST_PATH_ARGS) unless options.any? { |opt| opt =~ %r{/features/} }
......
describe QA::Runtime::Env do
include Support::StubENV
describe '.chrome_headless?' do
shared_examples 'boolean method' do |method, env_key, default|
context 'when there is an env variable set' do
it 'returns false when falsey values specified' do
stub_env('CHROME_HEADLESS', 'false')
expect(described_class.chrome_headless?).to be_falsey
stub_env(env_key, 'false')
expect(described_class.public_send(method)).to be_falsey
stub_env('CHROME_HEADLESS', 'no')
expect(described_class.chrome_headless?).to be_falsey
stub_env(env_key, 'no')
expect(described_class.public_send(method)).to be_falsey
stub_env('CHROME_HEADLESS', '0')
expect(described_class.chrome_headless?).to be_falsey
stub_env(env_key, '0')
expect(described_class.public_send(method)).to be_falsey
end
it 'returns true when anything else specified' do
stub_env('CHROME_HEADLESS', 'true')
expect(described_class.chrome_headless?).to be_truthy
stub_env(env_key, 'true')
expect(described_class.public_send(method)).to be_truthy
stub_env('CHROME_HEADLESS', '1')
expect(described_class.chrome_headless?).to be_truthy
stub_env(env_key, '1')
expect(described_class.public_send(method)).to be_truthy
stub_env('CHROME_HEADLESS', 'anything')
expect(described_class.chrome_headless?).to be_truthy
stub_env(env_key, 'anything')
expect(described_class.public_send(method)).to be_truthy
end
end
context 'when there is no env variable set' do
it 'returns the default, true' do
stub_env('CHROME_HEADLESS', nil)
expect(described_class.chrome_headless?).to be_truthy
it "returns the default, #{default}" do
stub_env(env_key, nil)
expect(described_class.public_send(method)).to be(default)
end
end
end
describe '.signup_disabled?' do
it_behaves_like 'boolean method', :signup_disabled?, 'SIGNUP_DISABLED', false
end
describe '.chrome_headless?' do
it_behaves_like 'boolean method', :chrome_headless?, 'CHROME_HEADLESS', true
end
describe '.running_in_ci?' do
context 'when there is an env variable set' do
it 'returns true if CI' do
......
......@@ -62,6 +62,20 @@ describe QA::Specs::Runner do
end
end
context 'when SIGNUP_DISABLED is true' do
before do
allow(QA::Runtime::Env).to receive(:signup_disabled?).and_return(true)
end
subject { described_class.new }
it 'it includes default args and excludes the skip_signup_disabled tag' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
end
def expect_rspec_runner_arguments(arguments)
expect(RSpec::Core::Runner).to receive(:run)
.with(arguments, $stderr, $stdout)
......
......@@ -599,35 +599,68 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
before do
project.add_developer(user)
sign_in(user)
post_cancel
end
context 'when job is cancelable' do
context 'when continue url is present' do
let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
it 'redirects to the canceled job page' do
expect(response).to have_gitlab_http_status(:found)
expect(response).to redirect_to(namespace_project_job_path(id: job.id))
context 'when continue to is a safe url' do
let(:url) { '/test' }
before do
post_cancel(continue: { to: url })
end
it 'redirects to the continue url' do
expect(response).to have_gitlab_http_status(:found)
expect(response).to redirect_to(url)
end
it 'transits to canceled' do
expect(job.reload).to be_canceled
end
end
it 'transits to canceled' do
expect(job.reload).to be_canceled
context 'when continue to is not a safe url' do
let(:url) { 'http://example.com' }
it 'raises an error' do
expect { cancel_with_redirect(url) }.to raise_error
end
end
end
context 'when job is not cancelable' do
let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
context 'when continue url is not present' do
before do
post_cancel
end
it 'returns unprocessable_entity' do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
context 'when job is cancelable' do
let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
it 'redirects to the builds page' do
expect(response).to have_gitlab_http_status(:found)
expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id))
end
it 'transits to canceled' do
expect(job.reload).to be_canceled
end
end
context 'when job is not cancelable' do
let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
it 'returns unprocessable_entity' do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
end
def post_cancel
post :cancel, namespace_id: project.namespace,
project_id: project,
id: job.id
def post_cancel(additional_params = {})
post :cancel, { namespace_id: project.namespace,
project_id: project,
id: job.id }.merge(additional_params)
end
end
......
......@@ -76,28 +76,6 @@ describe Projects::MergeRequestsController do
expect(response).to be_success
end
context "loads notes" do
let(:first_contributor) { create(:user) }
let(:contributor) { create(:user) }
let(:merge_request) { create(:merge_request, author: first_contributor, target_project: project, source_project: project) }
let(:contributor_merge_request) { create(:merge_request, :merged, author: contributor, target_project: project, source_project: project) }
# the order here is important
# as the controller reloads these from DB, references doesn't correspond after
let!(:first_contributor_note) { create(:note, author: first_contributor, noteable: merge_request, project: project) }
let!(:contributor_note) { create(:note, author: contributor, noteable: merge_request, project: project) }
let!(:owner_note) { create(:note, author: user, noteable: merge_request, project: project) }
it "with special_role FIRST_TIME_CONTRIBUTOR" do
go(format: :html)
notes = assigns(:notes)
expect(notes).to match(a_collection_containing_exactly(an_object_having_attributes(special_role: Note::SpecialRole::FIRST_TIME_CONTRIBUTOR),
an_object_having_attributes(special_role: nil),
an_object_having_attributes(special_role: nil)
))
end
end
context "that is invalid" do
let(:merge_request) { create(:invalid_merge_request, target_project: project, source_project: project) }
......
# frozen_string_literal: true
require 'spec_helper'
describe PendingTodosFinder do
let(:user) { create(:user) }
describe '#execute' do
it 'returns only pending todos' do
create(:todo, :done, user: user)
todo = create(:todo, :pending, user: user)
todos = described_class.new(user).execute
expect(todos).to eq([todo])
end
it 'supports retrieving of todos for a specific project' do
project1 = create(:project)
project2 = create(:project)
create(:todo, :pending, user: user, project: project2)
todo = create(:todo, :pending, user: user, project: project1)
todos = described_class.new(user, project_id: project1.id).execute
expect(todos).to eq([todo])
end
it 'supports retrieving of todos for a specific todo target' do
issue = create(:issue)
note = create(:note)
todo = create(:todo, :pending, user: user, target: issue)
create(:todo, :pending, user: user, target: note)
todos = described_class.new(user, target_id: issue.id).execute
expect(todos).to eq([todo])
end
it 'supports retrieving of todos for a specific target type' do
issue = create(:issue)
note = create(:note)
todo = create(:todo, :pending, user: user, target: issue)
create(:todo, :pending, user: user, target: note)
todos = described_class.new(user, target_type: issue.class).execute
expect(todos).to eq([todo])
end
it 'supports retrieving of todos for a specific commit ID' do
create(:todo, :pending, user: user, commit_id: '456')
todo = create(:todo, :pending, user: user, commit_id: '123')
todos = described_class.new(user, commit_id: '123').execute
expect(todos).to eq([todo])
end
end
end
......@@ -105,9 +105,24 @@ describe TodosFinder do
todos = finder.new(user, { sort: 'priority' }).execute
puts todos.to_sql
expect(todos).to eq([todo_3, todo_5, todo_4, todo_2, todo_1])
end
end
end
describe '#any_for_target?' do
it 'returns true if there are any todos for the given target' do
todo = create(:todo, :pending)
finder = described_class.new(todo.user)
expect(finder.any_for_target?(todo.target)).to eq(true)
end
it 'returns false if there are no todos for the given target' do
issue = create(:issue)
finder = described_class.new(issue.author)
expect(finder.any_for_target?(issue)).to eq(false)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe UsersWithPendingTodosFinder do
describe '#execute' do
it 'returns the users for all pending todos of a target' do
issue = create(:issue)
note = create(:note)
todo = create(:todo, :pending, target: issue)
create(:todo, :pending, target: note)
users = described_class.new(issue).execute
expect(users).to eq([todo.user])
end
end
end
......@@ -17,7 +17,7 @@ describe Gitlab::Ci::Status::Build::Scheduled do
let(:build) { create(:ci_build, scheduled_at: 1.minute.since, project: project) }
it 'shows execute_in of the scheduled job' do
Timecop.freeze do
Timecop.freeze(Time.now.change(usec: 0)) do
expect(subject.status_tooltip).to include('00:01:00')
end
end
......
......@@ -262,7 +262,7 @@ describe Ci::Build do
it 'schedules BuildScheduleWorker at the right time' do
Timecop.freeze do
expect(Ci::BuildScheduleWorker)
.to receive(:perform_at).with(1.minute.since, build.id)
.to receive(:perform_at).with(be_like_time(1.minute.since), build.id)
subject
end
......
......@@ -4388,6 +4388,29 @@ describe Project do
end
end
describe '.find_without_deleted' do
it 'returns nil if the project is about to be removed' do
project = create(:project, pending_delete: true)
expect(described_class.find_without_deleted(project.id)).to be_nil
end
it 'returns a project when it is not about to be removed' do
project = create(:project)
expect(described_class.find_without_deleted(project.id)).to eq(project)
end
end
describe '.for_group' do
it 'returns the projects for a given group' do
group = create(:group)
project = create(:project, namespace: group)
expect(described_class.for_group(group)).to eq([project])
end
end
def rugged_config
rugged_repo(project.repository).config
end
......
......@@ -173,4 +173,129 @@ describe Todo do
expect(subject).not_to be_self_assigned
end
end
describe '.for_action' do
it 'returns the todos for a given action' do
create(:todo, action: Todo::MENTIONED)
todo = create(:todo, action: Todo::ASSIGNED)
expect(described_class.for_action(Todo::ASSIGNED)).to eq([todo])
end
end
describe '.for_author' do
it 'returns the todos for a given author' do
user1 = create(:user)
user2 = create(:user)
todo = create(:todo, author: user1)
create(:todo, author: user2)
expect(described_class.for_author(user1)).to eq([todo])
end
end
describe '.for_project' do
it 'returns the todos for a given project' do
project1 = create(:project)
project2 = create(:project)
todo = create(:todo, project: project1)
create(:todo, project: project2)
expect(described_class.for_project(project1)).to eq([todo])
end
end
describe '.for_group' do
it 'returns the todos for a given group' do
group1 = create(:group)
group2 = create(:group)
todo = create(:todo, group: group1)
create(:todo, group: group2)
expect(described_class.for_group(group1)).to eq([todo])
end
end
describe '.for_type' do
it 'returns the todos for a given target type' do
todo = create(:todo, target: create(:issue))
create(:todo, target: create(:merge_request))
expect(described_class.for_type(Issue)).to eq([todo])
end
end
describe '.for_target' do
it 'returns the todos for a given target' do
todo = create(:todo, target: create(:issue))
create(:todo, target: create(:merge_request))
expect(described_class.for_target(todo.target)).to eq([todo])
end
end
describe '.for_commit' do
it 'returns the todos for a commit ID' do
todo = create(:todo, commit_id: '123')
create(:todo, commit_id: '456')
expect(described_class.for_commit('123')).to eq([todo])
end
end
describe '.for_group_and_descendants' do
it 'returns the todos for a group and its descendants' do
parent_group = create(:group)
child_group = create(:group, parent: parent_group)
todo1 = create(:todo, group: parent_group)
todo2 = create(:todo, group: child_group)
todos = described_class.for_group_and_descendants(parent_group)
expect(todos).to include(todo1)
# Nested groups only work on PostgreSQL, so on MySQL todo2 won't be
# present.
expect(todos).to include(todo2) if Gitlab::Database.postgresql?
end
end
describe '.any_for_target?' do
it 'returns true if there are todos for a given target' do
todo = create(:todo)
expect(described_class.any_for_target?(todo.target)).to eq(true)
end
it 'returns false if there are no todos for a given target' do
issue = create(:issue)
expect(described_class.any_for_target?(issue)).to eq(false)
end
end
describe '.update_state' do
it 'updates the state of todos' do
todo = create(:todo, :pending)
ids = described_class.update_state(:done)
todo.reload
expect(ids).to eq([todo.id])
expect(todo.state).to eq('done')
end
it 'does not update todos that already have the given state' do
create(:todo, :pending)
expect(described_class.update_state(:pending)).to be_empty
end
end
end
......@@ -227,7 +227,7 @@ describe Ci::BuildPresenter do
it 'returns execution time' do
Timecop.freeze do
is_expected.to eq(60.0)
is_expected.to be_like_time(60.0)
end
end
end
......
......@@ -4,23 +4,29 @@ describe PruneOldEventsWorker do
describe '#perform' do
let(:user) { create(:user) }
let!(:expired_event) { create(:event, :closed, author: user, created_at: 13.months.ago) }
let!(:not_expired_event) { create(:event, :closed, author: user, created_at: 1.day.ago) }
let!(:exactly_12_months_event) { create(:event, :closed, author: user, created_at: 12.months.ago) }
let!(:expired_event) { create(:event, :closed, author: user, created_at: 25.months.ago) }
let!(:not_expired_1_day_event) { create(:event, :closed, author: user, created_at: 1.day.ago) }
let!(:not_expired_13_month_event) { create(:event, :closed, author: user, created_at: 13.months.ago) }
let!(:not_expired_2_years_event) { create(:event, :closed, author: user, created_at: 2.years.ago) }
it 'prunes events older than 12 months' do
it 'prunes events older than 2 years' do
expect { subject.perform }.to change { Event.count }.by(-1)
expect(Event.find_by(id: expired_event.id)).to be_nil
end
it 'leaves fresh events' do
subject.perform
expect(not_expired_event.reload).to be_present
expect(not_expired_1_day_event.reload).to be_present
end
it 'leaves events from exactly 12 months ago' do
it 'leaves events from 13 months ago' do
subject.perform
expect(exactly_12_months_event).to be_present
expect(not_expired_13_month_event.reload).to be_present
end
it 'leaves events from 2 years ago' do
subject.perform
expect(not_expired_2_years_event).to be_present
end
end
end
......@@ -61,3 +61,6 @@ fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
......@@ -20,7 +20,7 @@ coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
......
......@@ -64,6 +64,9 @@ acs-*.bib
# changes
*.soc
# comment
*.cut
# cprotect
*.cpt
......@@ -205,6 +208,9 @@ pythontex-files-*/
# easy-todo
*.lod
# xcolor
*.xcp
# xmpincl
*.xmpi
......
......@@ -4,6 +4,7 @@
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
......@@ -76,6 +77,7 @@ StyleCopReport.xml
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
......@@ -290,8 +292,8 @@ paket-files/
.idea/
*.sln.iml
# CodeRush
.cr/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
......
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