diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md index aec734870d6..3e58d2a867e 100644 --- a/.gitlab/issue_templates/Bug.md +++ b/.gitlab/issue_templates/Bug.md @@ -1,3 +1,4 @@ + ### Summary diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index add24303e7b..9501e35b178 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -6,7 +6,7 @@ import { __ } from '../../locale'; import Sidebar from '../../right_sidebar'; import eventHub from '../../sidebar/event_hub'; import assigneeTitle from '../../sidebar/components/assignees/assignee_title'; -import assignees from '../../sidebar/components/assignees/assignees'; +import assignees from '../../sidebar/components/assignees/assignees.vue'; import DueDateSelectors from '../../due_date_select'; import './sidebar/remove_issue'; import IssuableContext from '../../issuable_context'; diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js index 034f2923b3b..46d89c825f9 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js @@ -14,10 +14,10 @@ import CycleAnalyticsStore from './cycle_analytics_store'; Vue.use(Translate); -$(() => { +export default () => { const OVERVIEW_DIALOG_COOKIE = 'cycle_analytics_help_dismissed'; - gl.cycleAnalyticsApp = new Vue({ + new Vue({ // eslint-disable-line no-new el: '#cycle-analytics', name: 'CycleAnalytics', components: { @@ -132,4 +132,4 @@ $(() => { }, }, }); -}); +}; diff --git a/app/assets/javascripts/ide/components/ide_context_bar.vue b/app/assets/javascripts/ide/components/ide_context_bar.vue index dd947f66969..9d933b8891d 100644 --- a/app/assets/javascripts/ide/components/ide_context_bar.vue +++ b/app/assets/javascripts/ide/components/ide_context_bar.vue @@ -1,8 +1,8 @@ + + + diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js index 9e47039d920..8269fe1281d 100644 --- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js +++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js @@ -1,6 +1,6 @@ import Flash from '../../../flash'; import AssigneeTitle from './assignee_title'; -import Assignees from './assignees'; +import Assignees from './assignees.vue'; import Store from '../../stores/sidebar_store'; import eventHub from '../../event_hub'; @@ -28,8 +28,8 @@ export default { }, }, components: { - 'assignee-title': AssigneeTitle, - assignees: Assignees, + AssigneeTitle, + Assignees, }, methods: { assignSelf() { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 0cf67734237..4c9732c26d9 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -103,6 +103,7 @@ .issuable-show-labels { a { margin-bottom: 5px; + margin-right: 5px; display: inline-block; .color-label { @@ -116,6 +117,12 @@ } &.has-labels { + // this font size is a fix to + // prevent unintended spacing between labels + // which shows up when rendering markup has white-space + // characters present. + // see: https://css-tricks.com/fighting-the-space-between-inline-block-elements/#article-header-id-3 + font-size: 0; margin-bottom: -5px; } } diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb index b71f1e5fef4..4856be61e88 100644 --- a/app/controllers/projects/pages_domains_controller.rb +++ b/app/controllers/projects/pages_domains_controller.rb @@ -3,7 +3,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController before_action :require_pages_enabled! before_action :authorize_update_pages!, except: [:show] - before_action :domain, only: [:show, :destroy, :verify] + before_action :domain, except: [:new, :create] def show end @@ -24,8 +24,11 @@ class Projects::PagesDomainsController < Projects::ApplicationController redirect_to project_pages_domain_path(@project, @domain) end + def edit + end + def create - @domain = @project.pages_domains.create(pages_domain_params) + @domain = @project.pages_domains.create(create_params) if @domain.valid? redirect_to project_pages_domain_path(@project, @domain) @@ -34,6 +37,16 @@ class Projects::PagesDomainsController < Projects::ApplicationController end end + def update + if @domain.update(update_params) + redirect_to project_pages_path(@project), + status: 302, + notice: 'Domain was updated' + else + render 'edit' + end + end + def destroy @domain.destroy @@ -49,12 +62,12 @@ class Projects::PagesDomainsController < Projects::ApplicationController private - def pages_domain_params - params.require(:pages_domain).permit( - :certificate, - :key, - :domain - ) + def create_params + params.require(:pages_domain).permit(:key, :certificate, :domain) + end + + def update_params + params.require(:pages_domain).permit(:key, :certificate) end def domain diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 13c784bea0d..609620a62bb 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -49,7 +49,7 @@ module Ci ref_protected: 1 } - cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at + cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at, :ip_address # Searches for runners matching the given query. # @@ -157,7 +157,7 @@ module Ci end def update_cached_info(values) - values = values&.slice(:version, :revision, :platform, :architecture) || {} + values = values&.slice(:version, :revision, :platform, :architecture, :ip_address) || {} values[:contacted_at] = Time.now cache_attributes(values) diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 0e235a6d2a0..379a8068023 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -15,6 +15,8 @@ module Projects return error("Could not set the default branch") unless project.change_head(params[:default_branch]) end + ensure_wiki_exists if enabling_wiki? + if project.update_attributes(params.except(:default_branch)) if project.previous_changes.include?('path') project.rename_repo @@ -52,5 +54,18 @@ module Projects project.repository.exists? && new_branch && new_branch != project.default_branch end + + def enabling_wiki? + return false if @project.wiki_enabled? + + params[:project_feature_attributes][:wiki_access_level].to_i > ProjectFeature::DISABLED + end + + def ensure_wiki_exists + ProjectWiki.new(project, project.owner).wiki + rescue ProjectWiki::CouldNotCreateWikiError + log_error("Could not create wiki for #{project.full_name}") + Gitlab::Metrics.counter(:wiki_can_not_be_created_total, 'Counts the times we failed to create a wiki') + end end end diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index 140688b52d3..e1cee584929 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -16,6 +16,8 @@ = runner.description %td = runner.version + %td + = runner.ip_address %td - if runner.shared? n/a diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index abec3607cab..9f13dbbbd82 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -60,6 +60,7 @@ %th Runner token %th Description %th Version + %th IP Address %th Projects %th Jobs %th Tags diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml index d98e0564da4..02395b6eb9b 100644 --- a/app/views/projects/cycle_analytics/show.html.haml +++ b/app/views/projects/cycle_analytics/show.html.haml @@ -2,7 +2,6 @@ - page_title "Cycle Analytics" - content_for :page_specific_javascripts do = webpack_bundle_tag('common_vue') - = webpack_bundle_tag('cycle_analytics') #cycle-analytics{ class: container_class, "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } } - if @cycle_analytics_no_data diff --git a/app/views/projects/pages_domains/_form.html.haml b/app/views/projects/pages_domains/_form.html.haml index ca1b41b140a..d81b07832bb 100644 --- a/app/views/projects/pages_domains/_form.html.haml +++ b/app/views/projects/pages_domains/_form.html.haml @@ -1,34 +1,30 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'form-horizontal fieldset-form' } do |f| - - if @domain.errors.any? - #error_explanation - .alert.alert-danger - - @domain.errors.full_messages.each do |msg| - %p= msg +- if @domain.errors.any? + #error_explanation + .alert.alert-danger + - @domain.errors.full_messages.each do |msg| + %p= msg + +.form-group + = f.label :domain, class: 'control-label' do + Domain + .col-sm-10 + = f.text_field :domain, required: true, autocomplete: 'off', class: 'form-control', disabled: @domain.persisted? + +- if Gitlab.config.pages.external_https + .form-group + = f.label :certificate, class: 'control-label' do + Certificate (PEM) + .col-sm-10 + = f.text_area :certificate, rows: 5, class: 'form-control' + %span.help-inline Upload a certificate for your domain with all intermediates .form-group - = f.label :domain, class: 'control-label' do - Domain + = f.label :key, class: 'control-label' do + Key (PEM) .col-sm-10 - = f.text_field :domain, required: true, autocomplete: 'off', class: 'form-control' - - - if Gitlab.config.pages.external_https - .form-group - = f.label :certificate, class: 'control-label' do - Certificate (PEM) - .col-sm-10 - = f.text_area :certificate, rows: 5, class: 'form-control' - %span.help-inline Upload a certificate for your domain with all intermediates - - .form-group - = f.label :key, class: 'control-label' do - Key (PEM) - .col-sm-10 - = f.text_area :key, rows: 5, class: 'form-control' - %span.help-inline Upload a private key for your certificate - - else - .nothing-here-block - Support for custom certificates is disabled. - Ask your system's administrator to enable it. - - .form-actions - = f.submit 'Create New Domain', class: "btn btn-save" + = f.text_area :key, rows: 5, class: 'form-control' + %span.help-inline Upload a private key for your certificate +- else + .nothing-here-block + Support for custom certificates is disabled. + Ask your system's administrator to enable it. diff --git a/app/views/projects/pages_domains/edit.html.haml b/app/views/projects/pages_domains/edit.html.haml new file mode 100644 index 00000000000..5645a4604bf --- /dev/null +++ b/app/views/projects/pages_domains/edit.html.haml @@ -0,0 +1,11 @@ +- add_to_breadcrumbs "Pages", project_pages_path(@project) +- breadcrumb_title @domain.domain +- page_title @domain.domain +%h3.page_title + = @domain.domain +%hr.clearfix +%div + = form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'form-horizontal fieldset-form' } do |f| + = render 'form', { f: f } + .form-actions + = f.submit 'Save Changes', class: "btn btn-save" diff --git a/app/views/projects/pages_domains/new.html.haml b/app/views/projects/pages_domains/new.html.haml index e1477c71d06..5a397c9d3c7 100644 --- a/app/views/projects/pages_domains/new.html.haml +++ b/app/views/projects/pages_domains/new.html.haml @@ -1,6 +1,10 @@ +- add_to_breadcrumbs "Pages", project_pages_path(@project) - page_title 'New Pages Domain' %h3.page_title New Pages Domain %hr.clearfix %div - = render 'form' + = form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'form-horizontal fieldset-form' } do |f| + = render 'form', { f: f } + .form-actions + = f.submit 'Create New Domain', class: "btn btn-save" diff --git a/app/views/projects/pages_domains/show.html.haml b/app/views/projects/pages_domains/show.html.haml index 72e9203bdb0..ba0713daee9 100644 --- a/app/views/projects/pages_domains/show.html.haml +++ b/app/views/projects/pages_domains/show.html.haml @@ -1,4 +1,7 @@ +- add_to_breadcrumbs "Pages", project_pages_path(@project) +- breadcrumb_title @domain.domain - page_title "#{@domain.domain}", 'Pages Domains' + - verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled? - if verification_enabled && @domain.unverified? %p.alert.alert-warning @@ -8,6 +11,7 @@ %h3.page-title Pages Domain + = link_to 'Edit', edit_project_pages_domain_path(@project, @domain), class: 'btn btn-success pull-right' .table-holder %table.table diff --git a/app/views/projects/runners/_form.html.haml b/app/views/projects/runners/_form.html.haml index e660fce652f..49c90869146 100644 --- a/app/views/projects/runners/_form.html.haml +++ b/app/views/projects/runners/_form.html.haml @@ -29,6 +29,11 @@ Token .col-sm-10 = f.text_field :token, class: 'form-control', readonly: true + .form-group + = label_tag :ip_address, class: 'control-label' do + IP Address + .col-sm-10 + = f.text_field :ip_address, class: 'form-control', readonly: true .form-group = label_tag :description, class: 'control-label' do Description diff --git a/app/views/projects/runners/show.html.haml b/app/views/projects/runners/show.html.haml index dfab04aa1fb..4e57f5f844d 100644 --- a/app/views/projects/runners/show.html.haml +++ b/app/views/projects/runners/show.html.haml @@ -40,6 +40,9 @@ %tr %td Version %td= @runner.version + %tr + %td IP Address + %td= @runner.ip_address %tr %td Revision %td= @runner.revision diff --git a/changelogs/unreleased/43489-display-runner-ip.yml b/changelogs/unreleased/43489-display-runner-ip.yml new file mode 100644 index 00000000000..621c2ec709a --- /dev/null +++ b/changelogs/unreleased/43489-display-runner-ip.yml @@ -0,0 +1,5 @@ +--- +title: Display Runner IP Address +merge_request: 17286 +author: +type: added diff --git a/changelogs/unreleased/43531-500-error-searching-wiki-incompatible-character-encodings-utf-8-and-ascii-8bit.yml b/changelogs/unreleased/43531-500-error-searching-wiki-incompatible-character-encodings-utf-8-and-ascii-8bit.yml new file mode 100644 index 00000000000..173710412a5 --- /dev/null +++ b/changelogs/unreleased/43531-500-error-searching-wiki-incompatible-character-encodings-utf-8-and-ascii-8bit.yml @@ -0,0 +1,5 @@ +--- +title: Fix code and wiki search results pages when non-ASCII text is displayed +merge_request: 17413 +author: +type: fixed diff --git a/changelogs/unreleased/43643-fix-mr-label-filtering.yml b/changelogs/unreleased/43643-fix-mr-label-filtering.yml new file mode 100644 index 00000000000..32a44aef243 --- /dev/null +++ b/changelogs/unreleased/43643-fix-mr-label-filtering.yml @@ -0,0 +1,5 @@ +--- +title: Enable filtering MR list based on clicked label in MR sidebar +merge_request: 17390 +author: +type: fixed diff --git a/changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml b/changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml new file mode 100644 index 00000000000..c0fa8e2e377 --- /dev/null +++ b/changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml @@ -0,0 +1,5 @@ +--- +title: Make sure wiki exists when it's enabled +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/assignees-vue-component-missing-data-container.yml b/changelogs/unreleased/assignees-vue-component-missing-data-container.yml new file mode 100644 index 00000000000..233d983b415 --- /dev/null +++ b/changelogs/unreleased/assignees-vue-component-missing-data-container.yml @@ -0,0 +1,5 @@ +--- +title: Add Assignees vue component missing data container +merge_request: 17426 +author: George Tsiolis +type: fixed diff --git a/changelogs/unreleased/feature-edit_pages_domain.yml b/changelogs/unreleased/feature-edit_pages_domain.yml new file mode 100644 index 00000000000..bd0af53296c --- /dev/null +++ b/changelogs/unreleased/feature-edit_pages_domain.yml @@ -0,0 +1,5 @@ +--- +title: 'Pages custom domain: allow update of key/certificate' +merge_request: 17376 +author: rfwatson +type: changed diff --git a/changelogs/unreleased/refactor-move-assignees-vue-component.yml b/changelogs/unreleased/refactor-move-assignees-vue-component.yml new file mode 100644 index 00000000000..98cfa6b4c81 --- /dev/null +++ b/changelogs/unreleased/refactor-move-assignees-vue-component.yml @@ -0,0 +1,5 @@ +--- +title: Move Assignees vue component +merge_request: 16952 +author: George Tsiolis +type: performance diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index b89f0419b91..2079d3acb72 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -103,4 +103,6 @@ Doorkeeper.configure do # Some applications require dynamic query parameters on their request_uri # set to true if you want this to be allowed # wildcard_redirect_uri false + + base_controller 'ApplicationController' end diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb index 8560d24526f..114c1cb512f 100644 --- a/config/initializers/lograge.rb +++ b/config/initializers/lograge.rb @@ -12,9 +12,14 @@ unless Sidekiq.server? config.lograge.logger = ActiveSupport::Logger.new(filename) # Add request parameters to log output config.lograge.custom_options = lambda do |event| + params = event.payload[:params] + .except(*%w(controller action format)) + .each_pair + .map { |k, v| { key: k, value: v } } + payload = { time: event.time.utc.iso8601(3), - params: event.payload[:params].except(*%w(controller action format)), + params: params, remote_ip: event.payload[:remote_ip], user_id: event.payload[:user_id], username: event.payload[:username] diff --git a/config/routes/project.rb b/config/routes/project.rb index dd1a9c3be3b..34636285c51 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -55,7 +55,7 @@ constraints(ProjectUrlConstrainer.new) do end resource :pages, only: [:show, :destroy] do - resources :domains, only: [:show, :new, :create, :destroy], controller: 'pages_domains', constraints: { id: %r{[^/]+} } do + resources :domains, except: :index, controller: 'pages_domains', constraints: { id: %r{[^/]+} } do member do post :verify end diff --git a/config/webpack.config.js b/config/webpack.config.js index 65785385554..d8ba3c06d3a 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -44,7 +44,6 @@ function generateEntries() { const manualEntries = { balsamiq_viewer: './blob/balsamiq_viewer.js', - cycle_analytics: './cycle_analytics/cycle_analytics_bundle.js', environments: './environments/environments_bundle.js', monitoring: './monitoring/monitoring_bundle.js', mr_notes: './mr_notes/index.js', @@ -59,7 +58,6 @@ function generateEntries() { terminal: './terminal/terminal_bundle.js', two_factor_auth: './two_factor_auth.js', - common: './commons/index.js', common_vue: './vue_shared/vue_resource_interceptor.js', locale: './locale/index.js', @@ -225,6 +223,33 @@ const config = { return `${moduleNames[0]}-${hash.substr(0, 6)}`; }), + // create cacheable common library bundle for all vue chunks + new webpack.optimize.CommonsChunkPlugin({ + name: 'common_vue', + chunks: [ + 'boards', + 'deploy_keys', + 'environments', + 'filtered_search', + 'groups', + 'monitoring', + 'mr_notes', + 'notebook_viewer', + 'pdf_viewer', + 'pipelines', + 'pipelines_details', + 'registry_list', + 'ide', + 'schedule_form', + 'schedules_index', + 'sidebar', + 'vue_merge_request_widget', + ], + minChunks: function(module, count) { + return module.resource && (/vue_shared/).test(module.resource); + }, + }), + // create cacheable common library bundles new webpack.optimize.CommonsChunkPlugin({ names: ['main', 'common', 'webpack_runtime'], diff --git a/db/migrate/20180222043024_add_ip_address_to_runner.rb b/db/migrate/20180222043024_add_ip_address_to_runner.rb new file mode 100644 index 00000000000..bf00560b5a8 --- /dev/null +++ b/db/migrate/20180222043024_add_ip_address_to_runner.rb @@ -0,0 +1,9 @@ +class AddIpAddressToRunner < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + add_column :ci_runners, :ip_address, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 5bb461169f1..3fb80065ff5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180216121030) do +ActiveRecord::Schema.define(version: 20180222043024) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -437,6 +437,7 @@ ActiveRecord::Schema.define(version: 20180216121030) do t.boolean "run_untagged", default: true, null: false t.boolean "locked", default: false, null: false t.integer "access_level", default: 0, null: false + t.string "ip_address" end add_index "ci_runners", ["contacted_at"], name: "index_ci_runners_on_contacted_at", using: :btree diff --git a/doc/README.md b/doc/README.md index 46fcb7c6baf..fb7a23e2750 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,5 +1,4 @@ --- -toc: false comments: false --- @@ -8,15 +7,9 @@ comments: false Welcome to [GitLab](https://about.gitlab.com/), a Git-based fully featured platform for software development! -GitLab offers the most scalable Git-based fully integrated platform for software development, with flexible products and subscription plans. - -With GitLab self-hosted, you deploy your own GitLab instance on-premises or on a private cloud of your choice. GitLab self-hosted is available for [free and with paid subscriptions](https://about.gitlab.com/products/): Libre, Starter, Premium, and Ultimate. - -Every feature available in Libre is also available in Starter, Premium, and Ultimate. -Starter features are also available in Premium and Ultimate, and Premium features are also -available in Ultimate. - -GitLab.com is our SaaS offering. It's hosted, managed, and administered by GitLab, with [free and paid plans](https://about.gitlab.com/gitlab-com/) for individuals and teams: Free, Bronze, Silver, and Gold. +GitLab offers the most scalable Git-based fully integrated platform for +software development, with flexible products and subscriptions. +To understand what features you have access to, check the [GitLab subscriptions](#gitlab-subscriptions) below. ## Shortcuts to GitLab's most visited docs @@ -124,8 +117,6 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i - [GitLab Integration](integration/README.md): Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. - [Trello Power-Up](integration/trello_power_up.md): Integrate with GitLab's Trello Power-Up ----- - ## Administrator documentation [Administration documentation](administration/index.md) applies to admin users of GitLab @@ -143,3 +134,42 @@ Learn how to contribute to GitLab: - [Development](development/README.md): All styleguides and explanations how to contribute. - [Legal](legal/README.md): Contributor license agreements. - [Writing documentation](development/writing_documentation.md): Contributing to GitLab Docs. + +## GitLab subscriptions + +You have two options to use GitLab: + +- GitLab self-hosted: Install, administer, and maintain your own GitLab instance. +- GitLab.com: GitLab's SaaS offering. You don't need to install anything to use GitLab.com, +you only need to [sign up](https://gitlab.com/users/sign_in) and start using GitLab +straight away. + +### GitLab self-hosted + +With GitLab self-hosted, you deploy your own GitLab instance on-premises or on a private cloud of your choice. GitLab self-hosted is available for [free and with paid subscriptions](https://about.gitlab.com/products/): Libre, Starter, Premium, and Ultimate. + +Every feature available in Libre is also available in Starter, Premium, and Ultimate. +Starter features are also available in Premium and Ultimate, and Premium features are also +available in Ultimate. + +### GitLab.com + +GitLab.com is hosted, managed, and administered by GitLab, Inc., with +[free and paid subscriptions](https://about.gitlab.com/gitlab-com/) for individuals +and teams: Free, Bronze, Silver, and Gold. + +GitLab.com subscriptions grants access +to the same features available in GitLab self-hosted, **expect +[administration](administration/index.md) tools and settings**: + +- GitLab.com Free includes the same features available in GitLab Libre +- GitLab.com Bronze includes the same features available in GitLab Starter +- GitLab.com Silver includes the same features available in GitLab Premium +- GitLab.com Gold includes the same features available in GitLab Ultimate + +For supporting the open source community and encouraging the development of +open source projects, GitLab grants access to **Gold** features +for all GitLab.com **public** projects, regardless of the subscription. + +To know more about GitLab subscriptions and licensing, please refer to the +[GitLab Product Marketing Handbook](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers). diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index f30a85b114e..23ce6a5f210 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -56,6 +56,9 @@ future GitLab releases.** | **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 | | **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags | +| **CI_RUNNER_VERSION** | all | 10.6 | GitLab Runner version that is executing the current job | +| **CI_RUNNER_REVISION** | all | 10.6 | GitLab Runner revision that is executing the current job | +| **CI_RUNNER_EXECUTABLE_ARCH** | all | 10.6 | The OS/architecture of the GitLab Runner executable (note that this is not necessarily the same as the environment of the executor) | | **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally | | **CI_PIPELINE_TRIGGERED** | all | all | The flag to indicate that job was [triggered] | | **CI_PIPELINE_SOURCE** | 10.0 | all | The source for this pipeline, one of: push, web, trigger, schedule, api, external. Pipelines created before 9.5 will have unknown as source | diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index 6c93c29124d..09957feee17 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -507,6 +507,7 @@ This is the entry point for our store. You can use the following as a guide: import Vue from 'vue'; import Vuex from 'vuex'; import * as actions from './actions'; +import * as getters from './getters'; import * as mutations from './mutations'; Vue.use(Vuex); @@ -514,6 +515,7 @@ Vue.use(Vuex); export default new Vuex.Store({ actions, getters, + mutations, state: { users: [], }, diff --git a/doc/integration/saml.md b/doc/integration/saml.md index 3ae98adc465..f8a7dd6b1dc 100644 --- a/doc/integration/saml.md +++ b/doc/integration/saml.md @@ -109,8 +109,7 @@ in your SAML IdP: 1. Change the value of `issuer` to a unique name, which will identify the application to the IdP. -1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you - installed GitLab via Omnibus or from source respectively. +1. For the changes to take effect, you must [reconfigure][] GitLab if you installed via Omnibus or [restart GitLab][] if you installed from source. 1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified in `issuer`. diff --git a/doc/user/markdown.md b/doc/user/markdown.md index ea7b1c9a0ed..650d60f1585 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -36,12 +36,16 @@ GFM honors the markdown specification in how [paragraphs and line breaks are han A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. Line-breaks, or softreturns, are rendered if you end a line with two or more spaces: - Roses are red [followed by two or more spaces] +[//]: # (Do *NOT* remove the two ending whitespaces in the following line.) +[//]: # (They are needed for the Markdown text to render correctly.) + Roses are red [followed by two or more spaces] Violets are blue Sugar is sweet -Roses are red +[//]: # (Do *NOT* remove the two ending whitespaces in the following line.) +[//]: # (They are needed for the Markdown text to render correctly.) +Roses are red Violets are blue Sugar is sweet diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 0de89f90e21..16027744164 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -34,7 +34,7 @@ With **[GitLab Enterprise Edition][ee]**, you can also: - View the deployment process across projects with [Multi-Project Pipeline Graphs](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html#multi-project-pipeline-graphs) (available only in GitLab Premium) - Request [approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers (available in GitLab Starter) - [Squash and merge](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html) for a cleaner commit history (available in GitLab Starter) -- Analise the impact of your changes with [Code Quality reports](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality_diff.html) (available in GitLab Starter) +- Analyze the impact of your changes with [Code Quality reports](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality_diff.html) (available in GitLab Starter) ## Use cases diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb index fbe30192a16..35ac0b4cbca 100644 --- a/lib/api/helpers/runner.rb +++ b/lib/api/helpers/runner.rb @@ -9,16 +9,22 @@ module API Gitlab::CurrentSettings.runners_registration_token) end - def get_runner_version_from_params - return unless params['info'].present? - - attributes_for_keys(%w(name version revision platform architecture), params['info']) - end - def authenticate_runner! forbidden! unless current_runner - current_runner.update_cached_info(get_runner_version_from_params) + current_runner + .update_cached_info(get_runner_details_from_request) + end + + def get_runner_details_from_request + return get_runner_ip unless params['info'].present? + + attributes_for_keys(%w(name version revision platform architecture), params['info']) + .merge(get_runner_ip) + end + + def get_runner_ip + { ip_address: request.ip } end def current_runner diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 5469cba69a6..91cdc564002 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -16,7 +16,8 @@ module API optional :tag_list, type: Array[String], desc: %q(List of Runner's tags) end post '/' do - attributes = attributes_for_keys [:description, :locked, :run_untagged, :tag_list] + attributes = attributes_for_keys([:description, :locked, :run_untagged, :tag_list]) + .merge(get_runner_details_from_request) runner = if runner_registration_token_valid? @@ -30,7 +31,6 @@ module API return forbidden! unless runner if runner.id - runner.update(get_runner_version_from_params) present runner, with: Entities::RunnerRegistrationDetails else not_found! diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb index ac12271a87e..52b44b9b3c5 100644 --- a/lib/gitlab/git/wiki.rb +++ b/lib/gitlab/git/wiki.rb @@ -59,7 +59,7 @@ module Gitlab end def pages(limit: nil) - @repository.gitaly_migrate(:wiki_get_all_pages, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled| + @repository.gitaly_migrate(:wiki_get_all_pages) do |is_enabled| if is_enabled gitaly_get_all_pages else @@ -68,9 +68,8 @@ module Gitlab end end - # Disable because of https://gitlab.com/gitlab-org/gitlab-ce/issues/42039 def page(title:, version: nil, dir: nil) - @repository.gitaly_migrate(:wiki_find_page, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled| + @repository.gitaly_migrate(:wiki_find_page) do |is_enabled| if is_enabled gitaly_find_page(title: title, version: version, dir: dir) else diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb index 5a5ae7f19d4..781783f4d97 100644 --- a/lib/gitlab/search_results.rb +++ b/lib/gitlab/search_results.rb @@ -1,6 +1,8 @@ module Gitlab class SearchResults class FoundBlob + include EncodingHelper + attr_reader :id, :filename, :basename, :ref, :startline, :data, :project_id def initialize(opts = {}) @@ -9,7 +11,7 @@ module Gitlab @basename = opts.fetch(:basename, nil) @ref = opts.fetch(:ref, nil) @startline = opts.fetch(:startline, nil) - @data = opts.fetch(:data, nil) + @data = encode_utf8(opts.fetch(:data, nil)) @per_page = opts.fetch(:per_page, 20) @project_id = opts.fetch(:project_id, nil) end diff --git a/scripts/security-harness b/scripts/security-harness index d454f44dff7..c60b3410095 100755 --- a/scripts/security-harness +++ b/scripts/security-harness @@ -21,6 +21,8 @@ else File.open(hook_path, 'w') do |file| IO.copy_stream(DATA, file) end + + File.chmod(0755, hook_path) end # Toggle the harness on or off diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb index 004b463e745..149b690ff70 100644 --- a/spec/controllers/oauth/authorizations_controller_spec.rb +++ b/spec/controllers/oauth/authorizations_controller_spec.rb @@ -34,6 +34,8 @@ describe Oauth::AuthorizationsController do end context 'with valid params' do + render_views + it 'returns 200 code and renders view' do get :new, params diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb index 2192fd5cae2..83a3799e883 100644 --- a/spec/controllers/projects/pages_domains_controller_spec.rb +++ b/spec/controllers/projects/pages_domains_controller_spec.rb @@ -53,6 +53,66 @@ describe Projects::PagesDomainsController do end end + describe 'GET edit' do + it "displays the 'edit' page" do + get(:edit, request_params.merge(id: pages_domain.domain)) + + expect(response).to have_gitlab_http_status(200) + expect(response).to render_template('edit') + end + end + + describe 'PATCH update' do + before do + controller.instance_variable_set(:@domain, pages_domain) + end + + let(:pages_domain_params) do + attributes_for(:pages_domain, :with_certificate, :with_key).slice(:key, :certificate) + end + + let(:params) do + request_params.merge(id: pages_domain.domain, pages_domain: pages_domain_params) + end + + it 'updates the domain' do + expect(pages_domain) + .to receive(:update) + .with(pages_domain_params) + .and_return(true) + + patch(:update, params) + end + + it 'redirects to the project page' do + patch(:update, params) + + expect(flash[:notice]).to eq 'Domain was updated' + expect(response).to redirect_to(project_pages_path(project)) + end + + context 'the domain is invalid' do + it 'renders the edit action' do + allow(pages_domain).to receive(:update).and_return(false) + + patch(:update, params) + + expect(response).to render_template('edit') + end + end + + context 'the parameters include the domain' do + it 'renders 400 Bad Request' do + expect(pages_domain) + .to receive(:update) + .with(hash_not_including(:domain)) + .and_return(true) + + patch(:update, params.deep_merge(pages_domain: { domain: 'abc' })) + end + end + end + describe 'POST verify' do let(:params) { request_params.merge(id: pages_domain.domain) } diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb index a96f2c186a4..2a0d235ef04 100644 --- a/spec/features/projects/pages_spec.rb +++ b/spec/features/projects/pages_spec.rb @@ -160,6 +160,37 @@ feature 'Pages' do expect(page).to have_content('my.test.domain.com') end + + describe 'updating the certificate for an existing domain' do + let!(:domain) do + create(:pages_domain, :with_key, :with_certificate, project: project) + end + + it 'allows the certificate to be updated' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Details' } + click_link 'Edit' + click_button 'Save Changes' + + expect(page).to have_content('Domain was updated') + end + + context 'when the certificate is invalid' do + it 'tells the user what the problem is' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Details' } + click_link 'Edit' + fill_in 'Certificate (PEM)', with: 'invalid data' + click_button 'Save Changes' + + expect(page).to have_content('Certificate must be a valid PEM certificate') + expect(page).to have_content('Certificate misses intermediates') + expect(page).to have_content("Key doesn't match the certificate") + end + end + end end end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 37a06b65481..3a8e7c05cc4 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -367,23 +367,6 @@ describe 'Pipelines', :js do expect(build.reload).to be_canceled end end - - context 'dropdown jobs list' do - it 'should keep the dropdown open when the user ctr/cmd + clicks in the job name' do - find('.js-builds-dropdown-button').click - dropdown_item = find('.mini-pipeline-graph-dropdown-item').native - - %i(alt control).each do |meta_key| - page.driver.browser.action - .key_down(meta_key) - .click(dropdown_item) - .key_up(meta_key) - .perform - end - - expect(page).to have_selector('.js-ci-action-icon') - end - end end context 'with pagination' do diff --git a/spec/javascripts/labels_select_spec.js b/spec/javascripts/labels_select_spec.js new file mode 100644 index 00000000000..b8f7b1dc855 --- /dev/null +++ b/spec/javascripts/labels_select_spec.js @@ -0,0 +1,43 @@ +import LabelsSelect from '~/labels_select'; + +const mockUrl = '/foo/bar/url'; + +const mockLabels = [ + { + id: 26, + title: 'Foo Label', + description: 'Foobar', + color: '#BADA55', + text_color: '#FFFFFF', + }, +]; + +describe('LabelsSelect', () => { + describe('getLabelTemplate', () => { + const label = mockLabels[0]; + let $labelEl; + + beforeEach(() => { + $labelEl = $(LabelsSelect.getLabelTemplate({ + labels: mockLabels, + issueUpdateURL: mockUrl, + })); + }); + + it('generated label item template has correct label URL', () => { + expect($labelEl.attr('href')).toBe('/foo/bar?label_name[]=Foo%20Label'); + }); + + it('generated label item template has correct label title', () => { + expect($labelEl.find('span.label').text()).toBe(label.title); + }); + + it('generated label item template has label description as title attribute', () => { + expect($labelEl.find('span.label').attr('title')).toBe(label.description); + }); + + it('generated label item template has correct label styles', () => { + expect($labelEl.find('span.label').attr('style')).toBe(`background-color: ${label.color}; color: ${label.text_color};`); + }); + }); +}); diff --git a/spec/javascripts/sidebar/assignees_spec.js b/spec/javascripts/sidebar/assignees_spec.js index c9453a21189..4e4343812bd 100644 --- a/spec/javascripts/sidebar/assignees_spec.js +++ b/spec/javascripts/sidebar/assignees_spec.js @@ -1,5 +1,5 @@ import Vue from 'vue'; -import Assignee from '~/sidebar/components/assignees/assignees'; +import Assignee from '~/sidebar/components/assignees/assignees.vue'; import UsersMock from './mock_data'; import UsersMockHelper from '../helpers/user_mock_data_helper'; diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index 1ebb0105cf5..d8250e4b4c6 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe Gitlab::ProjectSearchResults do @@ -105,6 +106,32 @@ describe Gitlab::ProjectSearchResults do end end + context 'when the search returns non-ASCII data' do + context 'with UTF-8' do + let(:results) { project.repository.search_files_by_content("файл", 'master') } + + it 'returns results as UTF-8' do + expect(subject.filename).to eq('encoding/russian.rb') + expect(subject.basename).to eq('encoding/russian') + expect(subject.ref).to eq('master') + expect(subject.startline).to eq(1) + expect(subject.data).to eq("Хороший файл") + end + end + + context 'with ISO-8859-1' do + let(:search_result) { "master:encoding/iso8859.txt\x001\x00\xC4\xFC\nmaster:encoding/iso8859.txt\x002\x00\nmaster:encoding/iso8859.txt\x003\x00foo\n".force_encoding(Encoding::ASCII_8BIT) } + + it 'returns results as UTF-8' do + expect(subject.filename).to eq('encoding/iso8859.txt') + expect(subject.basename).to eq('encoding/iso8859') + expect(subject.ref).to eq('master') + expect(subject.startline).to eq(1) + expect(subject.data).to eq("Äü\n\nfoo") + end + end + end + context "when filename has extension" do let(:search_result) { "master:CONTRIBUTE.md\x005\x00- [Contribute to GitLab](#contribute-to-gitlab)\n" } diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index f10b6e43d09..4021e537efc 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -122,6 +122,15 @@ describe API::Runner do end end end + + it "sets the runner's ip_address" do + post api('/runners'), + { token: registration_token }, + { 'REMOTE_ADDR' => '123.111.123.111' } + + expect(response).to have_gitlab_http_status 201 + expect(Ci::Runner.first.ip_address).to eq('123.111.123.111') + end end describe 'DELETE /api/v4/runners' do @@ -422,6 +431,15 @@ describe API::Runner do end end + it "sets the runner's ip_address" do + post api('/jobs/request'), + { token: runner.token }, + { 'User-Agent' => user_agent, 'REMOTE_ADDR' => '123.222.123.222' } + + expect(response).to have_gitlab_http_status 201 + expect(runner.reload.ip_address).to eq('123.222.123.222') + end + context 'when concurrently updating a job' do before do expect_any_instance_of(Ci::Build).to receive(:run!) diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index a0b97ceead9..ad5a289290c 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -123,6 +123,40 @@ describe Projects::UpdateService do end end + context 'when we update project but not enabling a wiki' do + it 'does not try to create an empty wiki' do + FileUtils.rm_rf(project.wiki.repository.path) + + result = update_project(project, user, { name: 'test1' }) + + expect(result).to eq({ status: :success }) + expect(project.wiki_repository_exists?).to be false + end + end + + context 'when enabling a wiki' do + it 'creates a wiki' do + project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED) + FileUtils.rm_rf(project.wiki.repository.path) + + result = update_project(project, user, project_feature_attributes: { wiki_access_level: ProjectFeature::ENABLED }) + + expect(result).to eq({ status: :success }) + expect(project.wiki_repository_exists?).to be true + expect(project.wiki_enabled?).to be true + end + + it 'logs an error and creates a metric when wiki can not be created' do + project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED) + + expect_any_instance_of(ProjectWiki).to receive(:wiki).and_raise(ProjectWiki::CouldNotCreateWikiError) + expect_any_instance_of(described_class).to receive(:log_error).with("Could not create wiki for #{project.full_name}") + expect(Gitlab::Metrics).to receive(:counter) + + update_project(project, user, project_feature_attributes: { wiki_access_level: ProjectFeature::ENABLED }) + end + end + context 'when updating a project that contains container images' do before do stub_container_registry_config(enabled: true)