Commit e5b05fe8 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge branch 'master' into artifacts-from-ref-and-build-name-api

* master: (261 commits)
  Add link to user profile to commit avatar (!5163)
  Refactor service settings view
  Fix a problem with processing a pipeline where stage only has manual actions
  A CHANGELOG entry
  Don't show other actions of the same name
  Use limit parameter rather than hardcoded value
  Remove icons from explore nav
  Change how we style redirect_to
  Use flash[:notice] only
  Create PipelinesSettingsController for showing settings page
  Fix a few nitpicks
  Allow to disable user request access to groups/projects
  Enable Style/MultilineTernaryOperator rubocop cop
  Fix review comments
  Update routes
  Update CHANGELOG
  Improve implementation of variables
  Log cron_jobs configuration instead of raising exception
  Added checks for migration downtime
  Ensure to_json methods take optional argument
  ...
parents 122b046b b4717017
......@@ -148,7 +148,7 @@ spinach 9 10: *spinach-knapsack
.spinach-knapsack-ruby23: &spinach-knapsack-ruby23
<<: *spinach-knapsack
<<: *ruby-23
rspec 0 20 ruby23: *rspec-knapsack-ruby23
rspec 1 20 ruby23: *rspec-knapsack-ruby23
rspec 2 20 ruby23: *rspec-knapsack-ruby23
......@@ -196,6 +196,7 @@ rake flog: *exec
rake flay: *exec
rake db:migrate:reset: *exec
license_finder: *exec
rake downtime_check: *exec
bundler:audit:
stage: test
......
......@@ -291,6 +291,10 @@ Style/MultilineMethodDefinitionBraceLayout:
Style/MultilineOperationIndentation:
Enabled: false
# Avoid multi-line `? :` (the ternary operator), use if/unless instead.
Style/MultilineTernaryOperator:
Enabled: true
# Favor unless over if for negative conditions (or control flow or).
Style/NegatedIf:
Enabled: true
......
......@@ -226,10 +226,6 @@ Style/LineEndConcatenation:
Style/MethodCallParentheses:
Enabled: false
# Offense count: 3
Style/MultilineTernaryOperator:
Enabled: false
# Offense count: 62
# Cop supports --auto-correct.
Style/MutableConstant:
......
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)
- Fix profile activity heatmap to show correct day name (eanplatter)
- Speed up ExternalWikiHelper#get_project_wiki_path
- 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
- 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
- Replace Haml with Hamlit to make view rendering faster. !3666
- Refresh the branch cache after `git gc` runs
- Allow to disable request access button on projects/groups
- Refactor repository paths handling to allow multiple git mount points
- Optimize system note visibility checking by memoizing the visible reference count !5070
- Add Application Setting to configure default Repository Path for new projects
- Delete award emoji when deleting a user
- Remove pinTo from Flash and make inline flash messages look nicer !4854 (winniehell)
- Add an API for downloading latest successful build from a particular branch or tag !5347
- Add link to profile to commit avatar !5163 (winniehell)
- Wrap code blocks on Activies and Todos page. !4783 (winniehell)
- Align flash messages with left side of page content !4959 (winniehell)
- Display tooltip for "Copy to Clipboard" button !5164 (winniehell)
......@@ -25,6 +30,9 @@ v 8.10.0 (unreleased)
- Escape file extension when parsing search results !5141 (winniehell)
- Apply the trusted_proxies config to the rack request object for use with rack_attack
- Upgrade to Rails 4.2.7. !5236
- Extend exposed environment variables for CI builds
- Allow to pull code with deploy key from public projects
- Use limit parameter rather than hardcoded value in `ldap:check` rake task (Mike Ricketts)
- Add Sidekiq queue duration to transaction metrics.
- Add a new column `artifacts_size` to table `ci_builds` !4964
- Let Workhorse serve format-patch diffs
......@@ -33,6 +41,7 @@ v 8.10.0 (unreleased)
- Added day name to contribution calendar tooltips
- Make images fit to the size of the viewport !4810
- 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
- Support U2F devices in Firefox. !5177
- Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
......@@ -50,6 +59,7 @@ v 8.10.0 (unreleased)
- The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020
- Updated project header design
- Issuable collapsed assignee tooltip is now the users name
- Fix compare view not changing code view rendering style
- Exclude email check from the standard health check
- Updated layout for Projects, Groups, Users on Admin area !4424
- Fix changing issue state columns in milestone view
......@@ -89,6 +99,7 @@ v 8.10.0 (unreleased)
- Avoid to retrieve MR closes_issues as much as possible.
- Add API endpoint for a group issues !4520 (mahcsig)
- Add Bugzilla integration !4930 (iamtjg)
- Fix new snippet style bug (elliotec)
- Instrument Rinku usage
- Be explicit to define merge request discussion variables
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
......@@ -99,6 +110,7 @@ v 8.10.0 (unreleased)
- Don't render discussion notes when requesting diff tab through AJAX
- Add basic system information like memory and disk usage to the admin panel
- Don't garbage collect commits that have related DB records like comments
- Allow to setup event by channel on slack service
- More descriptive message for git hooks and file locks
- Aliases of award emoji should be stored as original name. !5060 (dixpac)
- Handle custom Git hook result in GitLab UI
......@@ -124,13 +136,17 @@ v 8.10.0 (unreleased)
- Fix last update timestamp on issues not preserved on gitlab.com and project imports
- Fix issues importing projects from EE to CE
- Fix creating group with space in group path
- Improve cron_jobs loading error messages !5318
- Improve cron_jobs loading error messages !5318 / !5360
- 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
- Move builds settings out of project settings and rename Pipelines
- Add builds badge to Pipelines settings page
- Export and import avatar as part of project import/export
- Fix migration corrupting import data for old version upgrades
v 8.9.6
- Fix importing of events under notes for GitLab projects. !5154
......
......@@ -578,7 +578,7 @@ GEM
railties (>= 4.2.0, < 5.1)
rinku (2.0.0)
rotp (2.1.2)
rouge (2.0.3)
rouge (2.0.5)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
......
......@@ -232,7 +232,9 @@
.nav-block {
.controls {
float: right;
margin-top: 11px;
margin-top: 8px;
padding-bottom: 7px;
border-bottom: 1px solid $border-color;
}
}
......
......@@ -49,6 +49,17 @@
border-color: $border-dark;
color: $color;
}
svg {
path {
fill: $color;
}
use {
stroke: $color;
}
}
}
@mixin btn-green {
......@@ -173,6 +184,13 @@
.caret {
margin-left: 5px;
}
svg {
height: 15px;
width: auto;
position: relative;
top: 2px;
}
}
.btn-lg {
......
......@@ -198,6 +198,10 @@ header.header-pinned-nav {
.sidebar-collapsed-icon {
cursor: pointer;
.btn {
background-color: $gray-light;
}
}
}
......
......@@ -122,7 +122,8 @@
button {
float: right;
padding: 3px 5px;
padding: 1px 5px;
background-color: $gray-light;
}
}
......
......@@ -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) {
.issue-btn-group {
width: 100%;
......
......@@ -60,8 +60,10 @@
.ci_widget {
border-bottom: 1px solid #eef0f2;
i {
svg {
margin-right: 4px;
position: relative;
top: 1px;
}
&.ci-success {
......@@ -196,6 +198,16 @@
.merge-request-title {
margin-bottom: 2px;
.ci-status-link {
svg {
height: 16px;
width: 16px;
position: relative;
top: 3px;
}
}
}
}
......
......@@ -49,6 +49,14 @@
.commit-link {
.ci-status {
svg {
top: 1px;
margin-right: 0;
}
}
a:hover {
text-decoration: none;
}
......@@ -124,6 +132,15 @@
}
}
.stage-cell {
svg {
height: 18px;
width: 18px;
vertical-align: middle;
}
}
.duration,
.finished-at {
color: $table-text-gray;
......
......@@ -129,6 +129,17 @@
color: $layout-link-gray;
}
svg {
path {
fill: $layout-link-gray;
}
use {
stroke: $layout-link-gray;
}
}
.fa-caret-down {
margin-left: 3px;
}
......@@ -322,18 +333,53 @@ a.deploy-project-label {
}
.fork-namespaces {
.fork-thumbnail {
text-align: center;
margin-bottom: $gl-padding;
.caption {
padding: $gl-padding 0;
min-height: 30px;
}
.row {
-webkit-flex-wrap: wrap;
display: -webkit-flex;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.fork-thumbnail {
@include border-radius($border-radius-base);
background-color: $white-light;
border: 1px solid $border-white-light;
height: 202px;
margin: $gl-padding;
text-align: center;
width: 169px;
&:hover, &.forked {
background-color: $row-hover;
border-color: $row-hover-border;
}
.no-avatar {
width: 100px;
height: 100px;
background-color: $gray-light;
border: 1px solid $gray-dark;
margin: 0 auto;
@include border-radius(50%);
i {
font-size: 100px;
color: $gray-dark;
}
}
a {
display: block;
width: 100%;
height: 100%;
padding-top: $gl-padding;
color: $gl-gray;
.caption {
min-height: 30px;
padding: $gl-padding 0;
}
}
img {
@include border-radius(50%);
max-width: 100px;
img {
@include border-radius(50%);
max-width: 100px;
}
}
}
}
......@@ -486,6 +532,11 @@ pre.light-well {
> span {
margin-left: 10px;
}
svg {
position: relative;
top: 2px;
}
}
}
......
......@@ -41,6 +41,14 @@
color: $blue-normal;
border-color: $blue-normal;
}
svg {
height: 13px;
width: 13px;
position: relative;
top: 1px;
margin: 0 3px;
}
}
.ci-status-icon-success {
......
.tag-buttons {
line-height: 40px;
.btn:not(.dropdown-toggle) {
margin-left: 10px;
}
}
......@@ -60,6 +60,6 @@ class Admin::GroupsController < Admin::ApplicationController
end
def group_params
params.require(:group).permit(:name, :description, :path, :avatar, :visibility_level)
params.require(:group).permit(:name, :description, :path, :avatar, :visibility_level, :request_access_enabled)
end
end
class Admin::ServicesController < Admin::ApplicationController
include ServiceParams
before_action :service, only: [:edit, :update]
def index
......@@ -13,7 +15,7 @@ class Admin::ServicesController < Admin::ApplicationController
end
def update
if service.update_attributes(application_services_params[:service])
if service.update_attributes(service_params[:service])
redirect_to admin_application_settings_services_path,
notice: 'Application settings saved successfully'
else
......@@ -37,15 +39,4 @@ class Admin::ServicesController < Admin::ApplicationController
def service
@service ||= Service.where(id: params[:id], template: true).first
end
def application_services_params
application_services_params = params.permit(:id,
service: Projects::ServicesController::ALLOWED_PARAMS)
if application_services_params[:service].is_a?(Hash)
Projects::ServicesController::FILTER_BLANK_PARAMS.each do |param|
application_services_params[:service].delete(param) if application_services_params[:service][param].blank?
end
end
application_services_params
end
end
......@@ -7,7 +7,8 @@ module CreatesCommit
commit_params = @commit_params.merge(
source_project: @project,
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
......
module ServiceParams
extend ActiveSupport::Concern
ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_url, :api_version, :subdomain,
:room, :recipients, :project_url, :webhook,
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
:build_key, :server, :teamcity_url, :drone_url, :build_type,
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
:colorize_messages, :channels,
:push_events, :issues_events, :merge_requests_events, :tag_push_events,
:note_events, :build_events, :wiki_page_events,
:notify_only_broken_builds, :add_pusher,
:send_from_committer_email, :disable_diffs, :external_wiki_url,
:notify, :color,
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
:jira_issue_transition_id]
# Parameters to ignore if no value is specified
FILTER_BLANK_PARAMS = [:password]
def service_params
dynamic_params = []
dynamic_params.concat(@service.event_channel_names)
service_params = params.permit(:id, service: ALLOWED_PARAMS + dynamic_params)
if service_params[:service].is_a?(Hash)
FILTER_BLANK_PARAMS.each do |param|
service_params[:service].delete(param) if service_params[:service][param].blank?
end
end
service_params
end
end
......@@ -121,7 +121,7 @@ class GroupsController < Groups::ApplicationController
end
def group_params
params.require(:group).permit(:name, :description, :path, :avatar, :public, :visibility_level, :share_with_group_lock)
params.require(:group).permit(:name, :description, :path, :avatar, :public, :visibility_level, :share_with_group_lock, :request_access_enabled)
end
def load_events
......
......@@ -3,11 +3,6 @@ class Projects::BadgesController < Projects::ApplicationController
before_action :authorize_admin_project!, only: [:index]
before_action :no_cache_headers, except: [:index]
def index
@ref = params[:ref] || @project.default_branch || 'master'
@build_badge = Gitlab::Badge::Build.new(@project, @ref)
end
def build
badge = Gitlab::Badge::Build.new(project, params[:ref])
......
......@@ -38,6 +38,12 @@ class Projects::BlobController < Projects::ApplicationController
end
def update
if params[:file_path].present?
@previous_path = @path
@path = params[:file_path]
@commit_params[:file_path] = @path
end
after_edit_path =
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) +
......
......@@ -15,6 +15,7 @@ class Projects::CompareController < Projects::ApplicationController
end
def show
apply_diff_view_cookie!
end
def diff_for_path
......
class Projects::PipelinesSettingsController < Projects::ApplicationController
before_action :authorize_admin_pipeline!
def show
@ref = params[:ref] || @project.default_branch || 'master'
@build_badge = Gitlab::Badge::Build.new(@project, @ref)
end
def update
if @project.update_attributes(update_params)
flash[:notice] = "CI/CD Pipelines settings for '#{@project.name}' were successfully updated."
redirect_to namespace_project_pipelines_settings_path(@project.namespace, @project)
else
render 'index'
end
end
private
def create_params
params.require(:pipeline).permit(:ref)
end
def update_params
params.require(:project).permit(
:runners_token, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds
)
end
end
......@@ -25,7 +25,7 @@ class Projects::RefsController < Projects::ApplicationController
when "graphs_commits"
commits_namespace_project_graph_path(@project.namespace, @project, @id)
when "badges"
namespace_project_badges_path(@project.namespace, @project, ref: @id)
namespace_project_pipelines_settings_path(@project.namespace, @project, ref: @id)
else
namespace_project_commits_path(@project.namespace, @project, @id)
end
......
class Projects::ServicesController < Projects::ApplicationController
ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_url, :api_version, :subdomain,
:room, :recipients, :project_url, :webhook,
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
:build_key, :server, :teamcity_url, :drone_url, :build_type,
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
:colorize_messages, :channels,
:push_events, :issues_events, :merge_requests_events, :tag_push_events,
:note_events, :build_events, :wiki_page_events,
:notify_only_broken_builds, :add_pusher,
:send_from_committer_email, :disable_diffs, :external_wiki_url,
:notify, :color,
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
:jira_issue_transition_id]
# Parameters to ignore if no value is specified
FILTER_BLANK_PARAMS = [:password]
include ServiceParams
# Authorize
before_action :authorize_admin_project!
......@@ -33,7 +18,7 @@ class Projects::ServicesController < Projects::ApplicationController
end
def update
if @service.update_attributes(service_params)
if @service.update_attributes(service_params[:service])
redirect_to(
edit_namespace_project_service_path(@project.namespace, @project,
@service.to_param, notice:
......@@ -64,12 +49,4 @@ class Projects::ServicesController < Projects::ApplicationController
def service
@service ||= @project.services.find { |service| service.to_param == params[:id] }
end
def service_params
service_params = params.require(:service).permit(ALLOWED_PARAMS)
FILTER_BLANK_PARAMS.each do |param|
service_params.delete(param) if service_params[param].blank?
end
service_params
end
end
......@@ -296,7 +296,7 @@ class ProjectsController < Projects::ApplicationController
:issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds, :only_allow_merge_if_build_succeeds
:public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled
)
end
......
module AvatarsHelper
def author_avatar(commit_or_event, options = {})
user_avatar(options.merge({
user: commit_or_event.author,
user_name: commit_or_event.author_name,
user_email: commit_or_event.author_email,
}))
end
private
def user_avatar(options = {})
avatar_size = options[:size] || 16
user_name = options[:user].try(:name) || options[:user_name]
avatar = image_tag(
avatar_icon(options[:user] || options[:user_email], avatar_size),
class: "avatar has-tooltip hidden-xs s#{avatar_size}",
alt: "#{user_name}'s avatar",
title: user_name
)
if options[:user]
link_to(avatar, user_path(options[:user]))
elsif options[:user_email]
mail_to(options[:user_email], avatar)
end
end
end
......@@ -26,18 +26,20 @@ module CiStatusHelper
icon_name =
case status
when 'success'
'check'
'icon_status_success'
when 'success_with_warnings'
'icon_status_warning'
when 'failed'
'close'
'icon_status_failed'
when 'pending'
'clock-o'
'icon_status_pending'
when 'running'
'spinner'
'icon_status_running'
else
'circle'
'icon_status_cancel'
end
icon(icon_name + ' fw')
custom_icon(icon_name)
end
def render_commit_status(commit, tooltip_placement: 'auto left', cssclass: '')
......
......@@ -16,16 +16,6 @@ module CommitsHelper
commit_person_link(commit, options.merge(source: :committer))
end
def commit_author_avatar(commit, options = {})
options = options.merge(source: :author)
user = commit.send(options[:source])
source_email = clean(commit.send "#{options[:source]}_email".to_sym)
person_email = user.try(:email) || source_email
image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]} hidden-xs", width: options[:size], alt: "")
end
def image_diff_class(diff)
if diff.deleted_file
"deleted"
......
module ExternalWikiHelper
def get_project_wiki_path(project)
external_wiki_service = project.services.
find { |service| service.to_param == 'external_wiki' }
if external_wiki_service.present? && external_wiki_service.active?
external_wiki_service = project.external_wiki
if external_wiki_service
external_wiki_service.properties['external_wiki_url']
else
namespace_project_wiki_path(project.namespace, project, :home)
......
module ServicesHelper
def service_event_description(event)
case event
when "push"
"Event will be triggered by a push to the repository"
when "tag_push"
"Event will be triggered when a new tag is pushed to the repository"
when "note"
"Event will be triggered when someone adds a comment"
when "issue"
"Event will be triggered when an issue is created/updated/merged"
when "merge_request"
"Event will be triggered when a merge request is created/updated/merged"
when "build"
"Event will be triggered when a build status changes"
when "wiki_page"
"Event will be triggered when a wiki page is created/updated"
end
end
def service_event_field_name(event)
event = event.pluralize if %w[merge_request issue].include?(event)
"#{event}_events"
end
end
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)
minutes = interval_in_seconds / 60
seconds = interval_in_seconds - minutes * 60
......@@ -25,9 +15,19 @@ module TimeHelper
end
def duration_in_numbers(finished_at, started_at)
diff_in_seconds = finished_at.to_i - started_at.to_i
time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S"
interval = interval_in_seconds(started_at, finished_at)
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
......@@ -172,7 +172,7 @@ class Ability
rules << :read_build if project.public_builds?
unless owner || project.team.member?(user) || project_group_member?(project, user)
rules << :request_access
rules << :request_access if project.request_access_enabled
end
end
......@@ -373,7 +373,7 @@ class Ability
end
if group.public? || (group.internal? && !user.external?)
rules << :request_access unless group.users.include?(user)
rules << :request_access if group.request_access_enabled && group.users.exclude?(user)
end
rules.flatten
......
......@@ -97,7 +97,7 @@ module Ci
end
def other_actions
pipeline.manual_actions.where.not(id: self)
pipeline.manual_actions.where.not(name: name)
end
def playable?
......@@ -145,11 +145,14 @@ module Ci
end
def variables
variables = []
variables += predefined_variables
variables += yaml_variables if yaml_variables
variables += project_variables
variables += trigger_variables
variables = predefined_variables
variables += project.predefined_variables
variables += pipeline.predefined_variables
variables += runner.predefined_variables if runner
variables += project.container_registry_variables
variables += yaml_variables
variables += project.secret_variables
variables += trigger_request.user_variables if trigger_request
variables
end
......@@ -409,6 +412,14 @@ module Ci
self.update(artifacts_expire_at: nil)
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
def update_artifacts_size
......@@ -427,29 +438,30 @@ module Ci
self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil)
end
def project_variables
project.variables.map do |variable|
{ key: variable.key, value: variable.value, public: false }
end
end
def trigger_variables
if trigger_request && trigger_request.variables
trigger_request.variables.map do |key, value|
{ key: key, value: value, public: false }
end
else
[]
end
end
def predefined_variables
variables = []
variables << { key: :CI_BUILD_TAG, value: ref, public: true } if tag?
variables << { key: :CI_BUILD_NAME, value: name, public: true }
variables << { key: :CI_BUILD_STAGE, value: stage, public: true }
variables << { key: :CI_BUILD_TRIGGERED, value: 'true', public: true } if trigger_request
variables = [
{ key: 'CI', value: 'true', public: true },
{ key: 'GITLAB_CI', value: 'true', public: true },
{ key: 'CI_BUILD_ID', value: id.to_s, public: true },
{ key: 'CI_BUILD_TOKEN', value: token, public: false },
{ key: 'CI_BUILD_REF', value: sha, public: true },
{ key: 'CI_BUILD_BEFORE_SHA', value: before_sha, public: true },
{ key: 'CI_BUILD_REF_NAME', value: ref, public: true },
{ key: 'CI_BUILD_NAME', value: name, public: true },
{ key: 'CI_BUILD_STAGE', value: stage, public: true },
{ key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
{ key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true },
{ key: 'CI_SERVER_REVISION', value: Gitlab::REVISION, public: true }
]
variables << { key: 'CI_BUILD_TAG', value: ref, public: true } if tag?
variables << { key: 'CI_BUILD_TRIGGERED', value: 'true', public: true } if trigger_request
variables
end
def build_attributes_from_config
return {} unless pipeline.config_processor
pipeline.config_processor.build_attributes(name)
end
end
end
......@@ -203,6 +203,12 @@ module Ci
Note.for_commit_id(sha)
end
def predefined_variables
[
{ key: 'CI_PIPELINE_ID', value: id.to_s, public: true }
]
end
private
def build_builds_for_stages(stages, user, status, trigger_request)
......@@ -211,8 +217,9 @@ module Ci
# build builds only for the first stage that has builds available.
#
stages.any? do |stage|
CreateBuildsService.new(self)
.execute(stage, user, status, trigger_request).present?
CreateBuildsService.new(self).
execute(stage, user, status, trigger_request).
any?(&:active?)
end
end
......
......@@ -114,6 +114,14 @@ module Ci
tag_list.any?
end
def predefined_variables
[
{ key: 'CI_RUNNER_ID', value: id.to_s, public: true },
{ key: 'CI_RUNNER_DESCRIPTION', value: description, public: true },
{ key: 'CI_RUNNER_TAGS', value: tag_list.to_s, public: true }
]
end
private
def tag_constraints
......
......@@ -7,5 +7,13 @@ module Ci
has_many :builds, class_name: 'Ci::Build'
serialize :variables
def user_variables
return [] unless variables
variables.map do |key, value|
{ key: key, value: value, public: false }
end
end
end
end
......@@ -661,6 +661,22 @@ class Project < ActiveRecord::Base
update_column(:has_external_issue_tracker, services.external_issue_trackers.any?)
end
def external_wiki
if has_external_wiki.nil?
cache_has_external_wiki # Populate
end
if has_external_wiki
@external_wiki ||= services.external_wikis.first
else
nil
end
end
def cache_has_external_wiki
update_column(:has_external_wiki, services.external_wikis.any?)
end
def build_missing_services
services_templates = Service.where(template: true)
......@@ -1175,4 +1191,34 @@ class Project < ActiveRecord::Base
def ensure_dir_exist
gitlab_shell.add_namespace(repository_storage_path, namespace.path)
end
def predefined_variables
[
{ key: 'CI_PROJECT_ID', value: id.to_s, public: true },
{ key: 'CI_PROJECT_NAME', value: path, public: true },
{ key: 'CI_PROJECT_PATH', value: path_with_namespace, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: namespace.path, public: true },
{ key: 'CI_PROJECT_URL', value: web_url, public: true }
]
end
def container_registry_variables
return [] unless Gitlab.config.registry.enabled
variables = [
{ key: 'CI_REGISTRY', value: Gitlab.config.registry.host_port, public: true }
]
if container_registry_enabled?
variables << { key: 'CI_REGISTRY_IMAGE', value: container_registry_repository_url, public: true }
end
variables
end
def secret_variables
variables.map do |variable|
{ key: variable.key, value: variable.value, public: false }
end
end
end
......@@ -4,6 +4,9 @@ class SlackService < Service
validates :webhook, presence: true, url: true, if: :activated?
def initialize_properties
# Custom serialized properties initialization
self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) }
if properties.nil?
self.properties = {}
self.notify_only_broken_builds = true
......@@ -29,13 +32,15 @@ class SlackService < Service
end
def fields
[
{ type: 'text', name: 'webhook',
placeholder: 'https://hooks.slack.com/services/...' },
{ type: 'text', name: 'username', placeholder: 'username' },
{ type: 'text', name: 'channel', placeholder: '#channel' },
{ type: 'checkbox', name: 'notify_only_broken_builds' },
]
default_fields =
[
{ type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' },
{ type: 'text', name: 'username', placeholder: 'username' },
{ type: 'text', name: 'channel', placeholder: "#general" },
{ type: 'checkbox', name: 'notify_only_broken_builds' },
]
default_fields + build_event_channels
end
def supported_events
......@@ -74,7 +79,10 @@ class SlackService < Service
end
opt = {}
opt[:channel] = channel if channel
event_channel = get_channel_field(object_kind) || channel
opt[:channel] = event_channel if event_channel
opt[:username] = username if username
if message
......@@ -83,8 +91,35 @@ class SlackService < Service
end
end
def event_channel_names
supported_events.map { |event| event_channel_name(event) }
end
def event_field(event)
fields.find { |field| field[:name] == event_channel_name(event) }
end
def global_fields
fields.reject { |field| field[:name].end_with?('channel') }
end
private
def get_channel_field(event)
field_name = event_channel_name(event)
self.public_send(field_name)
end
def build_event_channels
supported_events.reduce([]) do |channels, event|
channels << { type: 'text', name: event_channel_name(event), placeholder: "#general" }
end
end
def event_channel_name(event)
"#{event}_channel"
end
def project_name
project.name_with_namespace.gsub(/\s/, '')
end
......
......@@ -392,6 +392,11 @@ class Repository
expire_cache if exists?
# expire cache that don't depend on repository data (when expiring)
expire_tags_cache
expire_tag_count_cache
expire_branches_cache
expire_branch_count_cache
expire_root_ref_cache
expire_emptiness_caches
expire_exists_cache
......@@ -733,6 +738,33 @@ class Repository
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)
commit_with_hooks(user, branch) do |ref|
committer = user_to_committer(user)
......
......@@ -17,6 +17,7 @@ class Service < ActiveRecord::Base
after_commit :reset_updated_properties
after_commit :cache_project_has_external_issue_tracker
after_commit :cache_project_has_external_wiki
belongs_to :project, inverse_of: :services
has_one :service_hook
......@@ -25,6 +26,7 @@ class Service < ActiveRecord::Base
scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) }
scope :issue_trackers, -> { where(category: 'issue_tracker') }
scope :external_wikis, -> { where(type: 'ExternalWikiService') }
scope :active, -> { where(active: true) }
scope :without_defaults, -> { where(default: false) }
......@@ -80,6 +82,18 @@ class Service < ActiveRecord::Base
Gitlab::PushDataBuilder.build_sample(project, user)
end
def event_channel_names
[]
end
def event_field(event)
nil
end
def global_fields
fields
end
def supported_events
%w(push tag_push issue merge_request wiki_page)
end
......@@ -212,4 +226,10 @@ class Service < ActiveRecord::Base
project.cache_has_external_issue_tracker
end
end
def cache_project_has_external_wiki
if project && !project.destroyed?
project.cache_has_external_wiki
end
end
end
......@@ -854,7 +854,7 @@ class User < ActiveRecord::Base
groups.joins(:shared_projects).select(:project_id)]
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) }
end
......
......@@ -9,12 +9,14 @@ module Files
@commit_message = params[:commit_message]
@file_path = params[:file_path]
@previous_path = params[:previous_path]
@file_content = if params[:file_content_encoding] == 'base64'
Base64.decode64(params[:file_content])
else
params[:file_content]
end
# Validate parameters
validate
# Create new branch if it different from source_branch
......
......@@ -3,7 +3,10 @@ require_relative "base_service"
module Files
class UpdateService < Files::BaseService
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
......@@ -9,7 +9,7 @@ module Projects
private
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)
notify_success
else
......@@ -21,6 +21,10 @@ module Projects
Gitlab::ImportExport::VersionSaver.new(shared: @shared)
end
def avatar_saver
Gitlab::ImportExport::AvatarSaver.new(project: project, shared: @shared)
end
def project_tree_saver
Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared)
end
......
......@@ -14,4 +14,8 @@ class AvatarUploader < CarrierWave::Uploader::Base
def reset_events_cache(file)
model.reset_events_cache if model.is_a?(User)
end
def exists?
model.avatar.file && model.avatar.file.exists?
end
end
......@@ -9,6 +9,10 @@
= render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
.form-group
.col-sm-offset-2.col-sm-10
= render 'shared/allow_request_access', form: f
- if @group.new_record?
.form-group
.col-sm-offset-2.col-sm-10
......
......@@ -4,11 +4,7 @@
#{time_ago_with_tooltip(event.created_at)}
= cache [event, current_application_settings, "v2.2"] do
- if event.author
= link_to user_path(event.author) do
= image_tag avatar_icon(event.author_email, 40), class: "avatar s40", alt:''
- else
= image_tag avatar_icon(event.author_email, 40), class: "avatar s40", alt:''
= author_avatar(event, size: 40)
- if event.created_project?
= render "events/event/created_project", event: event
......
......@@ -21,6 +21,10 @@
= render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
.form-group
.col-sm-offset-2.col-sm-10
= render 'shared/allow_request_access', form: f
.form-group
%hr
= f.label :share_with_group_lock, class: 'control-label' do
......
- project = @target_project || @project
- noteable_class = @noteable.class if @noteable.present?
- if @noteable
:javascript
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}"
GitLab.GfmAutoComplete.cachedData = undefined;
GitLab.GfmAutoComplete.setup();
:javascript
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_class, type_id: params[:id])}"
GitLab.GfmAutoComplete.cachedData = undefined;
GitLab.GfmAutoComplete.setup();
%ul.nav.nav-sidebar
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
= link_to explore_root_path, title: 'Projects' do
= icon('bookmark fw')
%span
Projects
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups' do
= icon('group fw')
%span
Groups
= nav_link(controller: :snippets) do
= link_to explore_snippets_path, title: 'Snippets' do
= icon('clipboard fw')
%span
Snippets
= nav_link(controller: :help) do
= link_to help_path, title: 'Help' do
= icon('question-circle fw')
%span
Help
......@@ -39,7 +39,7 @@
= link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
%span
Triggers
= nav_link(controller: :badges) do
= link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
= nav_link(controller: :pipelines_settings) do
= link_to namespace_project_pipelines_settings_path(@project.namespace, @project), title: 'CI/CD Pipelines' do
%span
Badges
CI/CD Pipelines
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/cropper.js')
= page_specific_javascript_tag('profile/application.js')
= page_specific_javascript_tag('profile/profile_bundle.js')
%fieldset.builds-feature
%h5.prepend-top-0
Builds
- unless @repository.gitlab_ci_yml
.form-group
%p Builds need to be configured before you can begin using Continuous Integration.
= link_to 'Get started with Builds', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
.form-group
%p Get recent application code using the following command:
.radio
= f.label :build_allow_git_fetch_false do
= f.radio_button :build_allow_git_fetch, 'false'
%strong git clone
%br
%span.descr Slower but makes sure you have a clean dir before every build
.radio
= f.label :build_allow_git_fetch_true do
= f.radio_button :build_allow_git_fetch, 'true'
%strong git fetch
%br
%span.descr Faster
.form-group
= f.label :build_timeout_in_minutes, 'Timeout', class: 'label-light'
= f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
%p.help-block per build in minutes
.form-group
= f.label :build_coverage_regex, "Test coverage parsing", class: 'label-light'
.input-group
%span.input-group-addon /
= f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
%span.input-group-addon /
%p.help-block
We will use this regular expression to find test coverage output in build trace.
Leave blank if you want to disable this feature
.bs-callout.bs-callout-info
%p Below are examples of regex for existing tools:
%ul
%li
Simplecov (Ruby) -
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
%code \d+\%\s*$
%li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
%li
gcovr (C/C++) -
%code ^TOTAL.*\s+(\d+\%)$
%li
tap --coverage-report=text-summary (Node.js) -
%code ^Statements\s*:\s*([^%]+)
.form-group
.checkbox
= f.label :public_builds do
= f.check_box :public_builds
%strong Public builds
.help-block Allow everyone to access builds for Public and Internal projects
.form-group.append-bottom-0
= f.label :runners_token, "Runners token", class: 'label-light'
= f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
%p.help-block The secure token used to checkout project.
- page_title 'Badges'
- badges_path = namespace_project_badges_path(@project.namespace, @project)
.prepend-top-10
.panel.panel-default
.panel-heading
%b Builds badge &middot;
= @build_badge.to_html
.pull-right
= render 'shared/ref_switcher', destination: 'badges', align_right: true
.panel-body
.row
.col-md-2.text-center
Markdown
.col-md-10.code.js-syntax-highlight
= highlight('.md', @build_badge.to_markdown)
.row
%hr
.row
.col-md-2.text-center
HTML
.col-md-10.code.js-syntax-highlight
= highlight('.html', @build_badge.to_html)
......@@ -4,7 +4,9 @@
= icon('code-fork')
= ref
%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)
%span.editor-file-name
......
......@@ -49,7 +49,7 @@
- if @build.duration
%p.build-detail-row
%span.build-light-text Duration:
#{duration_in_words(@build.finished_at, @build.started_at)}
= time_interval_in_words(@build.duration)
- if @build.finished_at
%p.build-detail-row
%span.build-light-text Finished:
......
......@@ -2,7 +2,7 @@
- if current_user && can?(current_user, :fork_project, @project)
- 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
= icon('code-fork fw')
= custom_icon('icon_fork')
Fork
%div.count-with-arrow
%span.arrow
......@@ -10,7 +10,7 @@
= @project.forks_count
- else
= 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
%div.count-with-arrow
%span.arrow
......
......@@ -27,7 +27,7 @@
%p.commit-title
- if commit = pipeline.commit
= commit_author_avatar(commit, size: 20)
= author_avatar(commit, size: 20)
= link_to_gfm truncate(commit.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "commit-row-message"
- else
Cant find HEAD commit for this branch
......@@ -35,7 +35,7 @@
- stages_status = pipeline.statuses.latest.stages_status
- stages.each do |stage|
%td
%td.stage-cell
- status = stages_status[stage]
- tooltip = "#{stage.titleize}: #{status || 'not found'}"
- if status
......
......@@ -9,7 +9,8 @@
= cache(cache_key) do
%li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" }
= commit_author_avatar(commit, size: 36)
= author_avatar(commit, size: 36)
.commit-info-block
.commit-row-title
%span.item-title
......
......@@ -32,6 +32,10 @@
%strong
= visibility_level_label(@project.visibility_level)
.light= visibility_level_description(@project.visibility_level, @project)
.form-group
= render 'shared/allow_request_access', form: f
.form-group
= f.label :tag_list, "Tags", class: 'label-light'
= f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control"
......@@ -86,8 +90,6 @@
%hr
= render 'merge_request_settings', f: f
%hr
= render 'builds_settings', f: f
%hr
%fieldset.features.append-bottom-default
%h5.prepend-top-0
Project avatar
......
......@@ -31,11 +31,11 @@
- if current_user && can?(current_user, :fork_project, @project)
- 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
= icon('code-fork fw')
= custom_icon('icon_fork')
Fork
- else
= 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
......
- page_title "Fork project"
- if @namespaces.present?
%h3.page-title Fork project
%p.lead
Click to fork the project to a user or group
%hr
.fork-namespaces
- @namespaces.in_groups_of(6, false) do |group|
.row
- group.each do |namespace|
.col-md-2.col-sm-3
- if fork = namespace.find_fork_of(@project)
.fork-thumbnail
= link_to project_path(fork), title: "Visit project fork", class: 'has-tooltip' do
= image_tag namespace_icon(namespace, 100)
.caption
%strong
= namespace.human_name
%div.text-primary
Already forked
- else
.fork-thumbnail
= link_to namespace_project_forks_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has-tooltip' do
= image_tag namespace_icon(namespace, 100)
.caption
%strong
= namespace.human_name
%p.light
Fork is a copy of a project repository.
.row.prepend-top-default
.col-lg-3
%h4.prepend-top-0
Fork project
%p
A fork is a copy of a project.
%br
Forking a repository allows you to do changes without affecting the original project.
- else
%h3 No available namespaces to fork the project
%p.slead
You must have permission to create a project in a namespace before forking.
Forking a repository allows you to make changes without affecting the original project.
.col-lg-9
.fork-namespaces
- if @namespaces.present?
%label.label-light
%span
Click to fork the project to a user or group
- @namespaces.in_groups_of(6, false) do |group|
.row
- group.each do |namespace|
- avatar = namespace_icon(namespace, 100)
- if fork = namespace.find_fork_of(@project)
.fork-thumbnail.forked
= link_to project_path(fork) do
- if /no_((\w*)_)*avatar/.match(avatar)
.no-avatar
= icon 'question'
- else
= image_tag avatar
.caption
= namespace.human_name
- else
.fork-thumbnail
= link_to namespace_project_forks_path(@project.namespace, @project, namespace_key: namespace.id), method: "POST" do
- if /no_((\w*)_)*avatar/.match(avatar)
.no-avatar
= icon 'question'
- else
= image_tag avatar
.caption
= namespace.human_name
- else
%label.label-light
%span
No available namespaces to fork the project.
%br
%small
You must have permission to create a project in a namespace before forking.
.save-project-loader.hide
.center
%h2
%i.fa.fa-spinner.fa-spin
Forking repository
%p Please wait a moment, this page will automatically refresh when ready.
.save-project-loader.hide
.center
%h2
%i.fa.fa-spinner.fa-spin
Forking repository
%p Please wait a moment, this page will automatically refresh when ready.
......@@ -51,7 +51,7 @@
%td.duration
- if generic_commit_status.duration
= 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
- if generic_commit_status.finished_at
......
......@@ -3,7 +3,7 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/chart.js')
= page_specific_javascript_tag('graphs/application.js')
= page_specific_javascript_tag('graphs/graphs_bundle.js')
= nav_link(action: :show) do
= link_to 'Contributors', namespace_project_graph_path
= nav_link(action: :commits) do
......
- page_title "Network", @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/raphael.js')
= page_specific_javascript_tag('network/application.js')
= page_specific_javascript_tag('network/network_bundle.js')
= render "projects/commits/head"
= render "head"
%div{ class: container_class }
......
- page_title "CI/CD Pipelines"
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
= page_title
.col-lg-9
%h5.prepend-top-0
Pipelines
= form_for @project, url: namespace_project_pipelines_settings_path(@project.namespace.becomes(Namespace), @project), remote: true, authenticity_token: true do |f|
%fieldset.builds-feature
- unless @repository.gitlab_ci_yml
.form-group
%p Pipelines need to be configured before you can begin using Continuous Integration.
= link_to 'Get started with CI/CD Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
.form-group
%p Get recent application code using the following command:
.radio
= f.label :build_allow_git_fetch_false do
= f.radio_button :build_allow_git_fetch, 'false'
%strong git clone
%br
%span.descr Slower but makes sure you have a clean dir before every build
.radio
= f.label :build_allow_git_fetch_true do
= f.radio_button :build_allow_git_fetch, 'true'
%strong git fetch
%br
%span.descr Faster
.form-group
= f.label :build_timeout_in_minutes, 'Timeout', class: 'label-light'
= f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
%p.help-block per build in minutes
.form-group
= f.label :build_coverage_regex, "Test coverage parsing", class: 'label-light'
.input-group
%span.input-group-addon /
= f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
%span.input-group-addon /
%p.help-block
We will use this regular expression to find test coverage output in build trace.
Leave blank if you want to disable this feature
.bs-callout.bs-callout-info
%p Below are examples of regex for existing tools:
%ul
%li
Simplecov (Ruby) -
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
%code \d+\%\s*$
%li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
%li
gcovr (C/C++) -
%code ^TOTAL.*\s+(\d+\%)$
%li
tap --coverage-report=text-summary (Node.js) -
%code ^Statements\s*:\s*([^%]+)
.form-group
.checkbox
= f.label :public_builds do
= f.check_box :public_builds
%strong Public pipelines
.help-block Allow everyone to access pipelines for Public and Internal projects
.form-group.append-bottom-default
= f.label :runners_token, "Runners token", class: 'label-light'
= f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
%p.help-block The secure token used to checkout project.
= f.submit 'Save changes', class: "btn btn-save"
%hr
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Builds Badge
.col-lg-9
.prepend-top-10
.panel.panel-default
.panel-heading
%b Builds badge &middot;
= @build_badge.to_html
.pull-right
= render 'shared/ref_switcher', destination: 'badges', align_right: true
.panel-body
.row
.col-md-2.text-center
Markdown
.col-md-10.code.js-syntax-highlight
= highlight('.md', @build_badge.to_markdown)
.row
%hr
.row
.col-md-2.text-center
HTML
.col-md-10.code.js-syntax-highlight
= highlight('.html', @build_badge.to_html)
......@@ -8,6 +8,7 @@
.col-lg-9
= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
= render 'shared/service_settings', form: form
= form.submit 'Save changes', class: 'btn btn-save'
&nbsp;
- if @service.valid? && @service.activated?
......
- @no_container = true
- page_title @tag.name, "Tags"
= render "projects/commits/head"
.row-content-block
.pull-right
- if can?(current_user, :push_code, @project)
= link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn has-tooltip', title: 'Edit release notes' do
= icon("pencil")
= link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse files' do
= icon('files-o')
= link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse commits' do
= icon('history')
- if can? current_user, :download_code, @project
= render 'projects/tags/download', ref: @tag.name, project: @project
- if can?(current_user, :admin_project, @project)
.pull-right
= 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
%i.fa.fa-trash-o
.title
%span.item-title= @tag.name
- if @commit
= render 'projects/branches/commit', commit: @commit, project: @project
- else
Cant find HEAD commit for this tag
- if @tag.message.present?
%pre.body
= strip_gpg_signature(@tag.message)
%div{ class: container_class }
.sub-header-block
.pull-right.tag-buttons
- if can?(current_user, :push_code, @project)
= link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Edit release notes' do
= icon("pencil")
= link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse files' do
= icon('files-o')
= link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse commits' do
= icon('history')
- if can? current_user, :download_code, @project
= render 'projects/tags/download', ref: @tag.name, project: @project
- if can?(current_user, :admin_project, @project)
.pull-right
= 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
%i.fa.fa-trash-o
.tag-info.append-bottom-10
.title
%span.item-title= @tag.name
- if @commit
= render 'projects/branches/commit', commit: @commit, project: @project
- else
Cant find HEAD commit for this tag
- if @tag.message.present?
%pre.body
= strip_gpg_signature(@tag.message)
.append-bottom-default.prepend-top-default
- if @release.description.present?
.description
.wiki
= preserve do
= markdown @release.description
- else
This tag has no release notes.
.append-bottom-default.prepend-top-default
- if @release.description.present?
.description
.wiki
= preserve do
= markdown @release.description
- else
This tag has no release notes.
.checkbox
= form.label :request_access_enabled do
= form.check_box :request_access_enabled
%strong Allow users to request access
%br
%span.descr Allow users to request access if visibility is public or internal.
......@@ -10,69 +10,28 @@
.col-sm-10
= form.check_box :active
- if @service.supported_events.length > 1
.form-group
= form.label :url, "Trigger", class: 'control-label'
.col-sm-10
- if @service.supported_events.include?("push")
%div
= form.check_box :push_events, class: 'pull-left'
.prepend-left-20
= form.label :push_events, class: 'list-label' do
%strong Push events
%p.light
This url will be triggered by a push to the repository
- if @service.supported_events.include?("tag_push")
%div
= form.check_box :tag_push_events, class: 'pull-left'
.prepend-left-20
= form.label :tag_push_events, class: 'list-label' do
%strong Tag push events
%p.light
This url will be triggered when a new tag is pushed to the repository
- if @service.supported_events.include?("note")
%div
= form.check_box :note_events, class: 'pull-left'
.prepend-left-20
= form.label :note_events, class: 'list-label' do
%strong Comments
%p.light
This url will be triggered when someone adds a comment
- if @service.supported_events.include?("issue")
%div
= form.check_box :issues_events, class: 'pull-left'
.prepend-left-20
= form.label :issues_events, class: 'list-label' do
%strong Issues events
%p.light
This url will be triggered when an issue is created/updated/merged
- if @service.supported_events.include?("merge_request")
%div
= form.check_box :merge_requests_events, class: 'pull-left'
.prepend-left-20
= form.label :merge_requests_events, class: 'list-label' do
%strong Merge Request events
%p.light
This url will be triggered when a merge request is created/updated/merged
- if @service.supported_events.include?("build")
%div
= form.check_box :build_events, class: 'pull-left'
.prepend-left-20
= form.label :build_events, class: 'list-label' do
%strong Build events
%p.light
This url will be triggered when a build status changes
- if @service.supported_events.include?("wiki_page")
%div
= form.check_box :wiki_page_events, class: 'pull-left'
.prepend-left-20
= form.label :wiki_page_events, class: 'list-label' do
%strong Wiki Page events
%p.light
This url will be triggered when a wiki page is created/updated
.form-group
= form.label :url, "Trigger", class: 'control-label'
.col-sm-10
- @service.supported_events.each do |event|
%div
= form.check_box service_event_field_name(event), class: 'pull-left'
.prepend-left-20
= form.label service_event_field_name(event), class: 'list-label' do
%strong
= event.humanize
- field = @service.event_field(event)
- if field
%p
= form.text_field field[:name], class: "form-control", placeholder: field[:placeholder]
%p.light
= service_event_description(event)
- @service.fields.each do |field|
- @service.global_fields.each do |field|
- type = field[:type]
- if type == 'fieldset'
......
<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>
......@@ -2,7 +2,7 @@
- page_description @user.bio
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/d3.js')
= page_specific_javascript_tag('users/application.js')
= page_specific_javascript_tag('users/users_bundle.js')
- header_title @user.name, user_path(@user)
- @no_container = true
......
......@@ -81,10 +81,10 @@ module Gitlab
config.assets.precompile << "print.css"
config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css"
config.assets.precompile << "graphs/application.js"
config.assets.precompile << "users/application.js"
config.assets.precompile << "network/application.js"
config.assets.precompile << "profile/application.js"
config.assets.precompile << "graphs/graphs_bundle.js"
config.assets.precompile << "users/users_bundle.js"
config.assets.precompile << "network/network_bundle.js"
config.assets.precompile << "profile/profile_bundle.js"
config.assets.precompile << "lib/utils/*.js"
config.assets.precompile << "lib/*.js"
config.assets.precompile << "u2f.js"
......
......@@ -4,14 +4,7 @@
require 'gitlab/current_settings'
include Gitlab::CurrentSettings
# If Sentry is enabled and the Rails app is running in production mode,
# this will construct the Report URI for Sentry.
if Rails.env.production? && current_application_settings.sentry_enabled
uri = URI.parse(current_application_settings.sentry_dsn)
CSP_REPORT_URI = "#{uri.scheme}://#{uri.host}/api#{uri.path}/csp-report/?sentry_key=#{uri.user}"
else
CSP_REPORT_URI = ''
end
CSP_REPORT_URI = ''
# Content Security Policy Headers
# For more information on CSP see:
......@@ -71,10 +64,7 @@ SecureHeaders::Configuration.default do |config|
upgrade_insecure_requests: true
}
# Reports are sent to Sentry if it's enabled.
if current_application_settings.sentry_enabled
config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
end
config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
# Allow Bootstrap Linter in development mode.
if Rails.env.development?
......
......@@ -18,7 +18,8 @@ Sidekiq.configure_server do |config|
if cron_jobs[k] && cron_jobs_required_keys.all? { |s| cron_jobs[k].key?(s) }
cron_jobs[k]['class'] = cron_jobs[k].delete('job_class')
else
raise("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
cron_jobs.delete(k)
Rails.logger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
end
end
Sidekiq::Cron::Job.load_from_hash! cron_jobs
......
......@@ -89,11 +89,10 @@ Rails.application.routes.draw do
mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\/(info\/lfs|gitlab-lfs)/.match(request.path_info) }, via: [:get, :post, :put]
# Help
get 'help' => 'help#index'
get 'help/*path' => 'help#show', as: :help_page
get 'help/shortcuts'
get 'help/ui' => 'help#ui'
get 'help' => 'help#index'
get 'help/shortcuts' => 'help#shortcuts'
get 'help/ui' => 'help#ui'
get 'help/*path' => 'help#show', as: :help_page
#
# Global snippets
......@@ -733,6 +732,10 @@ Rails.application.routes.draw do
resources :triggers, only: [:index, :create, :destroy]
resources :pipelines, only: [:index, :new, :create, :show] do
collection do
resource :pipelines_settings, path: 'settings', only: [:show, :update]
end
member do
post :cancel
post :retry
......
......@@ -7,7 +7,13 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration
class ProjectImportDataFake
extend AttrEncrypted
attr_accessor :credentials
attr_encrypted :credentials, key: Gitlab::Application.secrets.db_key_base, marshal: true, encode: true, :mode => :per_attribute_iv_and_salt
attr_encrypted :credentials,
key: Gitlab::Application.secrets.db_key_base,
marshal: true,
encode: true,
:mode => :per_attribute_iv_and_salt,
insecure_mode: true,
algorithm: 'aes-256-cbc'
end
def up
......
class AddRequestAccessEnabledToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
add_column_with_default :projects, :request_access_enabled, :boolean, default: true
end
def down
remove_column :projects, :request_access_enabled
end
end
class AddRequestAccessEnabledToGroups < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
add_column_with_default :namespaces, :request_access_enabled, :boolean, default: true
end
def down
remove_column :namespaces, :request_access_enabled
end
end
class AddHasExternalWikiToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
def change
add_column :projects, :has_external_wiki, :boolean
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160716115710) do
ActiveRecord::Schema.define(version: 20160718153603) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -664,16 +664,17 @@ ActiveRecord::Schema.define(version: 20160716115710) do
add_index "milestones", ["title"], name: "index_milestones_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
create_table "namespaces", force: :cascade do |t|
t.string "name", null: false
t.string "path", null: false
t.string "name", null: false
t.string "path", null: false
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "type"
t.string "description", default: "", null: false
t.string "description", default: "", null: false
t.string "avatar"
t.boolean "share_with_group_lock", default: false
t.integer "visibility_level", default: 20, null: false
t.boolean "share_with_group_lock", default: false
t.integer "visibility_level", default: 20, null: false
t.boolean "request_access_enabled", default: true, null: false
end
add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
......@@ -842,6 +843,8 @@ ActiveRecord::Schema.define(version: 20160716115710) do
t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false
t.boolean "has_external_issue_tracker"
t.string "repository_storage", default: "default", null: false
t.boolean "has_external_wiki"
t.boolean "request_access_enabled", default: true, null: false
end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
......
......@@ -18,25 +18,35 @@ The `API_TOKEN` will take the Secure Variable value: `SECURE`.
### Predefined variables (Environment Variables)
| Variable | Runner | Description |
|-------------------------|-----|--------|
| **CI** | 0.4 | Mark that build is executed in CI environment |
| **GITLAB_CI** | all | Mark that build is executed in GitLab CI environment |
| **CI_SERVER** | all | Mark that build is executed in CI environment |
| **CI_SERVER_NAME** | all | CI server that is used to coordinate builds |
| **CI_SERVER_VERSION** | all | Not yet defined |
| **CI_SERVER_REVISION** | all | Not yet defined |
| **CI_BUILD_REF** | all | The commit revision for which project is built |
| **CI_BUILD_TAG** | 0.5 | The commit tag name. Present only when building tags. |
| **CI_BUILD_NAME** | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
| **CI_BUILD_STAGE** | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_BUILD_REF_NAME** | all | The branch or tag name for which project is built |
| **CI_BUILD_ID** | all | The unique id of the current build that GitLab CI uses internally |
| **CI_BUILD_REPO** | all | The URL to clone the Git repository |
| **CI_BUILD_TRIGGERED** | 0.5 | The flag to indicate that build was [triggered] |
| **CI_BUILD_TOKEN** | 1.2 | Token used for authenticating with the GitLab Container Registry |
| **CI_PROJECT_ID** | all | The unique id of the current project that GitLab CI uses internally |
| **CI_PROJECT_DIR** | all | The full path where the repository is cloned and where the build is ran |
| Variable | GitLab | Runner | Description |
|-------------------------|--------|--------|-------------|
| **CI** | all | 0.4 | Mark that build is executed in CI environment |
| **GITLAB_CI** | all | all | Mark that build is executed in GitLab CI environment |
| **CI_SERVER** | all | all | Mark that build is executed in CI environment |
| **CI_SERVER_NAME** | all | all | The name of CI server that is used to coordinate builds |
| **CI_SERVER_VERSION** | all | all | GitLab version that is used to schedule builds |
| **CI_SERVER_REVISION** | all | all | GitLab revision that is used to schedule builds |
| **CI_BUILD_ID** | all | all | The unique id of the current build that GitLab CI uses internally |
| **CI_BUILD_REF** | all | all | The commit revision for which project is built |
| **CI_BUILD_TAG** | all | 0.5 | The commit tag name. Present only when building tags. |
| **CI_BUILD_NAME** | all | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
| **CI_BUILD_STAGE** | all | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_BUILD_REF_NAME** | all | all | The branch or tag name for which project is built |
| **CI_BUILD_REPO** | all | all | The URL to clone the Git repository |
| **CI_BUILD_TRIGGERED** | all | 0.5 | The flag to indicate that build was [triggered] |
| **CI_BUILD_TOKEN** | all | 1.2 | Token used for authenticating with the GitLab Container Registry |
| **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally |
| **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally |
| **CI_PROJECT_NAME** | 8.10 | 0.5 | The project name that is currently being built |
| **CI_PROJECT_NAMESPACE**| 8.10 | 0.5 | The project namespace that is currently being built |
| **CI_PROJECT_PATH** | 8.10 | 0.5 | The namespace with project name |
| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP address to access project |
| **CI_PROJECT_DIR** | all | all | The full path where the repository is cloned and where the build is run |
| **CI_REGISTRY** | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
| **CI_REGISTRY_IMAGE** | 8.10 | 0.5 | If the Container Registry is enabled for the project it returnes the address of the registry tied to the specific project |
| **CI_RUNNER_ID** | 8.10 | 0.5 | The unique id of runner being used |
| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
| **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags |
**Some of the variables are only available when using runner with at least defined version.**
......@@ -46,18 +56,28 @@ Example values:
export CI_BUILD_ID="50"
export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a"
export CI_BUILD_REF_NAME="master"
export CI_BUILD_REPO="https://gitlab.com/gitlab-org/gitlab-ce.git"
export CI_BUILD_REPO="https://gitab-ci-token:abcde-1234ABCD5678ef@gitlab.com/gitlab-org/gitlab-ce.git"
export CI_BUILD_TAG="1.0.0"
export CI_BUILD_NAME="spec:other"
export CI_BUILD_STAGE="test"
export CI_BUILD_TRIGGERED="true"
export CI_BUILD_TOKEN="abcde-1234ABCD5678ef"
export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
export CI_PIPELINE_ID="1000"
export CI_PROJECT_ID="34"
export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
export CI_PROJECT_NAME="gitlab-ce"
export CI_PROJECT_NAMESPACE="gitlab-org"
export CI_PROJECT_PATH="gitlab-org/gitlab-ce"
export CI_PROJECT_URL="https://gitlab.com/gitlab-org/gitlab-ce"
export CI_REGISTRY="registry.gitlab.com"
export CI_REGISTRY_IMAGE="registry.gitlab.com/gitlab-org/gitlab-ce"
export CI_RUNNER_ID="10"
export CI_RUNNER_DESCRIPTION="my runner"
export CI_RUNNER_TAGS="docker, linux"
export CI_SERVER="yes"
export CI_SERVER_NAME="GitLab CI"
export CI_SERVER_REVISION=""
export CI_SERVER_VERSION=""
export CI_SERVER_NAME="GitLab"
export CI_SERVER_REVISION="8.9.0"
export CI_SERVER_VERSION="70606bf"
```
### YAML-defined variables
......
......@@ -11,7 +11,8 @@ migrations are written carefully, can be applied online and adhere to the style
Migrations should not require GitLab installations to be taken offline unless
_absolutely_ necessary. If a migration requires downtime this should be
clearly mentioned during the review process as well as being documented in the
monthly release post.
monthly release post. For more information see the "Downtime Tagging" section
below.
When writing your migrations, also consider that databases might have stale data
or inconsistencies and guard for that. Try to make as little assumptions as possible
......@@ -20,35 +21,34 @@ about the state of the database.
Please don't depend on GitLab specific code since it can change in future versions.
If needed copy-paste GitLab code into the migration to make it forward compatible.
## Comments in the migration
## Downtime Tagging
Each migration you write needs to have the two following pieces of information
as comments.
Every migration must specify if it requires downtime or not, and if it should
require downtime it must also specify a reason for this. To do so, add the
following two constants to the migration class' body:
### Online, Offline, errors?
* `DOWNTIME`: a boolean that when set to `true` indicates the migration requires
downtime.
* `DOWNTIME_REASON`: a String containing the reason for the migration requiring
downtime. This constant **must** be set when `DOWNTIME` is set to `true`.
First, you need to provide information on whether the migration can be applied:
For example:
1. online without errors (works on previous version and new one)
2. online with errors on old instances after migrating
3. online with errors on new instances while migrating
4. offline (needs to happen without app servers to prevent db corruption)
For example:
```
# Migration type: online without errors (works on previous version and new one)
```ruby
class MyMigration < ActiveRecord::Migration
...
```
DOWNTIME = true
DOWNTIME_REASON = 'This migration requires downtime because ...'
It is always preferable to have a migration run online. If you expect the migration
to take particularly long (for instance, if it loops through all notes),
this is valuable information to add.
def change
...
end
end
```
If you don't provide the information it means that a migration is safe to run online.
It is an error (that is, CI will fail) if the `DOWNTIME` constant is missing
from a migration class.
### Reversibility
## Reversibility
Your migration should be reversible. This is very important, as it should
be possible to downgrade in case of a vulnerability or bugs.
......@@ -100,7 +100,7 @@ value of `10` you'd write the following:
class MyMigration < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
add_column_with_default(:projects, :foo, :integer, default: 10)
end
......
......@@ -26,14 +26,13 @@ After Slack is ready we need to setup GitLab. Here are the steps to achieve this
1. Navigate to Settings -> Services -> Slack
1. Pick the triggers you want to activate
1. Pick the triggers you want to activate and respective channel (`#general` by default).
1. Fill in your Slack details
- Webhook: Paste the Webhook URL from the step above
- Username: Fill this in if you want to change the username of the bot
- Channel: Fill this in if you want to change the channel where the messages will be posted
- Mark it as active
1. Save your settings
Have fun :)
......
......@@ -45,7 +45,7 @@ further configuration instructions and details. Contributions are welcome.
| PivotalTracker | Project Management Software (Source Commits Endpoint) |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
| [Redmine](redmine.md) | Redmine issue tracker |
| Slack | A team communication tool for the 21st century |
| [Slack](slack.md) | A team communication tool for the 21st century |
## Services Templates
......
# Slack Service
Go to your project's **Settings > Services > Slack** and you will see a checkbox with the following events that can be triggered:
* Push
* Issue
* Merge request
* Note
* Tag push
* Build
* Wiki page
Below each of these event checkboxes you will have an input to insert which Slack channel do you want to send that event message,
`#general` channel is default.
![Slack configuration](img/slack_configuration.png)
| Field | Description |
| ----- | ----------- |
| `Webhook` | The incoming webhook url which you have to setup on slack. (https://my.slack.com/services/new/incoming-webhook/) |
| `Username` | Optional username which can be on messages sent to slack. |
| `notify only broken builds` | Notify only about broken builds, when build events are marked to be sent.|
......@@ -90,6 +90,9 @@ GitLab account using the same e-mail address the invitation was sent to.
## Request access to a project
As a project owner you can enable or disable non members to request access to
your project. Go to the project settings and click on **Allow users to request access**.
As a user, you can request to be a member of a project. Go to the project you'd
like to be a member of, and click the **Request Access** button on the right
side of your screen.
......
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