Commit bc1b1f3e authored by Jason Plum's avatar Jason Plum Committed by DJ Mountney

scripts: add version mapping automation v1

Add `class VersionMappingDoc` to `manage_version.rb`

Built around RDoc, this class handles the updating of the version
mapping table in `doc/installation/version_mappings.md`.

Process:

- load `version_mappings.md`
- locate and store a copy of the table (RDoc::Markup::Paragraph)
- allow inserting a version to the top, if not already present
- write back to `version_mappings.md`

NOTE: currently, the output document is very poorly transformed.
RDoc::Markup::ToMarkdown butchers the output severely.

Missing:

- table entry ordering
- proper output formatting

[ci skip]
parent 1cbc4e17
---
title: Automate version mapping updates
merge_request: 704
author:
type: other
......@@ -35,4 +35,4 @@ gitlab/gitlab 1.4.1 11.6.2
Read more about our charts versioning [here](https://gitlab.com/charts/gitlab/blob/master/doc/development/release.md#chart-versioning)
Check the [releases documentation](../releases/index.md) for information on important releases,
and see the [changelog](https://gitlab.com/charts/gitlab/blob/master/CHANGELOG.md) for the full details on any release.
and see the [changelog](https://gitlab.com/charts/gitlab/blob/master/CHANGELOG.md) for the full details on any release.
require_relative 'version'
class VersionMapping
class Document
TABLE_HEADER = '| Chart version | GitLab version |'.freeze
TABLE_DIVIDE = '|---------------|----------------|'.freeze
def initialize(filepath)
unless filepath && File.exist?(filepath)
$stderr.puts "Version mapping documention must exist: #{filepath}"
exit 1
end
@filepath = filepath
$stdout.puts "Reading #{@filepath}"
@document = File.read(@filepath).split("\n")
unless @document.include?(TABLE_HEADER)
$stderr.puts "Version mapping documention must contain table: #{filepath}"
exit 1
end
end
def table
@table ||= extract_version_table
end
def write
update_version_table
$stdout.puts "Updating #{@filepath}"
File.write(@filepath, @document.join("\n"))
end
private
def extract_version_table
@table = Table.new
# find the table in the file
@index_start = @document.find_index(TABLE_HEADER)
# find the first blank line after the header, denoting end of table
@index_end = @document.drop(@index_start).find_index('')
table_content = @document.slice(@index_start, @index_end)
# convert the table into a VersionMapping::Table
# Note: drop(2) to dispose of TABLE_HEADER and TABLE_DIVIDE
table_content.drop(2).each do |item|
items = item.split('|').delete_if { |i| i == '' }
@table.append(Version.new(items[0].strip), Version.new(items[1].strip))
end
@table
end
def update_version_table
table_content = [TABLE_HEADER, TABLE_DIVIDE]
table.sort!.each do |entry|
table_content << "| #{entry[0]} | #{entry[1]} |"
end
@document[@index_start, @index_end] = table_content
@index_end = table_content.count
end
end
class Table
include Enumerable
def initialize
@entries = []
end
def append(chart_version, app_version)
chart_version = Version.new(chart_version) unless chart_version.instance_of? Version
app_version = Version.new(app_version) unless app_version.instance_of? Version
return unless chart_version.release? && app_version.release?
@entries.delete_if { |item| item[0] == chart_version }
@entries << [chart_version, app_version]
end
def sort!
@entries.sort! { |a, b| b[0] <=> a[0] }
end
def each(&block)
@entries.each(&block)
end
def count
@entries.count
end
end
# VersionMapping
attr_reader :document
def initialize(filepath)
@document = Document.new(filepath)
end
def insert_version(chart_version, app_version)
@document.table.append(chart_version, app_version)
end
def finalize
@document.write
end
end
......@@ -5,6 +5,7 @@ require 'yaml'
require_relative 'lib/version'
require_relative 'lib/version_fetcher'
require_relative 'lib/version_mapping'
Options = Struct.new(
:working_dir,
......@@ -119,7 +120,16 @@ class VersionUpdater
return if options.dry_run
chart.update_versions(@chart_version, @app_version)
# Never change appVersion in master branch
chart.update_versions(@chart_version, branch == 'master' ? nil : @app_version)
# Only insert into version_mapping when we have both versions, as releases
unless @app_version.nil?
if chart.version.release? && @app_version.release?
version_mapping.insert_version(chart.version, @app_version)
version_mapping.finalize
end
end
if @options.include_subcharts
@subchart_versions.each do |sub_chart, update_app_version|
......@@ -140,6 +150,10 @@ class VersionUpdater
@subcharts ||= Dir[File.join(working_dir, 'charts', 'gitlab', 'charts', '*', 'Chart.yaml')].map { |path| ChartFile.new(path) }
end
def version_mapping
@version_mapping ||= VersionMapping.new(File.join(working_dir, 'doc/installation/version_mappings.md'))
end
def populate_subchart_versions
@subchart_versions = subcharts.map do |sub_chart|
[ sub_chart, VersionFetcher.fetch(sub_chart.name, @app_version) ]
......@@ -182,6 +196,18 @@ class VersionUpdater
end
end
end
def branch
@branch ||= get_current_branch
end
def get_current_branch
git_command = 'git rev-parse --abbrev-ref HEAD 2>&1'.freeze
output = `#{git_command}`.chomp
raise(StandardError.new(output)) unless $?.success?
end
end
# Only auto-run when called as a script, and not included as a lib
......
......@@ -6,11 +6,13 @@ describe 'scripts/manage_version.rb' do
describe VersionUpdater do
let(:chart_file) { instance_double("ChartFile") }
let(:options) { Options.new }
let(:version_mapping) { instance_double("VersionMapping") }
before do
allow_any_instance_of(described_class).to receive(:subcharts).and_return([])
allow_any_instance_of(described_class).to receive(:chart).and_return(chart_file)
allow_any_instance_of(described_class).to receive(:working_dir).and_return(nil)
allow_any_instance_of(described_class).to receive(:version_mapping).and_return(version_mapping)
end
describe 'populate_chart_version' do
......@@ -19,6 +21,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(new_version: 'chart-version', new_app_version: 'app-version')
expect(chart_file).to receive(:update_versions).with('chart-version', 'app-version')
expect(version_mapping).not_to receive(:insert_version)
described_class.new(options)
end
end
......@@ -28,6 +31,17 @@ describe 'scripts/manage_version.rb' do
stub_versions(new_version: 'chart-version')
expect(chart_file).to receive(:update_versions).with('chart-version', nil)
expect(version_mapping).not_to receive(:insert_version)
described_class.new(options)
end
end
context 'chart_version and app_version provided on master branch' do
it 'ignores app_version for update_versions, adds version mapping entry' do
stub_versions(new_version: '1.0.0', app_version: 'master', new_app_version: '1.0.0', branch: 'master')
expect(chart_file).to receive(:update_versions).with('1.0.0', nil)
expect(version_mapping).to receive(:insert_version).with('1.0.0', '1.0.0')
described_class.new(options)
end
end
......@@ -46,6 +60,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: 'master', new_app_version: '10.8.1')
expect(chart_file).to receive(:update_versions).with('0.0.2', '10.8.1')
expect(version_mapping).to receive(:insert_version).with('0.0.2', '10.8.1')
described_class.new(options)
end
......@@ -53,6 +68,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: 'master', new_app_version: '10.8.0')
expect(chart_file).to receive(:update_versions).with('0.1.0', '10.8.0')
expect(version_mapping).to receive(:insert_version).with('0.1.0', '10.8.0')
described_class.new(options)
end
......@@ -60,6 +76,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: 'master', new_app_version: '11.0.0')
expect(chart_file).to receive(:update_versions).with('1.0.0', '11.0.0')
expect(version_mapping).to receive(:insert_version).with('1.0.0', '11.0.0')
described_class.new(options)
end
......@@ -67,6 +84,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: 'master', new_app_version: '11.0.0-rc1')
expect(chart_file).to receive(:update_versions).with('1.0.0', '11.0.0-rc1')
expect(version_mapping).not_to receive(:insert_version)
described_class.new(options)
end
end
......@@ -75,6 +93,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: '10.8.0', new_app_version: '10.8.1')
expect(chart_file).to receive(:update_versions).with('0.0.2', '10.8.1')
expect(version_mapping).to receive(:insert_version).with('0.0.2', '10.8.1')
described_class.new(options)
end
......@@ -82,6 +101,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: '10.7.5', new_app_version: '10.8.1')
expect(chart_file).to receive(:update_versions).with('0.1.0', '10.8.1')
expect(version_mapping).to receive(:insert_version).with('0.1.0', '10.8.1')
described_class.new(options)
end
......@@ -89,6 +109,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: '10.8.5', new_app_version: '11.1.5')
expect(chart_file).to receive(:update_versions).with('1.0.0', '11.1.5')
expect(version_mapping).to receive(:insert_version).with('1.0.0', '11.1.5')
described_class.new(options)
end
......@@ -96,6 +117,7 @@ describe 'scripts/manage_version.rb' do
stub_versions(version: '0.0.1', app_version: '11.0.0-rc1', new_app_version: '11.0.0-rc2')
expect(chart_file).to receive(:update_versions).with('0.0.1', '11.0.0-rc2')
expect(version_mapping).not_to receive(:insert_version)
described_class.new(options)
end
end
......@@ -103,11 +125,18 @@ describe 'scripts/manage_version.rb' do
end
end
def stub_versions(new_version: nil, version: '0.0.1', new_app_version: nil, app_version: '0.0.1')
def stub_versions(new_version: nil, version: '0.0.1', new_app_version: nil, app_version: '0.0.1', branch: nil)
options.chart_version = Version.new(new_version) if new_version
options.app_version = Version.new(new_app_version) if new_app_version
allow(chart_file).to receive(:version).and_return(Version.new(version)) if version
allow(chart_file).to receive(:app_version).and_return(Version.new(app_version)) if app_version
allow(chart_file).to receive(:update_versions).and_return(true)
allow(chart_file).to receive(:update_versions) do | chart_ver, app_ver |
allow(chart_file).to receive(:version).and_return(Version.new(chart_ver)) if chart_ver
allow(chart_file).to receive(:app_version).and_return(Version.new(app_ver)) if app_ver
end
allow(version_mapping).to receive(:finalize).and_return(true)
allow_any_instance_of(described_class).to receive(:branch).and_return(branch)
end
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