Skip to content

Commit

Permalink
Merge pull request xotahal#24 from thislooksfun/feature/add-presets
Browse files Browse the repository at this point in the history
feat: add commit_format option
  • Loading branch information
xotahal authored Jun 28, 2020
2 parents 15e2bbc + 197a694 commit bc5ee67
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 17 deletions.
31 changes: 29 additions & 2 deletions lib/fastlane/plugin/semantic_release/actions/analyze_commits.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module SharedValues
RELEASE_NEXT_PATCH_VERSION = :RELEASE_NEXT_PATCH_VERSION
RELEASE_NEXT_VERSION = :RELEASE_NEXT_VERSION
RELEASE_LAST_INCOMPATIBLE_CODEPUSH_VERSION = :RELEASE_LAST_INCOMPATIBLE_CODEPUSH_VERSION
CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN = :CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN
end

class AnalyzeCommitsAction < Action
Expand Down Expand Up @@ -89,6 +90,7 @@ def self.is_releasable(params)
UI.message("Found #{splitted.length} commits since last release")
releases = params[:releases]

format_pattern = lane_context[SharedValues::CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN]
splitted.each do |line|
parts = line.split("|")
subject = parts[0].strip
Expand All @@ -97,7 +99,8 @@ def self.is_releasable(params)
commit = Helper::SemanticReleaseHelper.parse_commit(
commit_subject: subject,
commit_body: parts[1],
releases: releases
releases: releases,
pattern: format_pattern
)

unless commit[:scope].nil?
Expand Down Expand Up @@ -169,13 +172,15 @@ def self.is_codepush_friendly(params)
releases = params[:releases]
codepush_friendly = params[:codepush_friendly]

format_pattern = lane_context[SharedValues::CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN]
splitted.each do |line|
# conventional commits are in format
# type: subject (fix: app crash - for example)
commit = Helper::SemanticReleaseHelper.parse_commit(
commit_subject: line.split("|")[0],
commit_body: line.split("|")[1],
releases: releases,
pattern: format_pattern,
codepush_friendly: codepush_friendly
)

Expand Down Expand Up @@ -229,6 +234,27 @@ def self.available_options
UI.user_error!("No match for analyze_commits action given, pass using `match: 'expr'`") unless value && !value.empty?
end
),
FastlaneCore::ConfigItem.new(
key: :commit_format,
description: "The commit format to apply. Presets are 'default' or 'angular', or you can provide your own Regexp. Note: the supplied regex _must_ have 4 capture groups, in order: type, scope, has_exclamation_mark, and subject",
default_value: "default",
is_string: false,
verify_block: proc do |value|
case value
when String
unless Helper::SemanticReleaseHelper.format_patterns.key?(value)
UI.user_error!("Invalid format preset: #{value}")
end

pattern = Helper::SemanticReleaseHelper.format_patterns[value]
when Regexp
pattern = value
else
UI.user_error!("Invalid option type: #{value.inspect}")
end
Actions.lane_context[SharedValues::CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN] = pattern
end
),
FastlaneCore::ConfigItem.new(
key: :releases,
description: "Map types of commit to release (major, minor, patch)",
Expand Down Expand Up @@ -283,7 +309,8 @@ def self.output
['RELEASE_NEXT_MINOR_VERSION', 'Minor number of the next version'],
['RELEASE_NEXT_PATCH_VERSION', 'Patch number of the next version'],
['RELEASE_NEXT_VERSION', 'Next version string in format (major.minor.patch)'],
['RELEASE_LAST_INCOMPATIBLE_CODEPUSH_VERSION', 'Last commit without codepush']
['RELEASE_LAST_INCOMPATIBLE_CODEPUSH_VERSION', 'Last commit without codepush'],
['CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN', 'The format pattern Regexp used to match commits (mainly for internal use)']
]
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,14 @@ def self.build_commit_link(commit, commit_url, format)
def self.parse_commits(commits)
parsed = []
# %s|%b|%H|%h|%an|%at
format_pattern = lane_context[SharedValues::CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN]
commits.each do |line|
splitted = line.split("|")

commit = Helper::SemanticReleaseHelper.parse_commit(
commit_subject: splitted[0],
commit_body: splitted[1]
commit_body: splitted[1],
pattern: format_pattern
)

