Read about our upcoming Code of Conduct on this issue

Commit c7c5ab45 authored by Douwe Maan's avatar Douwe Maan
Browse files

Merge branch 'master' into '26388-push-to-create-a-new-project'

# Conflicts:
#   lib/gitlab/path_regex.rb
......@@ -411,6 +411,8 @@ end
# Gitaly GRPC client
gem 'gitaly-proto', '~> 0.83.0', require: 'gitaly'
# Locked until https://github.com/google/protobuf/issues/4210 is closed
gem 'google-protobuf', '= 3.5.1'
gem 'toml-rb', '~> 0.3.15', require: false
......
......@@ -340,7 +340,7 @@ GEM
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
google-protobuf (3.5.1.1)
google-protobuf (3.5.1)
googleapis-common-protos-types (1.0.1)
google-protobuf (~> 3.0)
googleauth (0.5.3)
......@@ -1066,6 +1066,7 @@ DEPENDENCIES
gollum-rugged_adapter (~> 0.4.4)
gon (~> 6.1.0)
google-api-client (~> 0.13.6)
google-protobuf (= 3.5.1)
gpgme
grape (~> 1.0)
grape-entity (~> 0.6.0)
......
......@@ -35,10 +35,11 @@ export default class Clusters {
clusterStatus,
clusterStatusReason,
helpPath,
ingressHelpPath,
} = document.querySelector('.js-edit-cluster-form').dataset;
this.store = new ClustersStore();
this.store.setHelpPath(helpPath);
this.store.setHelpPaths(helpPath, ingressHelpPath);
this.store.updateStatus(clusterStatus);
this.store.updateStatusReason(clusterStatusReason);
this.service = new ClustersService({
......@@ -93,6 +94,7 @@ export default class Clusters {
props: {
applications: this.state.applications,
helpPath: this.state.helpPath,
ingressHelpPath: this.state.ingressHelpPath,
},
});
},
......@@ -172,7 +174,7 @@ export default class Clusters {
.map(appId => newApplicationMap[appId].title);
if (appTitles.length > 0) {
const text = sprintf(s__('ClusterIntegration|%{appList} was successfully installed on your cluster'), {
const text = sprintf(s__('ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster'), {
appList: appTitles.join(', '),
});
Flash(text, 'notice', this.successApplicationContainer);
......
......@@ -18,11 +18,16 @@
required: false,
default: '',
},
ingressHelpPath: {
type: String,
required: false,
default: '',
},
},
computed: {
generalApplicationDescription() {
return sprintf(
_.escape(s__(`ClusterIntegration|Install applications on your cluster.
_.escape(s__(`ClusterIntegration|Install applications on your Kubernetes cluster.
Read more about %{helpLink}`)),
{
helpLink: `<a href="${this.helpPath}">
......@@ -34,7 +39,7 @@
},
helmTillerDescription() {
return _.escape(s__(
`ClusterIntegration|Helm streamlines installing and managing Kubernets applications.
`ClusterIntegration|Helm streamlines installing and managing Kubernetes applications.
Tiller runs inside of your Kubernetes Cluster, and manages
releases of your charts.`,
));
......@@ -49,7 +54,7 @@
_.escape(s__(
`ClusterIntegration|%{boldNotice} This will add some extra resources
like a load balancer, which may incur additional costs depending on
the hosting provider Kubernetes is installed on. If you are using GKE,
the hosting provider your Kubernetes cluster is installed on. If you are using GKE,
you can %{pricingLink}.`,
)), {
boldNotice: `<strong>${_.escape(s__('ClusterIntegration|Note:'))}</strong>`,
......@@ -59,13 +64,28 @@
false,
);
const externalIpParagraph = sprintf(
_.escape(s__(
`ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS
at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}`,
)), {
ingressHelpLink: `<a href="${this.ingressHelpPath}">
${_.escape(s__('ClusterIntegration|More information'))}
</a>`,
},
false,
);
return `
<p>
${descriptionParagraph}
</p>
<p class="append-bottom-0">
<p>
${extraCostParagraph}
</p>
<p class="settings-message append-bottom-0">
${externalIpParagraph}
</p>
`;
},
gitlabRunnerDescription() {
......
......@@ -4,6 +4,7 @@ export default class ClusterStore {
constructor() {
this.state = {
helpPath: null,
ingressHelpPath: null,
status: null,
statusReason: null,
applications: {
......@@ -39,8 +40,9 @@ export default class ClusterStore {
};
}
setHelpPath(helpPath) {
setHelpPaths(helpPath, ingressHelpPath) {
this.state.helpPath = helpPath;
this.state.ingressHelpPath = ingressHelpPath;
}
updateStatus(status) {
......
......@@ -8,7 +8,7 @@ import { convertPermissionToBoolean } from './lib/utils/common_utils';
```
%button.js-project-feature-toggle.project-feature-toggle{ type: "button",
class: "#{'is-checked' if enabled?}",
'aria-label': _('Toggle Cluster') }
'aria-label': _('Toggle Kubernetes Cluster') }
%input{ type: "hidden", class: 'js-project-feature-toggle-input', value: enabled? }
```
*/
......
......@@ -42,7 +42,7 @@ def verify_billing
when 'true'
return
when 'false'
flash[:alert] = _('Please <a href=%{link_to_billing} target="_blank" rel="noopener noreferrer">enable billing for one of your projects to be able to create a cluster</a>, then try again.').html_safe % { link_to_billing: "https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral" }
flash[:alert] = _('Please <a href=%{link_to_billing} target="_blank" rel="noopener noreferrer">enable billing for one of your projects to be able to create a Kubernetes cluster</a>, then try again.').html_safe % { link_to_billing: "https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral" }
else
flash[:alert] = _('We could not verify that one of your projects on GCP has billing enabled. Please try again.')
end
......
......@@ -41,7 +41,7 @@ def update
head :no_content
end
format.html do
flash[:notice] = "Cluster was successfully updated."
flash[:notice] = _('Kubernetes cluster was successfully updated.')
redirect_to project_cluster_path(project, cluster)
end
end
......@@ -55,10 +55,10 @@ def update
def destroy
if cluster.destroy
flash[:notice] = "Cluster integration was successfully removed."
flash[:notice] = _('Kubernetes cluster integration was successfully removed.')
redirect_to project_clusters_path(project), status: 302
else
flash[:notice] = "Cluster integration was not removed."
flash[:notice] = _('Kubernetes cluster integration was not removed.')
render :show
end
end
......
......@@ -76,9 +76,9 @@ def history
@page = @project_wiki.find_page(params[:id])
if @page
@page_versions = Kaminari.paginate_array(@page.versions(page: params[:page]),
@page_versions = Kaminari.paginate_array(@page.versions(page: params[:page].to_i),
total_count: @page.count_versions)
.page(params[:page])
.page(params[:page])
else
redirect_to(
project_wiki_path(@project, :home),
......
......@@ -21,6 +21,7 @@ class Build < CommitStatus
has_many :job_artifacts, class_name: 'Ci::JobArtifact', foreign_key: :job_id, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :job_artifacts_archive, -> { where(file_type: Ci::JobArtifact.file_types[:archive]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
has_one :job_artifacts_metadata, -> { where(file_type: Ci::JobArtifact.file_types[:metadata]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
has_one :job_artifacts_trace, -> { where(file_type: Ci::JobArtifact.file_types[:trace]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
# The "environment" field for builds is a String, and is the unexpanded name
def persisted_environment
......
......@@ -9,9 +9,12 @@ class JobArtifact < ActiveRecord::Base
mount_uploader :file, JobArtifactUploader
delegate :open, :exists?, to: :file
enum file_type: {
archive: 1,
metadata: 2
metadata: 2,
trace: 3
}
def self.artifacts_size_for(project)
......
......@@ -180,7 +180,7 @@ def prevent_modification
return unless managed?
if api_url_changed? || token_changed? || ca_pem_changed?
errors.add(:base, "cannot modify managed cluster")
errors.add(:base, _('Cannot modify managed Kubernetes cluster'))
return false
end
......
......@@ -39,7 +39,6 @@ def remove_artifacts_metadata!
end
def artifacts_size
read_attribute(:artifacts_size).to_i +
job_artifacts_archive&.size.to_i + job_artifacts_metadata&.size.to_i
read_attribute(:artifacts_size).to_i + job_artifacts.sum(:size).to_i
end
end
......@@ -7,11 +7,12 @@ module Routable
has_one :route, as: :source, autosave: true, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :redirect_routes, as: :source, autosave: true, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
validates_associated :route
validates :route, presence: true
scope :with_route, -> { includes(:route) }
after_validation :set_path_errors
before_validation do
if full_path_changed? || full_name_changed?
prepare_route
......@@ -125,6 +126,11 @@ def build_full_path
private
def set_path_errors
route_path_errors = self.errors.delete(:"route.path")
self.errors[:path].concat(route_path_errors) if route_path_errors
end
def uncached_full_path
if route && route.path.present?
@full_path ||= route.path # rubocop:disable Gitlab/ModuleWithInstanceVariables
......
......@@ -20,6 +20,9 @@ class Namespace < ActiveRecord::Base
has_many :projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :project_statistics
# This should _not_ be `inverse_of: :namespace`, because that would also set
# `user.namespace` when this user creates a group with themselves as `owner`.
belongs_to :owner, class_name: "User"
belongs_to :parent, class_name: "Namespace"
......@@ -29,7 +32,6 @@ class Namespace < ActiveRecord::Base
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
presence: true,
uniqueness: { scope: :parent_id },
length: { maximum: 255 },
namespace_name: true
......
......@@ -245,8 +245,7 @@ class Project < ActiveRecord::Base
validates :path,
presence: true,
project_path: true,
length: { maximum: 255 },
uniqueness: { scope: :namespace_id }
length: { maximum: 255 }
validates :namespace, presence: true
validates :name, uniqueness: { scope: :namespace_id }
......@@ -511,10 +510,13 @@ def repository
@repository ||= Repository.new(full_path, self, disk_path: disk_path)
end
def reload_repository!
def cleanup
@repository&.cleanup
@repository = nil
end
alias_method :reload_repository!, :cleanup
def container_registry_url
if Gitlab.config.registry.enabled
"#{Gitlab.config.registry.host_port}/#{full_path.downcase}"
......
......@@ -150,9 +150,10 @@ def deprecated?
end
def deprecation_message
content = <<-MESSAGE.strip_heredoc
Kubernetes service integration has been deprecated. #{deprecated_message_content} your clusters using the new <a href=\'#{Gitlab::Routing.url_helpers.project_clusters_path(project)}'/>Clusters</a> page
MESSAGE
content = _("Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page") % {
deprecated_message_content: deprecated_message_content,
url: Gitlab::Routing.url_helpers.project_clusters_path(project)
}
content.html_safe
end
......@@ -248,9 +249,9 @@ def deprecation_validation
def deprecated_message_content
if active?
"Your cluster information on this page is still editable, but you are advised to disable and reconfigure"
_("Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure")
else
"Fields on this page are now uneditable, you can configure"
_("Fields on this page are now uneditable, you can configure")
end
end
end
......@@ -93,6 +93,10 @@ def raw_repository
alias_method :raw, :raw_repository
def cleanup
@raw_repository&.cleanup
end
# Return absolute path to repository
def path_to_repo
@path_to_repo ||= File.expand_path(
......
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