Commit 795c9f22 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'master' into refactor/ci-config-move-job-entries

* master: (321 commits)
  Fix the Sentry spam from CSP violations by disabling it.
  Limit git rev-list output count to one in forced push check
  Ensure Owners are included in the scope for authorized_projects
  Fix alignment of icons on project page
  Fix ci_status_helper_spec to look for new SVGs
  use 2.0.5, actually (2.0.4 was a bad release)
  upgrade rouge to 2.0.4
  Fix help page paths to make sure shortcuts and the UI help page work.
  fixes an issue cause by a bad merge
  Vertically align status icon within table
  Add new icons for every CI status
  Add global style for running icon
  Align running icon in merge request
  Add new running icon; add a bunch of styles to get svg to match existing fa icons
  Improve code design
  Fix broken builds_for_ref
  Move when tests before to make it no conflict with manual-actions
  Use value of `yaml_variables` and `when` from config_processor if undefined
  Add CHANGELOG entry
  CHANGELOG item
  ...

Conflicts:
	lib/ci/gitlab_ci_yaml_processor.rb
	spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
parents bb8bf642 79b02e40
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.
v 8.11.0 (unreleased)
- Fix of 'Commits being passed to custom hooks are already reachable when using the UI'
- Limit git rev-list output count to one in forced push check
v 8.10.0 (unreleased) v 8.10.0 (unreleased)
- Fix profile activity heatmap to show correct day name (eanplatter)
- Expose {should,force}_remove_source_branch (Ben Boeckel) - Expose {should,force}_remove_source_branch (Ben Boeckel)
- Add the functionality to be able to rename a file. !5049 (tiagonbotelho)
- Disable PostgreSQL statement timeout during migrations - Disable PostgreSQL statement timeout during migrations
- Fix projects dropdown loading performance with a simplified api cal. !5113 (tiagonbotelho) - Fix projects dropdown loading performance with a simplified api cal. !5113 (tiagonbotelho)
- Fix commit builds API, return all builds for all pipelines for given commit. !4849 - Fix commit builds API, return all builds for all pipelines for given commit. !4849
...@@ -16,25 +21,34 @@ v 8.10.0 (unreleased) ...@@ -16,25 +21,34 @@ v 8.10.0 (unreleased)
- Align flash messages with left side of page content !4959 (winniehell) - Align flash messages with left side of page content !4959 (winniehell)
- Display tooltip for "Copy to Clipboard" button !5164 (winniehell) - Display tooltip for "Copy to Clipboard" button !5164 (winniehell)
- Use default cursor for table header of project files !5165 (winniehell) - Use default cursor for table header of project files !5165 (winniehell)
- Store when and yaml variables in builds table
- Display last commit of deleted branch in push events !4699 (winniehell) - Display last commit of deleted branch in push events !4699 (winniehell)
- Escape file extension when parsing search results !5141 (winniehell) - Escape file extension when parsing search results !5141 (winniehell)
- Apply the trusted_proxies config to the rack request object for use with rack_attack - Apply the trusted_proxies config to the rack request object for use with rack_attack
- Upgrade to Rails 4.2.7. !5236 - Upgrade to Rails 4.2.7. !5236
- Allow to pull code with deploy key from public projects
- Add Sidekiq queue duration to transaction metrics. - Add Sidekiq queue duration to transaction metrics.
- Add a new column `artifacts_size` to table `ci_builds` !4964 - Add a new column `artifacts_size` to table `ci_builds` !4964
- Let Workhorse serve format-patch diffs - Let Workhorse serve format-patch diffs
- Display tooltip for mentioned users and groups !5261 (winniehell) - Display tooltip for mentioned users and groups !5261 (winniehell)
- Allow build email service to be tested
- Added day name to contribution calendar tooltips - Added day name to contribution calendar tooltips
- Make images fit to the size of the viewport !4810 - Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell) - Fix check for New Branch button on Issue page !4630 (winniehell)
- Fix GFM autocomplete not working on wiki pages
- Fix MR-auto-close text added to description. !4836 - Fix MR-auto-close text added to description. !4836
- Support U2F devices in Firefox. !5177 - Support U2F devices in Firefox. !5177
- Fix issue, preventing users w/o push access to sort tags !5105 (redetection) - Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
- Add Spring EmojiOne updates. - Add Spring EmojiOne updates.
- Added Rake task for tracking deployments !5320
- Fix fetching LFS objects for private CI projects
- Add the new 2016 Emoji! Adds 72 new emoji including bacon, facepalm, and selfie. !5237
- Add syntax for multiline blockquote using `>>>` fence !3954 - Add syntax for multiline blockquote using `>>>` fence !3954
- Fix viewing notification settings when a project is pending deletion - Fix viewing notification settings when a project is pending deletion
- Updated compare dropdown menus to use GL dropdown - Updated compare dropdown menus to use GL dropdown
- Redirects back to issue after clicking login link
- Eager load award emoji on notes - Eager load award emoji on notes
- Allow to define manual actions/builds on Pipelines and Environments
- Fix pagination when sorting by columns with lots of ties (like priority) - Fix pagination when sorting by columns with lots of ties (like priority)
- The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020 - The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020
- Updated project header design - Updated project header design
...@@ -47,21 +61,28 @@ v 8.10.0 (unreleased) ...@@ -47,21 +61,28 @@ v 8.10.0 (unreleased)
- Render inline diffs for multiple changed lines following eachother - Render inline diffs for multiple changed lines following eachother
- Wildcards for protected branches. !4665 - Wildcards for protected branches. !4665
- Allow importing from Github using Personal Access Tokens. (Eric K Idema) - Allow importing from Github using Personal Access Tokens. (Eric K Idema)
- API: Expose `due_date` for issues (Robert Schilling)
- API: Todos !3188 (Robert Schilling) - API: Todos !3188 (Robert Schilling)
- API: Expose shared groups for projects and shared projects for groups !5050 (Robert Schilling) - API: Expose shared groups for projects and shared projects for groups !5050 (Robert Schilling)
- API: Expose `developers_can_push` and `developers_can_merge` for branches !5208 (Robert Schilling)
- Add "Enabled Git access protocols" to Application Settings - Add "Enabled Git access protocols" to Application Settings
- Diffs will create button/diff form on demand no on server side - Diffs will create button/diff form on demand no on server side
- Reduce size of HTML used by diff comment forms - Reduce size of HTML used by diff comment forms
- Protected branches have a "Developers can Merge" setting. !4892 (original implementation by Mathias Vestergaard)
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- Only show New Snippet button to users that can create snippets. - Only show New Snippet button to users that can create snippets.
- PipelinesFinder uses git cache data - PipelinesFinder uses git cache data
- Track a user who created a pipeline
- Actually render old and new sections of parallel diff next to each other - Actually render old and new sections of parallel diff next to each other
- Throttle the update of `project.pushes_since_gc` to 1 minute. - Throttle the update of `project.pushes_since_gc` to 1 minute.
- Allow expanding and collapsing files in diff view (!4990) - Allow expanding and collapsing files in diff view (!4990)
- Collapse large diffs by default (!4990) - Collapse large diffs by default (!4990)
- Fix mentioned users list on diff notes - Fix mentioned users list on diff notes
- Fix creation of deployment on build that is retried, redeployed or rollback
- Don't parse Rinku returned value to DocFragment when it didn't change the original html string.
- Check for conflicts with existing Project's wiki path when creating a new project. - Check for conflicts with existing Project's wiki path when creating a new project.
- Show last push widget in upstream after push to fork - Show last push widget in upstream after push to fork
- Fix stage status shown for pipelines
- Cache todos pending/done dashboard query counts. - Cache todos pending/done dashboard query counts.
- Don't instantiate a git tree on Projects show default view - Don't instantiate a git tree on Projects show default view
- Bump Rinku to 2.0.0 - Bump Rinku to 2.0.0
...@@ -84,7 +105,9 @@ v 8.10.0 (unreleased) ...@@ -84,7 +105,9 @@ v 8.10.0 (unreleased)
- More descriptive message for git hooks and file locks - More descriptive message for git hooks and file locks
- Aliases of award emoji should be stored as original name. !5060 (dixpac) - Aliases of award emoji should be stored as original name. !5060 (dixpac)
- Handle custom Git hook result in GitLab UI - Handle custom Git hook result in GitLab UI
- Allow to access Container Registry for Public and Internal projects
- Allow '?', or '&' for label names - Allow '?', or '&' for label names
- Support redirected blobs for Container Registry integration
- Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests
- Add date when user joined the team on the member page - Add date when user joined the team on the member page
- Fix 404 redirect after validation fails importing a GitLab project - Fix 404 redirect after validation fails importing a GitLab project
...@@ -92,6 +115,7 @@ v 8.10.0 (unreleased) ...@@ -92,6 +115,7 @@ v 8.10.0 (unreleased)
- Add min value for project limit field on user's form !3622 (jastkand) - Add min value for project limit field on user's form !3622 (jastkand)
- Reset project pushes_since_gc when we enqueue the git gc call - Reset project pushes_since_gc when we enqueue the git gc call
- Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt) - Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt)
- Collapsed diffs lines/size don't acumulate to overflow diffs.
- Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel) - Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel)
- Style of import project buttons were fixed in the new project page. !5183 (rdemirbay) - Style of import project buttons were fixed in the new project page. !5183 (rdemirbay)
- Fix GitHub client requests when rate limit is disabled - Fix GitHub client requests when rate limit is disabled
...@@ -103,7 +127,14 @@ v 8.10.0 (unreleased) ...@@ -103,7 +127,14 @@ v 8.10.0 (unreleased)
- Fix last update timestamp on issues not preserved on gitlab.com and project imports - Fix last update timestamp on issues not preserved on gitlab.com and project imports
- Fix issues importing projects from EE to CE - Fix issues importing projects from EE to CE
- Fix creating group with space in group path - Fix creating group with space in group path
- Improve cron_jobs loading error messages !5318
- Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska) - Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska)
- Limit the number of retries on error to 3 for exporting projects
- Allow empty repositories on project import/export
- Render only commit message title in builds (Katarzyna Kobierska Ula Budziszewska)
- Allow bulk (un)subscription from issues in issue index
- Fix MR diff encoding issues exporting GitLab projects
- Export and import avatar as part of project import/export
v 8.9.6 v 8.9.6
- Fix importing of events under notes for GitLab projects. !5154 - Fix importing of events under notes for GitLab projects. !5154
...@@ -112,6 +143,7 @@ v 8.9.6 ...@@ -112,6 +143,7 @@ v 8.9.6
- Fix broken migration in MySQL. !5005 - Fix broken migration in MySQL. !5005
- Overwrite Host and X-Forwarded-Host headers in NGINX !5213 - Overwrite Host and X-Forwarded-Host headers in NGINX !5213
- Keeps issue number when importing from Gitlab.com - Keeps issue number when importing from Gitlab.com
- Add Pending tab for Builds (Katarzyna Kobierska, Urszula Budziszewska)
v 8.9.7 (unreleased) v 8.9.7 (unreleased)
- Fix import_data wrongly saved as a result of an invalid import_url - Fix import_data wrongly saved as a result of an invalid import_url
......
...@@ -52,7 +52,7 @@ gem 'browser', '~> 2.2' ...@@ -52,7 +52,7 @@ gem 'browser', '~> 2.2'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem 'gitlab_git', '~> 10.2' gem 'gitlab_git', '~> 10.3.2'
# LDAP Auth # LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes # GitLab fork with several improvements to original library. For full list of changes
...@@ -223,7 +223,7 @@ gem 'jquery-turbolinks', '~> 2.1.0' ...@@ -223,7 +223,7 @@ gem 'jquery-turbolinks', '~> 2.1.0'
gem 'addressable', '~> 2.3.8' gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.3.0' gem 'bootstrap-sass', '~> 3.3.0'
gem 'font-awesome-rails', '~> 4.6.1' gem 'font-awesome-rails', '~> 4.6.1'
gem 'gemojione', '~> 2.6' gem 'gemojione', '~> 3.0'
gem 'gon', '~> 6.0.1' gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2' gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0' gem 'jquery-rails', '~> 4.1.0'
...@@ -349,3 +349,6 @@ gem 'health_check', '~> 2.1.0' ...@@ -349,3 +349,6 @@ gem 'health_check', '~> 2.1.0'
# System information # System information
gem 'vmstat', '~> 2.1.0' gem 'vmstat', '~> 2.1.0'
gem 'sys-filesystem', '~> 1.1.6' gem 'sys-filesystem', '~> 1.1.6'
# Secure headers for Content Security Policy
gem 'secure_headers', '~> 3.3'
...@@ -255,7 +255,7 @@ GEM ...@@ -255,7 +255,7 @@ GEM
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
gemnasium-gitlab-service (0.2.6) gemnasium-gitlab-service (0.2.6)
rugged (~> 0.21) rugged (~> 0.21)
gemojione (2.6.1) gemojione (3.0.1)
json json
get_process_mem (0.2.0) get_process_mem (0.2.0)
gherkin-ruby (0.3.2) gherkin-ruby (0.3.2)
...@@ -274,7 +274,7 @@ GEM ...@@ -274,7 +274,7 @@ GEM
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab_git (10.2.3) gitlab_git (10.3.2)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
...@@ -578,7 +578,7 @@ GEM ...@@ -578,7 +578,7 @@ GEM
railties (>= 4.2.0, < 5.1) railties (>= 4.2.0, < 5.1)
rinku (2.0.0) rinku (2.0.0)
rotp (2.1.2) rotp (2.1.2)
rouge (2.0.3) rouge (2.0.5)
rqrcode (0.7.0) rqrcode (0.7.0)
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
...@@ -645,6 +645,8 @@ GEM ...@@ -645,6 +645,8 @@ GEM
sdoc (0.3.20) sdoc (0.3.20)
json (>= 1.1.3) json (>= 1.1.3)
rdoc (~> 3.10) rdoc (~> 3.10)
secure_headers (3.3.2)
useragent
seed-fu (2.3.6) seed-fu (2.3.6)
activerecord (>= 3.1) activerecord (>= 3.1)
activesupport (>= 3.1) activesupport (>= 3.1)
...@@ -767,6 +769,7 @@ GEM ...@@ -767,6 +769,7 @@ GEM
get_process_mem (~> 0) get_process_mem (~> 0)
unicorn (>= 4, < 6) unicorn (>= 4, < 6)
uniform_notifier (1.9.0) uniform_notifier (1.9.0)
useragent (0.16.7)
uuid (2.3.8) uuid (2.3.8)
macaddr (~> 1.0) macaddr (~> 1.0)
version_sorter (2.0.0) version_sorter (2.0.0)
...@@ -857,11 +860,11 @@ DEPENDENCIES ...@@ -857,11 +860,11 @@ DEPENDENCIES
foreman (~> 0.78.0) foreman (~> 0.78.0)
fuubar (~> 2.0.0) fuubar (~> 2.0.0)
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
gemojione (~> 2.6) gemojione (~> 3.0)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
github-markup (~> 1.4) github-markup (~> 1.4)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab_git (~> 10.2) gitlab_git (~> 10.3.2)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.2) gollum-lib (~> 4.2)
...@@ -944,6 +947,7 @@ DEPENDENCIES ...@@ -944,6 +947,7 @@ DEPENDENCIES
sass-rails (~> 5.0.0) sass-rails (~> 5.0.0)
scss_lint (~> 0.47.0) scss_lint (~> 0.47.0)
sdoc (~> 0.3.20) sdoc (~> 0.3.20)
secure_headers (~> 3.3)
seed-fu (~> 2.3.5) seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9) select2-rails (~> 3.5.9)
sentry-raven (~> 1.1.0) sentry-raven (~> 1.1.0)
......
# GitLab Maintenance Policy # GitLab Maintenance Policy
GitLab is a fast moving and evolving project. We currently don't have the resources to support many releases concurrently. We support exactly one stable release at any given time. GitLab follows the [Semantic Versioning](http://semver.org/) for its releases:
`(Major).(Minor).(Patch)` in a [pragmatic way].
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e). - **Major version**: Whenever there is something significant or any backwards
incompatible changes are introduced to the public API.
- **Minor version**: When new, backwards compatible functionality is introduced
to the public API or a minor feature is introduced, or when a set of smaller
features is rolled out.
- **Patch number**: When backwards compatible bug fixes are introduced that fix
incorrect behavior.
- **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API. The current stable release will receive security patches and bug fixes
- **Minor version**: When new, backwards compatible functionality is introduced to the public API or a minor feature is introduced, or when a set of smaller features is rolled out. (eg. `8.9.0` -> `8.9.1`). Feature releases will mark the next supported stable
- **Patch number**: When backwards compatible bug fixes are introduced that fix incorrect behavior. release where the minor version is increased numerically by increments of one
(eg. `8.9 -> 8.10`).
The current stable release will receive security patches and bug fixes (eg. `5.0` -> `5.0.1`). Feature releases will mark the next supported stable release where the minor version is increased numerically by increments of one (eg. `5.0 -> 5.1`). Our current policy is to support one stable release at any given time, but for
medium-level security issues, we may consider [backporting to the previous two
monthly releases][rel-sec].
We encourage everyone to run the latest stable release to ensure that you can easily upgrade to the most secure and feature rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable. We encourage everyone to run the latest stable release to ensure that you can
easily upgrade to the most secure and feature-rich GitLab experience. In order
to make sure you can easily run the most recent stable release, we are working
hard to keep the update process simple and reliable.
More information about the release procedures can be found in the doc/release directory. More information about the release procedures can be found in our
[release-tools documentation][rel]. You may also want to read our
[Responsible Disclosure Policy][disclosure].
[rel-sec]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/security.md#backporting
[rel]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/
[disclosure]: https://about.gitlab.com/disclosure/
[pragmatic way]: https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e
app/assets/images/emoji.png

