Commit 0ca22789 authored by Rémy Coutable's avatar Rémy Coutable

Merge remote-tracking branch 'origin/master' into rc/ce-to-ee-wednesday

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parents 8c823706 bafd5379
...@@ -9,7 +9,7 @@ variables: ...@@ -9,7 +9,7 @@ variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1" MYSQL_ALLOW_EMPTY_PASSWORD: "1"
# retry tests only in CI environment # retry tests only in CI environment
RSPEC_RETRY_RETRY_COUNT: "3" RSPEC_RETRY_RETRY_COUNT: "3"
ELASTIC_HOST: "registry.gitlab.com-gitlab-org-test-elastic-image" ELASTIC_HOST: "elasticsearch"
RAILS_ENV: "test" RAILS_ENV: "test"
SIMPLECOV: "true" SIMPLECOV: "true"
SETUP_DB: "true" SETUP_DB: "true"
...@@ -17,6 +17,8 @@ variables: ...@@ -17,6 +17,8 @@ variables:
GIT_DEPTH: "20" GIT_DEPTH: "20"
PHANTOMJS_VERSION: "2.1.1" PHANTOMJS_VERSION: "2.1.1"
GET_SOURCES_ATTEMPTS: "3" GET_SOURCES_ATTEMPTS: "3"
# This hack is needed to make ES not that memory hungry
ES_JAVA_OPTS: "-Xms600m -Xmx600m"
before_script: before_script:
- source ./scripts/prepare_build.sh - source ./scripts/prepare_build.sh
...@@ -55,7 +57,7 @@ stages: ...@@ -55,7 +57,7 @@ stages:
services: services:
- mysql:latest - mysql:latest
- redis:alpine - redis:alpine
- registry.gitlab.com/gitlab-org/test-elastic-image - elasticsearch:5.1
.rspec-knapsack: &rspec-knapsack .rspec-knapsack: &rspec-knapsack
stage: test stage: test
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
## 8.17.0 (2017-02-22)
- Read-only "auditor" user role. !998
- Also reset approvals on push when merge request is closed. !1051
- Copy commit SHA to clipboard. !1066
- Pull EE specific Gitlab::Auth code in to its own module. !1112
- Geo: Added `gitlab:geo:check` and improved `gitlab:envinfo` rake tasks. !1120
- Geo: send the new event type with the backfill function. !1157
- Re-add removed params from projects and issues V3 API. !1209
- Add configurable minimum mirror sync time in admin section. !1217
- Move RepositoryUpdateRemoteMirrorWorker jobs to project_mirror Sidekiq queue. !1234
- Change Builds word to Pipelines in Mirror settings page.
- Fix bundle tag in anaytics page.
- Support v4 API for GitLab Geo endpoints.
- Fixed merge request environment link not displaying.
- Reduce queries needed to check if node is a primary or secondary Geo node.
- Allow squashing merge requests into a single commit.
## 8.16.6 (2017-02-17) ## 8.16.6 (2017-02-17)
- Geo: send the new event type with the backfill function. !1157 - Geo: send the new event type with the backfill function. !1157
......
...@@ -2,6 +2,187 @@ ...@@ -2,6 +2,187 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 8.17.0 (2017-02-22)
- API: Fix file downloading. !0 (8267)
- Read true-up info from license and validate it. !1159
- Changed composer installer script in the CI PHP example doc. !4342 (Jeffrey Cafferata)
- Display fullscreen button on small screens. !5302 (winniehell)
- Add system hook for when a project is updated (other than rename/transfer). !5711 (Tommy Beadle)
- Fix notifications when set at group level. !6813 (Alexandre Maia)
- Project labels can now be promoted to group labels. !7242 (Olaf Tomalka)
- use webpack to bundle frontend assets and use karma for frontend testing. !7288
- Adds back ability to stop all environments. !7379
- Added labels empty state. !7443
- Add ability to define a coverage regex in the .gitlab-ci.yml. !7447 (Leandro Camargo)
- Disable automatic login after clicking email confirmation links. !7472
- Search feature: redirects to commit page if query is commit sha and only commit found. !8028 (YarNayar)
- Create a TODO for user who set auto-merge when a build fails, merge conflict occurs. !8056 (twonegatives)
- Don't group issues by project on group-level and dashboard issue indexes. !8111 (Bernardo Castro)
- Mark MR as WIP when pushing WIP commits. !8124 (Jurre Stender @jurre)
- Flag multiple empty lines in eslint, fix offenses. !8137
- Add sorting pipeline for a commit. !8319 (Takuya Noguchi)
- Adds service trigger events to api. !8324
- Update pipeline and commit links when CI status is updated. !8351
- Hide version check image if there is no internet connection. !8355 (Ken Ding)
- Prevent removal of input fields if it is the parent dropdown element. !8397
- Introduce maximum session time for terminal websocket connection. !8413
- Allow creating protected branches when user can merge to such branch. !8458
- Refactor MergeRequests::BuildService. !8462 (Rydkin Maxim)
- Added GitLab Pages to CE. !8463
- Support notes when a project is not specified (personal snippet notes). !8468
- Use warning icon in mini-graph if stage passed conditionally. !8503
- Don’t count tasks that are not defined as list items correctly. !8526
- Reformat messages ChatOps. !8528
- Copy commit SHA to clipboard. !8547
- Improve button accessibility on pipelines page. !8561
- Display project ID in project settings. !8572 (winniehell)
- PlantUML support for Markdown. !8588 (Horacio Sanson)
- Fix reply by email without sub-addressing for some clients from Microsoft and Apple. !8620
- Fix nested tasks in ordered list. !8626
- Fix Sort by Recent Sign-in in Admin Area. !8637 (Poornima M)
- Avoid repeated dashes in $CI_ENVIRONMENT_SLUG. !8638
- Only show Merge Request button when user can create a MR. !8639
- Prevent copying of line numbers in parallel diff view. !8706
- Improve build policy and access abilities. !8711
- API: Remove /projects/:id/keys/.. endpoints. !8716 (Robert Schilling)
- API: Remove deprecated 'expires_at' from project snippets. !8723 (Robert Schilling)
- Add `copy` backup strategy to combat file changed errors. !8728
- adds avatar for discussion note. !8734
- Add link verification to badge partial in order to render a badge without a link. !8740
- Reduce hits to LDAP on Git HTTP auth by reordering auth mechanisms. !8752
- prevent diff unfolding link from appearing when there are no more lines to show. !8761
- Redesign searchbar in admin project list. !8776
- Rename Builds to Pipelines, CI/CD Pipelines, or Jobs everywhere. !8787
- dismiss sidebar on repo buttons click. !8798 (Adam Pahlevi)
- fixed small mini pipeline graph line glitch. !8804
- Make all system notes lowercase. !8807
- Support unauthenticated LFS object downloads for public projects. !8824 (Ben Boeckel)
- Add read-only full_path and full_name attributes to Group API. !8827
- allow relative url change without recompiling frontend assets. !8831
- Use vue.js Pipelines table in commit and merge request view. !8844
- Use reCaptcha when an issue is identified as a spam. !8846
- resolve deprecation warnings. !8855 (Adam Pahlevi)
- Cop for gem fetched from a git source. !8856 (Adam Pahlevi)
- Remove flash warning from login page. !8864 (Gerald J. Padilla)
- Adds documentation for how to use Vue.js. !8866
- Add 'View on [env]' link to blobs and individual files in diffs. !8867
- Replace word user with member. !8872
- Change the reply shortcut to focus the field even without a selection. !8873 (Brian Hall)
- Unify MR diff file button style. !8874
- Unify projects search by removing /projects/:search endpoint. !8877
- Fix disable storing of sensitive information when importing a new repo. !8885 (Bernard Pietraga)
- Fix pipeline graph vertical spacing in Firefox and Safari. !8886
- Fix filtered search user autocomplete for gitlab instances that are hosted on a subdirectory. !8891
- Fix Ctrl+Click support for Todos and Merge Request page tabs. !8898
- Fix wrong call to ProjectCacheWorker.perform. !8910
- Don't perform Devise trackable updates on blocked User records. !8915
- Add ability to export project inherited group members to Import/Export. !8923
- replace `find_with_namespace` with `find_by_full_path`. !8949 (Adam Pahlevi)
- Fixes flickering of avatar border in mention dropdown. !8950
- Remove unnecessary queries for .atom and .json in Dashboard::ProjectsController#index. !8956
- Fix deleting projects with pipelines and builds. !8960
- Fix broken anchor links when special characters are used. !8961 (Andrey Krivko)
- Ensure autogenerated title does not cause failing spec. !8963 (brian m. carlson)
- Update doc for enabling or disabling GitLab CI. !8965 (Takuya Noguchi)
- Remove deprecated MR and Issue endpoints and preserve V3 namespace. !8967
- Fixed "substract" typo on /help/user/project/slash_commands. !8976 (Jason Aquino)
- Preserve backward compatibility CI/CD and disallow setting `coverage` regexp in global context. !8981
- use babel to transpile all non-vendor javascript assets regardless of file extension. !8988
- Fix MR widget url. !8989
- Fixes hover cursor on pipeline pagenation. !9003
- Layer award emoji dropdown over the right sidebar. !9004
- Do not display deploy keys in user's own ssh keys list. !9024
- upgrade babel 5.8.x to babel 6.22.x. !9072
- upgrade to webpack v2.2. !9078
- Trigger autocomplete after selecting a slash command. !9117
- Add space between text and loading icon in Megre Request Widget. !9119
- Fix job to pipeline renaming. !9147
- Replace static fixture for merge_request_tabs_spec.js. !9172 (winniehell)
- Replace static fixture for right_sidebar_spec.js. !9211 (winniehell)
- Show merge errors in merge request widget. !9229
- Increase process_commit queue weight from 2 to 3. !9326 (blackst0ne)
- Don't require lib/gitlab/request_profiler/middleware.rb in config/initializers/request_profiler.rb.
- Force new password after password reset via API. (George Andrinopoulos)
- Allows to search within project by commit hash. (YarNayar)
- Show organisation membership and delete comment on smaller viewports, plus change comment author name to username.
- Remove turbolinks.
- Convert pipeline action icons to svg to have them propperly positioned.
- Remove rogue scrollbars for issue comments with inline elements.
- Align Segoe UI label text.
- Color + and - signs in diffs to increase code legibility.
- Fix tab index order on branch commits list page. (Ryan Harris)
- Add hover style to copy icon on commit page header. (Ryan Harris)
- Remove hover animation from row elements.
- Improve pipeline status icon linking in widgets.
- Fix commit title bar and repository view copy clipboard button order on last commit in repository view.
- Fix mini-pipeline stage tooltip text wrapping.
- Updated builds info link on the project settings page. (Ryan Harris)
- 27240 Make progress bars consistent.
- Only render hr when user can't archive project.
- 27352-search-label-filter-header.
- Include :author, :project, and :target in Event.with_associations.
- Don't instantiate AR objects in Event.in_projects.
- Don't capitalize environment name in show page.
- Update and pin the `jwt` gem to ~> 1.5.6.
- Edited the column header for the environments list from created to updated and added created to environments detail page colum header titles.
- Give ci status text on pipeline graph a better font-weight.
- Add default labels to bulk assign dropdowns.
- Only return target project's comments for a commit.
- Fixes Pipelines table is not showing branch name for commit.
- Fix regression where cmd-click stopped working for todos and merge request tabs.
- Fix stray pipelines API request when showing MR.
- Fix Merge request pipelines displays JSON.
- Fix current build arrow indicator.
- Fix contribution activity alignment.
- Show Pipeline(not Job) in MR desktop notification.
- Fix tooltips in mini pipeline graph.
- Display loading indicator when filtering ref switcher dropdown.
- Show pipeline graph in MR widget if there are any stages.
- Fix icon colors in merge request widget mini graph.
- Improve blockquote formatting in notification emails.
- Adds container to tooltip in order to make it work with overflow:hidden in parent element.
- Restore pagination to admin abuse reports.
- Ensure export files are removed after a namespace is deleted.
- Add `y` keyboard shortcut to move to file permalink.
- Adds /target_branch slash command functionality for merge requests. (YarNayar)
- Patch Asciidocs rendering to block XSS.
- contribution calendar scrolls from right to left.
- Copying a rendered issue/comment will paste into GFM textareas as actual GFM.
- Don't delete assigned MRs/issues when user is deleted.
- Remove new branch button for confidential issues.
- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
- Don't connect in Gitlab::Database.adapter_name.
- Prevent users from creating notes on resources they can't access.
- Ignore encrypted attributes in Import/Export.
- Change rspec test to guarantee window is resized before visiting page.
- Prevent users from deleting system deploy keys via the project deploy key API.
- Fix XSS vulnerability in SVG attachments.
- Make MR-review-discussions more reliable.
- fix incorrect sidekiq concurrency count in admin background page. (wendy0402)
- Make notification_service spec DRYer by making test reusable. (YarNayar)
- Redirect http://someproject.git to http://someproject. (blackst0ne)
- Fixed group label links in issue/merge request sidebar.
- Improve gl.utils.handleLocationHash tests.
- Fixed Issuable sidebar not closing on smaller/mobile sized screens.
- Resets assignee dropdown when sidebar is open.
- Disallow system notes for closed issuables.
- Fix timezone on issue boards due date.
- Remove unused js response from refs controller.
- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
- Fixed merge requests tab extra margin when fixed to window.
- Patch XSS vulnerability in RDOC support.
- Refresh authorizations when transferring projects.
- Remove issue and MR counts from labels index.
- Don't use backup Active Record connections for Sidekiq.
- Add index to ci_trigger_requests for commit_id.
- Add indices to improve loading of labels page.
- Reduced query count for snippet search.
- Update GitLab Pages to v0.3.1.
- Upgrade omniauth gem to 1.3.2.
- Remove deprecated GitlabCiService.
- Requeue pending deletion projects.
## 8.16.6 (2017-02-17) ## 8.16.6 (2017-02-17)
- API: Fix file downloading. !0 (8267) - API: Fix file downloading. !0 (8267)
......
...@@ -104,9 +104,10 @@ gem 'unf', '~> 0.1.4' ...@@ -104,9 +104,10 @@ gem 'unf', '~> 0.1.4'
gem 'seed-fu', '~> 2.3.5' gem 'seed-fu', '~> 2.3.5'
# Search # Search
gem 'elasticsearch-model' gem 'elasticsearch-model', '~> 0.1.9'
gem 'elasticsearch-rails' gem 'elasticsearch-rails', '~> 0.1.9'
gem 'gitlab-elasticsearch-git', '~> 1.0.1', require: "elasticsearch/git" gem 'elasticsearch-api', '5.0.3'
gem 'gitlab-elasticsearch-git', '1.1.1', require: "elasticsearch/git"
# Markdown and HTML processing # Markdown and HTML processing
gem 'html-pipeline', '~> 1.11.0' gem 'html-pipeline', '~> 1.11.0'
......
...@@ -168,17 +168,17 @@ GEM ...@@ -168,17 +168,17 @@ GEM
railties (>= 4.2) railties (>= 4.2)
dropzonejs-rails (0.7.2) dropzonejs-rails (0.7.2)
rails (> 3.1) rails (> 3.1)
elasticsearch (1.0.15) elasticsearch (5.0.3)
elasticsearch-api (= 1.0.15) elasticsearch-api (= 5.0.3)
elasticsearch-transport (= 1.0.15) elasticsearch-transport (= 5.0.3)
elasticsearch-api (1.0.15) elasticsearch-api (5.0.3)
multi_json multi_json
elasticsearch-model (0.1.8) elasticsearch-model (0.1.9)
activesupport (> 3) activesupport (> 3)
elasticsearch (> 0.4) elasticsearch (> 0.4)
hashie hashie
elasticsearch-rails (0.1.8) elasticsearch-rails (0.1.9)
elasticsearch-transport (1.0.15) elasticsearch-transport (5.0.3)
faraday faraday
multi_json multi_json
email_reply_trimmer (0.1.6) email_reply_trimmer (0.1.6)
...@@ -264,12 +264,12 @@ GEM ...@@ -264,12 +264,12 @@ GEM
mime-types (>= 1.19) mime-types (>= 1.19)
rugged (>= 0.23.0b) rugged (>= 0.23.0b)
github-markup (1.4.0) github-markup (1.4.0)
gitlab-elasticsearch-git (1.0.1) gitlab-elasticsearch-git (1.1.1)
activemodel (~> 4.2) activemodel (~> 4.2)
activesupport (~> 4.2) activesupport (~> 4.2)
charlock_holmes (~> 0.7) charlock_holmes (~> 0.7)
elasticsearch-api (~> 1.0) elasticsearch-api
elasticsearch-model (~> 0.1.8) elasticsearch-model (~> 0.1.9)
github-linguist (~> 4.7) github-linguist (~> 4.7)
rugged (~> 0.24) rugged (~> 0.24)
gitlab-flowdock-git-hook (1.0.1) gitlab-flowdock-git-hook (1.0.1)
...@@ -352,7 +352,7 @@ GEM ...@@ -352,7 +352,7 @@ GEM
temple (~> 0.7.6) temple (~> 0.7.6)
thor thor
tilt tilt
hashie (3.4.4) hashie (3.5.1)
health_check (2.2.1) health_check (2.2.1)
rails (>= 4.0) rails (>= 4.0)
hipchat (1.5.2) hipchat (1.5.2)
...@@ -886,8 +886,9 @@ DEPENDENCIES ...@@ -886,8 +886,9 @@ DEPENDENCIES
diffy (~> 3.1.0) diffy (~> 3.1.0)
doorkeeper (~> 4.2.0) doorkeeper (~> 4.2.0)
dropzonejs-rails (~> 0.7.1) dropzonejs-rails (~> 0.7.1)
elasticsearch-model elasticsearch-api (= 5.0.3)
elasticsearch-rails elasticsearch-model (~> 0.1.9)
elasticsearch-rails (~> 0.1.9)
email_reply_trimmer (~> 0.1) email_reply_trimmer (~> 0.1)
email_spec (~> 1.6.0) email_spec (~> 1.6.0)
factory_girl_rails (~> 4.7.0) factory_girl_rails (~> 4.7.0)
...@@ -905,7 +906,7 @@ DEPENDENCIES ...@@ -905,7 +906,7 @@ DEPENDENCIES
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
gemojione (~> 3.0) gemojione (~> 3.0)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
gitlab-elasticsearch-git (~> 1.0.1) gitlab-elasticsearch-git (= 1.1.1)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-license (~> 1.0) gitlab-license (~> 1.0)
gitlab-markup (~> 1.5.1) gitlab-markup (~> 1.5.1)
......
...@@ -141,7 +141,7 @@ module Elastic ...@@ -141,7 +141,7 @@ module Elastic
{ {
query: { query: {
bool: { bool: {
must: [{ term: { iid: iid } }] filter: [{ term: { iid: iid } }]
} }
} }
} }
...@@ -155,7 +155,8 @@ module Elastic ...@@ -155,7 +155,8 @@ module Elastic
options[:public_and_internal_projects] options[:public_and_internal_projects]
) )
query_hash[:query][:bool][:filter] = { query_hash[:query][:bool][:filter] ||= []
query_hash[:query][:bool][:filter] << {
has_parent: { has_parent: {
parent_type: "project", parent_type: "project",
query: { query: {
......
...@@ -7,14 +7,14 @@ module Elastic ...@@ -7,14 +7,14 @@ module Elastic
mappings _parent: { type: 'project' } do mappings _parent: { type: 'project' } do
indexes :id, type: :integer indexes :id, type: :integer
indexes :iid, type: :integer, index: :not_analyzed indexes :iid, type: :integer
indexes :title, type: :string, indexes :title, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :description, type: :string, indexes :description, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :created_at, type: :date indexes :created_at, type: :date
indexes :updated_at, type: :date indexes :updated_at, type: :date
indexes :state, type: :string indexes :state, type: :text
indexes :project_id, type: :integer indexes :project_id, type: :integer
indexes :author_id, type: :integer indexes :author_id, type: :integer
indexes :assignee_id, type: :integer indexes :assignee_id, type: :integer
...@@ -79,7 +79,7 @@ module Elastic ...@@ -79,7 +79,7 @@ module Elastic
{ term: { confidential: false } } { term: { confidential: false } }
end end
query_hash[:query][:bool][:must] << filter query_hash[:query][:bool][:filter] << filter
query_hash query_hash
end end
end end
......
...@@ -8,18 +8,18 @@ module Elastic ...@@ -8,18 +8,18 @@ module Elastic
mappings _parent: { type: 'project' } do mappings _parent: { type: 'project' } do
indexes :id, type: :integer indexes :id, type: :integer
indexes :iid, type: :integer indexes :iid, type: :integer
indexes :target_branch, type: :string, indexes :target_branch, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :source_branch, type: :string, indexes :source_branch, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :title, type: :string, indexes :title, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :description, type: :string, indexes :description, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :created_at, type: :date indexes :created_at, type: :date
indexes :updated_at, type: :date indexes :updated_at, type: :date
indexes :state, type: :string indexes :state, type: :text
indexes :merge_status, type: :string indexes :merge_status, type: :text
indexes :source_project_id, type: :integer indexes :source_project_id, type: :integer
indexes :target_project_id, type: :integer indexes :target_project_id, type: :integer
indexes :author_id, type: :integer indexes :author_id, type: :integer
......
...@@ -7,9 +7,9 @@ module Elastic ...@@ -7,9 +7,9 @@ module Elastic
mappings _parent: { type: 'project' } do mappings _parent: { type: 'project' } do
indexes :id, type: :integer indexes :id, type: :integer
indexes :title, type: :string, indexes :title, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :description, type: :string, indexes :description, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :project_id, type: :integer indexes :project_id, type: :integer
indexes :created_at, type: :date indexes :created_at, type: :date
......
...@@ -7,7 +7,7 @@ module Elastic ...@@ -7,7 +7,7 @@ module Elastic
mappings _parent: { type: 'project' } do mappings _parent: { type: 'project' } do
indexes :id, type: :integer indexes :id, type: :integer
indexes :note, type: :string, indexes :note, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :project_id, type: :integer indexes :project_id, type: :integer
indexes :created_at, type: :date indexes :created_at, type: :date
......
...@@ -7,16 +7,16 @@ module Elastic ...@@ -7,16 +7,16 @@ module Elastic
mappings do mappings do
indexes :id, type: :integer indexes :id, type: :integer
indexes :name, type: :string, indexes :name, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :path, type: :string, indexes :path, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :name_with_namespace, type: :string, indexes :name_with_namespace, type: :text,
index_options: 'offsets', index_options: 'offsets',
analyzer: :my_ngram_analyzer analyzer: :my_ngram_analyzer
indexes :path_with_namespace, type: :string, indexes :path_with_namespace, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :description, type: :string, indexes :description, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :namespace_id, type: :integer indexes :namespace_id, type: :integer
indexes :created_at, type: :date indexes :created_at, type: :date
...@@ -91,7 +91,7 @@ module Elastic ...@@ -91,7 +91,7 @@ module Elastic
} }
end end
query_hash[:query][:bool][:filter] = { and: filters } query_hash[:query][:bool][:filter] = filters
query_hash[:sort] = [:_score] query_hash[:sort] = [:_score]
......
...@@ -7,15 +7,15 @@ module Elastic ...@@ -7,15 +7,15 @@ module Elastic
mappings do mappings do
indexes :id, type: :integer indexes :id, type: :integer
indexes :title, type: :string, indexes :title, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :file_name, type: :string, indexes :file_name, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :content, type: :string, indexes :content, type: :text,
index_options: 'offsets' index_options: 'offsets'
indexes :created_at, type: :date indexes :created_at, type: :date
indexes :updated_at, type: :date indexes :updated_at, type: :date
indexes :state, type: :string indexes :state, type: :text
indexes :project_id, type: :integer indexes :project_id, type: :integer
indexes :author_id, type: :integer indexes :author_id, type: :integer
indexes :visibility_level, type: :integer indexes :visibility_level, type: :integer
......
...@@ -55,7 +55,7 @@ module Files ...@@ -55,7 +55,7 @@ module Files
file_path = action[:file_path] file_path = action[:file_path]
file_path = action[:previous_path] if action[:action] == :move file_path = action[:previous_path] if action[:action] == :move
blob = repository.blob_at_branch(params[:branch_name], file_path) blob = repository.blob_at_branch(params[:branch], file_path)
unless blob unless blob
raise_error("File to be #{action[:action]}d `#{file_path}` does not exist.") raise_error("File to be #{action[:action]}d `#{file_path}` does not exist.")
...@@ -89,7 +89,7 @@ module Files ...@@ -89,7 +89,7 @@ module Files
def validate_create(action) def validate_create(action)
return if project.empty_repo? return if project.empty_repo?
if repository.blob_at_branch(params[:branch_name], action[:file_path]) if repository.blob_at_branch(params[:branch], action[:file_path])
raise_error("Your changes could not be committed because a file with the name `#{action[:file_path]}` already exists.") raise_error("Your changes could not be committed because a file with the name `#{action[:file_path]}` already exists.")
end end
end end
...@@ -102,14 +102,14 @@ module Files ...@@ -102,14 +102,14 @@ module Files
raise_error("You must supply the original file path when moving file `#{action[:file_path]}`.") raise_error("You must supply the original file path when moving file `#{action[:file_path]}`.")
end end
blob = repository.blob_at_branch(params[:branch_name], action[:file_path]) blob = repository.blob_at_branch(params[:branch], action[:file_path])
if blob if blob
raise_error("Move destination `#{action[:file_path]}` already exists.") raise_error("Move destination `#{action[:file_path]}` already exists.")
end end
if action[:content].nil? if action[:content].nil?
blob = repository.blob_at_branch(params[:branch_name], action[:previous_path]) blob = repository.blob_at_branch(params[:branch], action[:previous_path])
blob.load_all_data!(repository) if blob.truncated? blob.load_all_data!(repository) if blob.truncated?
params[:actions][index][:content] = blob.data params[:actions][index][:content] = blob.data
end end
......
...@@ -36,7 +36,7 @@ class ElasticIndexerWorker ...@@ -36,7 +36,7 @@ class ElasticIndexerWorker
client.delete index: klass.index_name, type: klass.document_type, id: record_id client.delete index: klass.index_name, type: klass.document_type, id: record_id
end end
clear_project_indexes(record_id) if klass == Project clear_project_data(record_id) if klass == Project
end end
rescue Elasticsearch::Transport::Transport::Errors::NotFound, ActiveRecord::RecordNotFound rescue Elasticsearch::Transport::Transport::Errors::NotFound, ActiveRecord::RecordNotFound
# These errors can happen in several cases, including: # These errors can happen in several cases, including:
...@@ -56,43 +56,33 @@ class ElasticIndexerWorker ...@@ -56,43 +56,33 @@ class ElasticIndexerWorker
end end
end end
def clear_project_indexes(record_id) def clear_project_data(record_id)
remove_repository_index(record_id) remove_children_documents(Repository.document_type, record_id)
remove_wiki_index(record_id) remove_children_documents(ProjectWiki.document_type, record_id)
remove_nested_content(record_id) remove_children_documents(MergeRequest.document_type, record_id)
remove_documents_by_project_id(record_id)
end end
def remove_repository_index(record_id) def remove_documents_by_project_id(record_id)
client.delete_by_query({
index: Repository.__elasticsearch__.index_name,
body: {
query: {
or: [
{ term: { "commit.rid" => record_id } },
{ term: { "blob.rid" => record_id } }
]
}
}
})
end
def remove_nested_content(record_id)
client.delete_by_query({ client.delete_by_query({
index: Project.__elasticsearch__.index_name, index: Project.__elasticsearch__.index_name,
body: { body: {
query: { query: {
term: { "_parent" => record_id } term: { "project_id" => record_id }
} }
} }
}) })
end end
def remove_wiki_index(record_id) def remove_children_documents(document_type, parent_record_id)
client.delete_by_query({ client.delete_by_query({
index: ProjectWiki.__elasticsearch__.index_name, index: Project.__elasticsearch__.index_name,
body: { body: {
query: { query: {
term: { "blob.rid" => "wiki_#{record_id}" } parent_id: {
type: document_type,
id: parent_record_id
}
} }
} }
}) })
......
---
title: Read-only "auditor" user role
merge_request: 998
author:
---
title: Also reset approvals on push when merge request is closed
merge_request: 1051
author:
---
title: 'Geo: Added `gitlab:geo:check` and improved `gitlab:envinfo` rake tasks'
merge_request: 1120
author:
---
title: Re-add removed params from projects and issues V3 API
merge_request: 1209
author:
---
title: Change Builds word to Pipelines in Mirror settings page
merge_request:
author:
---
title: Fix bundle tag in anaytics page
merge_request:
author:
---
title: 'API: Use `post ":id/#{type}/:subscribable_id/subscribe"` to subscribe and
`post ":id/#{type}/:subscribable_id/unsubscribe"` to unsubscribe from a resource'
merge_request: 1274
author: Robert Schilling
---
title: 'Copy commit SHA to clipboard'
merge_request: 1066
--- ---
title: Align Segoe UI label text title: Update Elasticsearch to 5.1
merge_request: merge_request:
author: author:
--- ---
title: 27240 Make progress bars consistent title: "[Elasticsearch] More efficient search"
merge_request: merge_request:
author: author:
---
title: Support v4 API for GitLab Geo endpoints
merge_request:
author:
---
title: Pull EE specific Gitlab::Auth code in to its own module
merge_request: 1112
author:
---
title: Add configurable minimum mirror sync time in admin section
merge_request: 1217
author:
---
title: Allow squashing merge requests into a single commit
merge_request:
author:
---
title: Rename Builds to Pipelines, CI/CD Pipelines, or Jobs everywhere
merge_request: 8787
author:
---
title: Don't require lib/gitlab/request_profiler/middleware.rb in config/initializers/request_profiler.rb
merge_request:
author:
---
title: Use reCaptcha when an issue is identified as a spam
merge_request: 8846
author:
---
title: Unify projects search by removing /projects/:search endpoint
merge_request: 8877
author:
---
title: Standardize branch name params as branch on V4 API
merge_request: 8936
author:
---
title: Allow creating protected branches when user can merge to such branch
merge_request: 8458
author:
---
title: Adds service trigger events to api
merge_request: 8324
author:
---
title: Create a TODO for user who set auto-merge when a build fails, merge conflict occurs
merge_request: 8056
author: twonegatives
---
title: Don't group issues by project on group-level and dashboard issue indexes.
merge_request: 8111
author: Bernardo Castro
---
title: Fix disable storing of sensitive information when importing a new repo
merge_request: 8885
author: Bernard Pietraga
---
title: Adds back ability to stop all environments
merge_request: 7379
author:
---
title: Force new password after password reset via API
merge_request:
author: George Andrinopoulos
---
title: Fix Ctrl+Click support for Todos and Merge Request page tabs
merge_request: 8898
author:
---
title: Refactor MergeRequests::BuildService
merge_request: 8462
author: Rydkin Maxim
---
title: 'Allows to search within project by commit hash'
merge_request:
author: YarNayar
---
title: Fix nested tasks in ordered list
merge_request: 8626
author:
---
title: Show organisation membership and delete comment on smaller viewports, plus change comment author name to username
merge_request:
author:
---
title: Prevent removal of input fields if it is the parent dropdown element
merge_request: 8397
author:
---
title: Remove flash warning from login page
merge_request: 8864
author: Gerald J. Padilla
---
title: Replace word user with member
merge_request: 8872
author:
---
title: Remove turbolinks.
merge_request: !8570
author:
---
title: Update pipeline and commit links when CI status is updated
merge_request: 8351
author:
---
title: Convert pipeline action icons to svg to have them propperly positioned
merge_request:
author:
---
title: Remove rogue scrollbars for issue comments with inline elements
merge_request:
author:
---
title: Don’t count tasks that are not defined as list items correctly
merge_request: 8526
author:
---
title: Add sorting pipeline for a commit
merge_request: 8319
author: Takuya Noguchi
---
title: Color + and - signs in diffs to increase code legibility
merge_request:
author:
---
title: Improve button accessibility on pipelines page
merge_request: 8561
author:
---
title: Fix tab index order on branch commits list page
merge_request:
author: Ryan Harris
---
title: Fix Sort by Recent Sign-in in Admin Area
merge_request: 8637
author: Poornima M
---
title: Add hover style to copy icon on commit page header
merge_request:
author: Ryan Harris
---
title: prevent diff unfolding link from appearing when there are no more lines to
show
merge_request: 8761
author:
---
title: Avoid repeated dashes in $CI_ENVIRONMENT_SLUG
merge_request: 8638
author:
---
title: Fixes hover cursor on pipeline pagenation
merge_request: 9003
author:
---
title: Add link verification to badge partial in order to render a badge without a link
merge_request: 8740
author:
---
title: Improve pipeline status icon linking in widgets
merge_request:
author:
---
title: Fix commit title bar and repository view copy clipboard button order on last commit in repository view
merge_request:
author:
---
title: Fix mini-pipeline stage tooltip text wrapping
merge_request:
author:
---
title: Prevent copying of line numbers in parallel diff view
merge_request: 8706
author:
---
title: Updated builds info link on the project settings page
merge_request:
author: Ryan Harris
---
title: fixed small mini pipeline graph line glitch
merge_request: 8804
author:
---
title: Unify MR diff file button style
merge_request: 8874
author:
---
title: Only render hr when user can't archive project.
merge_request: !8917
author:
---
title: Fix pipeline graph vertical spacing in Firefox and Safari
merge_request: 8886
author:
---
title: 27352-search-label-filter-header
merge_request:
author:
---
title: Include :author, :project, and :target in Event.with_associations
merge_request:
author:
---
title: Don't instantiate AR objects in Event.in_projects
merge_request:
author:
---
title: Don't capitalize environment name in show page
merge_request:
author:
---
title: Update and pin the `jwt` gem to ~> 1.5.6
merge_request:
author:
---
title: Edited the column header for the environments list from created to updated and added created to environments detail page colum header titles
merge_request:
author:
---
title: Fixes flickering of avatar border in mention dropdown
merge_request: 8950
author:
---
title: Fix MR widget url
merge_request: 8989
author:
---
title: Layer award emoji dropdown over the right sidebar
merge_request: 9004
author:
---
title: Update doc for enabling or disabling GitLab CI
merge_request: 8965
author: Takuya Noguchi
---
title: Give ci status text on pipeline graph a better font-weight
merge_request:
author:
---
title: Add default labels to bulk assign dropdowns
merge_request:
author:
---
title: Only return target project's comments for a commit
merge_request:
author:
---
title: Fixes Pipelines table is not showing branch name for commit
merge_request:
author:
---
title: Trigger autocomplete after selecting a slash command
merge_request: 9117
author:
---
title: Fix regression where cmd-click stopped working for todos and merge request
tabs
merge_request:
author:
---
title: Fix stray pipelines API request when showing MR
merge_request:
author:
---
title: Fix Merge request pipelines displays JSON
merge_request:
author:
---
title: Fix current build arrow indicator
merge_request:
author:
---
title: Fix contribution activity alignment
merge_request:
author:
---
title: Add space between text and loading icon in Megre Request Widget
merge_request: 9119
author:
---
title: Show Pipeline(not Job) in MR desktop notification
merge_request:
author:
---
title: Fix tooltips in mini pipeline graph
merge_request:
author:
---
title: Display loading indicator when filtering ref switcher dropdown
merge_request:
author:
---
title: Show pipeline graph in MR widget if there are any stages
merge_request:
author:
---
title: Fix icon colors in merge request widget mini graph
merge_request:
author:
---
title: Improve blockquote formatting in notification emails
merge_request:
author:
---
title: Adds container to tooltip in order to make it work with overflow:hidden in
parent element
merge_request:
author:
---
title: Restore pagination to admin abuse reports
merge_request:
author:
---
title: Fix notifications when set at group level
merge_request: 6813
author: Alexandre Maia
---
title: Ensure export files are removed after a namespace is deleted
merge_request:
author:
---
title: Add `y` keyboard shortcut to move to file permalink
merge_request:
author:
---
title: Remove deprecated MR and Issue endpoints and preserve V3 namespace
merge_request: 8967
author:
---
title: Adds /target_branch slash command functionality for merge requests
merge_request:
author: YarNayar
---
title: Add system hook for when a project is updated (other than rename/transfer)
merge_request: 5711
author: Tommy Beadle
---
title: 'API: Remove deprecated ''expires_at'' from project snippets'
merge_request: 8723
author: Robert Schilling
---
title: use babel to transpile all non-vendor javascript assets regardless of file
extension
merge_request: 8988
author:
---
title: Hide version check image if there is no internet connection
merge_request: 8355
author: Ken Ding
---
title: Increase process_commit queue weight from 2 to 3
merge_request: 9326
author: blackst0ne
---
title: 'Copy commit SHA to clipboard'
merge_request: 8547
---
title: contribution calendar scrolls from right to left
merge_request:
author:
---
title: Cop for gem fetched from a git source
merge_request: 8856
author: Adam Pahlevi
---
title: Copying a rendered issue/comment will paste into GFM textareas as actual GFM
merge_request:
author:
---
title: Disable automatic login after clicking email confirmation links
merge_request: 7472
author:
---
title: Display project ID in project settings
merge_request: 8572
author: winniehell
---
title: Adds documentation for how to use Vue.js
merge_request: 8866
author:
---
title: Replace static fixture for right_sidebar_spec.js
merge_request: 9211
author: winniehell
---
title: Add read-only full_path and full_name attributes to Group API
merge_request: 8827
author:
---
title: Change the reply shortcut to focus the field even without a selection.
merge_request: 8873
author: Brian Hall
---
title: Use vue.js Pipelines table in commit and merge request view
merge_request: 8844
author:
---
title: Use warning icon in mini-graph if stage passed conditionally
merge_request: 8503
author:
---
title: Remove new branch button for confidential issues
merge_request:
author:
---
title: Don't allow project guests to subscribe to merge requests through the API
merge_request:
author: Robert Schilling
---
title: Don't connect in Gitlab::Database.adapter_name
merge_request:
author:
---
title: Improve build policy and access abilities
merge_request: 8711
author:
---
title: Fix deleting projects with pipelines and builds
merge_request: 8960
author:
---
title: resolve deprecation warnings
merge_request: 8855
author: Adam Pahlevi
---
title: Preserve backward compatibility CI/CD and disallow setting `coverage` regexp in global context
merge_request: 8981
author:
---
title: Prevent users from creating notes on resources they can't access
merge_request:
author:
---
title: Ignore encrypted attributes in Import/Export
merge_request:
author:
---
title: Add ability to export project inherited group members to Import/Export
merge_request: 8923
author:
---
title: Fix job to pipeline renaming
merge_request: 9147
author:
---
title: Fix reply by email without sub-addressing for some clients from
Microsoft and Apple
merge_request: 8620
author:
---
title: Change rspec test to guarantee window is resized before visiting page
merge_request:
author:
---
title: Prevent users from deleting system deploy keys via the project deploy key API
merge_request:
author:
---
title: Make MR-review-discussions more reliable
merge_request:
author:
---
title: fix incorrect sidekiq concurrency count in admin background page
merge_request:
author: wendy0402
---
title: replace `find_with_namespace` with `find_by_full_path`
merge_request: 8949
author: Adam Pahlevi
---
title: Make notification_service spec DRYer by making test reusable
merge_request:
author: YarNayar
---
title: Redirect http://someproject.git to http://someproject
merge_request:
author: blackst0ne
---
title: use webpack to bundle frontend assets and use karma for frontend testing
merge_request: 7288
author:
---
title: Fixed group label links in issue/merge request sidebar
merge_request:
author:
---
title: Ensure autogenerated title does not cause failing spec
merge_request: 8963
author: brian m. carlson
---
title: Changed composer installer script in the CI PHP example doc
merge_request: 4342
author: Jeffrey Cafferata
---
title: Improve gl.utils.handleLocationHash tests
merge_request:
author:
---
title: Fixed Issuable sidebar not closing on smaller/mobile sized screens
merge_request:
author:
---
title: Add ability to define a coverage regex in the .gitlab-ci.yml
merge_request: 7447
author: Leandro Camargo
---
title: Resets assignee dropdown when sidebar is open
merge_request:
author:
---
title: Disallow system notes for closed issuables
merge_request:
author:
---
title: Fix timezone on issue boards due date
merge_request:
author:
---
title: Remove unused js response from refs controller
merge_request:
author:
---
title: Added GitLab Pages to CE
merge_request: 8463
author:
---
title: "Project labels can now be promoted to group labels"
merge_request: 7242
author: Olaf Tomalka
---
title: Support unauthenticated LFS object downloads for public projects
merge_request: 8824
author: Ben Boeckel
---
title: PlantUML support for Markdown
merge_request: 8588
author: Horacio Sanson
---
title: Replace static fixture for merge_request_tabs_spec.js
merge_request: 9172
author: winniehell
---
title: adds avatar for discussion note
merge_request: 8734
author:
---
title: Fixed merge requests tab extra margin when fixed to window
merge_request:
author:
---
title: Flag multiple empty lines in eslint, fix offenses.
merge_request: 8137
author:
---
title: dismiss sidebar on repo buttons click
merge_request: 8798
author: Adam Pahlevi
---
title: Support notes when a project is not specified (personal snippet notes)
merge_request: 8468
author:
---
title: Make all system notes lowercase
merge_request: 8807
author:
---
title: Redesign searchbar in admin project list
merge_request: 8776
author:
---
title: 'Search feature: redirects to commit page if query is commit sha and only commit
found'
merge_request: 8028
author: YarNayar
---
title: allow relative url change without recompiling frontend assets
merge_request: 8831
author:
---
title: 'API: Remove /projects/:id/keys/.. endpoints'
merge_request: 8716
author: Robert Schilling
---
title: Remove issue and MR counts from labels index
merge_request:
author:
---
title: Add 'View on [env]' link to blobs and individual files in diffs
merge_request: 8867
author:
---
title: Don't perform Devise trackable updates on blocked User records
merge_request: 8915
author:
---
title: Add index to ci_trigger_requests for commit_id
merge_request:
author:
---
title: Add indices to improve loading of labels page
merge_request:
author:
---
title: Fixed "substract" typo on /help/user/project/slash_commands
merge_request: 8976
author: Jason Aquino
---
title: Display fullscreen button on small screens
merge_request: 5302
author: winniehell
---
title: Reduced query count for snippet search
merge_request:
author:
---
title: Only show Merge Request button when user can create a MR
merge_request: 8639
author:
---
title: Introduce maximum session time for terminal websocket connection
merge_request: 8413
author:
---
title: Update GitLab Pages to v0.3.1
merge_request:
author:
---
title: upgrade babel 5.8.x to babel 6.22.x
merge_request: 9072
author:
---
title: Upgrade omniauth gem to 1.3.2
merge_request:
author:
---
title: upgrade to webpack v2.2
merge_request: 9078
author:
---
title: Mark MR as WIP when pushing WIP commits
merge_request: 8124
author: Jurre Stender @jurre
--- ---
title: Remove hover animation from row elements title: Chat slash commands show labels correctly
merge_request: merge_request:
author: author:
---
title: Reformat messages ChatOps
merge_request: 8528
author:
---
title: Remove deprecated GitlabCiService
merge_request:
author:
---
title: Requeue pending deletion projects
merge_request:
author:
...@@ -193,11 +193,11 @@ POST /projects/:id/repository/branches ...@@ -193,11 +193,11 @@ POST /projects/:id/repository/branches
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project | | `id` | integer | yes | The ID of a project |
| `branch_name` | string | yes | The name of the branch | | `branch` | string | yes | The name of the branch |
| `ref` | string | yes | The branch name or commit SHA to create branch from | | `ref` | string | yes | The branch name or commit SHA to create branch from |
```bash ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/branches?branch_name=newbranch&ref=master" curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/branches?branch=newbranch&ref=master"
``` ```
Example response: Example response:
......
...@@ -69,7 +69,7 @@ POST /projects/:id/repository/commits ...@@ -69,7 +69,7 @@ POST /projects/:id/repository/commits
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME | | `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME |
| `branch_name` | string | yes | The name of a branch | | `branch` | string | yes | The name of a branch |
| `commit_message` | string | yes | Commit message | | `commit_message` | string | yes | Commit message |
| `actions[]` | array | yes | An array of action hashes to commit as a batch. See the next table for what attributes it can take. | | `actions[]` | array | yes | An array of action hashes to commit as a batch. See the next table for what attributes it can take. |
| `author_email` | string | no | Specify the commit author's email address | | `author_email` | string | no | Specify the commit author's email address |
...@@ -87,7 +87,7 @@ POST /projects/:id/repository/commits ...@@ -87,7 +87,7 @@ POST /projects/:id/repository/commits
```bash ```bash
PAYLOAD=$(cat << 'JSON' PAYLOAD=$(cat << 'JSON'
{ {
"branch_name": "master", "branch": "master",
"commit_message": "some commit message", "commit_message": "some commit message",
"actions": [ "actions": [
{ {
......
...@@ -523,7 +523,7 @@ If the user is already subscribed to the issue, the status code `304` ...@@ -523,7 +523,7 @@ If the user is already subscribed to the issue, the status code `304`
is returned. is returned.
``` ```
POST /projects/:id/issues/:issue_id/subscription POST /projects/:id/issues/:issue_id/subscribe
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -532,7 +532,7 @@ POST /projects/:id/issues/:issue_id/subscription ...@@ -532,7 +532,7 @@ POST /projects/:id/issues/:issue_id/subscription
| `issue_id` | integer | yes | The ID of a project's issue | | `issue_id` | integer | yes | The ID of a project's issue |
```bash ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/subscription curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/subscribe
``` ```
Example response: Example response:
...@@ -579,7 +579,7 @@ from it. If the user is not subscribed to the issue, the ...@@ -579,7 +579,7 @@ from it. If the user is not subscribed to the issue, the
status code `304` is returned. status code `304` is returned.
``` ```
DELETE /projects/:id/issues/:issue_id/subscription POST /projects/:id/issues/:issue_id/unsubscribe
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -588,7 +588,7 @@ DELETE /projects/:id/issues/:issue_id/subscription ...@@ -588,7 +588,7 @@ DELETE /projects/:id/issues/:issue_id/subscription
| `issue_id` | integer | yes | The ID of a project's issue | | `issue_id` | integer | yes | The ID of a project's issue |
```bash ```bash
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/subscription curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/unsubscribe
``` ```
Example response: Example response:
......
...@@ -188,12 +188,12 @@ Example response: ...@@ -188,12 +188,12 @@ Example response:
## Subscribe to a label ## Subscribe to a label
Subscribes the authenticated user to a label to receive notifications. Subscribes the authenticated user to a label to receive notifications.
If the user is already subscribed to the label, the status code `304` If the user is already subscribed to the label, the status code `304`
is returned. is returned.
``` ```
POST /projects/:id/labels/:label_id/subscription POST /projects/:id/labels/:label_id/subscribe
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -202,7 +202,7 @@ POST /projects/:id/labels/:label_id/subscription ...@@ -202,7 +202,7 @@ POST /projects/:id/labels/:label_id/subscription
| `label_id` | integer or string | yes | The ID or title of a project's label | | `label_id` | integer or string | yes | The ID or title of a project's label |
```bash ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscribe
``` ```
Example response: Example response:
...@@ -228,7 +228,7 @@ from it. If the user is not subscribed to the label, the ...@@ -228,7 +228,7 @@ from it. If the user is not subscribed to the label, the
status code `304` is returned. status code `304` is returned.
``` ```
DELETE /projects/:id/labels/:label_id/subscription POST /projects/:id/labels/:label_id/unsubscribe
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -237,7 +237,7 @@ DELETE /projects/:id/labels/:label_id/subscription ...@@ -237,7 +237,7 @@ DELETE /projects/:id/labels/:label_id/subscription
| `label_id` | integer or string | yes | The ID or title of a project's label | | `label_id` | integer or string | yes | The ID or title of a project's label |
```bash ```bash
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/unsubscribe
``` ```
Example response: Example response:
......
...@@ -810,7 +810,7 @@ Subscribes the authenticated user to a merge request to receive notification. If ...@@ -810,7 +810,7 @@ Subscribes the authenticated user to a merge request to receive notification. If
status code `304` is returned. status code `304` is returned.
``` ```
POST /projects/:id/merge_requests/:merge_request_id/subscription POST /projects/:id/merge_requests/:merge_request_id/subscribe
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -819,7 +819,7 @@ POST /projects/:id/merge_requests/:merge_request_id/subscription ...@@ -819,7 +819,7 @@ POST /projects/:id/merge_requests/:merge_request_id/subscription
| `merge_request_id` | integer | yes | The ID of the merge request | | `merge_request_id` | integer | yes | The ID of the merge request |
```bash ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscription curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscribe
``` ```
Example response: Example response:
...@@ -884,7 +884,7 @@ notifications from that merge request. If the user is ...@@ -884,7 +884,7 @@ notifications from that merge request. If the user is
not subscribed to the merge request, the status code `304` is returned. not subscribed to the merge request, the status code `304` is returned.
``` ```
DELETE /projects/:id/merge_requests/:merge_request_id/subscription POST /projects/:id/merge_requests/:merge_request_id/subscribe
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -893,7 +893,7 @@ DELETE /projects/:id/merge_requests/:merge_request_id/subscription ...@@ -893,7 +893,7 @@ DELETE /projects/:id/merge_requests/:merge_request_id/subscription
| `merge_request_id` | integer | yes | The ID of the merge request | | `merge_request_id` | integer | yes | The ID of the merge request |
```bash ```bash
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscription curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscribe
``` ```
Example response: Example response:
......
...@@ -46,22 +46,22 @@ POST /projects/:id/repository/files ...@@ -46,22 +46,22 @@ POST /projects/:id/repository/files
``` ```
```bash ```bash
curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch_name=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20content&commit_message=create%20a%20new%20file' curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20content&commit_message=create%20a%20new%20file'
``` ```
Example response: Example response:
```json ```json
{ {
"file_path": "app/project.rb", "file_name": "app/project.rb",
"branch_name": "master" "branch": "master"
} }
``` ```
Parameters: Parameters:
- `file_path` (required) - Full path to new file. Ex. lib/class.rb - `file_path` (required) - Full path to new file. Ex. lib/class.rb
- `branch_name` (required) - The name of branch - `branch` (required) - The name of branch
- `encoding` (optional) - Change encoding to 'base64'. Default is text. - `encoding` (optional) - Change encoding to 'base64'. Default is text.
- `author_email` (optional) - Specify the commit author's email address - `author_email` (optional) - Specify the commit author's email address
- `author_name` (optional) - Specify the commit author's name - `author_name` (optional) - Specify the commit author's name
...@@ -75,22 +75,22 @@ PUT /projects/:id/repository/files ...@@ -75,22 +75,22 @@ PUT /projects/:id/repository/files
``` ```
```bash ```bash
curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch_name=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20other%20content&commit_message=update%20file' curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20other%20content&commit_message=update%20file'
``` ```
Example response: Example response:
```json ```json
{ {
"file_path": "app/project.rb", "file_name": "app/project.rb",
"branch_name": "master" "branch": "master"
} }
``` ```
Parameters: Parameters:
- `file_path` (required) - Full path to file. Ex. lib/class.rb - `file_path` (required) - Full path to file. Ex. lib/class.rb
- `branch_name` (required) - The name of branch - `branch` (required) - The name of branch
- `encoding` (optional) - Change encoding to 'base64'. Default is text. - `encoding` (optional) - Change encoding to 'base64'. Default is text.
- `author_email` (optional) - Specify the commit author's email address - `author_email` (optional) - Specify the commit author's email address
- `author_name` (optional) - Specify the commit author's name - `author_name` (optional) - Specify the commit author's name
...@@ -113,22 +113,22 @@ DELETE /projects/:id/repository/files ...@@ -113,22 +113,22 @@ DELETE /projects/:id/repository/files
``` ```
```bash ```bash
curl --request DELETE --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch_name=master&author_email=author%40example.com&author_name=Firstname%20Lastname&commit_message=delete%20file' curl --request DELETE --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&commit_message=delete%20file'
``` ```
Example response: Example response:
```json ```json
{ {
"file_path": "app/project.rb", "file_name": "app/project.rb",
"branch_name": "master" "branch": "master"
} }
``` ```
Parameters: Parameters:
- `file_path` (required) - Full path to file. Ex. lib/class.rb - `file_path` (required) - Full path to file. Ex. lib/class.rb
- `branch_name` (required) - The name of branch - `branch` (required) - The name of branch
- `author_email` (optional) - Specify the commit author's email address - `author_email` (optional) - Specify the commit author's email address
- `author_name` (optional) - Specify the commit author's name - `author_name` (optional) - Specify the commit author's name
- `commit_message` (required) - Commit message - `commit_message` (required) - Commit message
...@@ -29,4 +29,10 @@ changes are in V4: ...@@ -29,4 +29,10 @@ changes are in V4:
- Return pagination headers for all endpoints that return an array - Return pagination headers for all endpoints that return an array
- Removed `DELETE projects/:id/deploy_keys/:key_id/disable`. Use `DELETE projects/:id/deploy_keys/:key_id` instead - Removed `DELETE projects/:id/deploy_keys/:key_id/disable`. Use `DELETE projects/:id/deploy_keys/:key_id` instead
- Moved `PUT /users/:id/(block|unblock)` to `POST /users/:id/(block|unblock)` - Moved `PUT /users/:id/(block|unblock)` to `POST /users/:id/(block|unblock)`
- Make subscription API more RESTful. Use `post ":id/#{type}/:subscribable_id/subscribe"` to subscribe and `post ":id/#{type}/:subscribable_id/unsubscribe"` to unsubscribe from a resource.
- Labels filter on `projects/:id/issues` and `/issues` now matches only issues containing all labels (i.e.: Logical AND, not OR) - Labels filter on `projects/:id/issues` and `/issues` now matches only issues containing all labels (i.e.: Logical AND, not OR)
- Renamed param `branch_name` to `branch` on the following endpoints
- POST `:id/repository/branches`
- POST `:id/repository/commits`
- POST/PUT/DELETE `:id/repository/files`
- Renamed `branch_name` to `branch` on DELETE `id/repository/branches/:branch` response
...@@ -29,12 +29,7 @@ GitLab, or on a separate server. ...@@ -29,12 +29,7 @@ GitLab, or on a separate server.
## Requirements ## Requirements
These are the requirements needed for Elasticsearch to work: Elasticsearch 5.1.x.
- GitLab 8.4+
- Elasticsearch 2.4.x (with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed)
Please note that we don't support Elasticsearch 5.x at this time.
## Install Elasticsearch ## Install Elasticsearch
......
...@@ -7,7 +7,9 @@ module API ...@@ -7,7 +7,9 @@ module API
version 'v3', using: :path do version 'v3', using: :path do
mount ::API::V3::Boards mount ::API::V3::Boards
mount ::API::V3::Branches mount ::API::V3::Branches
mount ::API::V3::Commits
mount ::API::V3::DeployKeys mount ::API::V3::DeployKeys
mount ::API::V3::Files
mount ::API::V3::Issues mount ::API::V3::Issues
mount ::API::V3::Labels mount ::API::V3::Labels
mount ::API::V3::Members mount ::API::V3::Members
...@@ -17,6 +19,7 @@ module API ...@@ -17,6 +19,7 @@ module API
mount ::API::V3::Projects mount ::API::V3::Projects
mount ::API::V3::ProjectSnippets mount ::API::V3::ProjectSnippets
mount ::API::V3::Repositories mount ::API::V3::Repositories
mount ::API::V3::Subscriptions
mount ::API::V3::SystemHooks mount ::API::V3::SystemHooks
mount ::API::V3::Tags mount ::API::V3::Tags
mount ::API::V3::Todos mount ::API::V3::Todos
......
...@@ -97,13 +97,13 @@ module API ...@@ -97,13 +97,13 @@ module API
success Entities::RepoBranch success Entities::RepoBranch
end end
params do params do
requires :branch_name, type: String, desc: 'The name of the branch' requires :branch, type: String, desc: 'The name of the branch'
requires :ref, type: String, desc: 'Create branch from commit sha or existing branch' requires :ref, type: String, desc: 'Create branch from commit sha or existing branch'
end end
post ":id/repository/branches" do post ":id/repository/branches" do
authorize_push_project authorize_push_project
result = CreateBranchService.new(user_project, current_user). result = CreateBranchService.new(user_project, current_user).
execute(params[:branch_name], params[:ref]) execute(params[:branch], params[:ref])
if result[:status] == :success if result[:status] == :success
present result[:branch], present result[:branch],
...@@ -126,7 +126,7 @@ module API ...@@ -126,7 +126,7 @@ module API
if result[:status] == :success if result[:status] == :success
{ {
branch_name: params[:branch] branch: params[:branch]
} }
else else
render_api_error!(result[:message], result[:return_code]) render_api_error!(result[:message], result[:return_code])
......
...@@ -41,7 +41,7 @@ module API ...@@ -41,7 +41,7 @@ module API
detail 'This feature was introduced in GitLab 8.13' detail 'This feature was introduced in GitLab 8.13'
end end
params do params do
requires :branch_name, type: String, desc: 'The name of branch' requires :branch, type: String, desc: 'The name of branch'
requires :commit_message, type: String, desc: 'Commit message' requires :commit_message, type: String, desc: 'Commit message'
requires :actions, type: Array[Hash], desc: 'Actions to perform in commit' requires :actions, type: Array[Hash], desc: 'Actions to perform in commit'
optional :author_email, type: String, desc: 'Author email for commit' optional :author_email, type: String, desc: 'Author email for commit'
...@@ -50,9 +50,8 @@ module API ...@@ -50,9 +50,8 @@ module API
post ":id/repository/commits" do post ":id/repository/commits" do
authorize! :push_code, user_project authorize! :push_code, user_project
attrs = declared_params attrs = declared_params.merge(start_branch: declared_params[:branch], target_branch: declared_params[:branch])
attrs[:start_branch] = attrs[:branch_name]
attrs[:target_branch] = attrs[:branch_name]
attrs[:actions].map! do |action| attrs[:actions].map! do |action|
action[:action] = action[:action].to_sym action[:action] = action[:action].to_sym
action[:file_path].slice!(0) if action[:file_path] && action[:file_path].start_with?('/') action[:file_path].slice!(0) if action[:file_path] && action[:file_path].start_with?('/')
......
...@@ -4,8 +4,8 @@ module API ...@@ -4,8 +4,8 @@ module API
def commit_params(attrs) def commit_params(attrs)
{ {
file_path: attrs[:file_path], file_path: attrs[:file_path],
start_branch: attrs[:branch_name], start_branch: attrs[:branch],
target_branch: attrs[:branch_name], target_branch: attrs[:branch],
commit_message: attrs[:commit_message], commit_message: attrs[:commit_message],
file_content: attrs[:content], file_content: attrs[:content],
file_content_encoding: attrs[:encoding], file_content_encoding: attrs[:encoding],
...@@ -17,13 +17,13 @@ module API ...@@ -17,13 +17,13 @@ module API
def commit_response(attrs) def commit_response(attrs)
{ {
file_path: attrs[:file_path], file_path: attrs[:file_path],
branch_name: attrs[:branch_name] branch: attrs[:branch]
} }
end end
params :simple_file_params do params :simple_file_params do
requires :file_path, type: String, desc: 'The path to new file. Ex. lib/class.rb' requires :file_path, type: String, desc: 'The path to new file. Ex. lib/class.rb'
requires :branch_name, type: String, desc: 'The name of branch' requires :branch, type: String, desc: 'The name of branch'
requires :commit_message, type: String, desc: 'Commit Message' requires :commit_message, type: String, desc: 'Commit Message'
optional :author_email, type: String, desc: 'The email of the author' optional :author_email, type: String, desc: 'The email of the author'
optional :author_name, type: String, desc: 'The name of the author' optional :author_name, type: String, desc: 'The name of the author'
......
...@@ -21,7 +21,7 @@ module API ...@@ -21,7 +21,7 @@ module API
desc 'Subscribe to a resource' do desc 'Subscribe to a resource' do
success entity_class success entity_class
end end
post ":id/#{type}/:subscribable_id/subscription" do post ":id/#{type}/:subscribable_id/subscribe" do
resource = instance_exec(params[:subscribable_id], &finder) resource = instance_exec(params[:subscribable_id], &finder)
if resource.subscribed?(current_user, user_project) if resource.subscribed?(current_user, user_project)
...@@ -35,7 +35,7 @@ module API ...@@ -35,7 +35,7 @@ module API
desc 'Unsubscribe from a resource' do desc 'Unsubscribe from a resource' do
success entity_class success entity_class
end end
delete ":id/#{type}/:subscribable_id/subscription" do post ":id/#{type}/:subscribable_id/unsubscribe" do
resource = instance_exec(params[:subscribable_id], &finder) resource = instance_exec(params[:subscribable_id], &finder)
if !resource.subscribed?(current_user, user_project) if !resource.subscribed?(current_user, user_project)
......
require 'mime/types'
module API
module V3
class Commits < Grape::API
include PaginationParams
before { authenticate! }
before { authorize! :download_code, user_project }
params do
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects do
desc 'Get a project repository commits' do
success ::API::Entities::RepoCommit
end
params do
optional :ref_name, type: String, desc: 'The name of a repository branch or tag, if not given the default branch is used'
optional :since, type: DateTime, desc: 'Only commits after or in this date will be returned'
optional :until, type: DateTime, desc: 'Only commits before or in this date will be returned'
optional :page, type: Integer, default: 0, desc: 'The page for pagination'
optional :per_page, type: Integer, default: 20, desc: 'The number of results per page'
optional :path, type: String, desc: 'The file path'
end
get ":id/repository/commits" do
ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
offset = params[:page] * params[:per_page]
commits = user_project.repository.commits(ref,
path: params[:path],
limit: params[:per_page],
offset: offset,
after: params[:since],
before: params[:until])
present commits, with: ::API::Entities::RepoCommit
end
desc 'Commit multiple file changes as one commit' do
success ::API::Entities::RepoCommitDetail
detail 'This feature was introduced in GitLab 8.13'
end
params do
requires :branch_name, type: String, desc: 'The name of branch'
requires :commit_message, type: String, desc: 'Commit message'
requires :actions, type: Array[Hash], desc: 'Actions to perform in commit'
optional :author_email, type: String, desc: 'Author email for commit'
optional :author_name, type: String, desc: 'Author name for commit'
end
post ":id/repository/commits" do
authorize! :push_code, user_project
attrs = declared_params.dup
branch = attrs.delete(:branch_name)
attrs.merge!(branch: branch, start_branch: branch, target_branch: branch)
attrs[:actions].map! do |action|
action[:action] = action[:action].to_sym
action[:file_path].slice!(0) if action[:file_path] && action[:file_path].start_with?('/')
action[:previous_path].slice!(0) if action[:previous_path] && action[:previous_path].start_with?('/')
action
end
result = ::Files::MultiService.new(user_project, current_user, attrs).execute
if result[:status] == :success
commit_detail = user_project.repository.commits(result[:result], limit: 1).first
present commit_detail, with: ::API::Entities::RepoCommitDetail
else
render_api_error!(result[:message], 400)
end
end
desc 'Get a specific commit of a project' do
success ::API::Entities::RepoCommitDetail
failure [[404, 'Not Found']]
end
params do
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
end
get ":id/repository/commits/:sha" do
commit = user_project.commit(params[:sha])
not_found! "Commit" unless commit
present commit, with: ::API::Entities::RepoCommitDetail
end
desc 'Get the diff for a specific commit of a project' do
failure [[404, 'Not Found']]
end
params do
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
end
get ":id/repository/commits/:sha/diff" do
commit = user_project.commit(params[:sha])
not_found! "Commit" unless commit
commit.raw_diffs.to_a
end
desc "Get a commit's comments" do
success ::API::Entities::CommitNote
failure [[404, 'Not Found']]
end
params do
use :pagination
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
end
get ':id/repository/commits/:sha/comments' do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
notes = Note.where(commit_id: commit.id).order(:created_at)
present paginate(notes), with: ::API::Entities::CommitNote
end
desc 'Cherry pick commit into a branch' do
detail 'This feature was introduced in GitLab 8.15'
success ::API::Entities::RepoCommit
end
params do
requires :sha, type: String, desc: 'A commit sha to be cherry picked'
requires :branch, type: String, desc: 'The name of the branch'
end
post ':id/repository/commits/:sha/cherry_pick' do
authorize! :push_code, user_project
commit = user_project.commit(params[:sha])
not_found!('Commit') unless commit
branch = user_project.repository.find_branch(params[:branch])
not_found!('Branch') unless branch
commit_params = {
commit: commit,
create_merge_request: false,
source_project: user_project,
source_branch: commit.cherry_pick_branch_name,
target_branch: params[:branch]
}
result = ::Commits::CherryPickService.new(user_project, current_user, commit_params).execute
if result[:status] == :success
branch = user_project.repository.find_branch(params[:branch])
present user_project.repository.commit(branch.dereferenced_target), with: ::API::Entities::RepoCommit
else
render_api_error!(result[:message], 400)
end
end
desc 'Post comment to commit' do
success ::API::Entities::CommitNote
end
params do
requires :sha, type: String, regexp: /\A\h{6,40}\z/, desc: "The commit's SHA"
requires :note, type: String, desc: 'The text of the comment'
optional :path, type: String, desc: 'The file path'
given :path do
requires :line, type: Integer, desc: 'The line number'
requires :line_type, type: String, values: ['new', 'old'], default: 'new', desc: 'The type of the line'
end
end
post ':id/repository/commits/:sha/comments' do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
opts = {
note: params[:note],
noteable_type: 'Commit',
commit_id: commit.id
}
if params[:path]
commit.raw_diffs(all_diffs: true).each do |diff|
next unless diff.new_path == params[:path]
lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
lines.each do |line|
next unless line.new_pos == params[:line] && line.type == params[:line_type]
break opts[:line_code] = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos)
end
break if opts[:line_code]
end
opts[:type] = LegacyDiffNote.name if opts[:line_code]
end
note = ::Notes::CreateService.new(user_project, current_user, opts).execute
if note.save
present note, with: ::API::Entities::CommitNote
else
render_api_error!("Failed to save note #{note.errors.messages}", 400)
end
end
end
end
end
end
module API
module V3
class Files < Grape::API
helpers do
def commit_params(attrs)
{
file_path: attrs[:file_path],
start_branch: attrs[:branch],
target_branch: attrs[:branch],
commit_message: attrs[:commit_message],
file_content: attrs[:content],
file_content_encoding: attrs[:encoding],
author_email: attrs[:author_email],
author_name: attrs[:author_name]
}
end
def commit_response(attrs)
{
file_path: attrs[:file_path],
branch: attrs[:branch]
}
end
params :simple_file_params do
requires :file_path, type: String, desc: 'The path to new file. Ex. lib/class.rb'
requires :branch_name, type: String, desc: 'The name of branch'
requires :commit_message, type: String, desc: 'Commit Message'
optional :author_email, type: String, desc: 'The email of the author'
optional :author_name, type: String, desc: 'The name of the author'
end
params :extended_file_params do
use :simple_file_params
requires :content, type: String, desc: 'File content'
optional :encoding, type: String, values: %w[base64], desc: 'File encoding'
end
end
params do
requires :id, type: String, desc: 'The project ID'
end
resource :projects do
desc 'Get a file from repository'
params do
requires :file_path, type: String, desc: 'The path to the file. Ex. lib/class.rb'
requires :ref, type: String, desc: 'The name of branch, tag, or commit'
end
get ":id/repository/files" do
authorize! :download_code, user_project
commit = user_project.commit(params[:ref])
not_found!('Commit') unless commit
repo = user_project.repository
blob = repo.blob_at(commit.sha, params[:file_path])
not_found!('File') unless blob
blob.load_all_data!(repo)
status(200)
{
file_name: blob.name,
file_path: blob.path,
size: blob.size,
encoding: "base64",
content: Base64.strict_encode64(blob.data),
ref: params[:ref],
blob_id: blob.id,
commit_id: commit.id,
last_commit_id: repo.last_commit_id_for_path(commit.sha, params[:file_path])
}
end
desc 'Create new file in repository'
params do
use :extended_file_params
end
post ":id/repository/files" do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
file_params[:branch] = file_params.delete(:branch_name)
result = ::Files::CreateService.new(user_project, current_user, commit_params(file_params)).execute
if result[:status] == :success
status(201)
commit_response(file_params)
else
render_api_error!(result[:message], 400)
end
end
desc 'Update existing file in repository'
params do
use :extended_file_params
end
put ":id/repository/files" do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
file_params[:branch] = file_params.delete(:branch_name)
result = ::Files::UpdateService.new(user_project, current_user, commit_params(file_params)).execute
if result[:status] == :success
status(200)
commit_response(file_params)
else
http_status = result[:http_status] || 400
render_api_error!(result[:message], http_status)
end
end
desc 'Delete an existing file in repository'
params do
use :simple_file_params
end
delete ":id/repository/files" do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
file_params[:branch] = file_params.delete(:branch_name)
result = ::Files::DestroyService.new(user_project, current_user, commit_params(file_params)).execute
if result[:status] == :success
status(200)
commit_response(file_params)
else
render_api_error!(result[:message], 400)
end
end
end
end
end
end
module API
module V3
class Subscriptions < Grape::API
before { authenticate! }
subscribable_types = {
'merge_request' => proc { |id| find_merge_request_with_access(id, :update_merge_request) },
'merge_requests' => proc { |id| find_merge_request_with_access(id, :update_merge_request) },
'issues' => proc { |id| find_project_issue(id) },
'labels' => proc { |id| find_project_label(id) },
}
params do
requires :id, type: String, desc: 'The ID of a project'
requires :subscribable_id, type: String, desc: 'The ID of a resource'
end
resource :projects do
subscribable_types.each do |type, finder|
type_singularized = type.singularize
entity_class = ::API::Entities.const_get(type_singularized.camelcase)
desc 'Subscribe to a resource' do
success entity_class
end
post ":id/#{type}/:subscribable_id/subscription" do
resource = instance_exec(params[:subscribable_id], &finder)
if resource.subscribed?(current_user, user_project)
not_modified!
else
resource.subscribe(current_user, user_project)
present resource, with: entity_class, current_user: current_user, project: user_project
end
end
desc 'Unsubscribe from a resource' do
success entity_class
end
delete ":id/#{type}/:subscribable_id/subscription" do
resource = instance_exec(params[:subscribable_id], &finder)
if !resource.subscribed?(current_user, user_project)
not_modified!
else
resource.unsubscribe(current_user, user_project)
present resource, with: entity_class, current_user: current_user, project: user_project
end
end
end
end
end
end
end
...@@ -32,7 +32,7 @@ module Gitlab ...@@ -32,7 +32,7 @@ module Gitlab
}, },
{ {
title: "Labels", title: "Labels",
value: @resource.labels.any? ? @resource.label_names : "_None_", value: @resource.labels.any? ? @resource.label_names.join(', ') : "_None_",
short: true short: true
}, },
{ {
......
...@@ -1085,23 +1085,15 @@ namespace :gitlab do ...@@ -1085,23 +1085,15 @@ namespace :gitlab do
client = Elasticsearch::Client.new(host: ApplicationSetting.current.elasticsearch_host, client = Elasticsearch::Client.new(host: ApplicationSetting.current.elasticsearch_host,
port: ApplicationSetting.current.elasticsearch_port) port: ApplicationSetting.current.elasticsearch_port)
print "Elasticsearch version 2.4.x? ... " print "Elasticsearch version 5.1.x? ... "
version = Gitlab::VersionInfo.parse(client.info["version"]["number"]) version = Gitlab::VersionInfo.parse(client.info["version"]["number"])
if version.major == 2 && version.minor == 4 if version.major == 5 && version.minor == 1
puts "yes (#{version})".color(:green) puts "yes (#{version})".color(:green)
else else
puts "no, you have #{version}".color(:red) puts "no, you have #{version}".color(:red)
end end
print "Elasticsearch has plugin delete-by-query installed? ... "
if client.cat.plugins.include?("delete-by-query")
puts "yes".color(:green)
else
puts "no".color(:red)
end
end end
def check_gitlab_geo_node(node) def check_gitlab_geo_node(node)
......
...@@ -26,6 +26,21 @@ describe Gitlab::ChatCommands::Presenters::IssueShow do ...@@ -26,6 +26,21 @@ describe Gitlab::ChatCommands::Presenters::IssueShow do
end end
end end
context 'with labels' do
let(:label) { create(:label, project: project, title: 'mep') }
let(:label1) { create(:label, project: project, title: 'mop') }
before do
issue.labels << [label, label1]
end
it 'shows the labels' do
labels = attachment[:fields].find { |f| f[:title] == 'Labels' }
expect(labels[:value]).to eq("mep, mop")
end
end
context 'confidential issue' do context 'confidential issue' do
let(:issue) { create(:issue, project: project) } let(:issue) { create(:issue, project: project) }
......
...@@ -285,7 +285,7 @@ describe API::Branches, api: true do ...@@ -285,7 +285,7 @@ describe API::Branches, api: true do
describe "POST /projects/:id/repository/branches" do describe "POST /projects/:id/repository/branches" do
it "creates a new branch" do it "creates a new branch" do
post api("/projects/#{project.id}/repository/branches", user), post api("/projects/#{project.id}/repository/branches", user),
branch_name: 'feature1', branch: 'feature1',
ref: branch_sha ref: branch_sha
expect(response).to have_http_status(201) expect(response).to have_http_status(201)
...@@ -296,14 +296,14 @@ describe API::Branches, api: true do ...@@ -296,14 +296,14 @@ describe API::Branches, api: true do
it "denies for user without push access" do it "denies for user without push access" do
post api("/projects/#{project.id}/repository/branches", user2), post api("/projects/#{project.id}/repository/branches", user2),
branch_name: branch_name, branch: branch_name,
ref: branch_sha ref: branch_sha
expect(response).to have_http_status(403) expect(response).to have_http_status(403)
end end
it 'returns 400 if branch name is invalid' do it 'returns 400 if branch name is invalid' do
post api("/projects/#{project.id}/repository/branches", user), post api("/projects/#{project.id}/repository/branches", user),
branch_name: 'new design', branch: 'new design',
ref: branch_sha ref: branch_sha
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('Branch name is invalid') expect(json_response['message']).to eq('Branch name is invalid')
...@@ -311,12 +311,12 @@ describe API::Branches, api: true do ...@@ -311,12 +311,12 @@ describe API::Branches, api: true do
it 'returns 400 if branch already exists' do it 'returns 400 if branch already exists' do
post api("/projects/#{project.id}/repository/branches", user), post api("/projects/#{project.id}/repository/branches", user),
branch_name: 'new_design1', branch: 'new_design1',
ref: branch_sha ref: branch_sha
expect(response).to have_http_status(201) expect(response).to have_http_status(201)
post api("/projects/#{project.id}/repository/branches", user), post api("/projects/#{project.id}/repository/branches", user),
branch_name: 'new_design1', branch: 'new_design1',
ref: branch_sha ref: branch_sha
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('Branch already exists') expect(json_response['message']).to eq('Branch already exists')
...@@ -324,7 +324,7 @@ describe API::Branches, api: true do ...@@ -324,7 +324,7 @@ describe API::Branches, api: true do
it 'returns 400 if ref name is invalid' do it 'returns 400 if ref name is invalid' do
post api("/projects/#{project.id}/repository/branches", user), post api("/projects/#{project.id}/repository/branches", user),
branch_name: 'new_design3', branch: 'new_design3',
ref: 'foo' ref: 'foo'
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
expect(json_response['message']).to eq('Invalid reference name') expect(json_response['message']).to eq('Invalid reference name')
...@@ -339,14 +339,14 @@ describe API::Branches, api: true do ...@@ -339,14 +339,14 @@ describe API::Branches, api: true do
it "removes branch" do it "removes branch" do
delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user) delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['branch_name']).to eq(branch_name) expect(json_response['branch']).to eq(branch_name)
end end
it "removes a branch with dots in the branch name" do it "removes a branch with dots in the branch name" do
delete api("/projects/#{project.id}/repository/branches/with.1.2.3", user) delete api("/projects/#{project.id}/repository/branches/with.1.2.3", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['branch_name']).to eq("with.1.2.3") expect(json_response['branch']).to eq("with.1.2.3")
end end
it 'returns 404 if branch not exists' do it 'returns 404 if branch not exists' do
......
...@@ -107,7 +107,7 @@ describe API::Commits, api: true do ...@@ -107,7 +107,7 @@ describe API::Commits, api: true do
let(:message) { 'Created file' } let(:message) { 'Created file' }
let!(:invalid_c_params) do let!(:invalid_c_params) do
{ {
branch_name: 'master', branch: 'master',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -120,7 +120,7 @@ describe API::Commits, api: true do ...@@ -120,7 +120,7 @@ describe API::Commits, api: true do
end end
let!(:valid_c_params) do let!(:valid_c_params) do
{ {
branch_name: 'master', branch: 'master',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -162,7 +162,7 @@ describe API::Commits, api: true do ...@@ -162,7 +162,7 @@ describe API::Commits, api: true do
let(:message) { 'Deleted file' } let(:message) { 'Deleted file' }
let!(:invalid_d_params) do let!(:invalid_d_params) do
{ {
branch_name: 'markdown', branch: 'markdown',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -174,7 +174,7 @@ describe API::Commits, api: true do ...@@ -174,7 +174,7 @@ describe API::Commits, api: true do
end end
let!(:valid_d_params) do let!(:valid_d_params) do
{ {
branch_name: 'markdown', branch: 'markdown',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -203,7 +203,7 @@ describe API::Commits, api: true do ...@@ -203,7 +203,7 @@ describe API::Commits, api: true do
let(:message) { 'Moved file' } let(:message) { 'Moved file' }
let!(:invalid_m_params) do let!(:invalid_m_params) do
{ {
branch_name: 'feature', branch: 'feature',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -217,7 +217,7 @@ describe API::Commits, api: true do ...@@ -217,7 +217,7 @@ describe API::Commits, api: true do
end end
let!(:valid_m_params) do let!(:valid_m_params) do
{ {
branch_name: 'feature', branch: 'feature',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -248,7 +248,7 @@ describe API::Commits, api: true do ...@@ -248,7 +248,7 @@ describe API::Commits, api: true do
let(:message) { 'Updated file' } let(:message) { 'Updated file' }
let!(:invalid_u_params) do let!(:invalid_u_params) do
{ {
branch_name: 'master', branch: 'master',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -261,7 +261,7 @@ describe API::Commits, api: true do ...@@ -261,7 +261,7 @@ describe API::Commits, api: true do
end end
let!(:valid_u_params) do let!(:valid_u_params) do
{ {
branch_name: 'master', branch: 'master',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -291,7 +291,7 @@ describe API::Commits, api: true do ...@@ -291,7 +291,7 @@ describe API::Commits, api: true do
let(:message) { 'Multiple actions' } let(:message) { 'Multiple actions' }
let!(:invalid_mo_params) do let!(:invalid_mo_params) do
{ {
branch_name: 'master', branch: 'master',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
...@@ -319,7 +319,7 @@ describe API::Commits, api: true do ...@@ -319,7 +319,7 @@ describe API::Commits, api: true do
end end
let!(:valid_mo_params) do let!(:valid_mo_params) do
{ {
branch_name: 'master', branch: 'master',
commit_message: message, commit_message: message,
actions: [ actions: [
{ {
......
...@@ -104,7 +104,7 @@ describe API::Files, api: true do ...@@ -104,7 +104,7 @@ describe API::Files, api: true do
let(:valid_params) do let(:valid_params) do
{ {
file_path: 'newfile.rb', file_path: 'newfile.rb',
branch_name: 'master', branch: 'master',
content: 'puts 8', content: 'puts 8',
commit_message: 'Added newfile' commit_message: 'Added newfile'
} }
...@@ -153,7 +153,7 @@ describe API::Files, api: true do ...@@ -153,7 +153,7 @@ describe API::Files, api: true do
let(:valid_params) do let(:valid_params) do
{ {
file_path: file_path, file_path: file_path,
branch_name: 'master', branch: 'master',
content: 'puts 8', content: 'puts 8',
commit_message: 'Changed file' commit_message: 'Changed file'
} }
...@@ -193,7 +193,7 @@ describe API::Files, api: true do ...@@ -193,7 +193,7 @@ describe API::Files, api: true do
let(:valid_params) do let(:valid_params) do
{ {
file_path: file_path, file_path: file_path,
branch_name: 'master', branch: 'master',
commit_message: 'Changed file' commit_message: 'Changed file'
} }
end end
...@@ -241,7 +241,7 @@ describe API::Files, api: true do ...@@ -241,7 +241,7 @@ describe API::Files, api: true do
let(:put_params) do let(:put_params) do
{ {
file_path: file_path, file_path: file_path,
branch_name: 'master', branch: 'master',
content: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=', content: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=',
commit_message: 'Binary file with a \n should not be touched', commit_message: 'Binary file with a \n should not be touched',
encoding: 'base64' encoding: 'base64'
......
...@@ -1266,55 +1266,55 @@ describe API::Issues, api: true do ...@@ -1266,55 +1266,55 @@ describe API::Issues, api: true do
end end
end end
describe 'POST :id/issues/:issue_id/subscription' do describe 'POST :id/issues/:issue_id/subscribe' do
it 'subscribes to an issue' do it 'subscribes to an issue' do
post api("/projects/#{project.id}/issues/#{issue.id}/subscription", user2) post api("/projects/#{project.id}/issues/#{issue.id}/subscribe", user2)
expect(response).to have_http_status(201) expect(response).to have_http_status(201)
expect(json_response['subscribed']).to eq(true) expect(json_response['subscribed']).to eq(true)
end end
it 'returns 304 if already subscribed' do it 'returns 304 if already subscribed' do
post api("/projects/#{project.id}/issues/#{issue.id}/subscription", user) post api("/projects/#{project.id}/issues/#{issue.id}/subscribe", user)
expect(response).to have_http_status(304) expect(response).to have_http_status(304)
end end
it 'returns 404 if the issue is not found' do it 'returns 404 if the issue is not found' do
post api("/projects/#{project.id}/issues/123/subscription", user) post api("/projects/#{project.id}/issues/123/subscribe", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
it 'returns 404 if the issue is confidential' do it 'returns 404 if the issue is confidential' do
post api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscription", non_member) post api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscribe", non_member)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
describe 'DELETE :id/issues/:issue_id/subscription' do describe 'POST :id/issues/:issue_id/unsubscribe' do
it 'unsubscribes from an issue' do it 'unsubscribes from an issue' do
delete api("/projects/#{project.id}/issues/#{issue.id}/subscription", user) post api("/projects/#{project.id}/issues/#{issue.id}/unsubscribe", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(201)
expect(json_response['subscribed']).to eq(false) expect(json_response['subscribed']).to eq(false)
end end
it 'returns 304 if not subscribed' do it 'returns 304 if not subscribed' do
delete api("/projects/#{project.id}/issues/#{issue.id}/subscription", user2) post api("/projects/#{project.id}/issues/#{issue.id}/unsubscribe", user2)
expect(response).to have_http_status(304) expect(response).to have_http_status(304)
end end
it 'returns 404 if the issue is not found' do it 'returns 404 if the issue is not found' do
delete api("/projects/#{project.id}/issues/123/subscription", user) post api("/projects/#{project.id}/issues/123/unsubscribe", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
it 'returns 404 if the issue is confidential' do it 'returns 404 if the issue is confidential' do
delete api("/projects/#{project.id}/issues/#{confidential_issue.id}/subscription", non_member) post api("/projects/#{project.id}/issues/#{confidential_issue.id}/unsubscribe", non_member)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
......
...@@ -318,10 +318,10 @@ describe API::Labels, api: true do ...@@ -318,10 +318,10 @@ describe API::Labels, api: true do
end end
end end
describe "POST /projects/:id/labels/:label_id/subscription" do describe "POST /projects/:id/labels/:label_id/subscribe" do
context "when label_id is a label title" do context "when label_id is a label title" do
it "subscribes to the label" do it "subscribes to the label" do
post api("/projects/#{project.id}/labels/#{label1.title}/subscription", user) post api("/projects/#{project.id}/labels/#{label1.title}/subscribe", user)
expect(response).to have_http_status(201) expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(label1.title) expect(json_response["name"]).to eq(label1.title)
...@@ -331,7 +331,7 @@ describe API::Labels, api: true do ...@@ -331,7 +331,7 @@ describe API::Labels, api: true do
context "when label_id is a label ID" do context "when label_id is a label ID" do
it "subscribes to the label" do it "subscribes to the label" do
post api("/projects/#{project.id}/labels/#{label1.id}/subscription", user) post api("/projects/#{project.id}/labels/#{label1.id}/subscribe", user)
expect(response).to have_http_status(201) expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(label1.title) expect(json_response["name"]).to eq(label1.title)
...@@ -343,7 +343,7 @@ describe API::Labels, api: true do ...@@ -343,7 +343,7 @@ describe API::Labels, api: true do
before { label1.subscribe(user, project) } before { label1.subscribe(user, project) }
it "returns 304" do it "returns 304" do
post api("/projects/#{project.id}/labels/#{label1.id}/subscription", user) post api("/projects/#{project.id}/labels/#{label1.id}/subscribe", user)
expect(response).to have_http_status(304) expect(response).to have_http_status(304)
end end
...@@ -351,21 +351,21 @@ describe API::Labels, api: true do ...@@ -351,21 +351,21 @@ describe API::Labels, api: true do
context "when label ID is not found" do context "when label ID is not found" do
it "returns 404 error" do it "returns 404 error" do
post api("/projects/#{project.id}/labels/1234/subscription", user) post api("/projects/#{project.id}/labels/1234/subscribe", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
end end
describe "DELETE /projects/:id/labels/:label_id/subscription" do describe "POST /projects/:id/labels/:label_id/unsubscribe" do
before { label1.subscribe(user, project) } before { label1.subscribe(user, project) }
context "when label_id is a label title" do context "when label_id is a label title" do
it "unsubscribes from the label" do it "unsubscribes from the label" do
delete api("/projects/#{project.id}/labels/#{label1.title}/subscription", user) post api("/projects/#{project.id}/labels/#{label1.title}/unsubscribe", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(label1.title) expect(json_response["name"]).to eq(label1.title)
expect(json_response["subscribed"]).to be_falsey expect(json_response["subscribed"]).to be_falsey
end end
...@@ -373,9 +373,9 @@ describe API::Labels, api: true do ...@@ -373,9 +373,9 @@ describe API::Labels, api: true do
context "when label_id is a label ID" do context "when label_id is a label ID" do
it "unsubscribes from the label" do it "unsubscribes from the label" do
delete api("/projects/#{project.id}/labels/#{label1.id}/subscription", user) post api("/projects/#{project.id}/labels/#{label1.id}/unsubscribe", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(label1.title) expect(json_response["name"]).to eq(label1.title)
expect(json_response["subscribed"]).to be_falsey expect(json_response["subscribed"]).to be_falsey
end end
...@@ -385,7 +385,7 @@ describe API::Labels, api: true do ...@@ -385,7 +385,7 @@ describe API::Labels, api: true do
before { label1.unsubscribe(user, project) } before { label1.unsubscribe(user, project) }
it "returns 304" do it "returns 304" do
delete api("/projects/#{project.id}/labels/#{label1.id}/subscription", user) post api("/projects/#{project.id}/labels/#{label1.id}/unsubscribe", user)
expect(response).to have_http_status(304) expect(response).to have_http_status(304)
end end
...@@ -393,7 +393,7 @@ describe API::Labels, api: true do ...@@ -393,7 +393,7 @@ describe API::Labels, api: true do
context "when label ID is not found" do context "when label ID is not found" do
it "returns 404 error" do it "returns 404 error" do
delete api("/projects/#{project.id}/labels/1234/subscription", user) post api("/projects/#{project.id}/labels/1234/unsubscribe", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
......
...@@ -740,22 +740,22 @@ describe API::MergeRequests, api: true do ...@@ -740,22 +740,22 @@ describe API::MergeRequests, api: true do
end end
end end
describe 'POST :id/merge_requests/:merge_request_id/subscription' do describe 'POST :id/merge_requests/:merge_request_id/subscribe' do
it 'subscribes to a merge request' do it 'subscribes to a merge request' do
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", admin) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscribe", admin)
expect(response).to have_http_status(201) expect(response).to have_http_status(201)
expect(json_response['subscribed']).to eq(true) expect(json_response['subscribed']).to eq(true)
end end
it 'returns 304 if already subscribed' do it 'returns 304 if already subscribed' do
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", user) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscribe", user)
expect(response).to have_http_status(304) expect(response).to have_http_status(304)
end end
it 'returns 404 if the merge request is not found' do it 'returns 404 if the merge request is not found' do
post api("/projects/#{project.id}/merge_requests/123/subscription", user) post api("/projects/#{project.id}/merge_requests/123/subscribe", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
...@@ -764,28 +764,28 @@ describe API::MergeRequests, api: true do ...@@ -764,28 +764,28 @@ describe API::MergeRequests, api: true do
guest = create(:user) guest = create(:user)
project.team << [guest, :guest] project.team << [guest, :guest]
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", guest) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscribe", guest)
expect(response).to have_http_status(403) expect(response).to have_http_status(403)
end end
end end
describe 'DELETE :id/merge_requests/:merge_request_id/subscription' do describe 'POST :id/merge_requests/:merge_request_id/unsubscribe' do
it 'unsubscribes from a merge request' do it 'unsubscribes from a merge request' do
delete api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", user) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/unsubscribe", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(201)
expect(json_response['subscribed']).to eq(false) expect(json_response['subscribed']).to eq(false)
end end
it 'returns 304 if not subscribed' do it 'returns 304 if not subscribed' do
delete api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", admin) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/unsubscribe", admin)
expect(response).to have_http_status(304) expect(response).to have_http_status(304)
end end
it 'returns 404 if the merge request is not found' do it 'returns 404 if the merge request is not found' do
post api("/projects/#{project.id}/merge_requests/123/subscription", user) post api("/projects/#{project.id}/merge_requests/123/unsubscribe", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
...@@ -794,7 +794,7 @@ describe API::MergeRequests, api: true do ...@@ -794,7 +794,7 @@ describe API::MergeRequests, api: true do
guest = create(:user) guest = create(:user)
project.team << [guest, :guest] project.team << [guest, :guest]
delete api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscription", guest) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/unsubscribe", guest)
expect(response).to have_http_status(403) expect(response).to have_http_status(403)
end end
......
require 'spec_helper'
require 'mime/types'
describe API::V3::Commits, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
let!(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
let!(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
let!(:another_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'another comment on a commit') }
before { project.team << [user, :reporter] }
describe "List repository commits" do
context "authorized user" do
before { project.team << [user2, :reporter] }
it "returns project commits" do
commit = project.repository.commit
get v3_api("/projects/#{project.id}/repository/commits", user)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.first['id']).to eq(commit.id)
expect(json_response.first['committer_name']).to eq(commit.committer_name)
expect(json_response.first['committer_email']).to eq(commit.committer_email)
end
end
context "unauthorized user" do
it "does not return project commits" do
get v3_api("/projects/#{project.id}/repository/commits")
expect(response).to have_http_status(401)
end
end
context "since optional parameter" do
it "returns project commits since provided parameter" do
commits = project.repository.commits("master")
since = commits.second.created_at
get v3_api("/projects/#{project.id}/repository/commits?since=#{since.utc.iso8601}", user)
expect(json_response.size).to eq 2
expect(json_response.first["id"]).to eq(commits.first.id)
expect(json_response.second["id"]).to eq(commits.second.id)
end
end
context "until optional parameter" do
it "returns project commits until provided parameter" do
commits = project.repository.commits("master")
before = commits.second.created_at
get v3_api("/projects/#{project.id}/repository/commits?until=#{before.utc.iso8601}", user)
if commits.size >= 20
expect(json_response.size).to eq(20)
else
expect(json_response.size).to eq(commits.size - 1)
end
expect(json_response.first["id"]).to eq(commits.second.id)
expect(json_response.second["id"]).to eq(commits.third.id)
end
end
context "invalid xmlschema date parameters" do
it "returns an invalid parameter error message" do
get v3_api("/projects/#{project.id}/repository/commits?since=invalid-date", user)
expect(response).to have_http_status(400)
expect(json_response['error']).to eq('since is invalid')
end
end
context "path optional parameter" do
it "returns project commits matching provided path parameter" do
path = 'files/ruby/popen.rb'
get v3_api("/projects/#{project.id}/repository/commits?path=#{path}", user)
expect(json_response.size).to eq(3)
expect(json_response.first["id"]).to eq("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
end
end
end
describe "Create a commit with multiple files and actions" do
let!(:url) { "/projects/#{project.id}/repository/commits" }
it 'returns a 403 unauthorized for user without permissions' do
post v3_api(url, user2)
expect(response).to have_http_status(403)
end
it 'returns a 400 bad request if no params are given' do
post v3_api(url, user)
expect(response).to have_http_status(400)
end
context :create do
let(:message) { 'Created file' }
let!(:invalid_c_params) do
{
branch_name: 'master',
commit_message: message,
actions: [
{
action: 'create',
file_path: 'files/ruby/popen.rb',
content: 'puts 8'
}
]
}
end
let!(:valid_c_params) do
{
branch_name: 'master',
commit_message: message,
actions: [
{
action: 'create',
file_path: 'foo/bar/baz.txt',
content: 'puts 8'
}
]
}
end
it 'a new file in project repo' do
post v3_api(url, user), valid_c_params
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(message)
expect(json_response['committer_name']).to eq(user.name)
expect(json_response['committer_email']).to eq(user.email)
end
it 'returns a 400 bad request if file exists' do
post v3_api(url, user), invalid_c_params
expect(response).to have_http_status(400)
end
context 'with project path in URL' do
let(:url) { "/projects/#{project.namespace.path}%2F#{project.path}/repository/commits" }
it 'a new file in project repo' do
post v3_api(url, user), valid_c_params
expect(response).to have_http_status(201)
end
end
end
context :delete do
let(:message) { 'Deleted file' }
let!(:invalid_d_params) do
{
branch_name: 'markdown',
commit_message: message,
actions: [
{
action: 'delete',
file_path: 'doc/api/projects.md'
}
]
}
end
let!(:valid_d_params) do
{
branch_name: 'markdown',
commit_message: message,
actions: [
{
action: 'delete',
file_path: 'doc/api/users.md'
}
]
}
end
it 'an existing file in project repo' do
post v3_api(url, user), valid_d_params
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(message)
end
it 'returns a 400 bad request if file does not exist' do
post v3_api(url, user), invalid_d_params
expect(response).to have_http_status(400)
end
end
context :move do
let(:message) { 'Moved file' }
let!(:invalid_m_params) do
{
branch_name: 'feature',
commit_message: message,
actions: [
{
action: 'move',
file_path: 'CHANGELOG',
previous_path: 'VERSION',
content: '6.7.0.pre'
}
]
}
end
let!(:valid_m_params) do
{
branch_name: 'feature',
commit_message: message,
actions: [
{
action: 'move',
file_path: 'VERSION.txt',
previous_path: 'VERSION',
content: '6.7.0.pre'
}
]
}
end
it 'an existing file in project repo' do
post v3_api(url, user), valid_m_params
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(message)
end
it 'returns a 400 bad request if file does not exist' do
post v3_api(url, user), invalid_m_params
expect(response).to have_http_status(400)
end
end
context :update do
let(:message) { 'Updated file' }
let!(:invalid_u_params) do
{
branch_name: 'master',
commit_message: message,
actions: [
{
action: 'update',
file_path: 'foo/bar.baz',
content: 'puts 8'
}
]
}
end
let!(:valid_u_params) do
{
branch_name: 'master',
commit_message: message,
actions: [
{
action: 'update',
file_path: 'files/ruby/popen.rb',
content: 'puts 8'
}
]
}
end
it 'an existing file in project repo' do
post v3_api(url, user), valid_u_params
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(message)
end
it 'returns a 400 bad request if file does not exist' do
post v3_api(url, user), invalid_u_params
expect(response).to have_http_status(400)
end
end
context "multiple operations" do
let(:message) { 'Multiple actions' }
let!(:invalid_mo_params) do
{
branch_name: 'master',
commit_message: message,
actions: [
{
action: 'create',
file_path: 'files/ruby/popen.rb',
content: 'puts 8'
},
{
action: 'delete',
file_path: 'doc/v3_api/projects.md'
},
{
action: 'move',
file_path: 'CHANGELOG',
previous_path: 'VERSION',
content: '6.7.0.pre'
},
{
action: 'update',
file_path: 'foo/bar.baz',
content: 'puts 8'
}
]
}
end
let!(:valid_mo_params) do
{
branch_name: 'master',
commit_message: message,
actions: [
{
action: 'create',
file_path: 'foo/bar/baz.txt',
content: 'puts 8'
},
{
action: 'delete',
file_path: 'Gemfile.zip'
},
{
action: 'move',
file_path: 'VERSION.txt',
previous_path: 'VERSION',
content: '6.7.0.pre'
},
{
action: 'update',
file_path: 'files/ruby/popen.rb',
content: 'puts 8'
}
]
}
end
it 'are commited as one in project repo' do
post v3_api(url, user), valid_mo_params
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(message)
end
it 'return a 400 bad request if there are any issues' do
post v3_api(url, user), invalid_mo_params
expect(response).to have_http_status(400)
end
end
end
describe "Get a single commit" do
context "authorized user" do
it "returns a commit by sha" do
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
expect(response).to have_http_status(200)
expect(json_response['id']).to eq(project.repository.commit.id)
expect(json_response['title']).to eq(project.repository.commit.title)
expect(json_response['stats']['additions']).to eq(project.repository.commit.stats.additions)
expect(json_response['stats']['deletions']).to eq(project.repository.commit.stats.deletions)
expect(json_response['stats']['total']).to eq(project.repository.commit.stats.total)
end
it "returns a 404 error if not found" do
get v3_api("/projects/#{project.id}/repository/commits/invalid_sha", user)
expect(response).to have_http_status(404)
end
it "returns nil for commit without CI" do
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
expect(response).to have_http_status(200)
expect(json_response['status']).to be_nil
end
it "returns status for CI" do
pipeline = project.ensure_pipeline('master', project.repository.commit.sha)
pipeline.update(status: 'success')
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
expect(response).to have_http_status(200)
expect(json_response['status']).to eq(pipeline.status)
end
it "returns status for CI when pipeline is created" do
project.ensure_pipeline('master', project.repository.commit.sha)
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
expect(response).to have_http_status(200)
expect(json_response['status']).to eq("created")
end
end
context "unauthorized user" do
it "does not return the selected commit" do
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}")
expect(response).to have_http_status(401)
end
end
end
describe "Get the diff of a commit" do
context "authorized user" do
before { project.team << [user2, :reporter] }
it "returns the diff of the selected commit" do
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.length).to be >= 1
expect(json_response.first.keys).to include "diff"
end
it "returns a 404 error if invalid commit" do
get v3_api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user)
expect(response).to have_http_status(404)
end
end
context "unauthorized user" do
it "does not return the diff of the selected commit" do
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff")
expect(response).to have_http_status(401)
end
end
end
describe 'Get the comments of a commit' do
context 'authorized user' do
it 'returns merge_request comments' do
get v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.length).to eq(2)
expect(json_response.first['note']).to eq('a comment on a commit')
expect(json_response.first['author']['id']).to eq(user.id)
end
it 'returns a 404 error if merge_request_id not found' do
get v3_api("/projects/#{project.id}/repository/commits/1234ab/comments", user)
expect(response).to have_http_status(404)
end
end
context 'unauthorized user' do
it 'does not return the diff of the selected commit' do
get v3_api("/projects/#{project.id}/repository/commits/1234ab/comments")
expect(response).to have_http_status(401)
end
end
end
describe 'POST :id/repository/commits/:sha/cherry_pick' do
let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
context 'authorized user' do
it 'cherry picks a commit' do
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'master'
expect(response).to have_http_status(201)
expect(json_response['title']).to eq(master_pickable_commit.title)
expect(json_response['message']).to eq(master_pickable_commit.message)
expect(json_response['author_name']).to eq(master_pickable_commit.author_name)
expect(json_response['committer_name']).to eq(user.name)
end
it 'returns 400 if commit is already included in the target branch' do
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'markdown'
expect(response).to have_http_status(400)
expect(json_response['message']).to eq('Sorry, we cannot cherry-pick this commit automatically.
A cherry-pick may have already been performed with this commit, or a more recent commit may have updated some of its content.')
end
it 'returns 400 if you are not allowed to push to the target branch' do
project.team << [user2, :developer]
protected_branch = create(:protected_branch, project: project, name: 'feature')
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user2), branch: protected_branch.name
expect(response).to have_http_status(400)
expect(json_response['message']).to eq('You are not allowed to push into this branch')
end
it 'returns 400 for missing parameters' do
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
expect(response).to have_http_status(400)
expect(json_response['error']).to eq('branch is missing')
end
it 'returns 404 if commit is not found' do
post v3_api("/projects/#{project.id}/repository/commits/abcd0123/cherry_pick", user), branch: 'master'
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Commit Not Found')
end
it 'returns 404 if branch is not found' do
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'foo'
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Branch Not Found')
end
it 'returns 400 for missing parameters' do
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
expect(response).to have_http_status(400)
expect(json_response['error']).to eq('branch is missing')
end
end
context 'unauthorized user' do
it 'does not cherry pick the commit' do
post v3_api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick"), branch: 'master'
expect(response).to have_http_status(401)
end
end
end
describe 'Post comment to commit' do
context 'authorized user' do
it 'returns comment' do
post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment'
expect(response).to have_http_status(201)
expect(json_response['note']).to eq('My comment')
expect(json_response['path']).to be_nil
expect(json_response['line']).to be_nil
expect(json_response['line_type']).to be_nil
end
it 'returns the inline comment' do
post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.raw_diffs.first.new_path, line: 1, line_type: 'new'
expect(response).to have_http_status(201)
expect(json_response['note']).to eq('My comment')
expect(json_response['path']).to eq(project.repository.commit.raw_diffs.first.new_path)
expect(json_response['line']).to eq(1)
expect(json_response['line_type']).to eq('new')
end
it 'returns 400 if note is missing' do
post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user)
expect(response).to have_http_status(400)
end
it 'returns 404 if note is attached to non existent commit' do
post v3_api("/projects/#{project.id}/repository/commits/1234ab/comments", user), note: 'My comment'
expect(response).to have_http_status(404)
end
end
context 'unauthorized user' do
it 'does not return the diff of the selected commit' do
post v3_api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments")
expect(response).to have_http_status(401)
end
end
end
end
require 'spec_helper'
describe API::V3::Files, api: true do
include ApiHelpers
let(:user) { create(:user) }
let!(:project) { create(:project, :repository, namespace: user.namespace ) }
let(:guest) { create(:user) { |u| project.add_guest(u) } }
let(:file_path) { 'files/ruby/popen.rb' }
let(:params) do
{
file_path: file_path,
ref: 'master'
}
end
let(:author_email) { FFaker::Internet.email }
# I have to remove periods from the end of the name
# This happened when the user's name had a suffix (i.e. "Sr.")
# This seems to be what git does under the hood. For example, this commit:
#
# $ git commit --author='Foo Sr. <foo@example.com>' -m 'Where's my trailing period?'
#
# results in this:
#
# $ git show --pretty
# ...
# Author: Foo Sr <foo@example.com>
# ...
let(:author_name) { FFaker::Name.name.chomp("\.") }
before { project.team << [user, :developer] }
describe "GET /projects/:id/repository/files" do
let(:route) { "/projects/#{project.id}/repository/files" }
shared_examples_for 'repository files' do
it "returns file info" do
get v3_api(route, current_user), params
expect(response).to have_http_status(200)
expect(json_response['file_path']).to eq(file_path)
expect(json_response['file_name']).to eq('popen.rb')
expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
end
context 'when no params are given' do
it_behaves_like '400 response' do
let(:request) { get v3_api(route, current_user) }
end
end
context 'when file_path does not exist' do
let(:params) do
{
file_path: 'app/models/application.rb',
ref: 'master',
}
end
it_behaves_like '404 response' do
let(:request) { get v3_api(route, current_user), params }
let(:message) { '404 File Not Found' }
end
end
context 'when repository is disabled' do
include_context 'disabled repository'
it_behaves_like '403 response' do
let(:request) { get v3_api(route, current_user), params }
end
end
end
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository files' do
let(:project) { create(:project, :public) }
let(:current_user) { nil }
end
end
context 'when unauthenticated', 'and project is private' do
it_behaves_like '404 response' do
let(:request) { get v3_api(route), params }
let(:message) { '404 Project Not Found' }
end
end
context 'when authenticated', 'as a developer' do
it_behaves_like 'repository files' do
let(:current_user) { user }
end
end
context 'when authenticated', 'as a guest' do
it_behaves_like '403 response' do
let(:request) { get v3_api(route, guest), params }
end
end
end
describe "POST /projects/:id/repository/files" do
let(:valid_params) do
{
file_path: 'newfile.rb',
branch_name: 'master',
content: 'puts 8',
commit_message: 'Added newfile'
}
end
it "creates a new file in project repo" do
post v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(201)
expect(json_response['file_path']).to eq('newfile.rb')
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(user.email)
expect(last_commit.author_name).to eq(user.name)
end
it "returns a 400 bad request if no params given" do
post v3_api("/projects/#{project.id}/repository/files", user)
expect(response).to have_http_status(400)
end
it "returns a 400 if editor fails to create file" do
allow_any_instance_of(Repository).to receive(:commit_file).
and_return(false)
post v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(400)
end
context "when specifying an author" do
it "creates a new file with the specified author" do
valid_params.merge!(author_email: author_email, author_name: author_name)
post v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(201)
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(author_email)
expect(last_commit.author_name).to eq(author_name)
end
end
end
describe "PUT /projects/:id/repository/files" do
let(:valid_params) do
{
file_path: file_path,
branch_name: 'master',
content: 'puts 8',
commit_message: 'Changed file'
}
end
it "updates existing file in project repo" do
put v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(200)
expect(json_response['file_path']).to eq(file_path)
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(user.email)
expect(last_commit.author_name).to eq(user.name)
end
it "returns a 400 bad request if no params given" do
put v3_api("/projects/#{project.id}/repository/files", user)
expect(response).to have_http_status(400)
end
context "when specifying an author" do
it "updates a file with the specified author" do
valid_params.merge!(author_email: author_email, author_name: author_name, content: "New content")
put v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(200)
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(author_email)
expect(last_commit.author_name).to eq(author_name)
end
end
end
describe "DELETE /projects/:id/repository/files" do
let(:valid_params) do
{
file_path: file_path,
branch_name: 'master',
commit_message: 'Changed file'
}
end
it "deletes existing file in project repo" do
delete v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(200)
expect(json_response['file_path']).to eq(file_path)
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(user.email)
expect(last_commit.author_name).to eq(user.name)
end
it "returns a 400 bad request if no params given" do
delete v3_api("/projects/#{project.id}/repository/files", user)
expect(response).to have_http_status(400)
end
it "returns a 400 if fails to create file" do
allow_any_instance_of(Repository).to receive(:remove_file).and_return(false)
delete v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(400)
end
context "when specifying an author" do
it "removes a file with the specified author" do
valid_params.merge!(author_email: author_email, author_name: author_name)
delete v3_api("/projects/#{project.id}/repository/files", user), valid_params
expect(response).to have_http_status(200)
last_commit = project.repository.commit.raw
expect(last_commit.author_email).to eq(author_email)
expect(last_commit.author_name).to eq(author_name)
end
end
end
describe "POST /projects/:id/repository/files with binary file" do
let(:file_path) { 'test.bin' }
let(:put_params) do
{
file_path: file_path,
branch_name: 'master',
content: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=',
commit_message: 'Binary file with a \n should not be touched',
encoding: 'base64'
}
end
let(:get_params) do
{
file_path: file_path,
ref: 'master',
}
end
before do
post v3_api("/projects/#{project.id}/repository/files", user), put_params
end
it "remains unchanged" do
get v3_api("/projects/#{project.id}/repository/files", user), get_params
expect(response).to have_http_status(200)
expect(json_response['file_path']).to eq(file_path)
expect(json_response['file_name']).to eq(file_path)
expect(json_response['content']).to eq(put_params[:content])
end
end
end
...@@ -67,4 +67,86 @@ describe API::V3::Labels, api: true do ...@@ -67,4 +67,86 @@ describe API::V3::Labels, api: true do
expect(priority_label_response['subscribed']).to be_falsey expect(priority_label_response['subscribed']).to be_falsey
end end
end end
describe "POST /projects/:id/labels/:label_id/subscription" do
context "when label_id is a label title" do
it "subscribes to the label" do
post v3_api("/projects/#{project.id}/labels/#{label1.title}/subscription", user)
expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(label1.title)
expect(json_response["subscribed"]).to be_truthy
end
end
context "when label_id is a label ID" do
it "subscribes to the label" do
post v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(label1.title)
expect(json_response["subscribed"]).to be_truthy
end
end
context "when user is already subscribed to label" do
before { label1.subscribe(user, project) }
it "returns 304" do
post v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
expect(response).to have_http_status(304)
end
end
context "when label ID is not found" do
it "returns 404 error" do
post v3_api("/projects/#{project.id}/labels/1234/subscription", user)
expect(response).to have_http_status(404)
end
end
end
describe "DELETE /projects/:id/labels/:label_id/subscription" do
before { label1.subscribe(user, project) }
context "when label_id is a label title" do
it "unsubscribes from the label" do
delete v3_api("/projects/#{project.id}/labels/#{label1.title}/subscription", user)
expect(response).to have_http_status(200)
expect(json_response["name"]).to eq(label1.title)
expect(json_response["subscribed"]).to be_falsey
end
end
context "when label_id is a label ID" do
it "unsubscribes from the label" do
delete v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
expect(response).to have_http_status(200)
expect(json_response["name"]).to eq(label1.title)
expect(json_response["subscribed"]).to be_falsey
end
end
context "when user is already unsubscribed from label" do
before { label1.unsubscribe(user, project) }
it "returns 304" do
delete v3_api("/projects/#{project.id}/labels/#{label1.id}/subscription", user)
expect(response).to have_http_status(304)
end
end
context "when label ID is not found" do
it "returns 404 error" do
delete v3_api("/projects/#{project.id}/labels/1234/subscription", user)
expect(response).to have_http_status(404)
end
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment