"Fossies" - the Fresh Open Source Software Archive

Member "discourse-3.1.3/lib/tasks/release_note.rake" (9 Nov 2023, 4122 Bytes) of package /linux/www/discourse-3.1.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "release_note.rake": 3.0.6_vs_3.1.0.

    1 # frozen_string_literal: true
    2 
    3 DATE_REGEX ||= /\A\d{4}-\d{2}-\d{2}/
    4 
    5 CHANGE_TYPES ||= [
    6   { pattern: /\AFEATURE:/, heading: "New Features" },
    7   { pattern: /\AFIX:/, heading: "Bug Fixes" },
    8   { pattern: /\AUX:/, heading: "UX Changes" },
    9   { pattern: /\ASECURITY:/, heading: "Security Changes" },
   10   { pattern: /\APERF:/, heading: "Performance" },
   11   { pattern: /\AA11Y:/, heading: "Accessibility" },
   12 ]
   13 
   14 desc "generate a release note from the important commits"
   15 task "release_note:generate", :from, :to, :repo do |t, args|
   16   repo = args[:repo] || "."
   17   changes = find_changes(repo, args[:from], args[:to])
   18 
   19   CHANGE_TYPES.each { |ct| print_changes(ct[:heading], changes[ct], "###") }
   20 
   21   puts "(no changes)", "" if changes.values.all?(&:empty?)
   22 end
   23 
   24 # To use with all-the-plugins:
   25 #  1. Make sure you have a local, up-to-date clone of https://github.com/discourse/all-the-plugins
   26 #  2. In all-the-plugins, `git submodule update --init --recursive --remote`
   27 #  3. Change back to your discourse directory
   28 #  4. rake "release_note:plugins:generate[ 2021-06-01 , 2021-07-01 , /path/to/all-the-plugins/plugins/* , discourse ]"
   29 desc "generate release notes for all official plugins in a directory"
   30 task "release_note:plugins:generate", :from, :to, :plugin_glob, :org do |t, args|
   31   from = args[:from]
   32   to = args[:to]
   33   plugin_glob = args[:plugin_glob] || "./plugins/*"
   34   git_org = args[:org]
   35 
   36   all_repos = Dir.glob(plugin_glob).filter { |f| File.directory?(f) && File.exist?("#{f}/.git") }
   37 
   38   if git_org
   39     all_repos =
   40       all_repos.filter do |dir|
   41         `git -C #{dir} remote get-url origin`.match?(%r{github.com[/:]#{git_org}/})
   42       end
   43   end
   44 
   45   no_changes_repos = []
   46 
   47   all_repos.each do |dir|
   48     name = File.basename(dir)
   49     changes = find_changes(dir, from, to)
   50 
   51     if changes.values.all?(&:empty?)
   52       no_changes_repos << name
   53       next
   54     end
   55 
   56     puts "### #{name}\n\n"
   57     CHANGE_TYPES.each { |ct| print_changes(ct[:heading], changes[ct], "####") }
   58   end
   59 
   60   puts "(No changes found in #{no_changes_repos.join(", ")})"
   61 end
   62 
   63 def find_changes(repo, from, to)
   64   dates = from&.match?(DATE_REGEX) || to&.match?(DATE_REGEX)
   65 
   66   if !dates
   67     from ||= `git -C #{repo} describe --tags --abbrev=0`.strip
   68     to ||= "HEAD"
   69   end
   70 
   71   cmd = "git -C #{repo} log --pretty='tformat:%s' "
   72   if dates
   73     cmd += "--after '#{from}' " if from
   74     cmd += "--before '#{to}' " if to
   75   else
   76     cmd += "#{from}..#{to}"
   77   end
   78 
   79   out = `#{cmd}`
   80   raise "Status #{$?.exitstatus} running git log\n#{out}" if !$?.success?
   81 
   82   changes = {}
   83   CHANGE_TYPES.each { |ct| changes[ct] = Set.new }
   84 
   85   out.each_line do |comment|
   86     next if comment =~ /\A\s*Revert/
   87     split_comments(comment).each do |line|
   88       ct = CHANGE_TYPES.find { |t| line =~ t[:pattern] }
   89       changes[ct] << better(line) if ct
   90     end
   91   end
   92 
   93   changes
   94 end
   95 
   96 def print_changes(heading, changes, importance)
   97   return if changes.length == 0
   98 
   99   puts "#{importance} #{heading}", ""
  100   puts changes.to_a, ""
  101 end
  102 
  103 def better(line)
  104   line = remove_prefix(line)
  105   line = escape_brackets(line)
  106   line = remove_pull_request(line)
  107   line[0] = '\#' if line[0] == "#"
  108   if line[0]
  109     line[0] = line[0].capitalize
  110     "- " + line
  111   else
  112     nil
  113   end
  114 end
  115 
  116 def remove_prefix(line)
  117   line.gsub(/\A(FIX|FEATURE|UX|SECURITY|PERF|A11Y):/, "").strip
  118 end
  119 
  120 def escape_brackets(line)
  121   line.gsub("<", "`<").gsub(">", ">`").gsub("[", "`[").gsub("]", "]`")
  122 end
  123 
  124 def remove_pull_request(line)
  125   line.gsub(/ \(\#\d+\)\z/, "")
  126 end
  127 
  128 def split_comments(text)
  129   text = normalize_terms(text)
  130   terms = %w[FIX: FEATURE: UX: SECURITY: PERF: A11Y:]
  131   terms.each do |term|
  132     text = text.gsub(/(#{term})+/i, term)
  133     text = newlines_at_term(text, term)
  134   end
  135   text.split("\n")
  136 end
  137 
  138 def normalize_terms(text)
  139   text = text.gsub(/(BUGFIX|FIX|BUG):/i, "FIX:")
  140   text = text.gsub(/FEATURE:/i, "FEATURE:")
  141   text = text.gsub(/(UX|UI):/i, "UX:")
  142   text = text.gsub(/(SECURITY):/i, "SECURITY:")
  143   text = text.gsub(/(PERF):/i, "PERF:")
  144   text = text.gsub(/(A11Y):/i, "A11Y:")
  145 end
  146 
  147 def newlines_at_term(text, term)
  148   text = text.split(term).map { |l| l.strip }.join("\n#{term} ") if text.include?(term)
  149   text
  150 end