commit[:hash] = splitted[2]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ module Fastlane

module Helper
class SemanticReleaseHelper
def self.format_patterns
return {
"default" => /^(docs|fix|feat|chore|style|refactor|perf|test)(?:\((.*)\))?(!?)\: (.*)/,
"angular" => /^(\w*)(?:\((.*)\))?(): (.*)/
}
end

# class methods that you define here become available in your action
# as `Helper::SemanticReleaseHelper.your_method`
#
Expand All @@ -18,7 +25,7 @@ def self.parse_commit(params)
commit_body = params[:commit_body]
releases = params[:releases]
codepush_friendly = params[:codepush_friendly]
pattern = /^(docs|fix|feat|chore|style|refactor|perf|test)(\((.*)\))?(!?)\: (.*)/
pattern = params[:pattern]
breaking_change_pattern = /BREAKING CHANGES?: (.*)/
codepush_pattern = /codepush?: (.*)/

Expand All @@ -32,13 +39,13 @@ def self.parse_commit(params)

unless matched.nil?
type = matched[1]
scope = matched[3]
scope = matched[2]

result[:is_valid] = true
result[:type] = type
result[:scope] = scope
result[:has_exclamation_mark] = matched[4] == '!'
result[:subject] = matched[5]
result[:has_exclamation_mark] = matched[3] == '!'
result[:subject] = matched[4]

unless releases.nil?
result[:release] = releases[type.to_sym]
Expand Down
155 changes: 155 additions & 0 deletions spec/analyze_commits_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,161 @@ def execute_lane_test(params)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_LAST_INCOMPATIBLE_CODEPUSH_VERSION]).to eq("0.0.3")
end

describe "commit_format" do
describe "default" do
it "should allow for certain types" do
commits = [
"docs: ...|",
"fix: ...|",
"feat: ...|",
"chore: ...|",
"style: ...|",
"refactor: ...|",
"perf: ...|",
"test: ...|"
]
test_analyze_commits(commits)

is_releasable = execute_lane_test(
match: 'v*',
releases: {
docs: "minor",
fix: "minor",
feat: "minor",
chore: "minor",
style: "minor",
refactor: "minor",
perf: "minor",
test: "minor"
}
)
expect(is_releasable).to eq(true)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION]).to eq("1.8.0")
end

it "should not allow for custom types" do
commits = [
"foo: ...|",
"bar: ...|",
"baz: ...|"
]
test_analyze_commits(commits)

is_releasable = execute_lane_test(
match: 'v*',
releases: {
foo: "minor",
bar: "minor",
baz: "minor"
}
)
expect(is_releasable).to eq(false)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION]).to eq("1.0.8")
end
end

describe "angular" do
it "should allow for default types" do
commits = [
"docs: ...|",
"fix: ...|",
"feat: ...|",
"chore: ...|",
"style: ...|",
"refactor: ...|",
"perf: ...|",
"test: ...|"
]
test_analyze_commits(commits)

is_releasable = execute_lane_test(
match: 'v*',
commit_format: 'angular',
releases: {
docs: "minor",
fix: "minor",
feat: "minor",
chore: "minor",
style: "minor",
refactor: "minor",
perf: "minor",
test: "minor"
}
)
expect(is_releasable).to eq(true)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION]).to eq("1.8.0")
end

it "should allow for custom types" do
commits = [
"foo: ...|",
"bar: ...|",
"baz: ...|"
]
test_analyze_commits(commits)

is_releasable = execute_lane_test(
match: 'v*',
commit_format: 'angular',
releases: {
foo: "minor",
bar: "minor",
baz: "minor"
}
)
expect(is_releasable).to eq(true)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION]).to eq("1.3.0")
end
end

describe "custom" do
format_pattern = /^prefix-(foo|bar|baz)(?:\.(.*))?(): (.*)/
commits = [
"prefix-foo.ios: ...|",
"prefix-foo.android: ...|",
"prefix-bar.ios: ...|",
"prefix-bar.android: ...|",
"prefix-baz.ios: ...|",
"prefix-baz.android: ...|",
"prefix-qux.ios: ...|",
"prefix-qux.android: ...|"
]

it "should allow for arbetrary formatting" do
test_analyze_commits(commits)

