captive-release 0.11.0 → 0.12.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a8fd7809824a87b08805de31f9ddc40af157b6ba41e0b76e19f90edd4c9ade2
|
|
4
|
+
data.tar.gz: 33dff63edd19f1889f5fa014271eff8640b6cba8effc7937ab9332fe2bf14316
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9cfbc9751d8b2607e05512a7120f3773d3553526786e57d47a45d557e97bda793e26f09be493f015c3caaf982329f5363576a61e14399ecef1fa4157d913b352
|
|
7
|
+
data.tar.gz: 6a114be8ba3248b560619b8e345e1ec8e9a9d9b009b73d7723be59ba743bae25ba519f1f9baf533e772e16608741d0a77fdc1ab42007a359a6a38b49b266ffee
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CaptiveRelease
|
|
4
|
+
# Complète les notes générées par GitHub, qui ne listent que les PR mergées : un commit
|
|
5
|
+
# poussé directement sur la branche n'y apparaît jamais, même quand il porte la feature
|
|
6
|
+
# qui justifie le bump.
|
|
7
|
+
class DirectCommits
|
|
8
|
+
COMMIT_VERSION = /\A🔖 Set version /
|
|
9
|
+
|
|
10
|
+
def initialize(api)
|
|
11
|
+
@api = api
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Sans plage, il n'y a pas de tag précédent : lister les commits reviendrait à lister
|
|
15
|
+
# l'historique entier.
|
|
16
|
+
def completer(notes)
|
|
17
|
+
plage = notes.plage or return notes
|
|
18
|
+
lignes = commits(*plage).map { ligne(_1) }
|
|
19
|
+
lignes.empty? ? notes : notes.ajouter("## Commits directs\n#{lignes.join("\n")}\n")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def commits(depuis, jusqu_a)
|
|
25
|
+
@api.get("compare/#{depuis}...#{jusqu_a}")["commits"].reject do |commit|
|
|
26
|
+
titre(commit).match?(COMMIT_VERSION) || !@api.get("commits/#{commit["sha"]}/pulls").empty?
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def ligne(commit)
|
|
31
|
+
auteur = commit.dig("author", "login")
|
|
32
|
+
"* #{titre(commit)}#{" by @#{auteur}" if auteur} in #{commit["sha"]}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def titre(commit) = commit.dig("commit", "message")[/.*/]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -23,15 +23,22 @@ module CaptiveRelease
|
|
|
23
23
|
@http = http || GithubHttp.new(token: token)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
def get(chemin) = analyser(@http.get(adresse(chemin)), "200")
|
|
27
|
+
|
|
26
28
|
def post(chemin, corps, attendu:)
|
|
27
|
-
|
|
29
|
+
analyser(@http.post(adresse(chemin), JSON.generate(corps)), attendu)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def adresse(chemin) = URI("#{HOTE}/#{depot.path(chemin)}")
|
|
35
|
+
|
|
36
|
+
def analyser(reponse, attendu)
|
|
28
37
|
refuser(reponse) unless reponse.code == attendu
|
|
29
38
|
|
|
30
39
|
reponse.body.to_s.empty? ? nil : JSON.parse(reponse.body)
|
|
31
40
|
end
|
|
32
41
|
|
|
33
|
-
private
|
|
34
|
-
|
|
35
42
|
def refuser(reponse)
|
|
36
43
|
raise Messages.t(:github_api_error, code: reponse.code, message: GithubErrorMessage.from(reponse.body.to_s))
|
|
37
44
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "github_api"
|
|
4
|
+
require_relative "direct_commits"
|
|
5
|
+
require_relative "release_notes"
|
|
4
6
|
|
|
5
7
|
module CaptiveRelease
|
|
6
8
|
# Crée la release GitHub d'une version. Elle compose ce qu'elle demande ; l'API, son
|
|
@@ -9,7 +11,6 @@ module CaptiveRelease
|
|
|
9
11
|
# GitHub refuse (422) un corps de release plus long. Sans tag précédent, les notes
|
|
10
12
|
# générées couvrent tout l'historique et dépassent vite cette limite.
|
|
11
13
|
CORPS_MAX = 125_000
|
|
12
|
-
COUPURE = "\n\n…"
|
|
13
14
|
|
|
14
15
|
def self.create(version:, remote_url:, token:, api: nil)
|
|
15
16
|
api ||= GithubApi.new(remote_url: remote_url, token: token)
|
|
@@ -35,21 +36,7 @@ module CaptiveRelease
|
|
|
35
36
|
|
|
36
37
|
def notes(tag)
|
|
37
38
|
corps = @api.post("releases/generate-notes", { "tag_name" => tag }, attendu: "200")["body"].to_s
|
|
38
|
-
corps.
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Coupe à une fin de ligne et garde le lien Full Changelog final, qui mène à la liste complète.
|
|
42
|
-
def tronquer(corps)
|
|
43
|
-
tete, pied = separer_pied(corps)
|
|
44
|
-
place = CORPS_MAX - COUPURE.length - pied.length
|
|
45
|
-
coupe = tete[0, place]
|
|
46
|
-
coupe = coupe[0, coupe.rindex("\n")] if coupe.include?("\n")
|
|
47
|
-
"#{coupe}#{COUPURE}#{pied}"
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def separer_pied(corps)
|
|
51
|
-
index = corps.rindex("\n**Full Changelog**")
|
|
52
|
-
index ? [ corps[0, index], "\n#{corps[index..]}" ] : [ corps, "" ]
|
|
39
|
+
DirectCommits.new(@api).completer(ReleaseNotes.new(corps)).tronquer(CORPS_MAX).to_s
|
|
53
40
|
end
|
|
54
41
|
end
|
|
55
42
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CaptiveRelease
|
|
4
|
+
# Le texte des notes d'une release, découpé autour de son pied : le lien Full Changelog,
|
|
5
|
+
# qui mène à la liste complète et doit survivre à tout ajout ou toute coupe.
|
|
6
|
+
class ReleaseNotes
|
|
7
|
+
PIED = /(?:\n|\A)\*\*Full Changelog\*\*/
|
|
8
|
+
COMPARAISON = %r{/compare/(?<depuis>\S+?)\.\.\.(?<jusqu_a>\S+)}
|
|
9
|
+
COUPURE = "\n\n…"
|
|
10
|
+
|
|
11
|
+
def initialize(corps)
|
|
12
|
+
index = corps.rindex(PIED)
|
|
13
|
+
@tete, @pied = index ? [ corps[0, index], corps[index..] ] : [ corps, "" ]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Les tags qui bornent les notes ; nil sans tag précédent.
|
|
17
|
+
def plage = @pied.match(COMPARAISON)&.captures
|
|
18
|
+
|
|
19
|
+
def ajouter(section) = ReleaseNotes.new("#{@tete.rstrip}\n\n#{section}#{@pied}")
|
|
20
|
+
|
|
21
|
+
# Coupe à une fin de ligne, pour ne pas laisser un lien ou un émoji à moitié.
|
|
22
|
+
def tronquer(max)
|
|
23
|
+
return self if to_s.length <= max
|
|
24
|
+
|
|
25
|
+
coupe = @tete[0, max - COUPURE.length - @pied.length - 1]
|
|
26
|
+
coupe = coupe[0, coupe.rindex("\n")] if coupe.include?("\n")
|
|
27
|
+
ReleaseNotes.new("#{coupe}#{COUPURE}\n#{@pied}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s = "#{@tete}#{@pied}"
|
|
31
|
+
end
|
|
32
|
+
end
|
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.12.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/direct_commits.rb
|
|
36
37
|
- lib/captive_release/exclusion_input.rb
|
|
37
38
|
- lib/captive_release/framework_detector.rb
|
|
38
39
|
- lib/captive_release/gemfile_lock_refresh.rb
|
|
@@ -58,6 +59,7 @@ files:
|
|
|
58
59
|
- lib/captive_release/prerelease_iteration.rb
|
|
59
60
|
- lib/captive_release/release_command.rb
|
|
60
61
|
- lib/captive_release/release_confirmation.rb
|
|
62
|
+
- lib/captive_release/release_notes.rb
|
|
61
63
|
- lib/captive_release/release_overview.rb
|
|
62
64
|
- lib/captive_release/release_preconditions.rb
|
|
63
65
|
- lib/captive_release/release_publication.rb
|