diff --git a/app/assets/javascripts/admin/addon/components/plugin-commit-hash.hbs b/app/assets/javascripts/admin/addon/components/plugin-commit-hash.hbs new file mode 100644 index 00000000000..441febf757f --- /dev/null +++ b/app/assets/javascripts/admin/addon/components/plugin-commit-hash.hbs @@ -0,0 +1,7 @@ +{{#if this.commitHash}} + {{this.shortCommitHash}} +{{/if}} \ No newline at end of file diff --git a/app/assets/javascripts/admin/addon/components/plugin-commit-hash.js b/app/assets/javascripts/admin/addon/components/plugin-commit-hash.js new file mode 100644 index 00000000000..0848db33c5e --- /dev/null +++ b/app/assets/javascripts/admin/addon/components/plugin-commit-hash.js @@ -0,0 +1,11 @@ +import Component from "@glimmer/component"; + +export default class PluginCommitHash extends Component { + get shortCommitHash() { + return this.commitHash?.slice(0, 7); + } + + get commitHash() { + return this.args.plugin.commit_hash; + } +} diff --git a/app/assets/javascripts/admin/addon/templates/plugins-index.hbs b/app/assets/javascripts/admin/addon/templates/plugins-index.hbs index 36916108607..c02746557af 100644 --- a/app/assets/javascripts/admin/addon/templates/plugins-index.hbs +++ b/app/assets/javascripts/admin/addon/templates/plugins-index.hbs @@ -42,7 +42,8 @@
{{i18n "admin.plugins.version"}}
- {{plugin.version}} + {{plugin.version}}
+
{{i18n "admin.plugins.enabled"}}
diff --git a/app/assets/stylesheets/common/admin/plugins.scss b/app/assets/stylesheets/common/admin/plugins.scss index 8a0061b5852..a070e836bea 100644 --- a/app/assets/stylesheets/common/admin/plugins.scss +++ b/app/assets/stylesheets/common/admin/plugins.scss @@ -11,6 +11,12 @@ font-weight: bold; } } + td.version { + .commit-hash { + color: var(--primary-low-mid); + font-size: var(--font-down-1); + } + } .grid { @media screen and (min-width: 550px) { tr { diff --git a/app/serializers/admin_plugin_serializer.rb b/app/serializers/admin_plugin_serializer.rb index 75a0771612c..e80e157fc94 100644 --- a/app/serializers/admin_plugin_serializer.rb +++ b/app/serializers/admin_plugin_serializer.rb @@ -10,7 +10,9 @@ class AdminPluginSerializer < ApplicationSerializer :enabled, :enabled_setting, :has_settings, - :is_official + :is_official, + :commit_hash, + :commit_url def id object.directory_name @@ -68,4 +70,12 @@ class AdminPluginSerializer < ApplicationSerializer def is_official Plugin::Metadata::OFFICIAL_PLUGINS.include?(object.name) end + + def commit_hash + object.commit_hash + end + + def commit_url + object.commit_url + end end diff --git a/lib/discourse.rb b/lib/discourse.rb index 728b559b618..1e5d85e66da 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -1141,6 +1141,7 @@ module Discourse Discourse.git_version Discourse.git_branch Discourse.full_version + Discourse.plugins.each { |p| p.commit_url } end, Thread.new do require "actionview_precompiler" diff --git a/lib/git_repo.rb b/lib/git_repo.rb new file mode 100644 index 00000000000..4d8dcb952ac --- /dev/null +++ b/lib/git_repo.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class GitRepo + attr_reader :path, :name + + def initialize(path, name = nil) + @path = path + @name = name + @memoize = {} + end + + def url + url = run("config --get remote.origin.url") + return if url.blank? + + url.sub!(/\Agit@github\.com:/, "https://github.com/") + url.sub!(/\.git\z/, "") + url + end + + def latest_local_commit + run "rev-parse HEAD" + end + + protected + + def run(cmd) + @memoize[cmd] ||= begin + cmd = "git #{cmd}".split(" ") + Discourse::Utils.execute_command(*cmd, chdir: path).strip + rescue => e + Discourse.warn_exception(e, message: "Error running git command: #{cmd} in #{path}") + nil + end + end +end diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index eba36d1f756..c1278def0a0 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -516,6 +516,19 @@ class Plugin::Instance initializers << block end + def commit_hash + git_repo.latest_local_commit + end + + def commit_url + return if commit_hash.blank? + "#{git_repo.url}/commit/#{commit_hash}" + end + + def git_repo + @git_repo ||= GitRepo.new(directory, name) + end + def before_auth(&block) if @before_auth_complete raise "Auth providers must be registered before omniauth middleware. after_initialize is too late!" diff --git a/spec/lib/git_repo_spec.rb b/spec/lib/git_repo_spec.rb new file mode 100644 index 00000000000..4620cf36422 --- /dev/null +++ b/spec/lib/git_repo_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +RSpec.describe GitRepo do + let(:git_repo) { GitRepo.new("/tmp", "discourse") } + + it "returns the correct URL" do + Discourse::Utils.stubs(:execute_command).returns("https://github.com/username/my_plugin.git") + expect(git_repo.url).to eq("https://github.com/username/my_plugin") + Discourse::Utils.stubs(:execute_command).returns("git@github.com/username/my_plugin.git") + expect(git_repo.url).to eq("https://github.com/username/my_plugin") + end + + it "returns the correct commit hash" do + Discourse::Utils.expects(:execute_command).returns("123456") + expect(git_repo.latest_local_commit).to eq("123456") + end +end diff --git a/spec/lib/plugin/instance_spec.rb b/spec/lib/plugin/instance_spec.rb index ce202acb5a8..2957b94cab2 100644 --- a/spec/lib/plugin/instance_spec.rb +++ b/spec/lib/plugin/instance_spec.rb @@ -11,6 +11,13 @@ RSpec.describe Plugin::Instance do expect(plugin.name).to eq("plugin-name") expect(plugin.path).to eq("#{Rails.root}/spec/fixtures/plugins/my_plugin/plugin.rb") + + git_repo = plugin.git_repo + plugin.git_repo.stubs(:latest_local_commit).returns("123456") + plugin.git_repo.stubs(:url).returns("http://github.com/discourse/discourse-plugin") + + expect(plugin.commit_hash).to eq("123456") + expect(plugin.commit_url).to eq("http://github.com/discourse/discourse-plugin/commit/123456") end it "does not blow up on missing directory" do diff --git a/spec/serializers/admin_plugin_serializer_spec.rb b/spec/serializers/admin_plugin_serializer_spec.rb index 0ca42794713..6e242356606 100644 --- a/spec/serializers/admin_plugin_serializer_spec.rb +++ b/spec/serializers/admin_plugin_serializer_spec.rb @@ -11,4 +11,18 @@ RSpec.describe AdminPluginSerializer do expect(subject.enabled_setting).to eq("test") end end + + describe "commit_hash" do + it "should return commit_hash and commit_url" do + instance = Plugin::Instance.find_all("#{Rails.root}/spec/fixtures/plugins")[0] + subject = described_class.new(instance) + + git_repo = instance.git_repo + git_repo.stubs(:latest_local_commit).returns("123456") + git_repo.stubs(:url).returns("http://github.com/discourse/discourse-plugin") + + expect(subject.commit_hash).to eq("123456") + expect(subject.commit_url).to eq("http://github.com/discourse/discourse-plugin/commit/123456") + end + end end