diff options
47 files changed, 548 insertions, 132 deletions
diff --git a/.gitignore b/.gitignore index 0fb97ffb98e..f3decfd7dfe 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ eslint-report.html /public/uploads/ /shared/artifacts/ /spec/javascripts/fixtures/blob/pdf/ +/spec/javascripts/fixtures/blob/balsamiq/ /rails_best_practices_output.html /tags /tmp/* @@ -367,6 +367,6 @@ gem 'vmstat', '~> 2.3.0' gem 'sys-filesystem', '~> 1.1.6' # Gitaly GRPC client -gem 'gitaly', '~> 0.6.0' +gem 'gitaly', '~> 0.7.0' gem 'toml-rb', '~> 0.3.15', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 6c52f1d70d9..873cd8781ef 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -265,7 +265,7 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) gherkin-ruby (0.3.2) - gitaly (0.6.0) + gitaly (0.7.0) google-protobuf (~> 3.1) grpc (~> 1.0) github-linguist (4.7.6) @@ -924,7 +924,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.2.0) - gitaly (~> 0.6.0) + gitaly (~> 0.7.0) github-linguist (~> 4.7.0) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-markup (~> 1.5.1) diff --git a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js index cdbfe36ca1c..c17877a276d 100644 --- a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js +++ b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js @@ -1,5 +1,3 @@ -/* global Flash */ - import sqljs from 'sql.js'; import { template as _template } from 'underscore'; @@ -15,19 +13,27 @@ const PREVIEW_TEMPLATE = _template(` class BalsamiqViewer { constructor(viewer) { this.viewer = viewer; - this.endpoint = this.viewer.dataset.endpoint; } - loadFile() { - const xhr = new XMLHttpRequest(); + loadFile(endpoint) { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + + xhr.open('GET', endpoint, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = loadEvent => this.fileLoaded(loadEvent, resolve, reject); + xhr.onerror = reject; + + xhr.send(); + }); + } - xhr.open('GET', this.endpoint, true); - xhr.responseType = 'arraybuffer'; + fileLoaded(loadEvent, resolve, reject) { + if (loadEvent.target.status !== 200) return reject(); - xhr.onload = this.renderFile.bind(this); - xhr.onerror = BalsamiqViewer.onError; + this.renderFile(loadEvent); - xhr.send(); + return resolve(); } renderFile(loadEvent) { @@ -103,12 +109,6 @@ class BalsamiqViewer { static parseTitle(resource) { return JSON.parse(resource.values[0][2]).name; } - - static onError() { - const flash = new Flash('Balsamiq file could not be loaded.'); - - return flash; - } } export default BalsamiqViewer; diff --git a/app/assets/javascripts/blob/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq_viewer.js index 1dacf84470f..8641a6fdae6 100644 --- a/app/assets/javascripts/blob/balsamiq_viewer.js +++ b/app/assets/javascripts/blob/balsamiq_viewer.js @@ -1,6 +1,22 @@ +/* global Flash */ + import BalsamiqViewer from './balsamiq/balsamiq_viewer'; -document.addEventListener('DOMContentLoaded', () => { - const balsamiqViewer = new BalsamiqViewer(document.getElementById('js-balsamiq-viewer')); - balsamiqViewer.loadFile(); -}); +function onError() { + const flash = new window.Flash('Balsamiq file could not be loaded.'); + + return flash; +} + +function loadBalsamiqFile() { + const viewer = document.getElementById('js-balsamiq-viewer'); + + if (!(viewer instanceof Element)) return; + + const endpoint = viewer.dataset.endpoint; + + const balsamiqViewer = new BalsamiqViewer(viewer); + balsamiqViewer.loadFile(endpoint).catch(onError); +} + +$(loadBalsamiqFile); diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index b99ccd453b8..b99ccd453b8 100755..100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb diff --git a/app/models/commit.rb b/app/models/commit.rb index 8d54ce6eb25..dbc0a22829e 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -327,13 +327,21 @@ class Commit def raw_diffs(*args) if Gitlab::GitalyClient.feature_enabled?(:commit_raw_diffs) - Gitlab::GitalyClient::Commit.diff_from_parent(self, *args) + Gitlab::GitalyClient::Commit.new(project.repository).diff_from_parent(self, *args) else raw.diffs(*args) end end - delegate :deltas, to: :raw, prefix: :raw + def raw_deltas + @deltas ||= Gitlab::GitalyClient.migrate(:commit_deltas) do |is_enabled| + if is_enabled + Gitlab::GitalyClient::Commit.new(project.repository).commit_deltas(self) + else + raw.deltas + end + end + end def diffs(diff_options = nil) Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options) diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml index 2d272a93b98..d6f4f1a206c 100644 --- a/app/views/projects/pipeline_schedules/_form.html.haml +++ b/app/views/projects/pipeline_schedules/_form.html.haml @@ -1,5 +1,6 @@ - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('schedule_form') + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'schedule_form' = form_for [@project.namespace.becomes(Namespace), @project, @schedule], as: :schedule, html: { id: "new-pipeline-schedule-form", class: "form-horizontal js-pipeline-schedule-form" } do |f| = form_errors(@schedule) diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml index a597d745e33..25c52175e3d 100644 --- a/app/views/projects/pipeline_schedules/index.html.haml +++ b/app/views/projects/pipeline_schedules/index.html.haml @@ -1,5 +1,6 @@ - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('schedules_index') + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'schedules_index' - @no_container = true - page_title "Pipeline Schedules" @@ -21,4 +22,3 @@ - else .light-well .nothing-here-block No schedules - diff --git a/changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml b/changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml new file mode 100644 index 00000000000..eac78e9ee1f --- /dev/null +++ b/changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml @@ -0,0 +1,4 @@ +--- +title: Add indices for auto_canceled_by_id for ci_pipelines and ci_builds on PostgreSQL +merge_request: 11034 +author: diff --git a/changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml b/changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml new file mode 100644 index 00000000000..8c7fa53a18b --- /dev/null +++ b/changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml @@ -0,0 +1,4 @@ +--- +title: Allow numeric values in gitlab-ci.yml +merge_request: 10607 +author: blackst0ne diff --git a/changelogs/unreleased/dturner-username.yml b/changelogs/unreleased/dturner-username.yml new file mode 100644 index 00000000000..09ba822ee65 --- /dev/null +++ b/changelogs/unreleased/dturner-username.yml @@ -0,0 +1,4 @@ +--- +title: add username field to push webhook +merge_request: +author: David Turner diff --git a/changelogs/unreleased/enable-auto-cancelling-by-default.yml b/changelogs/unreleased/enable-auto-cancelling-by-default.yml new file mode 100644 index 00000000000..8b1659bf38b --- /dev/null +++ b/changelogs/unreleased/enable-auto-cancelling-by-default.yml @@ -0,0 +1,4 @@ +--- +title: Enable cancelling non-HEAD pending pipelines by default for all projects +merge_request: 11023 +author: diff --git a/config/webpack.config.js b/config/webpack.config.js index 32064138ae4..5d5a42512b1 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -94,7 +94,7 @@ var config = { query: { mimetype: 'image/gif' }, }, { - test: /\.(worker\.js|pdf)$/, + test: /\.(worker\.js|pdf|bmpr)$/, exclude: /node_modules/, loader: 'file-loader', }, @@ -142,13 +142,15 @@ var config = { 'environments', 'environments_folder', 'filtered_search', - 'sidebar', 'issue_show', 'merge_conflicts', 'notebook_viewer', 'pdf_viewer', 'pipelines', 'pipelines_graph', + 'schedule_form', + 'schedules_index', + 'sidebar', ], minChunks: function(module, count) { return module.resource && (/vue_shared/).test(module.resource); diff --git a/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb b/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb new file mode 100644 index 00000000000..03bf626a08a --- /dev/null +++ b/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb @@ -0,0 +1,13 @@ +class MakeAutoCancelPendingPipelinesOnByDefault < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + change_column_default(:projects, :auto_cancel_pending_pipelines, 1) + end + + def down + change_column_default(:projects, :auto_cancel_pending_pipelines, 0) + end +end diff --git a/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb b/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb new file mode 100644 index 00000000000..b64d7e0e3f6 --- /dev/null +++ b/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb @@ -0,0 +1,21 @@ +class CreateIndexCiPipelinesAutoCanceledById < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + # MySQL would already have the index + unless index_exists?(:ci_pipelines, :auto_canceled_by_id) + add_concurrent_index(:ci_pipelines, :auto_canceled_by_id) + end + end + + def down + # We cannot remove index for MySQL because it's needed for foreign key + if Gitlab::Database.postgresql? + remove_concurrent_index(:ci_pipelines, :auto_canceled_by_id) + end + end +end diff --git a/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb b/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb new file mode 100644 index 00000000000..0a8d2c8ff61 --- /dev/null +++ b/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb @@ -0,0 +1,21 @@ +class CreateIndexCiBuildsAutoCanceledById < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + # MySQL would already have the index + unless index_exists?(:ci_builds, :auto_canceled_by_id) + add_concurrent_index(:ci_builds, :auto_canceled_by_id) + end + end + + def down + # We cannot remove index for MySQL because it's needed for foreign key + if Gitlab::Database.postgresql? + remove_concurrent_index(:ci_builds, :auto_canceled_by_id) + end + end +end diff --git a/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb b/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb new file mode 100644 index 00000000000..a19b73fc114 --- /dev/null +++ b/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb @@ -0,0 +1,15 @@ +class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + DOWNTIME = false + + def up + update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1) + end + + def down + # Nothing we can do! + end +end diff --git a/db/schema.rb b/db/schema.rb index 65eaccf766a..a683521c84b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -235,6 +235,7 @@ ActiveRecord::Schema.define(version: 20170508190732) do t.boolean "retried" end + add_index "ci_builds", ["auto_canceled_by_id"], name: "index_ci_builds_on_auto_canceled_by_id", using: :btree add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree add_index "ci_builds", ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree @@ -284,6 +285,7 @@ ActiveRecord::Schema.define(version: 20170508190732) do t.integer "pipeline_schedule_id" end + add_index "ci_pipelines", ["auto_canceled_by_id"], name: "index_ci_pipelines_on_auto_canceled_by_id", using: :btree add_index "ci_pipelines", ["pipeline_schedule_id"], name: "index_ci_pipelines_on_pipeline_schedule_id", using: :btree add_index "ci_pipelines", ["project_id", "ref", "status"], name: "index_ci_pipelines_on_project_id_and_ref_and_status", using: :btree add_index "ci_pipelines", ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree @@ -986,7 +988,7 @@ ActiveRecord::Schema.define(version: 20170508190732) do t.text "description_html" t.boolean "only_allow_merge_if_all_discussions_are_resolved" t.boolean "printing_merge_request_link_enabled", default: true, null: false - t.integer "auto_cancel_pending_pipelines", default: 0, null: false + t.integer "auto_cancel_pending_pipelines", default: 1, null: false t.string "import_jid" t.integer "cached_markdown_version" t.datetime "last_repository_updated_at" diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index f025a7e3496..96834e15bb9 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -146,7 +146,7 @@ private registries that could also require authentication. All you have to do is be explicit on the image definition in `.gitlab-ci.yml`. ```yaml -image: my.registry.tld:5000/namepace/image:tag +image: my.registry.tld:5000/namespace/image:tag ``` In the example above, GitLab Runner will look at `my.registry.tld:5000` for the diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index 30f209f80eb..41cae58782d 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -155,7 +155,7 @@ Find more information about different Runners in the [Runners](../runners/README.md) documentation. You can find whether any Runners are assigned to your project by going to -**Settings ➔ Runners**. Setting up a Runner is easy and straightforward. The +**Settings ➔ CI/CD Pipelines**. Setting up a Runner is easy and straightforward. The official Runner supported by GitLab is written in Go and its documentation can be found at <https://docs.gitlab.com/runner/>. @@ -168,7 +168,7 @@ Follow the links above to set up your own Runner or use a Shared Runner as described in the next section. Once the Runner has been set up, you should see it on the Runners page of your -project, following **Settings ➔ Runners**. +project, following **Settings ➔ CI/CD Pipelines**.  @@ -181,7 +181,7 @@ These are special virtual machines that run on GitLab's infrastructure and can build any project. To enable the **Shared Runners** you have to go to your project's -**Settings ➔ Runners** and click **Enable shared runners**. +**Settings ➔ CI/CD Pipelines** and click **Enable shared runners**. [Read more on Shared Runners](../runners/README.md). diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 045d3821f66..9a3bbcf2853 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -333,7 +333,7 @@ prefix the variable name with the dollar sign (`$`): ``` job_name: script: - - echo $CI_job_ID + - echo $CI_JOB_ID ``` You can also list all environment variables with the `export` command, diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 16308a957cb..8546a99a022 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -147,6 +147,10 @@ variables: DATABASE_URL: "postgres://postgres@postgres/my_database" ``` +>**Note:** +Integers (as well as strings) are legal both for variable's name and value. +Floats are not legal and cannot be used. + These variables can be later used in all executed commands and scripts. The YAML-defined variables are also set to all created service containers, thus allowing to fine tune them. Variables can be also defined on a @@ -1152,7 +1156,7 @@ Example: ```yaml variables: - GET_SOURCES_ATTEMPTS: "3" + GET_SOURCES_ATTEMPTS: 3 ``` You can set them in the global [`variables`](#variables) section or the diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 4eb7a8eee48..b36fd52603b 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -4,7 +4,7 @@ There are two editions of GitLab: [Enterprise Edition](https://about.gitlab.com/gitlab-ee/) (EE) and [Community Edition](https://about.gitlab.com/gitlab-ce/) (CE). GitLab CE is delivered via git from the [gitlabhq repository](https://gitlab.com/gitlab-org/gitlab-ce/tree/master). New versions of GitLab are released in stable branches and the master branch is for bleeding edge development. -EE releases are available not long after CE releases. To obtain the GitLab EE there is a [repository at gitlab.com](https://gitlab.com/subscribers/gitlab-ee). For more information about the release process see the section 'New versions and upgrading' in the readme. +EE releases are available not long after CE releases. To obtain the GitLab EE there is a [repository at gitlab.com](https://gitlab.com/gitlab-org/gitlab-ee). For more information about the release process see the section 'New versions and upgrading' in the readme. Both EE and CE require some add-on components called gitlab-shell and Gitaly. These components are available from the [gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell/tree/master) and [gitaly](https://gitlab.com/gitlab-org/gitaly/tree/master) repositories respectively. New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical. diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index e15daa2feae..48d49c5d40c 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -74,6 +74,7 @@ X-Gitlab-Event: Push Hook "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", "user_id": 4, "user_name": "John Smith", + "user_username": "jsmith", "user_email": "john@example.com", "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80", "project_id": 15, diff --git a/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb b/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb index 9b9a0a8125a..a78a85397bd 100644 --- a/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb +++ b/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb @@ -21,7 +21,13 @@ module Gitlab def validate_variables(variables) variables.is_a?(Hash) && - variables.all? { |key, value| validate_string(key) && validate_string(value) } + variables.flatten.all? do |value| + validate_string(value) || validate_integer(value) + end + end + + def validate_integer(value) + value.is_a?(Integer) end def validate_string(value) diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb index c3b0e651c3a..8acab605c91 100644 --- a/lib/gitlab/ci/config/entry/variables.rb +++ b/lib/gitlab/ci/config/entry/variables.rb @@ -15,6 +15,10 @@ module Gitlab def self.default {} end + + def value + Hash[@config.map { |key, value| [key.to_s, value.to_s] }] + end end end end diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb index 1ff34553f0a..e81d19a7a2e 100644 --- a/lib/gitlab/data_builder/push.rb +++ b/lib/gitlab/data_builder/push.rb @@ -11,6 +11,7 @@ module Gitlab # ref: String, # user_id: String, # user_name: String, + # user_username: String, # user_email: String # project_id: String, # repository: { @@ -51,6 +52,7 @@ module Gitlab message: message, user_id: user.id, user_name: user.name, + user_username: user.username, user_email: user.email, user_avatar: user.avatar_url, project_id: project.id, diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index f04a907004c..f3476dadec8 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -283,11 +283,15 @@ module Gitlab add_column(table, new, new_type, limit: old_col.limit, - default: old_col.default, null: old_col.null, precision: old_col.precision, scale: old_col.scale) + # We set the default value _after_ adding the column so we don't end up + # updating any existing data with the default value. This isn't + # necessary since we copy over old values further down. + change_column_default(table, new, old_col.default) if old_col.default + trigger_name = rename_trigger_name(table, old, new) quoted_table = quote_table_name(table) quoted_old = quote_column_name(old) diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index 40a4ad11372..5f4027e7e81 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -1,8 +1,14 @@ module Gitlab module DependencyLinker class BaseLinker - def self.link(plain_text, highlighted_text) - new(plain_text, highlighted_text).link + class_attribute :file_type + + def self.support?(blob_name) + Gitlab::FileDetector.type_of(blob_name) == file_type + end + + def self.link(*args) + new(*args).link end attr_accessor :plain_text, :highlighted_text diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb index 45be760d89e..9b82e126528 100644 --- a/lib/gitlab/dependency_linker/gemfile_linker.rb +++ b/lib/gitlab/dependency_linker/gemfile_linker.rb @@ -1,9 +1,7 @@ module Gitlab module DependencyLinker class GemfileLinker < BaseLinker - def self.support?(blob_name) - blob_name == 'Gemfile' || blob_name == 'gems.rb' - end + self.file_type = :gemfile private diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index f8b3d0b4965..c6a89597b23 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -12,6 +12,7 @@ module Gitlab version: 'version', gitignore: '.gitignore', koding: '.koding.yml', + gemfile: /\A(Gemfile|gems\.rb)\z/, gitlab_ci: '.gitlab-ci.yml', avatar: /\Alogo\.(png|jpg|gif)\z/, route_map: 'route-map.yml' diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index 019be151353..31d1b66b4f7 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -183,6 +183,8 @@ module Gitlab when Gitaly::CommitDiffResponse init_from_gitaly(raw_diff) prune_diff_if_eligible(collapse) + when Gitaly::CommitDelta + init_from_gitaly(raw_diff) when nil raise "Nil as raw diff passed" else @@ -278,15 +280,15 @@ module Gitlab end end - def init_from_gitaly(diff_msg) - @diff = diff_msg.raw_chunks.join - @new_path = encode!(diff_msg.to_path.dup) - @old_path = encode!(diff_msg.from_path.dup) - @a_mode = diff_msg.old_mode.to_s(8) - @b_mode = diff_msg.new_mode.to_s(8) - @new_file = diff_msg.from_id == BLANK_SHA - @renamed_file = diff_msg.from_path != diff_msg.to_path - @deleted_file = diff_msg.to_id == BLANK_SHA + def init_from_gitaly(msg) + @diff = msg.raw_chunks.join if msg.respond_to?(:raw_chunks) + @new_path = encode!(msg.to_path.dup) + @old_path = encode!(msg.from_path.dup) + @a_mode = msg.old_mode.to_s(8) + @b_mode = msg.new_mode.to_s(8) + @new_file = msg.from_id == BLANK_SHA + @renamed_file = msg.from_path != msg.to_path + @deleted_file = msg.to_id == BLANK_SHA end def prune_diff_if_eligible(collapse = false) diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb index 8e9323b05e1..15c57420fb2 100644 --- a/lib/gitlab/gitaly_client/commit.rb +++ b/lib/gitlab/gitaly_client/commit.rb @@ -5,41 +5,55 @@ module Gitlab # See http://stackoverflow.com/a/40884093/1856239 and https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012 EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze - attr_accessor :stub - def initialize(repository) @gitaly_repo = repository.gitaly_repository - @stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: repository.gitaly_channel) + @repository = repository end def is_ancestor(ancestor_id, child_id) + stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: @repository.gitaly_channel) request = Gitaly::CommitIsAncestorRequest.new( repository: @gitaly_repo, ancestor_id: ancestor_id, child_id: child_id ) - @stub.commit_is_ancestor(request).value + stub.commit_is_ancestor(request).value + end + + def diff_from_parent(commit, options = {}) + request_params = commit_diff_request_params(commit, options) + request_params[:ignore_whitespace_change] = options.fetch(:ignore_whitespace_change, false) + + response = diff_service_stub.commit_diff(Gitaly::CommitDiffRequest.new(request_params)) + Gitlab::Git::DiffCollection.new(response, options) end - class << self - def diff_from_parent(commit, options = {}) - repository = commit.project.repository - gitaly_repo = repository.gitaly_repository - stub = Gitaly::Diff::Stub.new(nil, nil, channel_override: repository.gitaly_channel) - parent = commit.parents[0] - parent_id = parent ? parent.id : EMPTY_TREE_ID - request = Gitaly::CommitDiffRequest.new( - repository: gitaly_repo, - left_commit_id: parent_id, - right_commit_id: commit.id, - ignore_whitespace_change: options.fetch(:ignore_whitespace_change, false), - paths: options.fetch(:paths, []) - ) - - Gitlab::Git::DiffCollection.new(stub.commit_diff(request), options) + def commit_deltas(commit) + request_params = commit_diff_request_params(commit) + + response = diff_service_stub.commit_delta(Gitaly::CommitDeltaRequest.new(request_params)) + response.flat_map do |msg| + msg.deltas.map { |d| Gitlab::Git::Diff.new(d) } end end + + private + + def commit_diff_request_params(commit, options = {}) + parent_id = commit.parents[0]&.id || EMPTY_TREE_ID + + { + repository: @gitaly_repo, + left_commit_id: parent_id, + right_commit_id: commit.id, + paths: options.fetch(:paths, []) + } + end + + def diff_service_stub + Gitaly::Diff::Stub.new(nil, nil, channel_override: @repository.gitaly_channel) + end end end end diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js new file mode 100644 index 00000000000..acd0aaf2a86 --- /dev/null +++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js @@ -0,0 +1,51 @@ +/* eslint-disable import/no-unresolved */ + +import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer'; +import bmprPath from '../../fixtures/blob/balsamiq/test.bmpr'; + +describe('Balsamiq integration spec', () => { + let container; + let endpoint; + let balsamiqViewer; + + preloadFixtures('static/balsamiq_viewer.html.raw'); + + beforeEach(() => { + loadFixtures('static/balsamiq_viewer.html.raw'); + + container = document.getElementById('js-balsamiq-viewer'); + balsamiqViewer = new BalsamiqViewer(container); + }); + + describe('successful response', () => { + beforeEach((done) => { + endpoint = bmprPath; + + balsamiqViewer.loadFile(endpoint).then(done).catch(done.fail); + }); + + it('does not show loading icon', () => { + expect(document.querySelector('.loading')).toBeNull(); + }); + + it('renders the balsamiq previews', () => { + expect(document.querySelectorAll('.previews .preview').length).not.toEqual(0); + }); + }); + + describe('error getting file', () => { + beforeEach((done) => { + endpoint = 'invalid/path/to/file.bmpr'; + + balsamiqViewer.loadFile(endpoint).then(done.fail, null).catch(done); + }); + + it('does not show loading icon', () => { + expect(document.querySelector('.loading')).toBeNull(); + }); + + it('does not render the balsamiq previews', () => { + expect(document.querySelectorAll('.previews .preview').length).toEqual(0); + }); + }); +}); diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js index 85816ee1f11..aa87956109f 100644 --- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js +++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js @@ -4,17 +4,11 @@ import ClassSpecHelper from '../../helpers/class_spec_helper'; describe('BalsamiqViewer', () => { let balsamiqViewer; - let endpoint; let viewer; describe('class constructor', () => { beforeEach(() => { - endpoint = 'endpoint'; - viewer = { - dataset: { - endpoint, - }, - }; + viewer = {}; balsamiqViewer = new BalsamiqViewer(viewer); }); @@ -22,25 +16,25 @@ describe('BalsamiqViewer', () => { it('should set .viewer', () => { expect(balsamiqViewer.viewer).toBe(viewer); }); + }); + + describe('fileLoaded', () => { - it('should set .endpoint', () => { - expect(balsamiqViewer.endpoint).toBe(endpoint); - }); }); describe('loadFile', () => { let xhr; + let loadFile; + const endpoint = 'endpoint'; beforeEach(() => { - endpoint = 'endpoint'; xhr = jasmine.createSpyObj('xhr', ['open', 'send']); balsamiqViewer = jasmine.createSpyObj('balsamiqViewer', ['renderFile']); - balsamiqViewer.endpoint = endpoint; spyOn(window, 'XMLHttpRequest').and.returnValue(xhr); - BalsamiqViewer.prototype.loadFile.call(balsamiqViewer); + loadFile = BalsamiqViewer.prototype.loadFile.call(balsamiqViewer, endpoint); }); it('should call .open', () => { @@ -54,6 +48,10 @@ describe('BalsamiqViewer', () => { it('should call .send', () => { expect(xhr.send).toHaveBeenCalled(); }); + + it('should return a promise', () => { + expect(loadFile).toEqual(jasmine.any(Promise)); + }); }); describe('renderFile', () => { @@ -325,18 +323,4 @@ describe('BalsamiqViewer', () => { expect(parseTitle).toBe('name'); }); }); - - describe('onError', () => { - beforeEach(() => { - spyOn(window, 'Flash'); - - BalsamiqViewer.onError(); - }); - - ClassSpecHelper.itShouldBeAStaticMethod(BalsamiqViewer, 'onError'); - - it('should instantiate Flash', () => { - expect(window.Flash).toHaveBeenCalledWith('Balsamiq file could not be loaded.'); - }); - }); }); diff --git a/spec/javascripts/fixtures/balsamiq.rb b/spec/javascripts/fixtures/balsamiq.rb new file mode 100644 index 00000000000..b5372821bf5 --- /dev/null +++ b/spec/javascripts/fixtures/balsamiq.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe 'Balsamiq file', '(JavaScript fixtures)', type: :controller do + include JavaScriptFixturesHelpers + + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project, namespace: namespace, path: 'balsamiq-project') } + + before(:all) do + clean_frontend_fixtures('blob/balsamiq/') + end + + it 'blob/balsamiq/test.bmpr' do |example| + blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr') + + store_frontend_fixture(blob.data.force_encoding('utf-8'), example.description) + end +end diff --git a/spec/javascripts/fixtures/balsamiq_viewer.html.haml b/spec/javascripts/fixtures/balsamiq_viewer.html.haml new file mode 100644 index 00000000000..18166ba4901 --- /dev/null +++ b/spec/javascripts/fixtures/balsamiq_viewer.html.haml @@ -0,0 +1 @@ +.file-content.balsamiq-viewer#js-balsamiq-viewer{ data: { endpoint: '/test' } } diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index cf03acbfd3a..23270ad5053 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -113,7 +113,7 @@ describe Gitlab::Ci::Config::Entry::Global do describe '#variables_value' do it 'returns variables' do - expect(global.variables_value).to eq(VAR: 'value') + expect(global.variables_value).to eq('VAR' => 'value') end end @@ -154,7 +154,7 @@ describe Gitlab::Ci::Config::Entry::Global do services: ['postgres:9.1', 'mysql:5.5'], stage: 'test', cache: { key: 'k', untracked: true, paths: ['public/'] }, - variables: { VAR: 'value' }, + variables: { 'VAR' => 'value' }, ignore: false, after_script: ['make clean'] }, spinach: { name: :spinach, diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb index f15f02f403e..84bfef9e8ad 100644 --- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb @@ -13,6 +13,14 @@ describe Gitlab::Ci::Config::Entry::Variables do it 'returns hash with key value strings' do expect(entry.value).to eq config end + + context 'with numeric keys and values in the config' do + let(:config) { { 10 => 20 } } + + it 'converts numeric key and numeric value into strings' do + expect(entry.value).to eq('10' => '20') + end + end end describe '#errors' do diff --git a/spec/lib/gitlab/data_builder/push_spec.rb b/spec/lib/gitlab/data_builder/push_spec.rb index dbcfb9b7400..e59cba35b2f 100644 --- a/spec/lib/gitlab/data_builder/push_spec.rb +++ b/spec/lib/gitlab/data_builder/push_spec.rb @@ -35,6 +35,7 @@ describe Gitlab::DataBuilder::Push, lib: true do it { expect(data[:ref]).to eq('refs/tags/v1.1.0') } it { expect(data[:user_id]).to eq(user.id) } it { expect(data[:user_name]).to eq(user.name) } + it { expect(data[:user_username]).to eq(user.username) } it { expect(data[:user_email]).to eq(user.email) } it { expect(data[:user_avatar]).to eq(user.avatar_url) } it { expect(data[:project_id]).to eq(project.id) } diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 737fac14f92..d6535f97665 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -382,11 +382,13 @@ describe Gitlab::Database::MigrationHelpers, lib: true do expect(model).to receive(:add_column). with(:users, :new, :integer, limit: old_column.limit, - default: old_column.default, null: old_column.null, precision: old_column.precision, scale: old_column.scale) + expect(model).to receive(:change_column_default). + with(:users, :new, old_column.default) + expect(model).to receive(:update_column_in_batches) expect(model).to receive(:copy_indexes).with(:users, :old, :new) @@ -406,11 +408,13 @@ describe Gitlab::Database::MigrationHelpers, lib: true do expect(model).to receive(:add_column). with(:users, :new, :integer, limit: old_column.limit, - default: old_column.default, null: old_column.null, precision: old_column.precision, scale: old_column.scale) + expect(model).to receive(:change_column_default). + with(:users, :new, old_column.default) + expect(model).to receive(:update_column_in_batches) expect(model).to receive(:copy_indexes).with(:users, :old, :new) diff --git a/spec/lib/gitlab/gitaly_client/commit_spec.rb b/spec/lib/gitlab/gitaly_client/commit_spec.rb index 08c072caf8c..cf1bc74779e 100644 --- a/spec/lib/gitlab/gitaly_client/commit_spec.rb +++ b/spec/lib/gitlab/gitaly_client/commit_spec.rb @@ -1,12 +1,13 @@ require 'spec_helper' describe Gitlab::GitalyClient::Commit do - describe '.diff_from_parent' do - let(:diff_stub) { double('Gitaly::Diff::Stub') } - let(:project) { create(:project, :repository) } - let(:repository_message) { project.repository.gitaly_repository } - let(:commit) { project.commit('913c66a37b4a45b9769037c55c2d238bd0942d2e') } + let(:diff_stub) { double('Gitaly::Diff::Stub') } + let(:project) { create(:project, :repository) } + let(:repository) { project.repository } + let(:repository_message) { repository.gitaly_repository } + let(:commit) { project.commit('913c66a37b4a45b9769037c55c2d238bd0942d2e') } + describe '#diff_from_parent' do context 'when a commit has a parent' do it 'sends an RPC request with the parent ID as left commit' do request = Gitaly::CommitDiffRequest.new( @@ -17,7 +18,7 @@ describe Gitlab::GitalyClient::Commit do expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_diff).with(request) - described_class.diff_from_parent(commit) + described_class.new(repository).diff_from_parent(commit) end end @@ -32,12 +33,12 @@ describe Gitlab::GitalyClient::Commit do expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_diff).with(request) - described_class.diff_from_parent(initial_commit) + described_class.new(repository).diff_from_parent(initial_commit) end end it 'returns a Gitlab::Git::DiffCollection' do - ret = described_class.diff_from_parent(commit) + ret = described_class.new(repository).diff_from_parent(commit) expect(ret).to be_kind_of(Gitlab::Git::DiffCollection) end @@ -47,7 +48,38 @@ describe Gitlab::GitalyClient::Commit do expect(Gitlab::Git::DiffCollection).to receive(:new).with(kind_of(Enumerable), options) - described_class.diff_from_parent(commit, options) + described_class.new(repository).diff_from_parent(commit, options) + end + end + + describe '#commit_deltas' do + context 'when a commit has a parent' do + it 'sends an RPC request with the parent ID as left commit' do + request = Gitaly::CommitDeltaRequest.new( + repository: repository_message, + left_commit_id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660', + right_commit_id: commit.id + ) + + expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_delta).with(request).and_return([]) + + described_class.new(repository).commit_deltas(commit) + end + end + + context 'when a commit does not have a parent' do + it 'sends an RPC request with empty tree ref as left commit' do + initial_commit = project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') + request = Gitaly::CommitDeltaRequest.new( + repository: repository_message, + left_commit_id: '4b825dc642cb6eb9a060e54bf8d69288fbee4904', + right_commit_id: initial_commit.id + ) + + expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_delta).with(request).and_return([]) + + described_class.new(repository).commit_deltas(initial_commit) + end end end end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 131fea8be43..72f83d63224 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -388,19 +388,4 @@ eos expect(described_class.valid_hash?('a' * 41)).to be false end end - - describe '#raw_diffs' do - context 'Gitaly commit_raw_diffs feature enabled' do - before do - allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(:commit_raw_diffs).and_return(true) - end - - it 'fetches diffs from Gitaly server' do - expect(Gitlab::GitalyClient::Commit).to receive(:diff_from_parent). - with(commit) - - commit.raw_diffs - end - end - end end diff --git a/spec/support/generate-seed-repo-rb b/spec/support/generate-seed-repo-rb new file mode 100755 index 00000000000..7335f74c0e9 --- /dev/null +++ b/spec/support/generate-seed-repo-rb @@ -0,0 +1,162 @@ +#!/usr/bin/env ruby +# +# # generate-seed-repo-rb +# +# This script generates the seed_repo.rb file used by lib/gitlab/git +# tests. The seed_repo.rb file needs to be updated anytime there is a +# Git push to https://gitlab.com/gitlab-org/gitlab-git-test. +# +# Usage: +# +# ./spec/support/generate-seed-repo-rb > spec/support/seed_repo.rb +# +# + +require 'erb' +require 'tempfile' + +SOURCE = 'https://gitlab.com/gitlab-org/gitlab-git-test.git'.freeze +SCRIPT_NAME = 'generate-seed-repo-rb'.freeze +REPO_NAME = 'gitlab-git-test.git'.freeze + +def main + Dir.mktmpdir do |dir| + unless system(*%W[git clone --bare #{SOURCE} #{REPO_NAME}], chdir: dir) + abort "git clone failed" + end + repo = File.join(dir, REPO_NAME) + erb = ERB.new(DATA.read) + erb.run(binding) + end +end + +def capture!(cmd, dir) + output = IO.popen(cmd, 'r', chdir: dir) { |io| io.read } + raise "command failed with #{$?}: #{cmd.join(' ')}" unless $?.success? + output.chomp +end + +main + +__END__ +# This file is generated by <%= SCRIPT_NAME %>. Do not edit this file manually. +# +# Seed repo: +<%= capture!(%w{git log --format=#\ %H\ %s}, repo) %> + +module SeedRepo + module BigCommit + ID = "913c66a37b4a45b9769037c55c2d238bd0942d2e".freeze + PARENT_ID = "cfe32cf61b73a0d5e9f13e774abde7ff789b1660".freeze + MESSAGE = "Files, encoding and much more".freeze + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets".freeze + FILES_COUNT = 2 + end + + module Commit + ID = "570e7b2abdd848b95f2f578043fc23bd6f6fd24d".freeze + PARENT_ID = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9".freeze + MESSAGE = "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n".freeze + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets".freeze + FILES = ["files/ruby/popen.rb", "files/ruby/regex.rb"].freeze + FILES_COUNT = 2 + C_FILE_PATH = "files/ruby".freeze + C_FILES = ["popen.rb", "regex.rb", "version_info.rb"].freeze + BLOB_FILE = %{%h3= @key.title\n%hr\n%pre= @key.key\n.actions\n = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => \"btn danger delete-key\"\n\n\n}.freeze + BLOB_FILE_PATH = "app/views/keys/show.html.haml".freeze + end + + module EmptyCommit + ID = "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9".freeze + PARENT_ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d".freeze + MESSAGE = "Empty commit".freeze + AUTHOR_FULL_NAME = "Rémy Coutable".freeze + FILES = [].freeze + FILES_COUNT = FILES.count + end + + module EncodingCommit + ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d".freeze + PARENT_ID = "66028349a123e695b589e09a36634d976edcc5e8".freeze + MESSAGE = "Add ISO-8859-encoded file".freeze + AUTHOR_FULL_NAME = "Stan Hu".freeze + FILES = ["encoding/iso8859.txt"].freeze + FILES_COUNT = FILES.count + end + + module FirstCommit + ID = "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863".freeze + PARENT_ID = nil + MESSAGE = "Initial commit".freeze + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets".freeze + FILES = ["LICENSE", ".gitignore", "README.md"].freeze + FILES_COUNT = 3 + end + + module LastCommit + ID = <%= capture!(%w[git show -s --format=%H HEAD], repo).inspect %>.freeze + PARENT_ID = <%= capture!(%w[git show -s --format=%P HEAD], repo).split.last.inspect %>.freeze + MESSAGE = <%= capture!(%w[git show -s --format=%s HEAD], repo).inspect %>.freeze + AUTHOR_FULL_NAME = <%= capture!(%w[git show -s --format=%an HEAD], repo).inspect %>.freeze + FILES = <%= + parents = capture!(%w[git show -s --format=%P HEAD], repo).split + merge_base = parents.size > 1 ? capture!(%w[git merge-base] + parents, repo) : parents.first + capture!( %W[git diff --name-only #{merge_base}..HEAD --], repo).split("\n").inspect + %>.freeze + FILES_COUNT = FILES.count + end + + module Repo + HEAD = "master".freeze + BRANCHES = %w[ +<%= capture!(%W[git for-each-ref --format=#{' ' * 3}%(refname:strip=2) refs/heads/], repo) %> + ].freeze + TAGS = %w[ +<%= capture!(%W[git for-each-ref --format=#{' ' * 3}%(refname:strip=2) refs/tags/], repo) %> + ].freeze + end + + module RubyBlob + ID = "7e3e39ebb9b2bf433b4ad17313770fbe4051649c".freeze + NAME = "popen.rb".freeze + CONTENT = <<-eos.freeze +require 'fileutils' +require 'open3' + +module Popen + extend self + + def popen(cmd, path=nil) + unless cmd.is_a?(Array) + raise RuntimeError, "System commands must be given as an array of strings" + end + + path ||= Dir.pwd + + vars = { + "PWD" => path + } + + options = { + chdir: path + } + + unless File.directory?(path) + FileUtils.mkdir_p(path) + end + + @cmd_output = "" + @cmd_status = 0 + + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + @cmd_output << stdout.read + @cmd_output << stderr.read + @cmd_status = wait_thr.value.exitstatus + end + + return @cmd_output, @cmd_status + end +end + eos + end +end diff --git a/spec/support/seed_repo.rb b/spec/support/seed_repo.rb index 99a500bbbb1..cfe7fc980a8 100644 --- a/spec/support/seed_repo.rb +++ b/spec/support/seed_repo.rb @@ -1,4 +1,8 @@ +# This file is generated by generate-seed-repo-rb. Do not edit this file manually. +# # Seed repo: +# 4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6 Merge branch 'master' into 'master' +# 0e1b353b348f8477bdbec1ef47087171c5032cd9 adds an executable with different permissions # 0e50ec4d3c7ce42ab74dda1d422cb2cbffe1e326 Merge branch 'lfs_pointers' into 'master' # 33bcff41c232a11727ac6d660bd4b0c2ba86d63d Add valid and invalid lfs pointers # 732401c65e924df81435deb12891ef570167d2e2 Update year in license file @@ -94,7 +98,12 @@ module SeedRepo master merge-test ].freeze - TAGS = %w[v1.0.0 v1.1.0 v1.2.0 v1.2.1].freeze + TAGS = %w[ + v1.0.0 + v1.1.0 + v1.2.0 + v1.2.1 + ].freeze end module RubyBlob diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 3289c2df1fb..f4bc63bcc6a 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -4,13 +4,16 @@ describe PostReceive do let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" } let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") } let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) } - let(:project) { create(:project, :repository) } let(:project_identifier) { "project-#{project.id}" } let(:key) { create(:key, user: project.owner) } let(:key_id) { key.shell_id } + let(:project) do + create(:project, :repository, auto_cancel_pending_pipelines: 'disabled') + end + context "as a sidekiq worker" do - it "reponds to #perform" do + it "responds to #perform" do expect(described_class.new).to respond_to(:perform) end end |