is_releasable = execute_lane_test(
match: 'v*',
commit_format: format_pattern,
releases: {
foo: "major",
bar: "minor",
baz: "patch"
}
)
expect(is_releasable).to eq(true)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION]).to eq("3.2.2")
end

it "should allow for arbetrary formatting with scope" do
test_analyze_commits(commits)

is_releasable = execute_lane_test(
match: 'v*',
commit_format: format_pattern,
releases: {
foo: "major",
bar: "minor",
baz: "patch"
},
ignore_scopes: ['android']
)
expect(is_releasable).to eq(true)
expect(Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION]).to eq("2.1.1")
end
end
end

after do
end
end
Expand Down
52 changes: 42 additions & 10 deletions spec/conventional_changelog_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,45 @@
describe Fastlane::Actions::ConventionalChangelogAction do
describe "Conventional Changelog" do
before do
Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN] = Fastlane::Helper::SemanticReleaseHelper.format_patterns["default"]
Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_NEXT_VERSION] = '1.0.2'
Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::RELEASE_ANALYZED] = true
end

def execute_lane_test
Fastlane::FastFile.new.parse("lane :test do conventional_changelog end").runner.execute(:test)
def execute_lane_test(params = {})
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( #{params} ) end").runner.execute(:test)
end

def execute_lane_test_plain
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( format: 'plain' ) end").runner.execute(:test)
execute_lane_test(format: 'plain')
end

def execute_lane_test_slack
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( format: 'slack' ) end").runner.execute(:test)
execute_lane_test(format: 'slack')
end

def execute_lane_test_author
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( display_author: true ) end").runner.execute(:test)
execute_lane_test(display_author: true)
end

def execute_lane_test_no_header
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( display_title: false ) end").runner.execute(:test)
execute_lane_test(display_title: false)
end

def execute_lane_test_no_header_plain
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( format: 'plain', display_title: false ) end").runner.execute(:test)
execute_lane_test(format: 'plain', display_title: false)
end

def execute_lane_test_no_header_slack
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( format: 'slack', display_title: false ) end").runner.execute(:test)
execute_lane_test(format: 'slack', display_title: false)
end

def execute_lane_test_no_links
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( display_links: false ) end").runner.execute(:test)
execute_lane_test(display_links: false)
end

def execute_lane_test_no_links_slack
Fastlane::FastFile.new.parse("lane :test do conventional_changelog( format: 'slack', display_links: false ) end").runner.execute(:test)
execute_lane_test(format: 'slack', display_links: false)
end

describe 'section creation' do
Expand Down Expand Up @@ -226,6 +227,37 @@ def execute_lane_test_no_links_slack
end
end

describe "commit format" do
format_pattern = /^prefix-(foo|bar|baz)(?:\.(.*))?(): (.*)/
commits = [
"prefix-foo: sub|body|long_hash|short_hash|Jiri Otahal|time",
"prefix-bar: sub|body|long_hash|short_hash|Jiri Otahal|time",
"prefix-baz.android: sub|body|long_hash|short_hash|Jiri Otahal|time",
"prefix-qux: sub|body|long_hash|short_hash|Jiri Otahal|time"
]

before do
Fastlane::Actions.lane_context[Fastlane::Actions::SharedValues::CONVENTIONAL_CHANGELOG_ACTION_FORMAT_PATTERN] = format_pattern
allow(Fastlane::Actions::ConventionalChangelogAction).to receive(:get_commits_from_hash).and_return(commits)
allow(Date).to receive(:today).and_return(Date.new(2019, 5, 25))
end

it "should use the commit format" do
result = "# 1.0.2 (2019-05-25)\n\n### Bazz\n- **android:** sub ([short_hash](/long_hash))\n\n### Foo\n- sub ([short_hash](/long_hash))\n\n### Bar\n- sub ([short_hash](/long_hash))\n\n### Other\n- prefix-qux: sub ([short_hash](/long_hash))"

changelog = execute_lane_test(
order: ['baz', 'foo', 'bar', 'no_type'],
sections: {
foo: "Foo",
bar: "Bar",
baz: "Bazz",
no_type: "Other"
}
)
expect(changelog).to eq(result)
end
end

after do
end
end
Expand Down

0 comments on commit bc5ee67

Please sign in to comment.