1000 KB | W: | H:

app/assets/images/emoji.png

1.04 MB | W: | H:

app/assets/images/emoji.png
app/assets/images/emoji.png
app/assets/images/emoji.png
app/assets/images/emoji.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/emoji@2x.png

2.38 MB | W: | H:

app/assets/images/emoji@2x.png

2.53 MB | W: | H:

app/assets/images/emoji@2x.png
app/assets/images/emoji@2x.png
app/assets/images/emoji@2x.png
app/assets/images/emoji@2x.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -250,6 +250,8 @@ class GitLabDropdown ...@@ -250,6 +250,8 @@ class GitLabDropdown
if self.options.clicked if self.options.clicked
self.options.clicked(selected, $el, e) self.options.clicked(selected, $el, e)
$el.trigger('blur')
# Finds an element inside wrapper element # Finds an element inside wrapper element
getElement: (selector) -> getElement: (selector) ->
@dropdown.find selector @dropdown.find selector
......
...@@ -85,12 +85,13 @@ class @IssuableBulkActions ...@@ -85,12 +85,13 @@ class @IssuableBulkActions
getFormDataAsObject: -> getFormDataAsObject: ->
formData = formData =
update: update:
state_event : @form.find('input[name="update[state_event]"]').val() state_event : @form.find('input[name="update[state_event]"]').val()
assignee_id : @form.find('input[name="update[assignee_id]"]').val() assignee_id : @form.find('input[name="update[assignee_id]"]').val()
milestone_id : @form.find('input[name="update[milestone_id]"]').val() milestone_id : @form.find('input[name="update[milestone_id]"]').val()
issues_ids : @form.find('input[name="update[issues_ids]"]').val() issues_ids : @form.find('input[name="update[issues_ids]"]').val()
add_label_ids : [] subscription_event : @form.find('input[name="update[subscription_event]"]').val()
remove_label_ids : [] add_label_ids : []
remove_label_ids : []
if @willUpdateLabels if @willUpdateLabels
@getLabelsToApply().map (id) -> @getLabelsToApply().map (id) ->
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
w.gl ?= {} w.gl ?= {}
w.gl.utils ?= {} w.gl.utils ?= {}
w.gl.utils.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
w.gl.utils.formatDate = (datetime) -> w.gl.utils.formatDate = (datetime) ->
dateFormat(datetime, 'mmm d, yyyy h:MMtt Z') dateFormat(datetime, 'mmm d, yyyy h:MMtt Z')
......
$ -> $ ->
$(".protected-branches-list :checkbox").change (e) -> $(".protected-branches-list :checkbox").change (e) ->
name = $(this).attr("name") name = $(this).attr("name")
if name == "developers_can_push" if name == "developers_can_push" || name == "developers_can_merge"
id = $(this).val() id = $(this).val()
checked = $(this).is(":checked") can_push = $(this).is(":checked")
url = $(this).data("url") url = $(this).data("url")
$.ajax $.ajax
type: "PUT" type: "PATCH"
url: url url: url
dataType: "json" dataType: "json"
data: data:
id: id id: id
protected_branch: protected_branch:
developers_can_push: checked "#{name}": can_push
success: -> success: ->
row = $(e.target) row = $(e.target)
......
class @SubscriptionSelect
constructor: ->
$('.js-subscription-event').each (i, el) ->
fieldName = $(el).data("field-name")
$(el).glDropdown(
selectable: true
fieldName: fieldName
toggleLabel: (selected, el, instance) =>
label = 'Subscription'
$item = instance.dropdown.find('.is-active')
label = $item.text() if $item.length
label
clicked: (item, $el, e)->
e.preventDefault()
id: (obj, el) ->
$(el).data("id")
)
...@@ -49,6 +49,17 @@ ...@@ -49,6 +49,17 @@
border-color: $border-dark; border-color: $border-dark;
color: $color; color: $color;
} }
svg {
path {
fill: $color;
}
use {
stroke: $color;
}
}
} }
@mixin btn-green { @mixin btn-green {
...@@ -173,6 +184,13 @@ ...@@ -173,6 +184,13 @@
.caret { .caret {
margin-left: 5px; margin-left: 5px;
} }
svg {
height: 15px;
width: auto;
position: relative;
top: 2px;
}
} }
.btn-lg { .btn-lg {
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
} }
&.wiki { &.wiki {
padding: $gl-padding; padding: 30px $gl-padding;
.highlight { .highlight {
margin-bottom: 9px; margin-bottom: 9px;
......
...@@ -198,6 +198,10 @@ header.header-pinned-nav { ...@@ -198,6 +198,10 @@ header.header-pinned-nav {
.sidebar-collapsed-icon { .sidebar-collapsed-icon {
cursor: pointer; cursor: pointer;
.btn {
background-color: $gray-light;
}
} }
} }
......
...@@ -37,39 +37,41 @@ ...@@ -37,39 +37,41 @@
} }
h1 { h1 {
font-size: 1.3em; font-size: 2em;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px; margin: 1em 0 10px;
padding: 0 0 10px; padding: 0 0 0.3em;
border-bottom: 1px solid #e7e9ed; border-bottom: 1px solid $btn-default-border;
color: $gl-gray-dark; color: $gl-gray-dark;
} }
h2 { h2 {
font-size: 1.2em; font-size: 1.6em;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px; margin: 1em 0 10px;
padding-bottom: 0.3em;
border-bottom: 1px solid $btn-default-border;
color: $gl-gray-dark; color: $gl-gray-dark;
} }
h3 { h3 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 1.1em; font-size: 1.4em;
} }
h4 { h4 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 0.98em; font-size: 1.25em;
} }
h5 { h5 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 0.95em; font-size: 1em;
} }
h6 { h6 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 0.90em; font-size: 0.95em;
} }
blockquote { blockquote {
...@@ -115,7 +117,7 @@ ...@@ -115,7 +117,7 @@
ul, ol { ul, ol {
padding: 0; padding: 0;
margin: 6px 0 6px 28px !important; margin: 3px 0 3px 28px !important;
} }
li { li {
......
...@@ -16,7 +16,7 @@ $border-color: #e5e5e5; ...@@ -16,7 +16,7 @@ $border-color: #e5e5e5;
$focus-border-color: #3aabf0; $focus-border-color: #3aabf0;
$table-border-color: #f0f0f0; $table-border-color: #f0f0f0;
$background-color: #fafafa; $background-color: #fafafa;
$dark-background-color: #f7f7f7; $dark-background-color: #f5f5f5;
$table-text-gray: #8f8f8f; $table-text-gray: #8f8f8f;
/* /*
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -122,7 +122,8 @@ ...@@ -122,7 +122,8 @@
button { button {
float: right; float: right;
padding: 3px 5px; padding: 1px 5px;
background-color: $gray-light;
} }
} }
......
...@@ -63,7 +63,7 @@ form.edit-issue { ...@@ -63,7 +63,7 @@ form.edit-issue {
.merge-request, .merge-request,
.issue { .issue {
&.today { &.today {
background: #f8feef; background: #f3fff2;
border-color: #e1e8d5; border-color: #e1e8d5;
} }
...@@ -78,6 +78,14 @@ form.edit-issue { ...@@ -78,6 +78,14 @@ form.edit-issue {
} }
} }
.merge-request-ci-status {
svg {
margin-right: 4px;
position: relative;
top: 1px;
}
}
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.issue-btn-group { .issue-btn-group {
width: 100%; width: 100%;
......
...@@ -60,8 +60,10 @@ ...@@ -60,8 +60,10 @@
.ci_widget { .ci_widget {
border-bottom: 1px solid #eef0f2; border-bottom: 1px solid #eef0f2;
i { svg {
margin-right: 4px; margin-right: 4px;
position: relative;
top: 1px;
} }
&.ci-success { &.ci-success {
...@@ -196,6 +198,16 @@ ...@@ -196,6 +198,16 @@
.merge-request-title { .merge-request-title {
margin-bottom: 2px; margin-bottom: 2px;
.ci-status-link {
svg {
height: 16px;
width: 16px;
position: relative;
top: 3px;
}
}
} }
} }
...@@ -270,7 +282,7 @@ ...@@ -270,7 +282,7 @@
.item-title { .item-title {
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
width: 49%; width: 45%;
} }
} }
......
.pipelines { .pipelines {
.stage { .stage {
max-width: 80px; max-width: 90px;
width: 80px; width: 90px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
...@@ -30,13 +30,17 @@ ...@@ -30,13 +30,17 @@
} }
.table.builds { .table.builds {
min-width: 1100px; min-width: 1200px;
tr { tr {
th { th {
padding: 16px; padding: 16px 8px;
border: none; border: none;
} }
td {
padding: 10px 8px;
}
} }
tbody { tbody {
...@@ -45,6 +49,14 @@ ...@@ -45,6 +49,14 @@
.commit-link { .commit-link {
.ci-status {
svg {
top: 1px;
margin-right: 0;
}
}
a:hover { a:hover {
text-decoration: none; text-decoration: none;
} }
...@@ -53,9 +65,8 @@ ...@@ -53,9 +65,8 @@
.branch-commit { .branch-commit {
.branch-name { .branch-name {
margin-left: 8px;
font-weight: bold; font-weight: bold;
max-width: 180px; max-width: 150px;
overflow: hidden; overflow: hidden;
display: inline-block; display: inline-block;
white-space: nowrap; white-space: nowrap;
...@@ -64,10 +75,15 @@ ...@@ -64,10 +75,15 @@
} }
svg { svg {
margin: 0 6px;
height: 14px; height: 14px;
width: auto; width: auto;
vertical-align: middle; vertical-align: middle;
fill: $table-text-gray;
}
.fa {
font-size: 12px;
color: $table-text-gray;
} }
.commit-id { .commit-id {
...@@ -100,6 +116,31 @@ ...@@ -100,6 +116,31 @@
} }
} }
.icon-container {
display: inline-block;
text-align: right;
width: 20px;
.fa {
position: relative;
right: 3px;
}
svg {
position: relative;
right: 1px;
}
}
.stage-cell {
svg {
height: 18px;
width: 18px;
vertical-align: middle;
}
}
.duration, .duration,
.finished-at { .finished-at {
color: $table-text-gray; color: $table-text-gray;
...@@ -107,21 +148,19 @@ ...@@ -107,21 +148,19 @@
.fa { .fa {
font-size: 12px; font-size: 12px;
margin-right: 4px;
} }
svg { svg {
height: 12px; width: 12px;
width: auto; height: auto;
vertical-align: middle; vertical-align: middle;
} margin-right: 4px;
.fa,
svg {
margin-right: 5px;
} }
} }
.pipeline-actions { .pipeline-actions {
min-width: 140px;
.btn { .btn {
margin: 0; margin: 0;
......
...@@ -129,6 +129,17 @@ ...@@ -129,6 +129,17 @@
color: $layout-link-gray; color: $layout-link-gray;
} }
svg {
path {
fill: $layout-link-gray;
}
use {
stroke: $layout-link-gray;
}
}
.fa-caret-down { .fa-caret-down {
margin-left: 3px; margin-left: 3px;
} }
...@@ -486,6 +497,11 @@ pre.light-well { ...@@ -486,6 +497,11 @@ pre.light-well {
> span { > span {
margin-left: 10px; margin-left: 10px;
} }
svg {
position: relative;
top: 2px;
}
} }
} }
......
...@@ -41,6 +41,14 @@ ...@@ -41,6 +41,14 @@
color: $blue-normal; color: $blue-normal;
border-color: $blue-normal; border-color: $blue-normal;
} }
svg {
height: 13px;
width: 13px;
position: relative;
top: 1px;
margin: 0 3px;
}
} }
.ci-status-icon-success { .ci-status-icon-success {
......
.tag-buttons {
line-height: 40px;
.btn:not(.dropdown-toggle) {
margin-left: 10px;
}
}
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
border-top: 1px solid $table-border-gray; border-top: 1px solid $table-border-gray;
td, th { td, th {
line-height: 23px; line-height: 21px;
} }
&:hover { &:hover {
......
...@@ -5,8 +5,10 @@ class Admin::BuildsController < Admin::ApplicationController ...@@ -5,8 +5,10 @@ class Admin::BuildsController < Admin::ApplicationController
@builds = @all_builds.order('created_at DESC') @builds = @all_builds.order('created_at DESC')
@builds = @builds =
case @scope case @scope
when 'pending'
@builds.pending.reverse_order
when 'running' when 'running'
@builds.running_or_pending.reverse_order @builds.running.reverse_order
when 'finished' when 'finished'
@builds.finished @builds.finished
else else
......
...@@ -7,7 +7,8 @@ module CreatesCommit ...@@ -7,7 +7,8 @@ module CreatesCommit
commit_params = @commit_params.merge( commit_params = @commit_params.merge(
source_project: @project, source_project: @project,
source_branch: @ref, source_branch: @ref,
target_branch: @target_branch target_branch: @target_branch,
previous_path: @previous_path
) )
result = service.new(@tree_edit_project, current_user, commit_params).execute result = service.new(@tree_edit_project, current_user, commit_params).execute
......
...@@ -10,7 +10,6 @@ module DiffForPath ...@@ -10,7 +10,6 @@ module DiffForPath
diff_commit = commit_for_diff(diff_file) diff_commit = commit_for_diff(diff_file)
blob = diff_file.blob(diff_commit) blob = diff_file.blob(diff_commit)
@expand_all_diffs = true
locals = { locals = {
diff_file: diff_file, diff_file: diff_file,
......
...@@ -38,6 +38,12 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -38,6 +38,12 @@ class Projects::BlobController < Projects::ApplicationController
end end
def update def update
if params[:file_path].present?
@previous_path = @path
@path = params[:file_path]
@commit_params[:file_path] = @path
end
after_edit_path = after_edit_path =
if from_merge_request && @target_branch == @ref if from_merge_request && @target_branch == @ref
diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) + diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) +
......
class Projects::BuildsController < Projects::ApplicationController class Projects::BuildsController < Projects::ApplicationController
before_action :build, except: [:index, :cancel_all] before_action :build, except: [:index, :cancel_all]
before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry] before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry, :play]
before_action :authorize_update_build!, except: [:index, :show, :status, :raw] before_action :authorize_update_build!, except: [:index, :show, :status, :raw]
layout 'project' layout 'project'
...@@ -10,8 +10,10 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -10,8 +10,10 @@ class Projects::BuildsController < Projects::ApplicationController
@builds = @all_builds.order('created_at DESC') @builds = @all_builds.order('created_at DESC')
@builds = @builds =
case @scope case @scope
when 'pending'
@builds.pending.reverse_order
when 'running' when 'running'
@builds.running_or_pending.reverse_order @builds.running.reverse_order
when 'finished' when 'finished'
@builds.finished @builds.finished
else else
...@@ -47,14 +49,19 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -47,14 +49,19 @@ class Projects::BuildsController < Projects::ApplicationController
end end
def retry def retry
unless @build.retryable? return render_404 unless @build.retryable?
return render_404
end
build = Ci::Build.retry(@build, current_user) build = Ci::Build.retry(@build, current_user)
redirect_to build_path(build) redirect_to build_path(build)
end end
def play
return render_404 unless @build.playable?
build = @build.play(current_user)
redirect_to build_path(build)
end
def cancel def cancel
@build.cancel @build.cancel
redirect_to build_path(@build) redirect_to build_path(@build)
......
...@@ -226,6 +226,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -226,6 +226,7 @@ class Projects::IssuesController < Projects::ApplicationController
:assignee_id, :assignee_id,
:milestone_id, :milestone_id,
:state_event, :state_event,
:subscription_event,
label_ids: [], label_ids: [],
add_label_ids: [], add_label_ids: [],
remove_label_ids: [] remove_label_ids: []
......
...@@ -50,6 +50,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -50,6 +50,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
end end
def protected_branch_params def protected_branch_params
params.require(:protected_branch).permit(:name, :developers_can_push) params.require(:protected_branch).permit(:name, :developers_can_push, :developers_can_merge)
end end
end end
...@@ -45,8 +45,9 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -45,8 +45,9 @@ class Projects::ServicesController < Projects::ApplicationController
end end
def test def test
data = Gitlab::PushDataBuilder.build_sample(project, current_user) data = @service.test_data(project, current_user)
outcome = @service.test(data) outcome = @service.test(data)
if outcome[:success] if outcome[:success]
message = { notice: 'We sent a request to the provided URL' } message = { notice: 'We sent a request to the provided URL' }
else else
......
...@@ -5,7 +5,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -5,7 +5,7 @@ class ProjectsController < Projects::ApplicationController
before_action :project, except: [:new, :create] before_action :project, except: [:new, :create]
before_action :repository, except: [:new, :create] before_action :repository, except: [:new, :create]
before_action :assign_ref_vars, only: [:show], if: :repo_exists? before_action :assign_ref_vars, only: [:show], if: :repo_exists?
before_action :tree, only: [:show], if: :project_view_files? before_action :tree, only: [:show], if: [:repo_exists?, :project_view_files?]
# Authorize # Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export] before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
......
...@@ -12,7 +12,7 @@ module BranchesHelper ...@@ -12,7 +12,7 @@ module BranchesHelper
def can_push_branch?(project, branch_name) def can_push_branch?(project, branch_name)
return false unless project.repository.branch_exists?(branch_name) return false unless project.repository.branch_exists?(branch_name)
::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(branch_name) ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch_name)
end end
def project_branches def project_branches
......
...@@ -26,18 +26,20 @@ module CiStatusHelper ...@@ -26,18 +26,20 @@ module CiStatusHelper
icon_name = icon_name =
case status case status
when 'success' when 'success'
'check' 'icon_status_success'
when 'success_with_warnings'
'icon_status_warning'
when 'failed' when 'failed'
'close' 'icon_status_failed'
when 'pending' when 'pending'
'clock-o' 'icon_status_pending'
when 'running' when 'running'
'spinner' 'icon_status_running'
else else
'circle' 'icon_status_cancel'
end end
icon(icon_name + ' fw') custom_icon(icon_name)
end end
def render_commit_status(commit, tooltip_placement: 'auto left', cssclass: '') def render_commit_status(commit, tooltip_placement: 'auto left', cssclass: '')
......
...@@ -9,7 +9,7 @@ module DiffHelper ...@@ -9,7 +9,7 @@ module DiffHelper
end end
def expand_all_diffs? def expand_all_diffs?
@expand_all_diffs || params[:expand_all_diffs].present? params[:expand_all_diffs].present?
end end
def diff_view def diff_view
...@@ -23,13 +23,14 @@ module DiffHelper ...@@ -23,13 +23,14 @@ module DiffHelper
end end
def diff_options def diff_options
default_options = Commit.max_diff_options options = { ignore_whitespace_change: hide_whitespace?, no_collapse: expand_all_diffs? }
if action_name == 'diff_for_path' if action_name == 'diff_for_path'
default_options[:paths] = params.values_at(:old_path, :new_path) options[:no_collapse] = true
options[:paths] = params.values_at(:old_path, :new_path)
end end
default_options.merge(ignore_whitespace_change: hide_whitespace?) Commit.max_diff_options.merge(options)
end end
def safe_diff_files(diffs, diff_refs: nil, repository: nil) def safe_diff_files(diffs, diff_refs: nil, repository: nil)
......
module TimeHelper module TimeHelper
def duration_in_words(finished_at, started_at)
if finished_at && started_at
interval_in_seconds = finished_at.to_i - started_at.to_i
elsif started_at
interval_in_seconds = Time.now.to_i - started_at.to_i
end
time_interval_in_words(interval_in_seconds)
end
def time_interval_in_words(interval_in_seconds) def time_interval_in_words(interval_in_seconds)
minutes = interval_in_seconds / 60 minutes = interval_in_seconds / 60
seconds = interval_in_seconds - minutes * 60 seconds = interval_in_seconds - minutes * 60
...@@ -25,9 +15,19 @@ module TimeHelper ...@@ -25,9 +15,19 @@ module TimeHelper
end end
def duration_in_numbers(finished_at, started_at) def duration_in_numbers(finished_at, started_at)
diff_in_seconds = finished_at.to_i - started_at.to_i interval = interval_in_seconds(started_at, finished_at)
time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S" time_format = interval < 1.hour ? "%M:%S" : "%H:%M:%S"
Time.at(diff_in_seconds).utc.strftime(time_format) Time.at(interval).utc.strftime(time_format)
end
private
def interval_in_seconds(started_at, finished_at = nil)
if started_at && finished_at
finished_at.to_i - started_at.to_i
elsif started_at
Time.now.to_i - started_at.to_i
end
end end
end end
...@@ -6,6 +6,7 @@ module Emails ...@@ -6,6 +6,7 @@ module Emails
add_project_headers add_project_headers
add_build_headers('failed') add_build_headers('failed')
mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha)) mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha))
end end
......
...@@ -204,7 +204,8 @@ class Ability ...@@ -204,7 +204,8 @@ class Ability
:download_code, :download_code,
:fork_project, :fork_project,
:read_commit_status, :read_commit_status,
:read_pipeline :read_pipeline,
:read_container_image
] ]
end end
......
...@@ -5,6 +5,7 @@ module Ci ...@@ -5,6 +5,7 @@ module Ci
belongs_to :erased_by, class_name: 'User' belongs_to :erased_by, class_name: 'User'
serialize :options serialize :options
serialize :yaml_variables
validates :coverage, numericality: true, allow_blank: true validates :coverage, numericality: true, allow_blank: true
validates_presence_of :ref validates_presence_of :ref
...@@ -14,6 +15,7 @@ module Ci ...@@ -14,6 +15,7 @@ module Ci
scope :with_artifacts, ->() { where.not(artifacts_file: nil) } scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
scope :manual_actions, ->() { where(when: :manual) }
mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader mount_uploader :artifacts_metadata, ArtifactUploader
...@@ -52,7 +54,10 @@ module Ci ...@@ -52,7 +54,10 @@ module Ci
new_build.stage = build.stage new_build.stage = build.stage
new_build.stage_idx = build.stage_idx new_build.stage_idx = build.stage_idx
new_build.trigger_request = build.trigger_request new_build.trigger_request = build.trigger_request
new_build.yaml_variables = build.yaml_variables
new_build.when = build.when
new_build.user = user new_build.user = user
new_build.environment = build.environment
new_build.save new_build.save
MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build)
new_build new_build
...@@ -87,6 +92,29 @@ module Ci ...@@ -87,6 +92,29 @@ module Ci
end end
end end
def manual?
self.when == 'manual'
end
def other_actions
pipeline.manual_actions.where.not(id: self)
end
def playable?
project.builds_enabled? && commands.present? && manual?
end
def play(current_user = nil)
# Try to queue a current build
if self.queue
self.update(user: current_user)
self
else
# Otherwise we need to create a duplicate
Ci::Build.retry(self, current_user)
end
end
def retryable? def retryable?
project.builds_enabled? && commands.present? && complete? project.builds_enabled? && commands.present? && complete?
end end
...@@ -376,6 +404,14 @@ module Ci ...@@ -376,6 +404,14 @@ module Ci
self.update(artifacts_expire_at: nil) self.update(artifacts_expire_at: nil)
end end
def when
read_attribute(:when) || build_attributes_from_config[:when] || 'on_success'
end
def yaml_variables
read_attribute(:yaml_variables) || build_attributes_from_config[:yaml_variables] || []
end
private private
def update_artifacts_size def update_artifacts_size
...@@ -394,30 +430,6 @@ module Ci ...@@ -394,30 +430,6 @@ module Ci
self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil) self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil)
end end
def yaml_variables
global_yaml_variables + job_yaml_variables
end
def global_yaml_variables
if pipeline.config_processor
pipeline.config_processor.global_variables.map do |key, value|
{ key: key, value: value, public: true }
end
else
[]
end
end
def job_yaml_variables
if pipeline.config_processor
pipeline.config_processor.job_variables(name).map do |key, value|
{ key: key, value: value, public: true }
end
else
[]
end
end
def project_variables def project_variables
project.variables.map do |variable| project.variables.map do |variable|
{ key: variable.key, value: variable.value, public: false } { key: variable.key, value: variable.value, public: false }
...@@ -442,5 +454,11 @@ module Ci ...@@ -442,5 +454,11 @@ module Ci
variables << { key: :CI_BUILD_TRIGGERED, value: 'true', public: true } if trigger_request variables << { key: :CI_BUILD_TRIGGERED, value: 'true', public: true } if trigger_request
variables variables
end end
def build_attributes_from_config
return {} unless pipeline.config_processor
pipeline.config_processor.build_attributes(name)
end
end end
end end
...@@ -6,6 +6,8 @@ module Ci ...@@ -6,6 +6,8 @@ module Ci
self.table_name = 'ci_commits' self.table_name = 'ci_commits'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
belongs_to :user
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id
...@@ -49,6 +51,10 @@ module Ci ...@@ -49,6 +51,10 @@ module Ci
commit.try(:message) commit.try(:message)
end end
def git_commit_title
commit.try(:title)
end
def short_sha def short_sha
Ci::Pipeline.truncate_sha(sha) Ci::Pipeline.truncate_sha(sha)
end end
...@@ -63,6 +69,10 @@ module Ci ...@@ -63,6 +69,10 @@ module Ci
!tag? !tag?
end end
def manual_actions
builds.latest.manual_actions
end
def retryable? def retryable?
builds.latest.any? do |build| builds.latest.any? do |build|
build.failed? && build.retryable? build.failed? && build.retryable?
......
...@@ -22,6 +22,10 @@ class CommitStatus < ActiveRecord::Base ...@@ -22,6 +22,10 @@ class CommitStatus < ActiveRecord::Base
scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) } scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) }
state_machine :status, initial: :pending do state_machine :status, initial: :pending do
event :queue do
transition skipped: :pending
end
event :run do event :run do
transition pending: :running transition pending: :running
end end
......
...@@ -16,10 +16,10 @@ module Statuseable ...@@ -16,10 +16,10 @@ module Statuseable
deduce_status = "(CASE deduce_status = "(CASE
WHEN (#{builds})=0 THEN NULL WHEN (#{builds})=0 THEN NULL
WHEN (#{builds})=(#{success})+(#{ignored}) THEN 'success'
WHEN (#{builds})=(#{pending}) THEN 'pending'
WHEN (#{builds})=(#{canceled})+(#{success})+(#{ignored}) THEN 'canceled'
WHEN (#{builds})=(#{skipped}) THEN 'skipped' WHEN (#{builds})=(#{skipped}) THEN 'skipped'
WHEN (#{builds})=(#{success})+(#{ignored})+(#{skipped}) THEN 'success'
WHEN (#{builds})=(#{pending})+(#{skipped}) THEN 'pending'
WHEN (#{builds})=(#{canceled})+(#{success})+(#{ignored})+(#{skipped}) THEN 'canceled'
WHEN (#{running})+(#{pending})>0 THEN 'running' WHEN (#{running})+(#{pending})>0 THEN 'running'
ELSE 'failed' ELSE 'failed'
END)" END)"
......
...@@ -32,4 +32,8 @@ class Deployment < ActiveRecord::Base ...@@ -32,4 +32,8 @@ class Deployment < ActiveRecord::Base
def keep_around_commit def keep_around_commit
project.repository.keep_around(self.sha) project.repository.keep_around(self.sha)
end end
def manual_actions
deployable.try(:other_actions)
end
end end
...@@ -552,7 +552,13 @@ class MergeRequest < ActiveRecord::Base ...@@ -552,7 +552,13 @@ class MergeRequest < ActiveRecord::Base
end end
def can_be_merged_by?(user) def can_be_merged_by?(user)
::Gitlab::GitAccess.new(user, project, 'web').can_push_to_branch?(target_branch) access = ::Gitlab::UserAccess.new(user, project: project)
access.can_push_to_branch?(target_branch) || access.can_merge_to_branch?(target_branch)
end
def can_be_merged_via_command_line_by?(user)
access = ::Gitlab::UserAccess.new(user, project: project)
access.can_push_to_branch?(target_branch)
end end
def mergeable_ci_state? def mergeable_ci_state?
......
class MergeRequestDiff < ActiveRecord::Base class MergeRequestDiff < ActiveRecord::Base
include Sortable include Sortable
include Importable include Importable
include EncodingHelper
# Prevent store of diff if commits amount more then 500 # Prevent store of diff if commits amount more then 500
COMMITS_SAFE_SIZE = 100 COMMITS_SAFE_SIZE = 100
...@@ -211,6 +212,14 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -211,6 +212,14 @@ class MergeRequestDiff < ActiveRecord::Base
branch_base_commit.try(:sha) branch_base_commit.try(:sha)
end end
def utf8_st_diffs
st_diffs.map do |diff|
diff.each do |k, v|
diff[k] = encode_utf8(v) if v.respond_to?(:encoding)
end
end
end
# #
# #save or #update_attributes providing changes on serialized attributes do a lot of # #save or #update_attributes providing changes on serialized attributes do a lot of
# serialization and deserialization calls resulting in bad performance. # serialization and deserialization calls resulting in bad performance.
......
...@@ -162,7 +162,7 @@ class Project < ActiveRecord::Base ...@@ -162,7 +162,7 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true validates :namespace, presence: true
validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id
validates :import_url, addressable_url: true, if: :import_url validates :import_url, addressable_url: true, if: :external_import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 } validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create validate :check_limit, on: :create
validate :avatar_type, validate :avatar_type,
...@@ -482,7 +482,7 @@ class Project < ActiveRecord::Base ...@@ -482,7 +482,7 @@ class Project < ActiveRecord::Base
end end
def create_or_update_import_data(data: nil, credentials: nil) def create_or_update_import_data(data: nil, credentials: nil)
return unless valid_import_url? return unless import_url.present? && valid_import_url?
project_import_data = import_data || build_import_data project_import_data = import_data || build_import_data
if data if data
...@@ -838,6 +838,10 @@ class Project < ActiveRecord::Base ...@@ -838,6 +838,10 @@ class Project < ActiveRecord::Base
protected_branches.matching(branch_name).any?(&:developers_can_push) protected_branches.matching(branch_name).any?(&:developers_can_push)
end end
def developers_can_merge_to_protected_branch?(branch_name)
protected_branches.matching(branch_name).any?(&:developers_can_merge)
end
def forked? def forked?
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end end
...@@ -1038,8 +1042,8 @@ class Project < ActiveRecord::Base ...@@ -1038,8 +1042,8 @@ class Project < ActiveRecord::Base
pipelines.order(id: :desc).find_by(sha: sha, ref: ref) pipelines.order(id: :desc).find_by(sha: sha, ref: ref)
end end
def ensure_pipeline(sha, ref) def ensure_pipeline(sha, ref, current_user = nil)
pipeline(sha, ref) || pipelines.create(sha: sha, ref: ref) pipeline(sha, ref) || pipelines.create(sha: sha, ref: ref, user: current_user)
end end
def enable_ci def enable_ci
......
...@@ -42,6 +42,19 @@ class BuildsEmailService < Service ...@@ -42,6 +42,19 @@ class BuildsEmailService < Service
end end
end end
def can_test?
project.builds.count > 0
end
def disabled_title
"Please setup a build on your repository."
end
def test_data(project = nil, user = nil)
build = project.builds.last
Gitlab::BuildDataBuilder.build(build)
end
def fields def fields
[ [
{ type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' }, { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' },
...@@ -50,6 +63,20 @@ class BuildsEmailService < Service ...@@ -50,6 +63,20 @@ class BuildsEmailService < Service
] ]
end end
def test(data)
begin
# bypass build status verification when testing
data[:build_status] = "failed"
data[:build_allow_failure] = false
result = execute(data)
rescue StandardError => error
return { success: false, result: error }
end
{ success: true, result: result }
end
def should_build_be_notified?(data) def should_build_be_notified?(data)
case data[:build_status] case data[:build_status]
when 'success' when 'success'
......
...@@ -704,6 +704,7 @@ class Repository ...@@ -704,6 +704,7 @@ class Repository
options[:commit] = { options[:commit] = {
message: message, message: message,
branch: ref, branch: ref,
update_ref: false,
} }
raw_repository.mkdir(path, options) raw_repository.mkdir(path, options)
...@@ -719,6 +720,7 @@ class Repository ...@@ -719,6 +720,7 @@ class Repository
options[:commit] = { options[:commit] = {
message: message, message: message,
branch: ref, branch: ref,
update_ref: false,
} }
options[:file] = { options[:file] = {
...@@ -731,6 +733,33 @@ class Repository ...@@ -731,6 +733,33 @@ class Repository
end end
end end
def update_file(user, path, content, branch:, previous_path:, message:)
commit_with_hooks(user, branch) do |ref|
committer = user_to_committer(user)
options = {}
options[:committer] = committer
options[:author] = committer
options[:commit] = {
message: message,
branch: ref,
update_ref: false
}
options[:file] = {
content: content,
path: path,
update: true
}
if previous_path
options[:file][:previous_path] = previous_path
Gitlab::Git::Blob.rename(raw_repository, options)
else
Gitlab::Git::Blob.commit(raw_repository, options)
end
end
end
def remove_file(user, path, message, branch) def remove_file(user, path, message, branch)
commit_with_hooks(user, branch) do |ref| commit_with_hooks(user, branch) do |ref|
committer = user_to_committer(user) committer = user_to_committer(user)
...@@ -739,7 +768,8 @@ class Repository ...@@ -739,7 +768,8 @@ class Repository
options[:author] = committer options[:author] = committer
options[:commit] = { options[:commit] = {
message: message, message: message,
branch: ref branch: ref,
update_ref: false,
} }
options[:file] = { options[:file] = {
...@@ -769,9 +799,9 @@ class Repository ...@@ -769,9 +799,9 @@ class Repository
end end
end end
def merge(user, source_sha, target_branch, options = {}) def merge(user, merge_request, options = {})
our_commit = rugged.branches[target_branch].target our_commit = rugged.branches[merge_request.target_branch].target
their_commit = rugged.lookup(source_sha) their_commit = rugged.lookup(merge_request.diff_head_sha)
raise "Invalid merge target" if our_commit.nil? raise "Invalid merge target" if our_commit.nil?
raise "Invalid merge source" if their_commit.nil? raise "Invalid merge source" if their_commit.nil?
...@@ -779,14 +809,15 @@ class Repository ...@@ -779,14 +809,15 @@ class Repository
merge_index = rugged.merge_commits(our_commit, their_commit) merge_index = rugged.merge_commits(our_commit, their_commit)
return false if merge_index.conflicts? return false if merge_index.conflicts?
commit_with_hooks(user, target_branch) do |ref| commit_with_hooks(user, merge_request.target_branch) do
actual_options = options.merge( actual_options = options.merge(
parents: [our_commit, their_commit], parents: [our_commit, their_commit],
tree: merge_index.write_tree(rugged), tree: merge_index.write_tree(rugged),
update_ref: ref
) )
Rugged::Commit.create(rugged, actual_options) commit_id = Rugged::Commit.create(rugged, actual_options)
merge_request.update(in_progress_merge_commit_sha: commit_id)
commit_id
end end
end end
...@@ -796,15 +827,14 @@ class Repository ...@@ -796,15 +827,14 @@ class Repository
return false unless revert_tree_id return false unless revert_tree_id
commit_with_hooks(user, base_branch) do |ref| commit_with_hooks(user, base_branch) do
committer = user_to_committer(user) committer = user_to_committer(user)
source_sha = Rugged::Commit.create(rugged, source_sha = Rugged::Commit.create(rugged,
message: commit.revert_message, message: commit.revert_message,
author: committer, author: committer,
committer: committer, committer: committer,
tree: revert_tree_id, tree: revert_tree_id,
parents: [rugged.lookup(source_sha)], parents: [rugged.lookup(source_sha)])
update_ref: ref)
end end
end end
...@@ -814,7 +844,7 @@ class Repository ...@@ -814,7 +844,7 @@ class Repository
return false unless cherry_pick_tree_id return false unless cherry_pick_tree_id
commit_with_hooks(user, base_branch) do |ref| commit_with_hooks(user, base_branch) do
committer = user_to_committer(user) committer = user_to_committer(user)
source_sha = Rugged::Commit.create(rugged, source_sha = Rugged::Commit.create(rugged,
message: commit.message, message: commit.message,
...@@ -825,8 +855,7 @@ class Repository ...@@ -825,8 +855,7 @@ class Repository
}, },
committer: committer, committer: committer,
tree: cherry_pick_tree_id, tree: cherry_pick_tree_id,
parents: [rugged.lookup(source_sha)], parents: [rugged.lookup(source_sha)])
update_ref: ref)
end end
end end
...@@ -927,20 +956,6 @@ class Repository ...@@ -927,20 +956,6 @@ class Repository
Gitlab::Popen.popen(args, path_to_repo) Gitlab::Popen.popen(args, path_to_repo)
end end
def with_tmp_ref(oldrev = nil)
random_string = SecureRandom.hex
tmp_ref = "refs/tmp/#{random_string}/head"
if oldrev && !Gitlab::Git.blank_ref?(oldrev)
rugged.references.create(tmp_ref, oldrev)
end
# Make commit in tmp ref
yield(tmp_ref)
ensure
rugged.references.delete(tmp_ref) rescue nil
end
def commit_with_hooks(current_user, branch) def commit_with_hooks(current_user, branch)
update_autocrlf_option update_autocrlf_option
...@@ -953,33 +968,31 @@ class Repository ...@@ -953,33 +968,31 @@ class Repository
oldrev = target_branch.target oldrev = target_branch.target
end end
with_tmp_ref(oldrev) do |tmp_ref| # Make commit
# Make commit in tmp ref newrev = yield(ref)
newrev = yield(tmp_ref)
unless newrev unless newrev
raise CommitError.new('Failed to create commit') raise CommitError.new('Failed to create commit')
end end
GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do
if was_empty || !target_branch if was_empty || !target_branch
# Create branch # Create branch
rugged.references.create(ref, newrev) rugged.references.create(ref, newrev)
else
# Update head
current_head = find_branch(branch).target
# Make sure target branch was not changed during pre-receive hook
if current_head == oldrev
rugged.references.update(ref, newrev)
else else
# Update head raise CommitError.new('Commit was rejected because branch received new push')
current_head = find_branch(branch).target
# Make sure target branch was not changed during pre-receive hook
if current_head == oldrev
rugged.references.update(ref, newrev)
else
raise CommitError.new('Commit was rejected because branch received new push')
end
end end
end end
newrev
end end
newrev
end end
def ls_files(ref) def ls_files(ref)
......
...@@ -76,6 +76,10 @@ class Service < ActiveRecord::Base ...@@ -76,6 +76,10 @@ class Service < ActiveRecord::Base
[] []
end end
def test_data(project, user)
Gitlab::PushDataBuilder.build_sample(project, user)
end
def supported_events def supported_events
%w(push tag_push issue merge_request wiki_page) %w(push tag_push issue merge_request wiki_page)
end end
...@@ -94,6 +98,11 @@ class Service < ActiveRecord::Base ...@@ -94,6 +98,11 @@ class Service < ActiveRecord::Base
!project.empty_repo? !project.empty_repo?
end end
# reason why service cannot be tested
def disabled_title
"Please setup a project repository."
end
# Provide convenient accessor methods # Provide convenient accessor methods
# for each serialized property. # for each serialized property.
# Also keep track of updated properties in a similar way as ActiveModel::Dirty # Also keep track of updated properties in a similar way as ActiveModel::Dirty
......
...@@ -85,6 +85,7 @@ class User < ActiveRecord::Base ...@@ -85,6 +85,7 @@ class User < ActiveRecord::Base
has_one :abuse_report, dependent: :destroy has_one :abuse_report, dependent: :destroy
has_many :spam_logs, dependent: :destroy has_many :spam_logs, dependent: :destroy
has_many :builds, dependent: :nullify, class_name: 'Ci::Build' has_many :builds, dependent: :nullify, class_name: 'Ci::Build'
has_many :pipelines, dependent: :nullify, class_name: 'Ci::Pipeline'
has_many :todos, dependent: :destroy has_many :todos, dependent: :destroy
has_many :notification_settings, dependent: :destroy has_many :notification_settings, dependent: :destroy
has_many :award_emoji, dependent: :destroy has_many :award_emoji, dependent: :destroy
...@@ -853,7 +854,7 @@ class User < ActiveRecord::Base ...@@ -853,7 +854,7 @@ class User < ActiveRecord::Base
groups.joins(:shared_projects).select(:project_id)] groups.joins(:shared_projects).select(:project_id)]
if min_access_level if min_access_level
scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } scope = { access_level: Gitlab::Access.all_values.select { |access| access >= min_access_level } }
relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) } relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) }
end end
......
...@@ -15,7 +15,7 @@ module Ci ...@@ -15,7 +15,7 @@ module Ci
status == 'success' status == 'success'
when 'on_failure' when 'on_failure'
status == 'failed' status == 'failed'
when 'always' when 'always', 'manual'
%w(success failed).include?(status) %w(success failed).include?(status)
end end
end end
...@@ -36,7 +36,9 @@ module Ci ...@@ -36,7 +36,9 @@ module Ci
:allow_failure, :allow_failure,
:stage, :stage,
:stage_idx, :stage_idx,
:environment) :environment,
:when,
:yaml_variables)
build_attrs.merge!(pipeline: @pipeline, build_attrs.merge!(pipeline: @pipeline,
ref: @pipeline.ref, ref: @pipeline.ref,
...@@ -45,6 +47,10 @@ module Ci ...@@ -45,6 +47,10 @@ module Ci
user: user, user: user,
project: @pipeline.project) project: @pipeline.project)
# TODO: The proper implementation for this is in
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5295
build_attrs[:status] = 'skipped' if build_attrs[:when] == 'manual'
## ##
# We do not persist new builds here. # We do not persist new builds here.
# Those will be persisted when @pipeline is saved. # Those will be persisted when @pipeline is saved.
......
...@@ -2,6 +2,7 @@ module Ci ...@@ -2,6 +2,7 @@ module Ci
class CreatePipelineService < BaseService class CreatePipelineService < BaseService
def execute def execute
pipeline = project.pipelines.new(params) pipeline = project.pipelines.new(params)
pipeline.user = current_user
unless ref_names.include?(params[:ref]) unless ref_names.include?(params[:ref])
pipeline.errors.add(:base, 'Reference not found') pipeline.errors.add(:base, 'Reference not found')
......
...@@ -23,7 +23,7 @@ module Commits ...@@ -23,7 +23,7 @@ module Commits
private private
def check_push_permissions def check_push_permissions
allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch) allowed = ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(@target_branch)
unless allowed unless allowed
raise ValidationError.new('You are not allowed to push into this branch') raise ValidationError.new('You are not allowed to push into this branch')
...@@ -31,7 +31,7 @@ module Commits ...@@ -31,7 +31,7 @@ module Commits
true true
end end
def create_target_branch(new_branch) def create_target_branch(new_branch)
# Temporary branch exists and contains the change commit # Temporary branch exists and contains the change commit
return success if repository.find_branch(new_branch) return success if repository.find_branch(new_branch)
......
...@@ -15,21 +15,19 @@ class CreateBranchService < BaseService ...@@ -15,21 +15,19 @@ class CreateBranchService < BaseService
return error('Branch already exists') return error('Branch already exists')
end end
new_branch = nil new_branch = if source_project != @project
repository.fetch_ref(
if source_project != @project source_project.repository.path_to_repo,
repository.with_tmp_ref do |tmp_ref| "refs/heads/#{ref}",
repository.fetch_ref( "refs/heads/#{branch_name}"
source_project.repository.path_to_repo, )
"refs/heads/#{ref}",
tmp_ref repository.after_create_branch
)
repository.find_branch(branch_name)
new_branch = repository.add_branch(current_user, branch_name, tmp_ref) else
end repository.add_branch(current_user, branch_name, ref)
else end
new_branch = repository.add_branch(current_user, branch_name, ref)
end
if new_branch if new_branch
success(new_branch) success(new_branch)
......
...@@ -14,7 +14,13 @@ class CreateCommitBuildsService ...@@ -14,7 +14,13 @@ class CreateCommitBuildsService
return false return false
end end
@pipeline = Ci::Pipeline.new(project: project, sha: sha, ref: ref, before_sha: before_sha, tag: tag) @pipeline = Ci::Pipeline.new(
project: project,
sha: sha,
ref: ref,
before_sha: before_sha,
tag: tag,
user: user)
## ##
# Skip creating pipeline if no gitlab-ci.yml is found # Skip creating pipeline if no gitlab-ci.yml is found
......
...@@ -9,12 +9,14 @@ module Files ...@@ -9,12 +9,14 @@ module Files
@commit_message = params[:commit_message] @commit_message = params[:commit_message]
@file_path = params[:file_path] @file_path = params[:file_path]
@previous_path = params[:previous_path]
@file_content = if params[:file_content_encoding] == 'base64' @file_content = if params[:file_content_encoding] == 'base64'
Base64.decode64(params[:file_content]) Base64.decode64(params[:file_content])
else else
params[:file_content] params[:file_content]
end end
# Validate parameters
validate validate
# Create new branch if it different from source_branch # Create new branch if it different from source_branch
...@@ -42,7 +44,7 @@ module Files ...@@ -42,7 +44,7 @@ module Files
end end
def validate def validate
allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch) allowed = ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(@target_branch)
unless allowed unless allowed
raise_error("You are not allowed to push into this branch") raise_error("You are not allowed to push into this branch")
......
...@@ -3,7 +3,10 @@ require_relative "base_service" ...@@ -3,7 +3,10 @@ require_relative "base_service"
module Files module Files
class UpdateService < Files::BaseService class UpdateService < Files::BaseService
def commit def commit
repository.commit_file(current_user, @file_path, @file_content, @commit_message, @target_branch, true) repository.update_file(current_user, @file_path, @file_content,
branch: @target_branch,
previous_path: @previous_path,
message: @commit_message)
end end
end end
end end
...@@ -89,7 +89,8 @@ class GitPushService < BaseService ...@@ -89,7 +89,8 @@ class GitPushService < BaseService
# Set protection on the default branch if configured # Set protection on the default branch if configured
if current_application_settings.default_branch_protection != PROTECTION_NONE if current_application_settings.default_branch_protection != PROTECTION_NONE
developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false
@project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push }) developers_can_merge = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_MERGE ? true : false
@project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push, developers_can_merge: developers_can_merge })
end end
end end
......
...@@ -101,6 +101,7 @@ class IssuableBaseService < BaseService ...@@ -101,6 +101,7 @@ class IssuableBaseService < BaseService
def update(issuable) def update(issuable)
change_state(issuable) change_state(issuable)
change_subscription(issuable)
filter_params filter_params
old_labels = issuable.labels.to_a old_labels = issuable.labels.to_a
...@@ -124,6 +125,15 @@ class IssuableBaseService < BaseService ...@@ -124,6 +125,15 @@ class IssuableBaseService < BaseService
end end
end end
def change_subscription(issuable)
case params.delete(:subscription_event)
when 'subscribe'
issuable.subscribe(current_user)
when 'unsubscribe'
issuable.unsubscribe(current_user)
end
end
def has_changes?(issuable, old_labels: []) def has_changes?(issuable, old_labels: [])
valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch] valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch]
......
...@@ -4,7 +4,7 @@ module Issues ...@@ -4,7 +4,7 @@ module Issues
issues_ids = params.delete(:issues_ids).split(",") issues_ids = params.delete(:issues_ids).split(",")
issue_params = params issue_params = params
%i(state_event milestone_id assignee_id add_label_ids remove_label_ids).each do |key| %i(state_event milestone_id assignee_id add_label_ids remove_label_ids subscription_event).each do |key|
issue_params.delete(key) unless issue_params[key].present? issue_params.delete(key) unless issue_params[key].present?
end end
......
...@@ -34,7 +34,7 @@ module MergeRequests ...@@ -34,7 +34,7 @@ module MergeRequests
committer: committer committer: committer
} }
commit_id = repository.merge(current_user, merge_request.diff_head_sha, merge_request.target_branch, options) commit_id = repository.merge(current_user, merge_request, options)
merge_request.update(merge_commit_sha: commit_id) merge_request.update(merge_commit_sha: commit_id)
rescue GitHooksService::PreReceiveError => e rescue GitHooksService::PreReceiveError => e
merge_request.update(merge_error: e.message) merge_request.update(merge_error: e.message)
...@@ -43,6 +43,8 @@ module MergeRequests ...@@ -43,6 +43,8 @@ module MergeRequests
merge_request.update(merge_error: "Something went wrong during merge") merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message) Rails.logger.error(e.message)
false false
ensure
merge_request.update(in_progress_merge_commit_sha: nil)
end end
def after_merge def after_merge
......
...@@ -48,7 +48,7 @@ module MergeRequests ...@@ -48,7 +48,7 @@ module MergeRequests
end end
def force_push? def force_push?
Gitlab::ForcePushCheck.force_push?(@project, @oldrev, @newrev) Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
end end
# Refresh merge request diff if we push to source or target branch of merge request # Refresh merge request diff if we push to source or target branch of merge request
......
...@@ -9,7 +9,7 @@ module Projects ...@@ -9,7 +9,7 @@ module Projects
private private
def save_all def save_all
if [version_saver, project_tree_saver, uploads_saver, repo_saver, wiki_repo_saver].all?(&:save) if [version_saver, avatar_saver, project_tree_saver, uploads_saver, repo_saver, wiki_repo_saver].all?(&:save)
Gitlab::ImportExport::Saver.save(project: project, shared: @shared) Gitlab::ImportExport::Saver.save(project: project, shared: @shared)
notify_success notify_success
else else
...@@ -21,6 +21,10 @@ module Projects ...@@ -21,6 +21,10 @@ module Projects
Gitlab::ImportExport::VersionSaver.new(shared: @shared) Gitlab::ImportExport::VersionSaver.new(shared: @shared)
end end
def avatar_saver
Gitlab::ImportExport::AvatarSaver.new(project: project, shared: @shared)
end
def project_tree_saver def project_tree_saver
Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared) Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared)
end end
......
...@@ -14,4 +14,8 @@ class AvatarUploader < CarrierWave::Uploader::Base ...@@ -14,4 +14,8 @@ class AvatarUploader < CarrierWave::Uploader::Base
def reset_events_cache(file) def reset_events_cache(file)
model.reset_events_cache if model.is_a?(User) model.reset_events_cache if model.is_a?(User)
end end
def exists?
model.avatar.file && model.avatar.file.exists?
end
end end
...@@ -10,15 +10,20 @@ ...@@ -10,15 +10,20 @@
All All
%span.badge.js-totalbuilds-count= @all_builds.count(:id) %span.badge.js-totalbuilds-count= @all_builds.count(:id)
%li{class: ('active' if @scope == 'pending')}
= link_to admin_builds_path(scope: :pending) do
Pending
%span.badge= number_with_delimiter(@all_builds.pending.count(:id))
%li{class: ('active' if @scope == 'running')} %li{class: ('active' if @scope == 'running')}
= link_to admin_builds_path(scope: :running) do = link_to admin_builds_path(scope: :running) do
Running Running
%span.badge.js-running-count= number_with_delimiter(@all_builds.running_or_pending.count(:id)) %span.badge= number_with_delimiter(@all_builds.running.count(:id))
%li{class: ('active' if @scope == 'finished')} %li{class: ('active' if @scope == 'finished')}
= link_to admin_builds_path(scope: :finished) do = link_to admin_builds_path(scope: :finished) do
Finished Finished
%span.badge.js-running-count= number_with_delimiter(@all_builds.finished.count(:id)) %span.badge= number_with_delimiter(@all_builds.finished.count(:id))
.nav-controls .nav-controls
- if @all_builds.running_or_pending.any? - if @all_builds.running_or_pending.any?
......
.emoji-menu .emoji-menu
= text_field_tag :emoji_search, "", class: "emoji-search search-input form-control", placeholder: "Seach emojis" = text_field_tag :emoji_search, "", class: "emoji-search search-input form-control", placeholder: "Search emoji"
.emoji-menu-content .emoji-menu-content
- Gitlab::AwardEmoji.emoji_by_category.each do |category, emojis| - Gitlab::AwardEmoji.emoji_by_category.each do |category, emojis|
%h5.emoji-menu-title %h5.emoji-menu-title
......
- project = @target_project || @project - project = @target_project || @project
- noteable_class = @noteable.class if @noteable.present?
- if @noteable :javascript
:javascript GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_class, type_id: params[:id])}"
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}" GitLab.GfmAutoComplete.cachedData = undefined;
GitLab.GfmAutoComplete.cachedData = undefined; GitLab.GfmAutoComplete.setup();
GitLab.GfmAutoComplete.setup();
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
= icon('code-fork') = icon('code-fork')
= ref = ref
%span.editor-file-name %span.editor-file-name
= @path - if current_action?(:edit) || current_action?(:update)
= text_field_tag 'file_path', (params[:file_path] || @path),
class: 'form-control new-file-path'
- if current_action?(:new) || current_action?(:create) - if current_action?(:new) || current_action?(:create)
%span.editor-file-name %span.editor-file-name
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
- if @build.duration - if @build.duration
%p.build-detail-row %p.build-detail-row
%span.build-light-text Duration: %span.build-light-text Duration:
#{duration_in_words(@build.finished_at, @build.started_at)} = time_interval_in_words(@build.duration)
- if @build.finished_at - if @build.finished_at
%p.build-detail-row %p.build-detail-row
%span.build-light-text Finished: %span.build-light-text Finished:
...@@ -94,9 +94,9 @@ ...@@ -94,9 +94,9 @@
.block .block
.title .title
Commit message Commit title
%p.build-light-text.append-bottom-0 %p.build-light-text.append-bottom-0
#{@build.pipeline.git_commit_message} #{@build.pipeline.git_commit_title}
- if @build.tags.any? - if @build.tags.any?
.block .block
......
...@@ -11,17 +11,22 @@ ...@@ -11,17 +11,22 @@
%span.badge.js-totalbuilds-count %span.badge.js-totalbuilds-count
= number_with_delimiter(@all_builds.count(:id)) = number_with_delimiter(@all_builds.count(:id))
%li{class: ('active' if @scope == 'pending')}
= link_to project_builds_path(@project, scope: :pending) do
Pending
%span.badge
= number_with_delimiter(@all_builds.pending.count(:id))
%li{class: ('active' if @scope == 'running')} %li{class: ('active' if @scope == 'running')}
= link_to project_builds_path(@project, scope: :running) do = link_to project_builds_path(@project, scope: :running) do
Running Running
%span.badge.js-running-count %span.badge
= number_with_delimiter(@all_builds.running_or_pending.count(:id)) = number_with_delimiter(@all_builds.running.count(:id))
%li{class: ('active' if @scope == 'finished')} %li{class: ('active' if @scope == 'finished')}
= link_to project_builds_path(@project, scope: :finished) do = link_to project_builds_path(@project, scope: :finished) do
Finished Finished
%span.badge.js-running-count %span.badge
= number_with_delimiter(@all_builds.finished.count(:id)) = number_with_delimiter(@all_builds.finished.count(:id))
.nav-controls .nav-controls
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- if current_user && can?(current_user, :fork_project, @project) - if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
%div.count-with-arrow %div.count-with-arrow
%span.arrow %span.arrow
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= @project.forks_count = @project.forks_count
- else - else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
%div.count-with-arrow %div.count-with-arrow
%span.arrow %span.arrow
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
%span.label.label-danger allowed to fail %span.label.label-danger allowed to fail
- if defined?(retried) && retried - if defined?(retried) && retried
%span.label.label-warning retried %span.label.label-warning retried
- if build.manual?
%span.label.label-info manual
- if defined?(runner) && runner - if defined?(runner) && runner
...@@ -79,6 +81,11 @@ ...@@ -79,6 +81,11 @@
- if build.active? - if build.active?
= link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do = link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
= icon('remove', class: 'cred') = icon('remove', class: 'cred')
- elsif defined?(allow_retry) && allow_retry && build.retryable? - elsif defined?(allow_retry) && allow_retry
= link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do - if build.retryable?
= icon('repeat') = link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
= icon('repeat')
- elsif build.playable?
= link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do
= icon('play')
...@@ -10,12 +10,13 @@ ...@@ -10,12 +10,13 @@
= link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id) do = link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id) do
%span ##{pipeline.id} %span ##{pipeline.id}
- if pipeline.ref - if pipeline.ref
.icon-container
= pipeline.tag? ? icon('tag') : icon('code-fork')
= link_to pipeline.ref, namespace_project_commits_path(@project.namespace, @project, pipeline.ref), class: "monospace branch-name" = link_to pipeline.ref, namespace_project_commits_path(@project.namespace, @project, pipeline.ref), class: "monospace branch-name"
= custom_icon("icon_commit") .icon-container
= custom_icon("icon_commit")
= link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: "commit-id monospace" = link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: "commit-id monospace"
- if pipeline.tag? - if pipeline.latest?
%span.label.label-primary tag
- elsif pipeline.latest?
%span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest %span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest
- if pipeline.triggered? - if pipeline.triggered?
%span.label.label-primary triggered %span.label.label-primary triggered
...@@ -32,9 +33,9 @@ ...@@ -32,9 +33,9 @@
Cant find HEAD commit for this branch Cant find HEAD commit for this branch
- stages_status = pipeline.statuses.stages_status - stages_status = pipeline.statuses.latest.stages_status
- stages.each do |stage| - stages.each do |stage|
%td %td.stage-cell
- status = stages_status[stage] - status = stages_status[stage]
- tooltip = "#{stage.titleize}: #{status || 'not found'}" - tooltip = "#{stage.titleize}: #{status || 'not found'}"
- if status - if status
...@@ -57,18 +58,31 @@ ...@@ -57,18 +58,31 @@
%td.pipeline-actions %td.pipeline-actions
.controls.hidden-xs.pull-right .controls.hidden-xs.pull-right
- artifacts = pipeline.builds.latest.select { |b| b.artifacts? } - artifacts = pipeline.builds.latest.select { |b| b.artifacts? }
- if artifacts.present? - actions = pipeline.manual_actions
.inline - if artifacts.present? || actions.any?
.btn-group .btn-group.inline
%a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'} - if actions.any?
= icon("download") .btn-group
%b.caret %a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
%ul.dropdown-menu.dropdown-menu-align-right = icon("play")
- artifacts.each do |build| %b.caret
%li %ul.dropdown-menu.dropdown-menu-align-right
= link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do - actions.each do |build|
= icon("download") %li
%span Download '#{build.name}' artifacts = link_to play_namespace_project_build_path(@project.namespace, @project, build), method: :post, rel: 'nofollow' do
= icon("play")
%span= build.name.humanize
- if artifacts.present?
.btn-group
%a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'}
= icon("download")
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
- artifacts.each do |build|
%li
= link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do
= icon("download")
%span Download '#{build.name}' artifacts
- if can?(current_user, :update_pipeline, @project) - if can?(current_user, :update_pipeline, @project)
.cancel-retry-btns.inline .cancel-retry-btns.inline
......
- if can?(current_user, :create_deployment, deployment) && deployment.deployable
.pull-right
- actions = deployment.manual_actions
- if actions.present?
.btn-group.inline
.btn-group
%a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
= icon("play")
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
- actions.each do |action|
%li
= link_to [:play, @project.namespace.becomes(Namespace), @project, action], method: :post, rel: 'nofollow' do
= icon("play")
%span= action.name.humanize
- if local_assigns.fetch(:allow_rollback, false)
= link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-build' do
- if deployment.last?
Retry
- else
Rollback
...@@ -7,17 +7,11 @@ ...@@ -7,17 +7,11 @@
%td %td
- if deployment.deployable - if deployment.deployable
= link_to namespace_project_build_path(@project.namespace, @project, deployment.deployable) do = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable] do
= "#{deployment.deployable.name} (##{deployment.deployable.id})" = "#{deployment.deployable.name} (##{deployment.deployable.id})"
%td %td
#{time_ago_with_tooltip(deployment.created_at)} #{time_ago_with_tooltip(deployment.created_at)}
%td %td
- if can?(current_user, :create_deployment, deployment) && deployment.deployable = render 'projects/deployments/actions', deployment: deployment, allow_rollback: true
.pull-right
= link_to retry_namespace_project_build_path(@project.namespace, @project, deployment.deployable), method: :post, class: 'btn btn-build' do
- if deployment.last?
Retry
- else
Rollback
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
- elsif blob_text_viewable?(blob) - elsif blob_text_viewable?(blob)
- if !project.repository.diffable?(blob) - if !project.repository.diffable?(blob)
.nothing-here-block This diff was suppressed by a .gitattributes entry. .nothing-here-block This diff was suppressed by a .gitattributes entry.
- elsif diff_file.collapsed?
- url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path))
.nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
This diff is collapsed. Click to expand it.
- elsif diff_file.diff_lines.length > 0 - elsif diff_file.diff_lines.length > 0
- if diff_file.collapsed_by_default? && !expand_all_diffs? - if diff_view == 'parallel'
- url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path))
.nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
This diff is collapsed. Click to expand it.
- elsif diff_view == 'parallel'
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
- else - else
= render "projects/diffs/text_file", diff_file: diff_file = render "projects/diffs/text_file", diff_file: diff_file
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.content-block.oneline-block.files-changed .content-block.oneline-block.files-changed
.inline-parallel-buttons .inline-parallel-buttons
- unless expand_all_diffs? - if !expand_all_diffs? && diff_files.any? { |diff_file| diff_file.collapsed? }
= link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: 'html')), class: 'btn btn-default' = link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: 'html')), class: 'btn btn-default'
- if show_whitespace_toggle - if show_whitespace_toggle
- if current_controller?(:commit) - if current_controller?(:commit)
......
...@@ -15,3 +15,6 @@ ...@@ -15,3 +15,6 @@
%td %td
- if last_deployment - if last_deployment
#{time_ago_with_tooltip(last_deployment.created_at)} #{time_ago_with_tooltip(last_deployment.created_at)}
%td
= render 'projects/deployments/actions', deployment: last_deployment
...@@ -28,4 +28,5 @@ ...@@ -28,4 +28,5 @@
%th Environment %th Environment
%th Last deployment %th Last deployment
%th Date %th Date
%th
= render @environments = render @environments
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%div{ class: container_class } %div{ class: container_class }
.top-area .top-area
.col-md-9 .col-md-9
%h3.page-title= @environment.name.titleize %h3.page-title= @environment.name.capitalize
.col-md-3 .col-md-3
.nav-controls .nav-controls
......
...@@ -31,11 +31,11 @@ ...@@ -31,11 +31,11 @@
- if current_user && can?(current_user, :fork_project, @project) - if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
- else - else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
%td.duration %td.duration
- if generic_commit_status.duration - if generic_commit_status.duration
= icon("clock-o") = icon("clock-o")
#{duration_in_words(generic_commit_status.finished_at, generic_commit_status.started_at)} = time_interval_in_words(generic_commit_status.duration)
%td.timestamp %td.timestamp
- if generic_commit_status.finished_at - if generic_commit_status.finished_at
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
%p %p
Please resolve these conflicts or Please resolve these conflicts or
- if @merge_request.can_be_merged_by?(current_user) - if @merge_request.can_be_merged_via_command_line_by?(current_user)
#{link_to "merge this request manually", "#modal_merge_info", class: "how_to_merge_link vlink", "data-toggle" => "modal"}. #{link_to "merge this request manually", "#modal_merge_info", class: "how_to_merge_link vlink", "data-toggle" => "modal"}.
- else - else
ask someone with write access to this repository to merge this request manually. ask someone with write access to this repository to merge this request manually.
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
.disabled-comment.text-center .disabled-comment.text-center
.disabled-comment-text.inline .disabled-comment-text.inline
Please Please
= link_to "register",new_user_session_path = link_to "register", new_session_path(:user, redirect_to_referer: 'yes')
or or
= link_to "login",new_user_session_path = link_to "login", new_session_path(:user, redirect_to_referer: 'yes')
to post a comment to post a comment
:javascript :javascript
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
.table-responsive .table-responsive
%table.table.protected-branches-list %table.table.protected-branches-list
%colgroup %colgroup
%col{ width: "20%" }
%col{ width: "30%" } %col{ width: "30%" }
%col{ width: "25%" } %col{ width: "25%" }
%col{ width: "25%" } %col{ width: "25%" }
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
%th Protected Branch %th Protected Branch
%th Commit %th Commit
%th Developers Can Push %th Developers Can Push
%th Developers Can Merge
- if can_admin_project - if can_admin_project
%th %th
%tbody %tbody
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
(branch was removed from repository) (branch was removed from repository)
%td %td
= check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url }) = check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url })
%td
= check_box_tag("developers_can_merge", protected_branch.id, protected_branch.developers_can_merge, data: { url: url })
- if can_admin_project - if can_admin_project
%td %td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right" = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"
...@@ -36,6 +36,14 @@ ...@@ -36,6 +36,14 @@
= f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0" = f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0"
%p.light.append-bottom-0 %p.light.append-bottom-0
Allow developers to push to this branch Allow developers to push to this branch
.form-group
= f.check_box :developers_can_merge, class: "pull-left"
.prepend-left-20
= f.label :developers_can_merge, "Developers can merge", class: "label-light append-bottom-0"
%p.light.append-bottom-0
Allow developers to accept merge requests to this branch
= f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true = f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
%hr %hr
= render "branches_list" = render "branches_list"
...@@ -12,5 +12,5 @@ ...@@ -12,5 +12,5 @@
&nbsp; &nbsp;
- if @service.valid? && @service.activated? - if @service.valid? && @service.activated?
- disabled = @service.can_test? ? '':'disabled' - disabled = @service.can_test? ? '':'disabled'
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}" = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled}", title: @service.disabled_title
= link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
- @no_container = true
- page_title @tag.name, "Tags" - page_title @tag.name, "Tags"
= render "projects/commits/head" = render "projects/commits/head"
.row-content-block %div{ class: container_class }
.pull-right .sub-header-block
- if can?(current_user, :push_code, @project) .pull-right.tag-buttons
= link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn has-tooltip', title: 'Edit release notes' do - if can?(current_user, :push_code, @project)
= icon("pencil") = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Edit release notes' do
= link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse files' do = icon("pencil")
= icon('files-o') = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse files' do
= link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse commits' do = icon('files-o')
= icon('history') = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse commits' do
- if can? current_user, :download_code, @project = icon('history')
= render 'projects/tags/download', ref: @tag.name, project: @project - if can? current_user, :download_code, @project
- if can?(current_user, :admin_project, @project) = render 'projects/tags/download', ref: @tag.name, project: @project
.pull-right - if can?(current_user, :admin_project, @project)
= link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do .pull-right
%i.fa.fa-trash-o = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
.title %i.fa.fa-trash-o
%span.item-title= @tag.name .tag-info.append-bottom-10
- if @commit .title
= render 'projects/branches/commit', commit: @commit, project: @project %span.item-title= @tag.name
- else - if @commit
Cant find HEAD commit for this tag = render 'projects/branches/commit', commit: @commit, project: @project
- if @tag.message.present? - else
%pre.body Cant find HEAD commit for this tag
= strip_gpg_signature(@tag.message) - if @tag.message.present?
%pre.body
= strip_gpg_signature(@tag.message)
.append-bottom-default.prepend-top-default .append-bottom-default.prepend-top-default
- if @release.description.present? - if @release.description.present?
.description .description
.wiki .wiki
= preserve do = preserve do
= markdown @release.description = markdown @release.description
- else - else
This tag has no release notes. This tag has no release notes.
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle id="a" cx="4" cy="4" r="4"/><mask id="d" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#a"/></mask><circle id="b" cx="20" cy="4" r="4"/><mask id="e" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#b"/></mask><circle id="c" cx="12" cy="30" r="4"/><mask id="f" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#c"/></mask></defs><g fill="none" fill-rule="evenodd" transform="translate(8 3)"><path fill="#7E7E7E" d="M10 19.667c-4.14-1.29-7.389-5.878-7.389-5.878C2.274 13.353 2 12.545 2 12.01V6h4v5.509c0 .276.166.65.367.831 0 0 1.136 1.028 1.746 1.574C9.617 15.261 11.048 16 12.09 16c1.028 0 2.41-.723 3.858-2.048.588-.54 1.84-1.742 1.84-1.742a.784.784 0 0 0 .211-.502V6h4v6.008c0 .548-.259 1.349-.601 1.795 0 0-3.21 4.707-7.399 5.916V27h-4v-7.333z"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#d)" xlink:href="#a"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#e)" xlink:href="#b"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#f)" xlink:href="#c"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#5C5C5C" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<rect width="10" height="1" x="2" y="6.5" fill="#5C5C5C" transform="rotate(45 7 7)" rx=".3"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#D22852" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<path fill="#D22852" d="M7.5,6.5 L7.5,4.30578971 C7.5,4.12531853 7.36809219,4 7.20537567,4 L6.79462433,4 C6.63904572,4 6.5,4.13690672 6.5,4.30578971 L6.5,6.5 L4.30578971,6.5 C4.12531853,6.5 4,6.63190781 4,6.79462433 L4,7.20537567 C4,7.36095428 4.13690672,7.5 4.30578971,7.5 L6.5,7.5 L6.5,9.69421029 C6.5,9.87468147 6.63190781,10 6.79462433,10 L7.20537567,10 C7.36095428,10 7.5,9.86309328 7.5,9.69421029 L7.5,7.5 L9.69421029,7.5 C9.87468147,7.5 10,7.36809219 10,7.20537567 L10,6.79462433 C10,6.63904572 9.86309328,6.5 9.69421029,6.5 L7.5,6.5 Z" transform="rotate(45 7 7)"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#E75E40" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<rect width="1" height="4" x="5" y="5" fill="#E75E40" rx=".3"/>
<rect width="1" height="4" x="8" y="5" fill="#E75E40" rx=".3"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#2D9FD8" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<path fill="#2D9FD8" d="M7,3.00800862 C9.09023405,3.13960661 10.7448145,4.87657932 10.7448145,7 C10.7448145,9.209139 8.95395346,11 6.74481446,11 C5.4560962,11 4.30972054,10.3905589 3.57817301,9.44416214 L7,7 L7,3.00800862 Z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#31AF64" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<g fill="#31AF64" transform="rotate(45 -.13 10.953)">
<rect width="1" height="5" x="2" rx=".3"/>
<rect width="3" height="1" y="4" rx=".3"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<g fill="#FF8A24" transform="translate(6 3)">
<rect width="2" height="5" rx=".5"/>
<rect width="2" height="2" y="6" rx=".5"/>
</g>
<use stroke="#FF8A24" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
</g>
</svg>
...@@ -44,9 +44,15 @@ ...@@ -44,9 +44,15 @@
placeholder: "Search authors", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: "update[assignee_id]" } }) placeholder: "Search authors", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: "update[assignee_id]" } })
.filter-item.inline .filter-item.inline
= dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update', filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } }) = dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update', filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } })
.filter-item.inline.labels-filter .filter-item.inline.labels-filter
= render "shared/issuable/label_dropdown", classes: ['js-filter-bulk-update', 'js-multiselect'], show_create: false, show_footer: false, extra_options: false, filter_submit: false, show_footer: false, data_options: { persist_when_hide: "true", field_name: "update[label_ids][]", show_no: false, show_any: false, use_id: true } = render "shared/issuable/label_dropdown", classes: ['js-filter-bulk-update', 'js-multiselect'], show_create: false, show_footer: false, extra_options: false, filter_submit: false, show_footer: false, data_options: { persist_when_hide: "true", field_name: "update[label_ids][]", show_no: false, show_any: false, use_id: true }
.filter-item.inline
= dropdown_tag("Subscription", options: { toggle_class: "js-subscription-event", title: "Change subscription", dropdown_class: "dropdown-menu-selectable", data: { field_name: "update[subscription_event]" } } ) do
%ul
%li
%a{href: "#", data: {id: "subscribe"}} Subscribe
%li
%a{href: "#", data: {id: "unsubscribe"}} Unsubscribe
= hidden_field_tag 'update[issues_ids]', [] = hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :state_event, params[:state_event] = hidden_field_tag :state_event, params[:state_event]
...@@ -63,6 +69,7 @@ ...@@ -63,6 +69,7 @@
new LabelsSelect(); new LabelsSelect();
new MilestoneSelect(); new MilestoneSelect();
new IssueStatusSelect(); new IssueStatusSelect();
new SubscriptionSelect();
$('form.filter-form').on('submit', function (event) { $('form.filter-form').on('submit', function (event) {
event.preventDefault(); event.preventDefault();
Turbolinks.visit(this.action + '&' + $(this).serialize()); Turbolinks.visit(this.action + '&' + $(this).serialize());
......
class ProjectExportWorker class ProjectExportWorker
include Sidekiq::Worker include Sidekiq::Worker
sidekiq_options queue: :gitlab_shell, retry: true sidekiq_options queue: :gitlab_shell, retry: 3
def perform(current_user_id, project_id) def perform(current_user_id, project_id)
current_user = User.find(current_user_id) current_user = User.find(current_user_id)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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