captive-release 0.8.0 → 0.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '028b75d95da7f0c5ae533774c1fc1bc353234bd569a58f9c83798e0519a592c2'
4
- data.tar.gz: bb5a5ffbbaf260dad04cd28afb303c476ae5dff295454bbf1b95708bfba58126
3
+ metadata.gz: a9e947f971c93535758990c20c7684e5178c345bfee6abddef43ee6584b1378a
4
+ data.tar.gz: bc5c688c4d49ad3326104a42e4209e9b99f22cd3dd3511cf5761c8843465053c
5
5
  SHA512:
6
- metadata.gz: ee228007f5b5cb48c7d2fb2402a019c287b4d2a8dc1e37df0e6a0f3c159af97ce4aa3e5e95e57d6b1b947538414c081ea78a998a056a8db80770d263ea3371d9
7
- data.tar.gz: 1a0ae25c85c204a1ac5431a4d1e704b67715b77c281763b103ff90da04a1a8550b628f4f1e3a785d743a1ec78b9c2d02b328ef1bee37ec5955085ad12b59666d
6
+ metadata.gz: c289101fc72ca8463baad9fd904c060c6a67890d2b0ece8c61e44ddca8df0d2ff387487b67facfcf1c16e69d90ac61516b83728ef1025ad8d8894bea76fbd680
7
+ data.tar.gz: 00bf4e5aad63a7ce24786c6a4c39aa1481244ec8bdf5725595084e49c783f98f66d5222a2f39b7adc149d553c931471dd23457fb49b6cf278df64bbf7f3cbc94
@@ -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 à la racine porte la version
5
- # bumpée, donc Gemfile.lock devient périmé et --deployment le refuse en CI si personne ne
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 le lock change,
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 needed?
21
- File.exist?(@files.path(LOCKFILE)) && @files.glob("*.gemspec").any? && !GitCommands.ignored?(LOCKFILE)
22
+ def lockfiles
23
+ @files.glob("**", LOCKFILE).map { |lock| @files.relative(lock) }.select { |lock| a_relancer?(lock) }
22
24
  rescue StandardError
23
- false
25
+ []
24
26
  end
25
27
 
26
- def call
27
- Shell.run! "bundle lock"
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
- sortie = Shell.capture("git diff --name-only && git diff --cached --name-only")
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.capture("git log --pretty=%s #{Shell.escape(tag)}..HEAD").lines.map(&:strip).reject(&:empty?)
21
+ Shell.capture_lines("git log --pretty=%s #{Shell.escape(tag)}..HEAD")
23
22
  end
24
23
 
25
24
  def self.current_branch
@@ -30,13 +30,15 @@ module CaptiveRelease
30
30
 
31
31
  def chemins_a_commiter
32
32
  chemins = @config.version_files.map(&:path)
33
- return chemins unless (refresh = GemfileLockRefresh.new).needed?
33
+ refresh = GemfileLockRefresh.new
34
+ locks = refresh.lockfiles
35
+ return chemins if locks.empty?
34
36
 
35
37
  @terminal.say "\n#{@terminal.bold(Messages.t(:refreshing_lockfile))}"
36
- refresh.call
37
- @terminal.done GemfileLockRefresh::LOCKFILE
38
+ refresh.call(locks)
39
+ locks.each { |lock| @terminal.done lock }
38
40
 
39
- chemins + [ GemfileLockRefresh::LOCKFILE ]
41
+ chemins + locks
40
42
  end
41
43
 
42
44
  def publication
@@ -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}" }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CaptiveRelease
4
- VERSION = "0.8.0"
4
+ VERSION = "0.8.1"
5
5
  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| File.read(chemin).match?(pattern) }
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
- chemin = @files.path(*GRADLE_PATH)
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) : exclude(found, demander)
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
@@ -38,6 +38,7 @@ require_relative "captive_release/build_command"
38
38
  require_relative "captive_release/menu"
39
39
  require_relative "captive_release/version_choice"
40
40
  require_relative "captive_release/gemfile_lock_refresh"
41
+ require_relative "captive_release/exclusion_input"
41
42
  require_relative "captive_release/git_release"
42
43
  require_relative "captive_release/changes_since"
43
44
  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.8.0
4
+ version: 0.8.1
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