summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-01-29 13:38:00 -0600
committerDouwe Maan <douwe@selenight.nl>2017-02-06 16:12:23 -0600
commit27f2ca94181880861269a7ddc07ae0d50a656d35 (patch)
treef93a26a7bf263e448f24230950db618bcd73b8f5
parentd147688af4adb6bcd6cb0f18797c70a8a451f4fa (diff)
downloadgitlab-ce-27f2ca94181880861269a7ddc07ae0d50a656d35.tar.gz
Add 'View on [env]' link to blobs and individual files in diffs
-rw-r--r--app/controllers/projects/blob_controller.rb3
-rw-r--r--app/controllers/projects/commit_controller.rb3
-rw-r--r--app/controllers/projects/compare_controller.rb4
-rw-r--r--app/controllers/projects/merge_requests_controller.rb8
-rw-r--r--app/helpers/commits_helper.rb11
-rw-r--r--app/models/ci/pipeline.rb8
-rw-r--r--app/models/environment.rb18
-rw-r--r--app/models/merge_request.rb6
-rw-r--r--app/models/project.rb47
-rw-r--r--app/models/repository.rb17
-rw-r--r--app/views/projects/blob/_actions.html.haml3
-rw-r--r--app/views/projects/commit/show.html.haml2
-rw-r--r--app/views/projects/compare/show.html.haml2
-rw-r--r--app/views/projects/diffs/_diffs.html.haml3
-rw-r--r--app/views/projects/diffs/_file.html.haml2
-rw-r--r--app/views/projects/merge_requests/_new_diffs.html.haml2
-rw-r--r--app/views/projects/merge_requests/show/_diffs.html.haml2
-rw-r--r--changelogs/unreleased/route-map.yml4
18 files changed, 129 insertions, 16 deletions
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 9940263ae24..1bdb8d45984 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -30,6 +30,9 @@ class Projects::BlobController < Projects::ApplicationController
end
def show
+ branch_name = @ref if @repository.branch_exists?(@ref)
+ @environment = @project.latest_environment_for(@commit, ref: branch_name)
+ @environment = nil unless can?(current_user, :read_environment, @environment)
end
def edit
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index b5a7078a3a1..08817afa1e9 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -95,6 +95,9 @@ class Projects::CommitController < Projects::ApplicationController
@diffs = commit.diffs(opts)
@notes_count = commit.notes.count
+
+ @environment = @project.latest_environment_for(@commit)
+ @environment = nil unless can?(current_user, :read_environment, @environment)
end
def define_note_vars
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 321cde255c3..6c94a79f842 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -57,6 +57,10 @@ class Projects::CompareController < Projects::ApplicationController
@diffs = @compare.diffs(diff_options)
+ branch_name = @head_ref if @repository.branch_exists?(@head_ref)
+ @environment = @project.latest_environment_for(@commit, ref: branch_name)
+ @environment = nil unless can?(current_user, :read_environment, @environment)
+
@diff_notes_disabled = true
@grouped_diff_discussions = {}
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 6eb542e4bd8..6a6d24db35d 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -103,6 +103,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
+ @environment = @merge_request.latest_environment
+ @environment = nil unless can?(current_user, :read_environment, @environment)
+
respond_to do |format|
format.html { define_discussion_vars }
format.json do
@@ -245,7 +248,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
@diff_notes_disabled = true
- render json: { html: view_to_html_string('projects/merge_requests/_new_diffs', diffs: @diffs) }
+ @environment = @merge_request.latest_environment
+ @environment = nil unless can?(current_user, :read_environment, @environment)
+
+ render json: { html: view_to_html_string('projects/merge_requests/_new_diffs', diffs: @diffs, environment: @environment) }
end
end
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 6dcb624c4da..a5cf4ddb6a3 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -205,6 +205,17 @@ module CommitsHelper
end
end
+ def view_on_environment_btn(commit_sha, diff_new_path, environment)
+ return unless environment && commit_sha
+
+ external_url = environment.external_url_for(diff_new_path, commit_sha)
+ return unless external_url
+
+ link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
+ icon('external-link')
+ end
+ end
+
def truncate_sha(sha)
Commit.truncate_sha(sha)
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index fab8497ec7d..8db53ea56dd 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -283,13 +283,7 @@ module Ci
def ci_yaml_file
return @ci_yaml_file if defined?(@ci_yaml_file)
- @ci_yaml_file ||= begin
- blob = project.repository.blob_at(sha, '.gitlab-ci.yml')
- blob.load_all_data!(project.repository)
- blob.data
- rescue
- nil
- end
+ @ci_yaml_file ||= project.repository.ci_yaml_file(sha)
end
def has_yaml_errors?
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 577367f1eed..909249dacca 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -51,6 +51,14 @@ class Environment < ActiveRecord::Base
state :stopped
end
+ def self.latest_for_commit(environments, commit)
+ environments.sort_by do |environment|
+ deployment = environment.first_deployment_for(commit)
+
+ deployment.try(:created_at) || DateTime.parse('1970-01-01')
+ end.last
+ end
+
def predefined_variables
[
{ key: 'CI_ENVIRONMENT_NAME', value: name, public: true },
@@ -171,6 +179,16 @@ class Environment < ActiveRecord::Base
self.slug = slugified
end
+ def external_url_for(path, commit_sha)
+ return unless self.external_url
+
+ public_path = project.public_path_for_source_path(path, commit_sha)
+ return unless public_path
+
+ # TODO: Verify this can't be used for XSS
+ URI.join(external_url, public_path).to_s
+ end
+
private
# Slugifying a name may remove the uniqueness guarantee afforded by it being
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 082adcafcc8..0155073a1c9 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -729,6 +729,12 @@ class MergeRequest < ActiveRecord::Base
end
end
+ def latest_environment
+ return @latest_environment if defined?(@latest_environment)
+
+ @latest_environment = Environment.latest_for_commit(environments, diff_head_commit)
+ end
+
def state_human_name
if merged?
"Merged"
diff --git a/app/models/project.rb b/app/models/project.rb
index 7c5fdad5122..ad22ab7577e 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1307,10 +1307,17 @@ class Project < ActiveRecord::Base
end
def environments_for(ref, commit: nil, with_tags: false)
- deployments_query = with_tags ? 'ref = ? OR tag IS TRUE' : 'ref = ?'
+ deps =
+ if ref
+ deployments_query = with_tags ? 'ref = ? OR tag IS TRUE' : 'ref = ?'
+ deployments.where(deployments_query, ref.to_s)
+ elsif commit
+ deps = deployments.where(sha: commit.sha)
+ else
+ Deployment.none
+ end
- environment_ids = deployments
- .where(deployments_query, ref.to_s)
+ environment_ids = deps
.group(:environment_id)
.select(:environment_id)
@@ -1324,12 +1331,46 @@ class Project < ActiveRecord::Base
end
end
+ def latest_environment_for(commit, ref: nil)
+ environments = environments_for(ref, commit: commit)
+ Environment.latest_for_commit(environments, commit)
+ end
+
def environments_recently_updated_on_branch(branch)
environments_for(branch).select do |environment|
environment.recently_updated_on_branch?(branch)
end
end
+ def route_map_for_commit(commit_sha)
+ @route_maps_by_commit ||= Hash.new do |h, sha|
+ h[sha] = begin
+ data = repository.route_map_file(sha)
+ next unless data
+
+ # TODO: Validate
+ YAML.safe_load(data).map do |mapping|
+ {
+ source: Regexp.new("^#{mapping['source'][1...-1]}$"),
+ public: mapping['public']
+ }
+ end
+ end
+ end
+
+ @route_maps_by_commit[commit_sha]
+ end
+
+ def public_path_for_source_path(path, commit_sha)
+ map = route_map_for_commit(commit_sha)
+ return unless map
+
+ mapping = map.find { |mapping| path =~ mapping[:source] }
+ return unless mapping
+
+ path.sub(mapping[:source], mapping[:public])
+ end
+
private
def cross_namespace_reference?(from)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 7cf09c52bf4..9aa0cc250f0 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -35,6 +35,9 @@ class Repository
avatar: :avatar
}
+ ROUTE_MAP_PATH = '.gitlab/route-map.yml'
+ GITLAB_CI_YML_PATH = '.gitlab-ci.yml'
+
# Wraps around the given method and caches its output in Redis and an instance
# variable.
#
@@ -1184,6 +1187,20 @@ class Repository
end
end
+ def route_map_file(sha)
+ blob = blob_at(sha, ROUTE_MAP_PATH)
+ return unless blob
+ blob.load_all_data!(self)
+ blob.data
+ end
+
+ def ci_yaml_file(sha)
+ blob = blob_at(sha, GITLAB_CI_YML_PATH)
+ return unless blob
+ blob.load_all_data!(self)
+ blob.data
+ end
+
private
def git_action(index, action)
diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml
index ff893ea74e1..fbe74495e1c 100644
--- a/app/views/projects/blob/_actions.html.haml
+++ b/app/views/projects/blob/_actions.html.haml
@@ -1,3 +1,6 @@
+.btn-group
+ = view_on_environment_btn(@commit.sha, @path, @environment) if @environment
+
.btn-group.tree-btn-group
= link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id),
class: 'btn btn-sm', target: '_blank'
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index 7afd3d80ef5..d5fc283aa8d 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -9,7 +9,7 @@
= render "ci_menu"
- else
.block-connector
- = render "projects/diffs/diffs", diffs: @diffs
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment
= render "projects/notes/notes_with_form"
- if can_collaborate_with_project?
- %w(revert cherry-pick).each do |type|
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index 9c8f58d4aea..0dfc9fe20ed 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -8,7 +8,7 @@
- if @commits.present?
= render "projects/commits/commit_list"
- = render "projects/diffs/diffs", diffs: @diffs
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment
- else
.light-well
.center
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 58c20e225c6..4b49bed835f 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -1,3 +1,4 @@
+- environment = local_assigns.fetch(:environment, nil)
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
- diff_files = diffs.diff_files
@@ -30,4 +31,4 @@
- file_hash = hexdigest(diff_file.file_path)
= render 'projects/diffs/file', file_hash: file_hash, project: diffs.project,
- diff_file: diff_file, diff_commit: diff_commit, blob: blob
+ diff_file: diff_file, diff_commit: diff_commit, blob: blob, environment: environment
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index fc478ccc995..f7aa4fb90f1 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -1,3 +1,4 @@
+- environment = local_assigns.fetch(:environment, nil)
.diff-file.file-holder{ id: file_hash, data: diff_file_html_data(project, diff_file.file_path, diff_commit.id) }
.file-title
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_commit, project: project, url: "##{file_hash}"
@@ -14,5 +15,6 @@
blob: blob, link_opts: link_opts)
= view_file_btn(diff_commit.id, diff_file.new_path, project)
+ = view_on_environment_btn(diff_commit.id, diff_file.new_path, environment) if environment
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, blob: blob, project: project
diff --git a/app/views/projects/merge_requests/_new_diffs.html.haml b/app/views/projects/merge_requests/_new_diffs.html.haml
index 74367ab9b7b..627fc4e9671 100644
--- a/app/views/projects/merge_requests/_new_diffs.html.haml
+++ b/app/views/projects/merge_requests/_new_diffs.html.haml
@@ -1 +1 @@
-= render "projects/diffs/diffs", diffs: @diffs, show_whitespace_toggle: false
+= render "projects/diffs/diffs", diffs: @diffs, environment: @environment, show_whitespace_toggle: false
diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml
index 5f048d04b27..7f0913ea516 100644
--- a/app/views/projects/merge_requests/show/_diffs.html.haml
+++ b/app/views/projects/merge_requests/show/_diffs.html.haml
@@ -1,5 +1,5 @@
- if @merge_request_diff.collected? || @merge_request_diff.overflow?
= render 'projects/merge_requests/show/versions'
- = render "projects/diffs/diffs", diffs: @diffs
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment
- elsif @merge_request_diff.empty?
.nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
diff --git a/changelogs/unreleased/route-map.yml b/changelogs/unreleased/route-map.yml
new file mode 100644
index 00000000000..71595745f9b
--- /dev/null
+++ b/changelogs/unreleased/route-map.yml
@@ -0,0 +1,4 @@
+---
+title: Add 'View on [env]' link to blobs and individual files in diffs
+merge_request:
+author: