captive-release 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/captive_release/bump_safety_net.rb +2 -1
- data/lib/captive_release/exclusion_input.rb +17 -0
- data/lib/captive_release/gemfile_lock_refresh.rb +20 -9
- data/lib/captive_release/git_commands.rb +2 -3
- data/lib/captive_release/github_release.rb +1 -1
- data/lib/captive_release/locales/en.yml +8 -2
- data/lib/captive_release/locales/fr.yml +8 -2
- data/lib/captive_release/prerelease_guard.rb +24 -0
- data/lib/captive_release/release_command.rb +7 -4
- data/lib/captive_release/ruby_gems_version.rb +31 -0
- data/lib/captive_release/semver.rb +16 -0
- data/lib/captive_release/shell.rb +2 -0
- data/lib/captive_release/version.rb +1 -1
- data/lib/captive_release/version_bumper.rb +33 -8
- data/lib/captive_release/version_choice.rb +8 -6
- data/lib/captive_release/version_detector.rb +7 -6
- data/lib/captive_release/version_file_selection.rb +1 -8
- data/lib/captive_release/version_format.rb +5 -4
- data/lib/captive_release/version_severity.rb +3 -3
- data/lib/captive_release.rb +4 -0
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 766da20e3b1cd49bbc782ea4a7dbf483bc852b025daf791c70a69b6bedc02088
|
|
4
|
+
data.tar.gz: 4b01cdae087a0c6b8990843d076b76325e158578df44278e40f28b6b7364b660
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0f6d0e2c5c1e1fe133c7260b0ad9dba99c99d6224efe152250f9472fb95f19a3ad367d45222f0f27afec06a0d2e89101f4ae851b395e4adc89763fb4741b8ff9
|
|
7
|
+
data.tar.gz: cafef79eae71b7c328cefe468d83981723967bdc2a49f0bb2cf4294c59f217aad8204c9e42f60d109eebe296d4793fb99f0b6fed0a68810ee3fd8eaa040ee343
|
|
@@ -10,7 +10,8 @@ module CaptiveRelease
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def verifier!(suggestion, courante, prochaine)
|
|
13
|
-
|
|
13
|
+
# La gravité d'une version a déjà été assumée par sa première pré-release.
|
|
14
|
+
return if suggestion.nil? || Semver.prerelease?(courante)
|
|
14
15
|
|
|
15
16
|
choisie = VersionSeverity.classify(from: courante, to: prochaine)
|
|
16
17
|
return if BumpSeverity::RANK.fetch(choisie, -1) >= BumpSeverity::RANK.fetch(suggestion)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CaptiveRelease
|
|
4
|
+
# Ce que veut dire la saisie d'exclusion : des rangs séparés par des virgules, numérotés à
|
|
5
|
+
# partir de 1 comme la liste affichée, et vide pour tout garder.
|
|
6
|
+
#
|
|
7
|
+
# Cette unité change quand la syntaxe de la saisie change, VersionFileSelection quand la
|
|
8
|
+
# façon de présenter le choix change.
|
|
9
|
+
module ExclusionInput
|
|
10
|
+
def self.apply(found, saisie)
|
|
11
|
+
return found if saisie.strip.empty?
|
|
12
|
+
|
|
13
|
+
rangs = saisie.split(",").map { |numero| numero.strip.to_i - 1 }
|
|
14
|
+
found.reject.with_index { |_, rang| rangs.include?(rang) }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module CaptiveRelease
|
|
4
|
-
# Remet Gemfile.lock d'aplomb après un bump : un .gemspec
|
|
5
|
-
#
|
|
6
|
-
# le relance.
|
|
4
|
+
# Remet les Gemfile.lock d'aplomb après un bump : un .gemspec porte la version bumpée, donc
|
|
5
|
+
# le Gemfile.lock de son dossier devient périmé et --deployment le refuse en CI si personne
|
|
6
|
+
# ne le relance. Dans un monorepo, ce dossier n'est pas forcément la racine.
|
|
7
7
|
#
|
|
8
|
-
# Cette unité change quand la façon de détecter ou de relancer
|
|
8
|
+
# Cette unité change quand la façon de détecter ou de relancer les locks change,
|
|
9
9
|
# ReleaseCommand quand la suite des étapes change.
|
|
10
10
|
class GemfileLockRefresh
|
|
11
11
|
LOCKFILE = "Gemfile.lock"
|
|
@@ -14,17 +14,28 @@ module CaptiveRelease
|
|
|
14
14
|
@files = files
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
# Les Gemfile.lock à relancer, relatifs à la racine : un par dossier qui porte un .gemspec.
|
|
18
|
+
#
|
|
17
19
|
# rescue : une arborescence hostile ne doit jamais faire échouer la release, la détection
|
|
18
20
|
# n'est qu'une commodité. Une fois vraie, l'exécution du bundle lock, elle, échoue haut
|
|
19
21
|
# la main si elle rate.
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
+
def lockfiles
|
|
23
|
+
@files.glob("**", LOCKFILE).map { |lock| @files.relative(lock) }.select { |lock| a_relancer?(lock) }
|
|
22
24
|
rescue StandardError
|
|
23
|
-
|
|
25
|
+
[]
|
|
24
26
|
end
|
|
25
27
|
|
|
26
|
-
def call
|
|
27
|
-
Shell.run!
|
|
28
|
+
def call(locks = lockfiles)
|
|
29
|
+
locks.each { |lock| Shell.run! commande(lock) }
|
|
28
30
|
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def a_relancer?(lock)
|
|
35
|
+
@files.glob(File.dirname(lock), "*.gemspec").any? && !GitCommands.ignored?(lock)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Le Gemfile d'un lock, c'est son chemin sans .lock : captive-ruby/Gemfile.lock → captive-ruby/Gemfile.
|
|
39
|
+
def commande(lock) = "bundle lock --gemfile #{Shell.escape(lock.delete_suffix('.lock'))}"
|
|
29
40
|
end
|
|
30
41
|
end
|
|
@@ -4,8 +4,7 @@ module CaptiveRelease
|
|
|
4
4
|
# Les commandes git d'une release. La façon de les lancer vit dans Shell.
|
|
5
5
|
class GitCommands
|
|
6
6
|
def self.dirty?
|
|
7
|
-
|
|
8
|
-
!sortie.lines.map(&:strip).reject(&:empty?).empty?
|
|
7
|
+
!Shell.capture("git diff --name-only && git diff --cached --name-only").empty?
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def self.remote_url = Shell.capture("git remote get-url origin 2>/dev/null")
|
|
@@ -19,7 +18,7 @@ module CaptiveRelease
|
|
|
19
18
|
# Les sujets de commit depuis le tag donné jusqu'à HEAD - la matière première de la
|
|
20
19
|
# suggestion de bump, un message par ligne, propre de toute ligne vide.
|
|
21
20
|
def self.messages_since(tag)
|
|
22
|
-
Shell.
|
|
21
|
+
Shell.capture_lines("git log --pretty=%s #{Shell.escape(tag)}..HEAD")
|
|
23
22
|
end
|
|
24
23
|
|
|
25
24
|
def self.current_branch
|
|
@@ -27,7 +27,7 @@ module CaptiveRelease
|
|
|
27
27
|
tag = "v#{version}"
|
|
28
28
|
@api.post("releases",
|
|
29
29
|
{ "tag_name" => tag, "name" => tag, "body" => notes(tag),
|
|
30
|
-
"draft" => false, "prerelease" =>
|
|
30
|
+
"draft" => false, "prerelease" => Semver.prerelease?(version), },
|
|
31
31
|
attendu: "201")["html_url"]
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -5,7 +5,7 @@ en:
|
|
|
5
5
|
|
|
6
6
|
Usage:
|
|
7
7
|
captive-release init [--files path[:type],...]
|
|
8
|
-
captive-release new [patch|minor|major|x.y.z] [--yes]
|
|
8
|
+
captive-release new [patch|minor|major|promote|x.y.z] [--yes]
|
|
9
9
|
captive-release build [--profile staging|production]
|
|
10
10
|
captive-release version
|
|
11
11
|
|
|
@@ -82,7 +82,13 @@ en:
|
|
|
82
82
|
suggestion_patch: no notable commit detected
|
|
83
83
|
choose_release_type: 'Choose release type:'
|
|
84
84
|
custom: Custom
|
|
85
|
-
|
|
85
|
+
bump_patch: Patch
|
|
86
|
+
bump_minor: Minor
|
|
87
|
+
bump_major: Major
|
|
88
|
+
bump_promote: Promote
|
|
89
|
+
bump_from_prerelease: 'Cannot %{type} from a pre-release: promote it or enter a version.'
|
|
90
|
+
prerelease_on_app: 'Cannot release pre-release %{version}: %{path} carries an app version, which allows no suffix.'
|
|
91
|
+
enter_version: 'Enter version (x.y.z or x.y.z-alpha.1): '
|
|
86
92
|
invalid_bump_type: 'Invalid bump type: %{type}. Use patch|minor|major|x.y.z'
|
|
87
93
|
invalid_semver: 'Invalid semver: %{value}'
|
|
88
94
|
invalid_version: 'Invalid version: %{value}'
|
|
@@ -5,7 +5,7 @@ fr:
|
|
|
5
5
|
|
|
6
6
|
Utilisation :
|
|
7
7
|
captive-release init [--files path[:type],...]
|
|
8
|
-
captive-release new [patch|minor|major|x.y.z] [--yes]
|
|
8
|
+
captive-release new [patch|minor|major|promote|x.y.z] [--yes]
|
|
9
9
|
captive-release build [--profile staging|production]
|
|
10
10
|
captive-release version
|
|
11
11
|
|
|
@@ -82,7 +82,13 @@ fr:
|
|
|
82
82
|
suggestion_patch: aucun commit notable détecté
|
|
83
83
|
choose_release_type: 'Choisissez le type de release :'
|
|
84
84
|
custom: Personnalisée
|
|
85
|
-
|
|
85
|
+
bump_patch: Patch
|
|
86
|
+
bump_minor: Minor
|
|
87
|
+
bump_major: Major
|
|
88
|
+
bump_promote: Promouvoir
|
|
89
|
+
bump_from_prerelease: 'Impossible de faire un %{type} depuis une pré-release : promouvez-la ou saisissez une version.'
|
|
90
|
+
prerelease_on_app: "Pré-release %{version} impossible : %{path} porte une version d'app, qui n'admet pas de suffixe."
|
|
91
|
+
enter_version: 'Saisissez la version (x.y.z ou x.y.z-alpha.1) : '
|
|
86
92
|
invalid_bump_type: 'Type de bump invalide : %{type}. Utilisez patch|minor|major|x.y.z'
|
|
87
93
|
invalid_semver: 'Semver invalide : %{value}'
|
|
88
94
|
invalid_version: 'Version invalide : %{value}'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CaptiveRelease
|
|
4
|
+
# Refuse une pré-release dès qu'une app porte la version : la version marketing iOS
|
|
5
|
+
# (CFBundleShortVersionString, que nourrissent aussi app.json et app.config.js) n'admet
|
|
6
|
+
# pas de suffixe. Une alpha d'app passe par un build interne, pas par une version.
|
|
7
|
+
class PrereleaseGuard
|
|
8
|
+
APP_TYPES = %w[ios_plist android_gradle app_json app_config_js].freeze
|
|
9
|
+
|
|
10
|
+
def initialize(terminal:)
|
|
11
|
+
@terminal = terminal
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def verifier!(version, fichiers)
|
|
15
|
+
return unless Semver.prerelease?(version)
|
|
16
|
+
|
|
17
|
+
app = fichiers.find { |fichier| APP_TYPES.include?(fichier.type) }
|
|
18
|
+
return unless app
|
|
19
|
+
|
|
20
|
+
@terminal.say @terminal.error(Messages.t(:prerelease_on_app, version: version, path: app.path))
|
|
21
|
+
exit 1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -18,6 +18,7 @@ module CaptiveRelease
|
|
|
18
18
|
suggestion = ReleaseOverview.new(terminal: @terminal).call(courante)
|
|
19
19
|
|
|
20
20
|
prochaine = VersionChoice.new(terminal: @terminal).call(courante, bump_arg)
|
|
21
|
+
PrereleaseGuard.new(terminal: @terminal).verifier!(prochaine, @config.version_files)
|
|
21
22
|
ReleaseConfirmation.new(terminal: @terminal).verifier!(suggestion, courante, prochaine) if confirmation
|
|
22
23
|
|
|
23
24
|
VersionFilesWriting.new(terminal: @terminal).call(prochaine, @config.version_files)
|
|
@@ -30,13 +31,15 @@ module CaptiveRelease
|
|
|
30
31
|
|
|
31
32
|
def chemins_a_commiter
|
|
32
33
|
chemins = @config.version_files.map(&:path)
|
|
33
|
-
|
|
34
|
+
refresh = GemfileLockRefresh.new
|
|
35
|
+
locks = refresh.lockfiles
|
|
36
|
+
return chemins if locks.empty?
|
|
34
37
|
|
|
35
38
|
@terminal.say "\n#{@terminal.bold(Messages.t(:refreshing_lockfile))}"
|
|
36
|
-
refresh.call
|
|
37
|
-
@terminal.done
|
|
39
|
+
refresh.call(locks)
|
|
40
|
+
locks.each { |lock| @terminal.done lock }
|
|
38
41
|
|
|
39
|
-
chemins +
|
|
42
|
+
chemins + locks
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
def publication
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "forwardable"
|
|
4
|
+
|
|
5
|
+
module CaptiveRelease
|
|
6
|
+
# Traduit entre semver et RubyGems, qui refuse 2.0.0-alpha.1 et attend 2.0.0.alpha.1.
|
|
7
|
+
# Le reste de l'outil ne voit que du semver ; seul le fichier parle RubyGems.
|
|
8
|
+
class RubyGemsVersion
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
GEM_PRERELEASE = /\A(\d+\.\d+\.\d+)\.(.+)\z/
|
|
12
|
+
|
|
13
|
+
def initialize(format)
|
|
14
|
+
@format = format
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def_delegator :@format, :expected
|
|
18
|
+
|
|
19
|
+
def read(content)
|
|
20
|
+
@format.read(content)&.sub(GEM_PRERELEASE, '\1-\2')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def write(content, old_version, new_version)
|
|
24
|
+
@format.write(content, vers_gem(old_version), vers_gem(new_version))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def vers_gem(version) = version.sub("-", ".")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CaptiveRelease
|
|
4
|
+
# Ce qu'est une version pour l'outil : x.y.z, éventuellement suivi d'une pré-release
|
|
5
|
+
# (-alpha, -rc.2). Les métadonnées de build (+sha) ne servent à rien ici et sont refusées.
|
|
6
|
+
module Semver
|
|
7
|
+
IDENT = /[0-9A-Za-z-]+/
|
|
8
|
+
PATTERN = /\A(\d+\.\d+\.\d+)(?:-#{IDENT}(?:\.#{IDENT})*)?\z/
|
|
9
|
+
|
|
10
|
+
def self.valid?(version) = version.to_s.match?(PATTERN)
|
|
11
|
+
|
|
12
|
+
def self.prerelease?(version) = version.to_s.include?("-")
|
|
13
|
+
|
|
14
|
+
def self.core(version) = version.to_s[PATTERN, 1]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -13,6 +13,8 @@ module CaptiveRelease
|
|
|
13
13
|
|
|
14
14
|
def self.capture(commande) = `#{commande}`.strip
|
|
15
15
|
|
|
16
|
+
def self.capture_lines(commande) = capture(commande).lines.map(&:strip).reject(&:empty?)
|
|
17
|
+
|
|
16
18
|
# Rubocop veut Shellwords, mais son échappement diffère du nôtre sur des chemins que git
|
|
17
19
|
# accepte : la liste blanche dit exactement ce qui passe sans protection.
|
|
18
20
|
def self.escape(chaine) = chaine.gsub(%r{[^a-zA-Z0-9._\-/]}) { |caractere| "\\#{caractere}" }
|
|
@@ -2,28 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
module CaptiveRelease
|
|
4
4
|
class VersionBumper
|
|
5
|
-
|
|
5
|
+
BUMP_TYPES = %w[patch minor major].freeze
|
|
6
|
+
PROMOTE = "promote"
|
|
6
7
|
|
|
7
8
|
def self.bump(current, type)
|
|
8
9
|
new(current).bump(type)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def initialize(current)
|
|
12
|
-
raise ArgumentError, Messages.t(:invalid_semver, value: current) unless
|
|
13
|
+
raise ArgumentError, Messages.t(:invalid_semver, value: current) unless Semver.valid?(current)
|
|
13
14
|
|
|
14
|
-
@
|
|
15
|
+
@current = current
|
|
16
|
+
@major, @minor, @patch = Semver.core(current).split(".").map(&:to_i)
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def bump(type)
|
|
18
|
-
|
|
20
|
+
type = type.to_s
|
|
21
|
+
verifier_depuis_prerelease!(type)
|
|
22
|
+
|
|
23
|
+
case type
|
|
19
24
|
when "major" then "#{@major + 1}.0.0"
|
|
20
25
|
when "minor" then "#{@major}.#{@minor + 1}.0"
|
|
21
26
|
when "patch" then "#{@major}.#{@minor}.#{@patch + 1}"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
type.to_s
|
|
27
|
+
when PROMOTE then promouvoir
|
|
28
|
+
else saisie(type)
|
|
26
29
|
end
|
|
27
30
|
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Depuis une pré-release, seule la promotion a un sens : un patch de 2.0.0-alpha
|
|
35
|
+
# donnerait 2.0.0 en semver, ce que personne ne lit comme un patch.
|
|
36
|
+
def verifier_depuis_prerelease!(type)
|
|
37
|
+
return unless Semver.prerelease?(@current) && BUMP_TYPES.include?(type)
|
|
38
|
+
|
|
39
|
+
raise ArgumentError, Messages.t(:bump_from_prerelease, type: type)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def promouvoir
|
|
43
|
+
raise ArgumentError, Messages.t(:invalid_version, value: PROMOTE) unless Semver.prerelease?(@current)
|
|
44
|
+
|
|
45
|
+
Semver.core(@current)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def saisie(type)
|
|
49
|
+
raise ArgumentError, Messages.t(:invalid_version, value: type) unless Semver.valid?(type)
|
|
50
|
+
|
|
51
|
+
type
|
|
52
|
+
end
|
|
28
53
|
end
|
|
29
54
|
end
|
|
@@ -7,8 +7,7 @@ module CaptiveRelease
|
|
|
7
7
|
# Cette unité change quand les façons de nommer une version changent, ReleaseCommand quand
|
|
8
8
|
# le geste de release change.
|
|
9
9
|
class VersionChoice
|
|
10
|
-
BUMP_TYPES =
|
|
11
|
-
SEMVER_RE = /\A\d+\.\d+\.\d+\z/
|
|
10
|
+
BUMP_TYPES = (VersionBumper::BUMP_TYPES + [ VersionBumper::PROMOTE ]).freeze
|
|
12
11
|
CUSTOM = "Custom"
|
|
13
12
|
|
|
14
13
|
def initialize(terminal:)
|
|
@@ -22,7 +21,7 @@ module CaptiveRelease
|
|
|
22
21
|
private
|
|
23
22
|
|
|
24
23
|
def resolve(current, type)
|
|
25
|
-
return VersionBumper.bump(current, type) if
|
|
24
|
+
return VersionBumper.bump(current, type) if Semver.valid?(type) || BUMP_TYPES.include?(type)
|
|
26
25
|
|
|
27
26
|
refuse(Messages.t(:invalid_bump_type, type: type))
|
|
28
27
|
end
|
|
@@ -33,17 +32,20 @@ module CaptiveRelease
|
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
# La valeur rendue est la version elle-même, sauf pour Custom qui n'en a pas encore une.
|
|
35
|
+
# Depuis une pré-release, seule la promotion est proposée : patch, minor et major y
|
|
36
|
+
# prêteraient à confusion.
|
|
36
37
|
def candidates_for(current)
|
|
37
|
-
|
|
38
|
+
types = Semver.prerelease?(current) ? [ VersionBumper::PROMOTE ] : VersionBumper::BUMP_TYPES
|
|
39
|
+
candidats = types.to_h do |type|
|
|
38
40
|
version = VersionBumper.bump(current, type)
|
|
39
|
-
[ "#{type
|
|
41
|
+
[ "#{Messages.t(:"bump_#{type}")} → #{@terminal.bold(version)}", version ]
|
|
40
42
|
end
|
|
41
43
|
candidats.merge("#{Messages.t(:custom)} → ?" => CUSTOM)
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def type_it
|
|
45
47
|
version = @terminal.ask(Messages.t(:enter_version))
|
|
46
|
-
return version if
|
|
48
|
+
return version if Semver.valid?(version)
|
|
47
49
|
|
|
48
50
|
refuse(Messages.t(:invalid_semver, value: version))
|
|
49
51
|
end
|
|
@@ -33,21 +33,22 @@ module CaptiveRelease
|
|
|
33
33
|
|
|
34
34
|
def by_content(segments, type, pattern)
|
|
35
35
|
@files.glob(*segments)
|
|
36
|
-
.select { |chemin|
|
|
36
|
+
.select { |chemin| contient?(chemin, pattern) }
|
|
37
37
|
.map { |chemin| version_file(chemin, type) }
|
|
38
|
-
rescue StandardError
|
|
39
|
-
[]
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
# Le build.gradle est à un chemin fixe : le chercher par glob remonterait ceux des
|
|
43
41
|
# modules Android embarqués, qui ne portent pas la version de l'app.
|
|
44
42
|
def android_gradle
|
|
45
|
-
|
|
46
|
-
return [] unless File.exist?(chemin) && File.read(chemin).match?(/versionName\s+['"]/)
|
|
43
|
+
return [] unless contient?(@files.path(*GRADLE_PATH), /versionName\s+['"]/)
|
|
47
44
|
|
|
48
45
|
[ VersionFile.new(GRADLE_PATH.join("/"), "android_gradle") ]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def contient?(chemin, pattern)
|
|
49
|
+
File.exist?(chemin) && File.read(chemin).match?(pattern)
|
|
49
50
|
rescue StandardError
|
|
50
|
-
|
|
51
|
+
false
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
def version_file(chemin, type) = VersionFile.new(@files.relative(chemin), type)
|
|
@@ -13,7 +13,7 @@ module CaptiveRelease
|
|
|
13
13
|
|
|
14
14
|
def call(found)
|
|
15
15
|
list(found)
|
|
16
|
-
found.size == 1 ? seul(found) :
|
|
16
|
+
found.size == 1 ? seul(found) : ExclusionInput.apply(found, demander)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
private
|
|
@@ -37,13 +37,6 @@ module CaptiveRelease
|
|
|
37
37
|
found
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
def exclude(found, saisie)
|
|
41
|
-
return found if saisie.strip.empty?
|
|
42
|
-
|
|
43
|
-
rangs = saisie.split(",").map { |numero| numero.strip.to_i - 1 }
|
|
44
|
-
found.reject.with_index { |_, rang| rangs.include?(rang) }
|
|
45
|
-
end
|
|
46
|
-
|
|
47
40
|
def readable_version(fichier)
|
|
48
41
|
fichier.read_version
|
|
49
42
|
rescue StandardError
|
|
@@ -63,12 +63,13 @@ module CaptiveRelease
|
|
|
63
63
|
},
|
|
64
64
|
expected: %("version": "x.y.z")),
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
"ruby_version" => RubyGemsVersion.new(
|
|
67
|
+
by_pattern(/VERSION\s*=\s*["'](.+?)["']/, %(VERSION = "x.y.z")) { |occurrence, nouvelle|
|
|
68
|
+
# Le style de guillemets du fichier est conservé : réécrire en double quand le
|
|
69
|
+
# fichier écrit en simple produirait un diff plus large que le changement de version.
|
|
70
70
|
occurrence.include?('"') ? %(VERSION = "#{nouvelle}") : %(VERSION = '#{nouvelle}')
|
|
71
71
|
},
|
|
72
|
+
),
|
|
72
73
|
|
|
73
74
|
"app_config_js" => by_label(/version:\s*/, "version: "),
|
|
74
75
|
"android_gradle" => by_label(/versionName\s+/, "versionName "),
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
module CaptiveRelease
|
|
4
4
|
# Classe la taille réelle d'un bump en comparant les composants major.minor.patch entre
|
|
5
5
|
# deux versions - y compris un semver tapé à la main, qui ne porte plus de "type" une fois
|
|
6
|
-
# sorti de VersionChoice.
|
|
6
|
+
# sorti de VersionChoice. Le suffixe de pré-release ne compte pas : 2.0.0-alpha est un major.
|
|
7
7
|
class VersionSeverity
|
|
8
8
|
def self.classify(from:, to:)
|
|
9
|
-
depart = from.split(".").map(&:to_i)
|
|
10
|
-
arrivee = to.split(".").map(&:to_i)
|
|
9
|
+
depart = Semver.core(from).split(".").map(&:to_i)
|
|
10
|
+
arrivee = Semver.core(to).split(".").map(&:to_i)
|
|
11
11
|
|
|
12
12
|
return "major" if depart[0] != arrivee[0]
|
|
13
13
|
return "minor" if depart[1] != arrivee[1]
|
data/lib/captive_release.rb
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "captive_release/version"
|
|
4
4
|
require_relative "captive_release/messages"
|
|
5
|
+
require_relative "captive_release/semver"
|
|
5
6
|
require_relative "captive_release/version_bumper"
|
|
7
|
+
require_relative "captive_release/ruby_gems_version"
|
|
6
8
|
require_relative "captive_release/version_format"
|
|
7
9
|
require_relative "captive_release/version_file"
|
|
8
10
|
require_relative "captive_release/build_config"
|
|
@@ -18,6 +20,7 @@ require_relative "captive_release/gitmoji_severity"
|
|
|
18
20
|
require_relative "captive_release/bump_suggestion"
|
|
19
21
|
require_relative "captive_release/version_severity"
|
|
20
22
|
require_relative "captive_release/bump_safety_net"
|
|
23
|
+
require_relative "captive_release/prerelease_guard"
|
|
21
24
|
require_relative "captive_release/github_repo"
|
|
22
25
|
require_relative "captive_release/github_http"
|
|
23
26
|
require_relative "captive_release/github_api"
|
|
@@ -38,6 +41,7 @@ require_relative "captive_release/build_command"
|
|
|
38
41
|
require_relative "captive_release/menu"
|
|
39
42
|
require_relative "captive_release/version_choice"
|
|
40
43
|
require_relative "captive_release/gemfile_lock_refresh"
|
|
44
|
+
require_relative "captive_release/exclusion_input"
|
|
41
45
|
require_relative "captive_release/git_release"
|
|
42
46
|
require_relative "captive_release/changes_since"
|
|
43
47
|
require_relative "captive_release/release_publication"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: captive-release
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Captive Studio
|
|
@@ -33,6 +33,7 @@ files:
|
|
|
33
33
|
- lib/captive_release/config_file.rb
|
|
34
34
|
- lib/captive_release/config_loader.rb
|
|
35
35
|
- lib/captive_release/config_writer.rb
|
|
36
|
+
- lib/captive_release/exclusion_input.rb
|
|
36
37
|
- lib/captive_release/framework_detector.rb
|
|
37
38
|
- lib/captive_release/gemfile_lock_refresh.rb
|
|
38
39
|
- lib/captive_release/git_commands.rb
|
|
@@ -53,12 +54,15 @@ files:
|
|
|
53
54
|
- lib/captive_release/menu.rb
|
|
54
55
|
- lib/captive_release/messages.rb
|
|
55
56
|
- lib/captive_release/options.rb
|
|
57
|
+
- lib/captive_release/prerelease_guard.rb
|
|
56
58
|
- lib/captive_release/release_command.rb
|
|
57
59
|
- lib/captive_release/release_confirmation.rb
|
|
58
60
|
- lib/captive_release/release_overview.rb
|
|
59
61
|
- lib/captive_release/release_preconditions.rb
|
|
60
62
|
- lib/captive_release/release_publication.rb
|
|
61
63
|
- lib/captive_release/repo_files.rb
|
|
64
|
+
- lib/captive_release/ruby_gems_version.rb
|
|
65
|
+
- lib/captive_release/semver.rb
|
|
62
66
|
- lib/captive_release/shell.rb
|
|
63
67
|
- lib/captive_release/terminal.rb
|
|
64
68
|
- lib/captive_release/version.rb
|