diff --git a/.flayignore b/.flayignore index 87cb3507b05..3d69bb2c985 100644 --- a/.flayignore +++ b/.flayignore @@ -8,3 +8,4 @@ lib/gitlab/redis/*.rb lib/gitlab/gitaly_client/operation_service.rb lib/gitlab/background_migration/* app/models/project_services/kubernetes_service.rb +lib/gitlab/workhorse.rb diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 70f41e4dc98..4890738aa3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -264,8 +264,17 @@ package-and-qa: stage: build cache: {} when: manual + variables: + GIT_STRATEGY: none + before_script: + # We need to download the script rather than clone the repo since the + # package-and-qa job will not be able to run when the branch gets + # deleted (when merging the MR). + - apk add --update openssl + - wget https://gitlab.com/gitlab-org/gitlab-ce/raw/$CI_COMMIT_SHA/scripts/trigger-build-omnibus + - chmod 755 trigger-build-omnibus script: - - scripts/trigger-build-omnibus + - ./trigger-build-omnibus only: - //@gitlab-org/gitlab-ce - //@gitlab-org/gitlab-ee diff --git a/CHANGELOG.md b/CHANGELOG.md index adb0ec9f5b1..8a90a7fcdc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 10.6.2 (2018-03-29) + +### Fixed (2 changes, 1 of them is from the community) + +- Don't capture trailing punctuation when autolinking. !17965 +- Cloning a repository over HTTPS with LDAP credentials causes a HTTP 401 Access denied. (Horatiu Eugen Vlad) + + ## 10.6.1 (2018-03-27) ### Security (1 change) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 8f63f4f9a10..36545ad338e 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.91.0 +0.92.0 diff --git a/Gemfile b/Gemfile index 035c86efff3..fd174a60c66 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,6 @@ end gem_versions = {} gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2' gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0' -gem_versions['html-pipeline'] = rails5? ? '~> 2.6.0' : '~> 1.11.0' gem_versions['rails'] = rails5? ? '5.0.6' : '4.2.10' gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9' # --- The end of special code for migrating to Rails 5.0 --- @@ -28,7 +27,7 @@ gem 'default_value_for', gem_versions['default_value_for'] gem 'mysql2', '~> 0.4.10', group: :mysql gem 'pg', '~> 0.18.2', group: :postgres -gem 'rugged', '~> 0.26.0' +gem 'rugged', '~> 0.27' gem 'grape-route-helpers', '~> 2.1.0' gem 'faraday', '~> 0.12' @@ -44,7 +43,7 @@ gem 'omniauth-cas3', '~> 1.1.4' gem 'omniauth-facebook', '~> 4.0.0' gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-gitlab', '~> 1.0.2' -gem 'omniauth-google-oauth2', '~> 0.5.2' +gem 'omniauth-google-oauth2', '~> 0.5.3' gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos gem 'omniauth-oauth2-generic', '~> 0.2.2' gem 'omniauth-saml', '~> 1.10' @@ -136,7 +135,7 @@ gem 'unf', '~> 0.1.4' gem 'seed-fu', '~> 2.3.7' # Markdown and HTML processing -gem 'html-pipeline', gem_versions['html-pipeline'] +gem 'html-pipeline', '~> 2.7.1' gem 'deckar01-task_list', '2.0.0' gem 'gitlab-markup', '~> 1.6.2' gem 'redcarpet', '~> 3.4' @@ -310,7 +309,7 @@ end group :development do gem 'foreman', '~> 0.84.0' - gem 'brakeman', '~> 3.6.0', require: false + gem 'brakeman', '~> 4.2', require: false gem 'letter_opener_web', '~> 1.3.0' gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false @@ -376,6 +375,8 @@ group :development, :test do gem 'stackprof', '~> 0.2.10', require: false gem 'simple_po_parser', '~> 1.1.2', require: false + + gem 'timecop', '~> 0.8.0' end group :test do @@ -385,7 +386,6 @@ group :test do gem 'webmock', '~> 2.3.2' gem 'test_after_commit', '~> 1.1' gem 'sham_rack', '~> 1.3.6' - gem 'timecop', '~> 0.8.0' gem 'concurrent-ruby', '~> 1.0.5' gem 'test-prof', '~> 0.2.5' end @@ -421,7 +421,7 @@ group :ed25519 do end # Gitaly GRPC client -gem 'gitaly-proto', '~> 0.88.0', require: 'gitaly' +gem 'gitaly-proto', '~> 0.91.0', require: 'gitaly' gem 'grpc', '~> 1.10.0' # Locked until https://github.com/google/protobuf/issues/4210 is closed diff --git a/Gemfile.lock b/Gemfile.lock index 7d8b22359b2..55e7bd9492a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -95,7 +95,7 @@ GEM autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) bootstrap_form (2.7.0) - brakeman (3.6.1) + brakeman (4.2.1) browser (2.2.0) builder (3.2.3) bullet (5.5.1) @@ -120,7 +120,7 @@ GEM activesupport (>= 4.0.0) mime-types (>= 1.16) cause (0.1) - charlock_holmes (0.7.5) + charlock_holmes (0.7.6) childprocess (0.7.0) ffi (~> 1.0, >= 1.0.11) chronic (0.10.2) @@ -290,7 +290,7 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) gherkin-ruby (0.3.2) - gitaly-proto (0.88.0) + gitaly-proto (0.91.0) google-protobuf (~> 3.1) grpc (~> 1.0) github-linguist (5.3.3) @@ -399,9 +399,9 @@ GEM hipchat (1.5.2) httparty mimemagic - html-pipeline (1.11.0) + html-pipeline (2.7.1) activesupport (>= 2) - nokogiri (~> 1.4) + nokogiri (>= 1.4) html2text (0.2.0) nokogiri (~> 1.6) htmlentities (4.3.4) @@ -550,11 +550,10 @@ GEM omniauth-gitlab (1.0.2) omniauth (~> 1.0) omniauth-oauth2 (~> 1.0) - omniauth-google-oauth2 (0.5.2) - jwt (~> 1.5) - multi_json (~> 1.3) + omniauth-google-oauth2 (0.5.3) + jwt (>= 1.5) omniauth (>= 1.1.1) - omniauth-oauth2 (>= 1.3.1) + omniauth-oauth2 (>= 1.5) omniauth-jwt (0.0.2) jwt omniauth (~> 1.1) @@ -566,8 +565,8 @@ GEM omniauth-oauth (1.1.0) oauth omniauth (~> 1.0) - omniauth-oauth2 (1.4.0) - oauth2 (~> 1.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) omniauth (~> 1.2) omniauth-oauth2-generic (0.2.2) omniauth-oauth2 (~> 1.0) @@ -814,7 +813,7 @@ GEM rubyzip (1.2.1) rufus-scheduler (3.4.0) et-orbi (~> 1.0) - rugged (0.26.0) + rugged (0.27.0) safe_yaml (1.0.4) sanitize (2.1.0) nokogiri (>= 1.4.4) @@ -1013,7 +1012,7 @@ DEPENDENCIES binding_of_caller (~> 0.7.2) bootstrap-sass (~> 3.3.0) bootstrap_form (~> 2.7.0) - brakeman (~> 3.6.0) + brakeman (~> 4.2) browser (~> 2.2) bullet (~> 5.5.0) bundler-audit (~> 0.5.0) @@ -1062,7 +1061,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly-proto (~> 0.88.0) + gitaly-proto (~> 0.91.0) github-linguist (~> 5.3.3) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-markup (~> 1.6.2) @@ -1084,7 +1083,7 @@ DEPENDENCIES hashie-forbidden_attributes health_check (~> 2.6.0) hipchat (~> 1.5.0) - html-pipeline (~> 1.11.0) + html-pipeline (~> 2.7.1) html2text httparty (~> 0.13.3) influxdb (~> 0.2) @@ -1118,7 +1117,7 @@ DEPENDENCIES omniauth-facebook (~> 4.0.0) omniauth-github (~> 1.1.1) omniauth-gitlab (~> 1.0.2) - omniauth-google-oauth2 (~> 0.5.2) + omniauth-google-oauth2 (~> 0.5.3) omniauth-jwt (~> 0.0.2) omniauth-kerberos (~> 0.3.0) omniauth-oauth2-generic (~> 0.2.2) @@ -1174,7 +1173,7 @@ DEPENDENCIES ruby-prof (~> 0.17.0) ruby_parser (~> 3.8) rufus-scheduler (~> 3.4) - rugged (~> 0.26.0) + rugged (~> 0.27) sanitize (~> 2.0) sass-rails (~> 5.0.6) scss_lint (~> 0.56.0) diff --git a/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico b/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico new file mode 100644 index 00000000000..48b1095370d Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_created.ico b/app/assets/images/ci_favicons/canary/favicon_status_created.ico new file mode 100644 index 00000000000..623c728faf6 Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_created.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_failed.ico b/app/assets/images/ci_favicons/canary/favicon_status_failed.ico new file mode 100644 index 00000000000..3073fe5a761 Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_failed.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_manual.ico b/app/assets/images/ci_favicons/canary/favicon_status_manual.ico new file mode 100644 index 00000000000..6c713d7b675 Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_manual.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_not_found.ico b/app/assets/images/ci_favicons/canary/favicon_status_not_found.ico new file mode 100644 index 00000000000..dbf855fdafd Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_not_found.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_pending.ico b/app/assets/images/ci_favicons/canary/favicon_status_pending.ico new file mode 100644 index 00000000000..ccd00606aeb Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_pending.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_running.ico b/app/assets/images/ci_favicons/canary/favicon_status_running.ico new file mode 100644 index 00000000000..968e7c4c2d4 Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_running.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico b/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico new file mode 100644 index 00000000000..7e3be35cc3a Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_success.ico b/app/assets/images/ci_favicons/canary/favicon_status_success.ico new file mode 100644 index 00000000000..a1fb6e91d65 Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_success.ico differ diff --git a/app/assets/images/ci_favicons/canary/favicon_status_warning.ico b/app/assets/images/ci_favicons/canary/favicon_status_warning.ico new file mode 100644 index 00000000000..5d931619fb2 Binary files /dev/null and b/app/assets/images/ci_favicons/canary/favicon_status_warning.ico differ diff --git a/app/assets/images/favicon-yellow.ico b/app/assets/images/favicon-yellow.ico new file mode 100644 index 00000000000..b650f277fb6 Binary files /dev/null and b/app/assets/images/favicon-yellow.ico differ diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index cbcefb2c18f..8ad3d18b302 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -10,6 +10,9 @@ const Api = { projectsPath: '/api/:version/projects.json', projectPath: '/api/:version/projects/:id', projectLabelsPath: '/:namespace_path/:project_path/labels', + mergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid', + mergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes', + mergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions', groupLabelsPath: '/groups/:namespace_path/-/labels', licensePath: '/api/:version/templates/licenses/:key', gitignorePath: '/api/:version/templates/gitignores/:key', @@ -22,25 +25,27 @@ const Api = { createBranchPath: '/api/:version/projects/:id/repository/branches', group(groupId, callback) { - const url = Api.buildUrl(Api.groupPath) - .replace(':id', groupId); - return axios.get(url) - .then(({ data }) => { - callback(data); + const url = Api.buildUrl(Api.groupPath).replace(':id', groupId); + return axios.get(url).then(({ data }) => { + callback(data); - return data; - }); + return data; + }); }, // Return groups list. Filtered by query groups(query, options, callback = $.noop) { const url = Api.buildUrl(Api.groupsPath); - return axios.get(url, { - params: Object.assign({ - search: query, - per_page: 20, - }, options), - }) + return axios + .get(url, { + params: Object.assign( + { + search: query, + per_page: 20, + }, + options, + ), + }) .then(({ data }) => { callback(data); @@ -51,12 +56,13 @@ const Api = { // Return namespaces list. Filtered by query namespaces(query, callback) { const url = Api.buildUrl(Api.namespacesPath); - return axios.get(url, { - params: { - search: query, - per_page: 20, - }, - }) + return axios + .get(url, { + params: { + search: query, + per_page: 20, + }, + }) .then(({ data }) => callback(data)); }, @@ -73,9 +79,10 @@ const Api = { defaults.membership = true; } - return axios.get(url, { - params: Object.assign(defaults, options), - }) + return axios + .get(url, { + params: Object.assign(defaults, options), + }) .then(({ data }) => { callback(data); @@ -85,8 +92,32 @@ const Api = { // Return single project project(projectPath) { - const url = Api.buildUrl(Api.projectPath) - .replace(':id', encodeURIComponent(projectPath)); + const url = Api.buildUrl(Api.projectPath).replace(':id', encodeURIComponent(projectPath)); + + return axios.get(url); + }, + + // Return Merge Request for project + mergeRequest(projectPath, mergeRequestId) { + const url = Api.buildUrl(Api.mergeRequestPath) + .replace(':id', encodeURIComponent(projectPath)) + .replace(':mrid', mergeRequestId); + + return axios.get(url); + }, + + mergeRequestChanges(projectPath, mergeRequestId) { + const url = Api.buildUrl(Api.mergeRequestChangesPath) + .replace(':id', encodeURIComponent(projectPath)) + .replace(':mrid', mergeRequestId); + + return axios.get(url); + }, + + mergeRequestVersions(projectPath, mergeRequestId) { + const url = Api.buildUrl(Api.mergeRequestVersionsPath) + .replace(':id', encodeURIComponent(projectPath)) + .replace(':mrid', mergeRequestId); return axios.get(url); }, @@ -102,30 +133,30 @@ const Api = { url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespacePath); } - return axios.post(url, { - label: data, - }) + return axios + .post(url, { + label: data, + }) .then(res => callback(res.data)) .catch(e => callback(e.response.data)); }, // Return group projects list. Filtered by query groupProjects(groupId, query, callback) { - const url = Api.buildUrl(Api.groupProjectsPath) - .replace(':id', groupId); - return axios.get(url, { - params: { - search: query, - per_page: 20, - }, - }) + const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId); + return axios + .get(url, { + params: { + search: query, + per_page: 20, + }, + }) .then(({ data }) => callback(data)); }, commitMultiple(id, data) { // see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions - const url = Api.buildUrl(Api.commitPath) - .replace(':id', encodeURIComponent(id)); + const url = Api.buildUrl(Api.commitPath).replace(':id', encodeURIComponent(id)); return axios.post(url, JSON.stringify(data), { headers: { 'Content-Type': 'application/json; charset=utf-8', @@ -136,39 +167,34 @@ const Api = { branchSingle(id, branch) { const url = Api.buildUrl(Api.branchSinglePath) .replace(':id', encodeURIComponent(id)) - .replace(':branch', branch); + .replace(':branch', encodeURIComponent(branch)); return axios.get(url); }, // Return text for a specific license licenseText(key, data, callback) { - const url = Api.buildUrl(Api.licensePath) - .replace(':key', key); - return axios.get(url, { - params: data, - }) + const url = Api.buildUrl(Api.licensePath).replace(':key', key); + return axios + .get(url, { + params: data, + }) .then(res => callback(res.data)); }, gitignoreText(key, callback) { - const url = Api.buildUrl(Api.gitignorePath) - .replace(':key', key); - return axios.get(url) - .then(({ data }) => callback(data)); + const url = Api.buildUrl(Api.gitignorePath).replace(':key', key); + return axios.get(url).then(({ data }) => callback(data)); }, gitlabCiYml(key, callback) { - const url = Api.buildUrl(Api.gitlabCiYmlPath) - .replace(':key', key); - return axios.get(url) - .then(({ data }) => callback(data)); + const url = Api.buildUrl(Api.gitlabCiYmlPath).replace(':key', key); + return axios.get(url).then(({ data }) => callback(data)); }, dockerfileYml(key, callback) { const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key); - return axios.get(url) - .then(({ data }) => callback(data)); + return axios.get(url).then(({ data }) => callback(data)); }, issueTemplate(namespacePath, projectPath, key, type, callback) { @@ -177,7 +203,8 @@ const Api = { .replace(':type', type) .replace(':project_path', projectPath) .replace(':namespace_path', namespacePath); - return axios.get(url) + return axios + .get(url) .then(({ data }) => callback(null, data)) .catch(callback); }, @@ -185,10 +212,13 @@ const Api = { users(query, options) { const url = Api.buildUrl(this.usersPath); return axios.get(url, { - params: Object.assign({ - search: query, - per_page: 20, - }, options), + params: Object.assign( + { + search: query, + per_page: 20, + }, + options, + ), }); }, diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js index 7dcf1aeed17..eb4e59d12b1 100644 --- a/app/assets/javascripts/behaviors/markdown/render_math.js +++ b/app/assets/javascripts/behaviors/markdown/render_math.js @@ -31,7 +31,7 @@ export default function renderMath($els) { if (!$els.length) return; Promise.all([ import(/* webpackChunkName: 'katex' */ 'katex'), - import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.css'), + import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.min.css'), ]).then(([katex]) => { renderWithKaTeX($els, katex); }).catch(() => flash(__('An error occurred while rendering KaTeX'))); diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index 8259133c95b..7e9770a9ea2 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -54,6 +54,7 @@ class GfmAutoComplete { alias: 'commands', searchKey: 'search', skipSpecialCharacterTest: true, + skipMarkdownCharacterTest: true, data: GfmAutoComplete.defaultLoadingData, displayTpl(value) { if (GfmAutoComplete.isLoading(value)) return GfmAutoComplete.Loading.template; @@ -376,15 +377,23 @@ class GfmAutoComplete { return $.fn.atwho.default.callbacks.filter(query, data, searchKey); }, beforeInsert(value) { - let resultantValue = value; + let withoutAt = value.substring(1); + const at = value.charAt(); + if (value && !this.setting.skipSpecialCharacterTest) { - const withoutAt = value.substring(1); - const regex = value.charAt() === '~' ? /\W|^\d+$/ : /\W/; + const regex = at === '~' ? /\W|^\d+$/ : /\W/; if (withoutAt && regex.test(withoutAt)) { - resultantValue = `${value.charAt()}"${withoutAt}"`; + withoutAt = `"${withoutAt}"`; } } - return resultantValue; + + // We can ignore this for quick actions because they are processed + // before Markdown. + if (!this.setting.skipMarkdownCharacterTest) { + withoutAt = withoutAt.replace(/([~\-_*`])/g, '\\$&'); + } + + return `${at}${withoutAt}`; }, matcher(flag, subtext) { const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers); diff --git a/app/assets/javascripts/ide/components/changed_file_icon.vue b/app/assets/javascripts/ide/components/changed_file_icon.vue index 0c54c992e51..037e3efb4ce 100644 --- a/app/assets/javascripts/ide/components/changed_file_icon.vue +++ b/app/assets/javascripts/ide/components/changed_file_icon.vue @@ -1,25 +1,25 @@