revision 1.2.7 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 682306be7408f18b9346de0b36dc9b98b1fc104209191bbb6cba601b9cba0509
4
- data.tar.gz: 0c48f5c2952dc1a2abe7c68010d708b48a93ad3da4fc63d9d031f05846f610d0
3
+ metadata.gz: 4668b7330bbac8c0ff2be80e329372715b4e9a1c855324208dad6d0975c3fc53
4
+ data.tar.gz: 27b0b200fd4e66fc6af0a579d4443d345f08e4205f1e89aafecebf7597d85365
5
5
  SHA512:
6
- metadata.gz: 55a4cefdae2b4014f90fad6c36865ad69745baa6e0b2944a41f37fc68632dc38d1487dd420210425cab22e555f01d1352d92db491dbc441206e3d2d06c4a8a8b
7
- data.tar.gz: '0369665bfdd54f97bdb1f7cf92c5f530199cd5beb80fb0b1cd7440060767786014285549f9a6bc7207ecee17ab8bdd848a11dd83fa38f1885aa88c42710189f1'
6
+ metadata.gz: 533d69c1f6746f5aeedbbe72420937ed6976eb6dad4dd2ca8a75a7b13df8fa749b65284b137764997f62157a395f42d3ab11f23295b6b5035e14a57b4f524988
7
+ data.tar.gz: cc6badb780cfff6bae1df61c5697df6c2c37db2221178fe9446c132aabbbe5d0b5a3ced994ca416b292dadef7276b99ef238b46ac502ea7b505955fcd951b05a
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  Gemfile.lock
13
13
 
14
14
  README.html
15
+ *.zip
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- #git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ # git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in revision.gemspec
6
6
  gemspec
data/README.org CHANGED
@@ -1,6 +1,5 @@
1
1
  #+TITLE: Revision management gem
2
2
  #+AUTHOR: Cormac Cannon
3
- #+EMAIL: cormac.cannon@neuromoddevices.com
4
3
  #+LANGUAGE: en
5
4
 
6
5
  # Generic properties
@@ -24,245 +23,254 @@
24
23
  # or alternatively #+SETUPFILE: theme-readtheorg.setup
25
24
 
26
25
  * Overview
26
+ This gem automates revision management for source projects. The tool is language agnostic (used for C, ruby and matlab projects, to date -- though you're probably better off using bundler for ruby projects). It supports per-project configuration using a yaml-format file called =releasables.yaml= located at the project root.
27
27
 
28
- This gem automates revision management for source projects. The tool is language agnostic (used for C, ruby and matlab projects, to date -- though you're
29
- probably better off using bundler for ruby projects). It supports per-project configuration using a yaml-format file called =releasables.yaml= located at
30
- the project root.
28
+ It currently supports the following functionality
29
+ - Manage 3-component revision IDs embedded natively in source file
30
+ - Embeds/updates/extracts changelog in source file header/footer comments
31
+ - Automatically prompts for a changelog entry each time a revision identifier is incremented
32
+ - Optionally commits and tags changes to a git repo after an update to the revision ID
33
+ - Builds and archives projects in zip format (including release notes and arbitrary release artefacts defined
34
+ - Deploys
31
35
 
32
- It currently supports the following functionality
33
- - Manage 3-component revision IDs embedded natively in source file
34
- - Embeds/updates/extracts changelog in source file header/footer comments
35
- - Automatically prompts for a changelog entry each time a revision identifier is incremented
36
- - Optionally commits and tags changes to a git repo after an update to the revision ID
37
- - Builds and archives projects in zip format (including release notes and arbitrary release artefacts defined
38
- - Deploys
36
+ Worked on sporadically to allow me to tag, archive and deploy projects in multiple languages in a consistent fashion.
39
37
 
40
38
  * Installation
41
39
  ** Dependencies
42
- Ruby / Rubygems installed
40
+ Ruby / Rubygems installed
43
41
 
44
42
  ** From rubygems.org
45
43
 
46
- #+BEGIN_SRC sh
47
- gem install revision
48
- #+END_SRC
44
+ #+BEGIN_SRC sh
45
+ gem install revision
46
+ #+END_SRC
49
47
 
50
48
  ** From source
51
49
 
50
+ #+BEGIN_SRC sh
51
+ git clone git@github.com:cormacc/revision
52
+ #+END_SRC
53
+
54
+
52
55
  *** Checkout
53
56
 
54
- #+BEGIN_SRC sh
55
- gem install bundler
56
- git clone git@git.nmd.ie:gem/revision
57
- cd revision
58
- #+END_SRC
57
+ #+BEGIN_SRC sh
58
+ gem install bundler
59
+ git clone git@github.com:cormacc/revision
60
+ cd revision
61
+ #+END_SRC
59
62
 
60
63
  *** Install
61
64
 
62
- #+BEGIN_SRC sh
63
- bundle install
64
- bundle exec rake install
65
- #+END_SRC
66
-
67
- #+RESULTS:
68
- #+begin_example
69
- Using rake 10.5.0
70
- Using bundler 1.16.0
71
- Using coderay 1.1.2
72
- Using diff-lcs 1.3
73
- Using git 1.3.0
74
- Using method_source 0.9.0
75
- Using pry 0.11.3
76
- Using rubyzip 1.2.1
77
- Using thor 0.19.4
78
- Using revision 1.0.0 from source at `.`
79
- Using rspec-support 3.7.0
80
- Using rspec-core 3.7.0
81
- Using rspec-expectations 3.7.0
82
- Using rspec-mocks 3.7.0
83
- Using rspec 3.7.0
84
- Bundle complete! 5 Gemfile dependencies, 15 gems now installed.
85
- Use `bundle info [gemname]` to see where a bundled gem is installed.
86
- revision 1.0.0 built to pkg/revision-1.0.0.gem.
87
- revision (1.0.0) installed.
88
- #+end_example
65
+ #+BEGIN_SRC sh
66
+ bundle install
67
+ bundle exec rake install
68
+ #+END_SRC
69
+
70
+ #+RESULTS:
71
+ #+begin_example
72
+ Using rake 10.5.0
73
+ Using bundler 1.16.0
74
+ Using coderay 1.1.2
75
+ Using diff-lcs 1.3
76
+ Using git 1.3.0
77
+ Using method_source 0.9.0
78
+ Using pry 0.11.3
79
+ Using rubyzip 1.2.1
80
+ Using thor 0.19.4
81
+ Using revision 1.0.0 from source at `.`
82
+ Using rspec-support 3.7.0
83
+ Using rspec-core 3.7.0
84
+ Using rspec-expectations 3.7.0
85
+ Using rspec-mocks 3.7.0
86
+ Using rspec 3.7.0
87
+ Bundle complete! 5 Gemfile dependencies, 15 gems now installed.
88
+ Use `bundle info [gemname]` to see where a bundled gem is installed.
89
+ revision 1.0.0 built to pkg/revision-1.0.0.gem.
90
+ revision (1.0.0) installed.
91
+ #+end_example
89
92
 
90
93
  * Usage
91
94
 
92
95
  ** Supported Commands
93
- Run the executable with no arguments to get usage instructions in your console window...
94
-
95
- #+BEGIN_SRC sh
96
- revision
97
- #+END_SRC
98
-
99
- #+RESULTS:
100
- #+begin_example
101
- Loading releasable definitions from /home/cormacc/nextcloud/nmd/gem/revision/releasables.yaml ...
102
- Commands:
103
- revision archive # Archive releasables
104
- revision changelog # Display change log on stdout
105
- revision help [COMMAND] # Describe available commands or one specific command
106
- revision info # Display info for all defined releasables
107
- revision major # Increment major revision index
108
- revision minor # Increment minor revision index
109
- revision patch # Increment patch revision index
110
- revision tag # Commit the current revision to a local git repo ...
111
-
112
- Options:
113
- [--dryrun], [--no-dryrun]
114
- [--id=ID]
115
-
116
- #+end_example
117
-
118
- #+BEGIN_NOTE
119
- The tool can be run from any subfolder of a project root -- it will traverse the tree until it finds
120
- an ancestor containing =releasables.yaml= OR can go no further (in which case it throws an error).
121
- #+END_NOTE
96
+ Run the executable with no arguments to get usage instructions in your console window...
97
+
98
+ #+BEGIN_SRC sh
99
+ revision
100
+ #+END_SRC
101
+
102
+ #+RESULTS:
103
+ #+begin_example
104
+ Loading releasable definitions from /home/cormacc/dev/gem/revision/releasables.yaml ...
105
+ Commands:
106
+ revision --version, -v # print the version
107
+ revision archive # Archive releasable(s)
108
+ revision build # Build releasable(s)
109
+ revision changelog # Display change log on stdout
110
+ revision deploy # Deploy releasable(s)
111
+ revision help [COMMAND] # Describe available commands or one specific command
112
+ revision info # Display info for all defined releasables
113
+ revision major # Increment major revision index
114
+ revision minor # Increment minor revision index
115
+ revision package # Build and archive releasables
116
+ revision patch # Increment patch revision index
117
+ revision tag # Commit the current revision to a local git repo ...
118
+
119
+ Options:
120
+ [--dryrun], [--no-dryrun]
121
+ [--id=ID]
122
+
123
+ #+end_example
124
+
125
+ #+BEGIN_NOTE
126
+ The tool can be run from any subfolder of a project root -- it will traverse the tree until it finds
127
+ an ancestor containing =releasables.yaml= OR can go no further (in which case it throws an error).
128
+ #+END_NOTE
122
129
 
123
130
  *** Operating on multiple releasables
124
131
 
125
- A single =releasables.yaml= file can define multiple releasables, either implicitly (via inclusion) or explicitly
126
- (see [[Configuration]] section below for examples). In this context, the ~info~ and ~archive~ commands
127
- will operate on all defined releasables, whereas the remaining commands will require the releasable
128
- to be specified using the ~--id=~ option, e.g.
132
+ A single =releasables.yaml= file can define multiple releasables, either implicitly (via inclusion) or explicitly
133
+ (see [[Configuration]] section below for examples). In this context, the ~info~ and ~archive~ commands
134
+ will operate on all defined releasables, whereas the remaining commands will require the releasable
135
+ to be specified using the ~--id=~ option, e.g.
129
136
 
130
- #+BEGIN_SRC sh
131
- revision minor --id=firmware
132
- #+END_SRC
137
+ #+BEGIN_SRC sh
138
+ revision minor --id=firmware
139
+ #+END_SRC
133
140
 
134
141
  ** Configuration
135
142
 
136
- YAML syntax is used for the configuration file. The [[Syntax]] and [[Examples]] sections below should provide sufficient
137
- introduction to the limit subset of language features required to use this tool, however further info
138
- may be found at the following links:
143
+ YAML syntax is used for the configuration file. The [[Syntax]] and [[Examples]] sections below should provide sufficient
144
+ introduction to the limit subset of language features required to use this tool, however further info
145
+ may be found at the following links:
139
146
 
140
- - http://docs.ansible.com/ansible/latest/YAMLSyntax.html
141
- - http://www.yaml.org/start.html
147
+ - http://docs.ansible.com/ansible/latest/YAMLSyntax.html
148
+ - http://www.yaml.org/start.html
142
149
 
143
150
  *** Syntax
144
151
 
145
- The =releasables.yaml= file should contain a top level ~:releasables~ node.
146
- Under this, you can create a list (or YAML /sequence/) of releasable definitions.
152
+ The =releasables.yaml= file should contain a top level ~:releasables~ node.
153
+ Under this, you can create a list (or YAML /sequence/) of releasable definitions.
147
154
 
148
- Each sequence item begins with a ~-~ and contains either a link to a folder containing its own =releasables.yaml=
149
- defining one or more releasables ...
155
+ Each sequence item begins with a ~-~ and contains either a link to a folder containing its own =releasables.yaml=
156
+ defining one or more releasables ...
150
157
 
151
- #+BEGIN_SRC yaml
152
- - :folder: relative/path/to/a/releasable/folder
153
- #+END_SRC
158
+ #+BEGIN_SRC yaml
159
+ - :folder: relative/path/to/a/releasable/folder
160
+ #+END_SRC
154
161
 
155
- ... or a single inline releasable definition.
162
+ ... or a single inline releasable definition.
156
163
 
157
- #+BEGIN_NOTE
158
- The lines beginning with '#' are explanatory comments
159
- #+END_NOTE
164
+ #+BEGIN_NOTE
165
+ The lines beginning with '#' are explanatory comments
166
+ #+END_NOTE
160
167
 
161
- #+BEGIN_SRC yaml
162
- - :id: my_releasable
163
- :revision:
164
- # Source file containing the revision identifier
165
- # This will also include changelog entries, embedded as comments
166
- :src: lib/revision/version.rb
167
- # Regex matching the source revision identifier. Must contain the following named capture groups
168
- # - major, minor, patch :: Numeric (uint) sequences representing the three revision ID components
169
- # - sep1, sep2 :: the characters separating the revision components
170
- # - prefix, postfix :: sufficient syntactic context to match the revision ID uniquely
171
- # N.B. this regex matches the version ID from the standard bundler gem skeleton,
172
- # e.g. VERSION = "1.1.0"
173
- :regex: (?<prefix>VERSION = ")(?<major>\d+)(?<sep1>\.)(?<minor>\d+)(?<sep2>\.)(?<patch>\d+)(?<postfix>")
174
- # Comment char for the project language -- prefixed to each line of changelog entries
175
- # Quotes only necessary here to prevent # being interpreted as the beginning of a YAML comment
176
- :comment_prefix: "#"
168
+ #+BEGIN_SRC yaml
169
+ - :id: my_releasable
170
+ :revision:
171
+ # Source file containing the revision identifier
172
+ # This will also include changelog entries, embedded as comments
173
+ :src: lib/revision/version.rb
174
+ # Regex matching the source revision identifier. Must contain the following named capture groups
175
+ # - major, minor, patch :: Numeric (uint) sequences representing the three revision ID components
176
+ # - sep1, sep2 :: the characters separating the revision components
177
+ # - prefix, postfix :: sufficient syntactic context to match the revision ID uniquely
178
+ # N.B. this regex matches the version ID from the standard bundler gem skeleton,
179
+ # e.g. VERSION = "1.1.0"
180
+ :regex: (?<prefix>VERSION = ")(?<major>\d+)(?<sep1>\.)(?<minor>\d+)(?<sep2>\.)(?<patch>\d+)(?<postfix>")
181
+ # Comment char for the project language -- prefixed to each line of changelog entries
182
+ # Quotes only necessary here to prevent # being interpreted as the beginning of a YAML comment
183
+ :comment_prefix: "#"
177
184
  # Sequence of build steps -- each item should be a valid shell command, prefixed with the YAML sequence item token, '- '
178
185
  :build_steps:
179
186
  - bundle exec rake install
180
- # Sequence defining the files (build artefacts) to package in the release archive.
181
- # Each artefact definition must include a :src: key/value pair.
182
- # An optional :dest: value may be provided to rename the file during packaging, or just (as in the first entry below)
183
- # to flatten the folder structure.
184
- # Any <VER> (or <REV>) in the :src: or :dest: placeholders wil be replaced with the current revision ID
185
- # The revision archive will also include the revision history extracted as a text file
186
- :artefacts:
187
- # A binary artefact -- the
188
- - :src: pkg/revision-<VER>.gem
189
- :dest: revision-<VER>.gem
190
- # This document -- the :dest: value defaults to duplicating :src: if not specified
191
- - :src: README.org
192
- #+END_SRC
187
+ # Sequence defining the files (build artefacts) to package in the release archive.
188
+ # Each artefact definition must include a :src: key/value pair.
189
+ # An optional :dest: value may be provided to rename the file during packaging, or just (as in the first entry below)
190
+ # to flatten the folder structure.
191
+ # Any <VER> (or <REV>) in the :src: or :dest: placeholders wil be replaced with the current revision ID
192
+ # The revision archive will also include the revision history extracted as a text file
193
+ :artefacts:
194
+ # A binary artefact -- the
195
+ - :src: pkg/revision-<VER>.gem
196
+ :dest: revision-<VER>.gem
197
+ # This document -- the :dest: value defaults to duplicating :src: if not specified
198
+ - :src: README.org
199
+ #+END_SRC
193
200
 
194
201
  **** TODO (or at least consider) add support for overridable defaults
195
- e.g. via a =.releasables= configuration file in the user home dir.
196
- Though this would be bad for collaborative development as the config file would live outside source control.
197
- Possibly useful to support inclusion of a controlled configuration file instead? Primarily to define
198
- a revision regex and comment prefix for a group of related releasables....
202
+ e.g. via a =.releasables= configuration file in the user home dir.
203
+ Though this would be bad for collaborative development as the config file would live outside source control.
204
+ Possibly useful to support inclusion of a controlled configuration file instead? Primarily to define
205
+ a revision regex and comment prefix for a group of related releasables....
199
206
 
200
207
  *** Examples
201
208
  **** C project
202
209
 
203
- #+BEGIN_NOTE
204
- The ~:regex:~ and ~:comment_prefix:~ keys are absent in the C example below. This project started life as
205
- managing some embedded C projects, and the default values reflect this.
206
- #+END_NOTE
207
-
208
- #+BEGIN_SRC yaml
209
- :releasables:
210
- - :id: mbt_cd_firmware
211
- :revision:
212
- :src: src/FirmwareRevision.c
213
- :build_steps:
214
- - make --jobs=8 -f Makefile CONF=bootloadable
210
+ #+BEGIN_NOTE
211
+ The ~:regex:~ and ~:comment_prefix:~ keys are absent in the C example below. This project started life as
212
+ managing some embedded C projects, and the default values reflect this.
213
+ #+END_NOTE
214
+
215
+ #+BEGIN_SRC yaml
216
+ :releasables:
217
+ - :id: mbt_cd_firmware
218
+ :revision:
219
+ :src: src/FirmwareRevision.c
220
+ :build_steps:
221
+ - make --jobs=8 -f Makefile CONF=bootloadable
215
222
  :artefacts:
216
223
  - :src: dist/bootloadable/production/firmware.production.hex
217
224
  :dest: mbt_cd_firmware_v<REV>.bootloadable.hex
218
- - :src: dist/default/production/firmware.production.hex
219
- :dest: mbt_cd_firmware_v<REV>.standalone.hex
220
- #+END_SRC
225
+ - :src: dist/default/production/firmware.production.hex
226
+ :dest: mbt_cd_firmware_v<REV>.standalone.hex
227
+ #+END_SRC
221
228
 
222
229
  **** Ruby project
223
230
 
224
- #+BEGIN_SRC yaml
225
- :releasables:
226
- - :id: revision
227
- :revision:
228
- :src: lib/revision/version.rb
229
- :regex: (?<prefix>VERSION = ")(?<major>\d+)(?<sep1>\.)(?<minor>\d+)(?<sep2>\.)(?<patch>\d+)(?<postfix>")
230
- :comment_prefix: "#"
231
- :build_steps:
232
- - bundle exec rake install
231
+ #+BEGIN_SRC yaml
232
+ :releasables:
233
+ - :id: revision
234
+ :revision:
235
+ :src: lib/revision/version.rb
236
+ :regex: (?<prefix>VERSION = ")(?<major>\d+)(?<sep1>\.)(?<minor>\d+)(?<sep2>\.)(?<patch>\d+)(?<postfix>")
237
+ :comment_prefix: "#"
238
+ :build_steps:
239
+ - bundle exec rake install
233
240
  :artefacts:
234
241
  - :src: pkg/revision-<VER>.gem
235
- #+END_SRC
242
+ #+END_SRC
236
243
 
237
244
  *** Heirarchical project
238
- Rather than defining the releasable parameters inline, a =releasables.yaml= list entry can contain a (relative or absolute) link to another folder containing it's own =releasables.yaml=.
245
+ Rather than defining the releasable parameters inline, a =releasables.yaml= list entry can contain a (relative or absolute) link to another folder containing it's own =releasables.yaml=.
239
246
 
240
- i.e assuming the earlier examples were in folders =examples/c= and =examples/ruby= relative to a common root, a separate =releasables.yaml=
241
- at that root could include them as follows...
247
+ i.e assuming the earlier examples were in folders =examples/c= and =examples/ruby= relative to a common root, a separate =releasables.yaml=
248
+ at that root could include them as follows...
242
249
 
243
- #+BEGIN_SRC yaml
244
- :releasables:
245
- - :folder: examples/c
246
- - :folder: examples/ruby
247
- #+END_SRC
250
+ #+BEGIN_SRC yaml
251
+ :releasables:
252
+ - :folder: examples/c
253
+ - :folder: examples/ruby
254
+ #+END_SRC
248
255
 
249
256
  **** TODO consider supporting a higher-level aggregate revision ID
250
257
 
251
- #+BEGIN_SRC yaml
252
- :revision:
253
- :src: release_log.txt
258
+ #+BEGIN_SRC yaml
259
+ :revision:
260
+ :src: release_log.txt
254
261
  :releasables:
255
262
  - :folder: examples/c
256
- - :folder: examples/ruby
257
- #+END_SRC
263
+ - :folder: examples/ruby
264
+ #+END_SRC
258
265
 
259
266
  * Development
260
267
 
261
- After checking out the repo, run =bin/setup= to install dependencies. Then, run =rake spec= to run the tests. You can also run =bin/console= for an interactive prompt that will allow you to experiment.
268
+ After checking out the repo, run =bin/setup= to install dependencies. Then, run =rake spec= to run the tests. You can also run =bin/console= for an interactive prompt that will allow you to experiment.
262
269
 
263
- To install this gem onto your local machine, run =bundle exec rake install=. To release a new version, update the version number in =version.rb=, and then run =bundle exec rake release=, which will create a git tag for the version, push git commits and tags, and push the =.gem= file to [rubygems.org](https://rubygems.org).
270
+ To install this gem onto your local machine, run =bundle exec rake install=.
264
271
 
272
+ To release a new version, update the version number in =version.rb=. You can do this using the gem, by entering =revision minor= (or =patch= or =major= as appropriate), and then run =bundle exec rake release=, which will create a git tag for the version, push git commits and tags, and push the =.gem= file to [rubygems.org](https://rubygems.org).
265
273
 
266
274
  * Contributing
267
275
 
268
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/revision.
276
+ Bug reports and pull requests are welcome on GitHub at https://github.com/cormacc/revision.
@@ -119,8 +119,26 @@ module Revision
119
119
  def do_increment(type)
120
120
  r = select_one
121
121
  increment_method = "#{type}_increment!"
122
- say "Incrementing #{r.revision} to #{r.revision.public_send(increment_method)}"
123
- options[:dryrun] ? r.revision.write_to_file : r.revision.write!
122
+ say "Incrementing #{r.revision} to #{r.revision.public_send(increment_method)} (#{r.revision.src})"
123
+ if options[:dryrun]
124
+ r.revision.write(r.revision.src + ".new")
125
+ r.secondary_revisions.each do |s|
126
+ say "Propagating revision update to #{s.src}"
127
+ s.major = r.revision.major
128
+ s.minor = r.revision.minor
129
+ s.patch = r.revision.patch
130
+ s.write(s.src + ".new")
131
+ end
132
+ else
133
+ r.revision.write!
134
+ r.secondary_revisions.each do |s|
135
+ say "Propagating revision update to #{s.src}"
136
+ s.major = r.revision.major
137
+ s.minor = r.revision.minor
138
+ s.patch = r.revision.patch
139
+ s.write!
140
+ end
141
+ end
124
142
  say ''
125
143
  say "The automatic commit / tag step assumes you're only checking in changes to existing files"
126
144
  say "You can answer 'n' at the prompt and use 'revision tag' to generate a commit with the latest changelog entry and an associated tag after manually adding any new files to the repo"
@@ -128,7 +146,7 @@ module Revision
128
146
  if ask("Rebuild and archive any releasables (Y/n)?").upcase!='N'
129
147
  r.package
130
148
  end
131
- if ask("Commit changes to existing files and add a Git tag (y/N)?").upcase=='Y'
149
+ if ask("Commit changes to existing files and add a Git tag (Y/n)?").upcase!='N'
132
150
  r.tag
133
151
  if ask("Push changes/tag to origin (Y/n)?").upcase=='N' || !r.push
134
152
  say "To push from the command line, type 'git push --tags' at a shell prompt"
@@ -15,10 +15,11 @@ class Revision::Info
15
15
  attr_accessor :regex
16
16
  attr_accessor :comment_prefix
17
17
 
18
- def initialize(file, regex: nil, comment_prefix: nil)
18
+ def initialize(file, regex: nil, comment_prefix: nil, embed_changelog: true)
19
19
  @src=file
20
20
  @regex = regex.nil? ? DEFAULT_REGEX : /#{regex}/
21
21
  @comment_prefix = comment_prefix || DEFAULT_COMMENT_PREFIX
22
+ @embed_changelog = embed_changelog
22
23
  matched = false
23
24
  File.open(@src).each_line do |line|
24
25
  if line =~ @regex
@@ -65,15 +66,16 @@ class Revision::Info
65
66
  ref_info = self.class.new(@src, regex: @regex)
66
67
  raise 'No revision identifiers incremented' if ref_info.to_s == self.to_s
67
68
 
68
- entry = get_changelog_entry
69
69
 
70
70
  text = File.read(@src)
71
71
  text.gsub!(@regex) { |match| "#{$~[:prefix]}#{@major}#{$~[:sep1]}#{@minor}#{$~[:sep2]}#{@patch}#{$~[:postfix]}" }
72
72
 
73
- #Insert start/end tags if not present
74
- text += new_changelog_placeholder unless text.match(CHANGELOG_START)
75
-
76
- text.gsub!(CHANGELOG_START) { |match| [match, format_changelog_entry(entry)].join("\n") }
73
+ if @embed_changelog
74
+ entry = get_changelog_entry
75
+ #Insert start/end tags if not present
76
+ text += new_changelog_placeholder unless text.match(CHANGELOG_START)
77
+ text.gsub!(CHANGELOG_START) { |match| [match, format_changelog_entry(entry)].join("\n") }
78
+ end
77
79
 
78
80
  File.open(output_file_name, 'w') { |f| f.write(text) }
79
81
  end
@@ -119,7 +121,7 @@ class Revision::Info
119
121
  # Prefixes the entry with an empty line, then prefixes each line with comment chars
120
122
  # and converts the line entries to a single string
121
123
  def format_changelog_entry(entry_lines)
122
- entry_lines.unshift('').map { |line| "#{@comment_prefix} #{line}"}.join("\n")
124
+ entry_lines.unshift('').map { |line| "#{@comment_prefix} #{line}".rstrip()}.join("\n")
123
125
  end
124
126
 
125
127
  def get_changelog_entry
@@ -17,7 +17,7 @@ module Revision
17
17
 
18
18
  REVISION_PLACEHOLDER = /<REV>|<VER>/
19
19
 
20
- attr_reader :root, :id, :revision, :build_steps, :artefacts, :git_tag_prefix
20
+ attr_reader :root, :id, :revision, :build_steps, :artefacts, :git_tag_prefix, :secondary_revisions
21
21
 
22
22
  # Load a file in yaml format containing one or more releasable definitions
23
23
  # @param root [String] An optional root directory argument
@@ -53,12 +53,17 @@ module Revision
53
53
  # @git_repo
54
54
  # end
55
55
 
56
+ def _build_revision_info(definition, embed_changelog: true)
57
+ Info.new(File.join(@root,definition[:src]), regex: definition[:regex], comment_prefix: definition[:comment_prefix], embed_changelog: embed_changelog)
58
+ end
59
+
56
60
  def initialize(root: nil, config: {})
57
61
 
58
62
  root ||= Dir.getwd
59
63
  @root = Pathname.new(root).realpath
60
64
  @id = config[:id] || File.basename(@root)
61
- @revision = Info.new(File.join(@root,config[:revision][:src]), regex: config[:revision][:regex], comment_prefix: config[:revision][:comment_prefix])
65
+ @revision = _build_revision_info(config[:revision], embed_changelog: true)
66
+ @secondary_revisions = config[:secondary_revisions].nil? ? [] : config[:secondary_revisions].map { |r| _build_revision_info(r, embed_changelog:false)}
62
67
  @git_tag_prefix = config[:revision][:git_tag_prefix].nil? ? 'v' : "#{config[:revision][:git_tag_prefix]}_v"
63
68
  # Legacy definition syntax compatibility
64
69
  @build_def = config[:build] ? config[:build] : { environment: { variables: {}}, steps: config[:build_steps]}
@@ -88,6 +93,20 @@ module Revision
88
93
  EOT
89
94
  end
90
95
 
96
+ def exec_pipeline(type, steps, skip_steps=0)
97
+ exec_steps = steps[skip_steps..-1]
98
+ puts "#{type} :: Executing steps #{skip_steps+1} to #{steps.length}..."
99
+ Dir.chdir(@root) do
100
+ exec_steps.each_with_index do |step, index|
101
+ step_index = index+1+skip_steps
102
+ puts "... (#{step_index}/#{steps.length}) #{step}"
103
+ system(step)
104
+ puts "{type} :: WARNING: step #{step_index}: #{step} exit status #{$?.exitstatus}" unless $?.exitstatus.zero?
105
+ end
106
+ end
107
+
108
+ end
109
+
91
110
  def build(skip_steps = 0)
92
111
  if @build_def.dig(:environment, :variables)
93
112
  @build_def[:environment][:variables].each do |key, value|
@@ -105,24 +124,29 @@ module Revision
105
124
  ENV[key] = value
106
125
  end
107
126
  end
108
- steps = @build_def[:steps][skip_steps..-1]
109
- puts "Executing #{steps.length} of #{@build_def[:steps].length} build steps..."
110
- Dir.chdir(@root) do
111
- steps.each_with_index do |step, index|
112
- step_index = index+1+skip_steps
113
- puts "... (#{step_index}/#{@build_def[:steps].length}) #{step}"
114
- system(step)
115
- puts "WARNING: build step #{step_index}: #{step} exit status #{$?.exitstatus}" unless $?.exitstatus.zero?
116
- end
117
- end
127
+ exec_pipeline('build', @build_def[:steps], skip_steps)
128
+ # steps = @build_def[:steps][skip_steps..-1]
129
+ # puts "Executing #{steps.length} of #{@build_def[:steps].length} build steps..."
130
+ # Dir.chdir(@root) do
131
+ # steps.each_with_index do |step, index|
132
+ # step_index = index+1+skip_steps
133
+ # puts "... (#{step_index}/#{@build_def[:steps].length}) #{step}"
134
+ # system(step)
135
+ # puts "WARNING: build step #{step_index}: #{step} exit status #{$?.exitstatus}" unless $?.exitstatus.zero?
136
+ # end
137
+ # end
118
138
  end
119
139
 
120
140
  def tag_id
121
141
  "#{@git_tag_prefix}#{revision}"
122
142
  end
123
143
 
144
+ def escape(a_string)
145
+ a_string.gsub('"',"\\\"")
146
+ end
147
+
124
148
  def tag_annotation
125
- @revision.last_changelog_entry.join("\n")
149
+ escape(@revision.last_changelog_entry.join("\n"))
126
150
  end
127
151
 
128
152
  def commit_message
@@ -133,7 +157,7 @@ module Revision
133
157
  commit_lines << "Also..."
134
158
  commit_lines += changelog_entry[2..-1]
135
159
  end
136
- commit_lines.join("\n")
160
+ escape(commit_lines.join("\n"))
137
161
  end
138
162
 
139
163
  def tag
@@ -142,6 +166,7 @@ module Revision
142
166
  puts commit_message
143
167
  system("git commit -a -m \"#{commit_message}\"")
144
168
  puts "Tagging as #{tag_id}"
169
+ puts "git tag -a #{tag_id} -m \"#{tag_annotation}\""
145
170
  system("git tag -a #{tag_id} -m \"#{tag_annotation}\"")
146
171
  end
147
172
  end
@@ -176,37 +201,89 @@ module Revision
176
201
  src = File.join(@root,src)
177
202
  dest = dest_prefix.empty? ? dest : File.join(dest_prefix, dest)
178
203
  amap[src] = dest
179
- puts "... (#{index+1}/#{@artefacts.length}) #{src} => #{dest}"
180
204
  end
181
205
  amap
182
206
  end
183
207
 
184
208
  def archive
185
209
  puts "Archiving #{@artefacts.length} build artefacts as #{archive_name}..."
186
- puts artefact_map
210
+ amap = artefact_map
187
211
  if File.exist?(archive_name)
188
212
  puts "... deleting existing archive"
189
213
  File.delete(archive_name)
190
214
  end
191
215
  Zip::File.open(archive_name, Zip::File::CREATE) do |zipfile|
192
- artefact_map.each { |src, dest| zipfile.add(dest,src) }
216
+ amap.each.with_index(1) do |entry, idx|
217
+ src, dest = entry
218
+ #TODO: Add directory processing....
219
+ puts "... (#{idx}/#{amap.length}) #{src} => #{dest}"
220
+ zipfile.add(dest, src)
221
+ end
193
222
  puts "... embedding revision history as #{changelog_name} "
194
223
  zipfile.get_output_stream(changelog_name) { |os| output_changelog(os)}
195
224
  end
225
+
226
+ if @config.dig(:archive)
227
+ archive_root = File.expand_path(@config[:archive])
228
+ puts "... moving #{archive_name} to #{archive_root}"
229
+ FileUtils.mkdir_p(archive_root)
230
+ FileUtils.mv(archive_name, archive_root)
231
+ end
196
232
  end
197
233
 
198
- # def deploy(destination)
199
234
  def deploy(destination='')
200
- if destination=='' and @config.dig(:deploy, :dest)
201
- destination = @config[:deploy][:dest]
235
+ destinations = []
236
+ if not destination.empty?
237
+ destinations.append({dest: destination})
238
+ elsif @config.dig(:deploy)
239
+ if @config[:deploy].kind_of?(Array)
240
+ destinations.append(*@config[:deploy])
241
+ else
242
+ destinations.append(@config[:deploy])
243
+ end
244
+ end
245
+
246
+ raise Errors::NotSpecified.new(':deploy') if destinations.empty?
247
+
248
+ if @config.dig(:deploy, :pre)
249
+ exec_pipeline('deploy (pre)', @config[:deploy][:pre])
250
+ end
251
+
252
+ destinations.each do |d|
253
+ destination = File.expand_path(d[:dest])
254
+
255
+ if d.dig(:pre)
256
+ exec_pipeline('deploy (pre / #{d[:dest]})', d[:pre])
257
+ end
258
+
259
+ puts "Deploying #{@artefacts.length} build artefacts to #{destination}..."
260
+ if not File.exist?(destination)
261
+ puts "... folder not found -> creating ... '#{destination}'"
262
+ FileUtils.mkdir_p(destination)
263
+ end
264
+ amap = artefact_map(destination)
265
+ amap.each.with_index(1) do |entry, idx|
266
+ src, dest = entry
267
+ puts "... (#{idx}/#{amap.length}) #{src} => #{dest}"
268
+ if File.exist?(dest)
269
+ puts "... deleting existing '#{dest}' ..."
270
+ FileUtils.rm_rf(dest)
271
+ end
272
+ puts "... deploying '#{src}' -> '#{dest}"
273
+ FileUtils.cp_r(src,dest)
274
+ end
275
+ File.open(File.join(destination,changelog_name),'w') { |f| output_changelog(f)}
276
+
277
+ if d.dig(:post)
278
+ exec_pipeline('deploy (post / #{d[:dest]})', d[:post])
279
+ end
202
280
  end
203
281
 
204
- raise Errors::NotSpecified.new(':deploy/:dest') if destination==''
205
- destination = File.expand_path(destination)
206
282
 
207
- puts "Deploying #{@artefacts.length} build artefacts to #{destination}..."
208
- artefact_map(destination).each { |src, dest| FileUtils.cp(src,dest) }
209
- #TODO Add changelog
283
+
284
+ if @config.dig(:deploy, :post)
285
+ exec_pipeline('deploy (post)', @config[:deploy][:post])
286
+ end
210
287
  end
211
288
 
212
289
  def package
@@ -1,93 +1,119 @@
1
1
  # Defines the revision ID for the revision gem
2
2
  module Revision
3
- VERSION = "1.2.7"
3
+ VERSION = "1.5.2".freeze
4
4
  end
5
5
 
6
6
  # <BEGIN CHANGELOG>
7
- #
7
+ #
8
+ # Version 1.5.2 (10 Jun 2020)
9
+ # - Uprevving around undeletable git tag
10
+ #
11
+ ## Version 1.5.1 (10 Jun 2020)
12
+ # - Escape " and ' in commit message when constructing git command line (' still problematic in some shells)
13
+ #
14
+ # Version 1.5.0 (13 Feb 2020)
15
+ # - Now handles multiple deployment destinations in releasables.yaml
16
+ #
17
+ # Version 1.4.1 (18 Nov 2019)
18
+ # - Updated to strip trailing whitespace after comment char for empty line
19
+ #
20
+ # Version 1.4.0 (10 Jun 2019)
21
+ # - Now allow the definition of one or more 'secondary_revisions', where a revision ID can be updated with or without an embedded changelog
22
+ #
23
+ # Version 1.3.1 (20 May 2019)
24
+ # - Corrected bug when deploying changelog:w
25
+ #
26
+ # Version 1.3.0 (20 May 2019)
27
+ # - Added :archive: (archive root definition)
28
+ # - Added optional :pre: and :post: steps to :deploy: definition
29
+ #
30
+ # Version 1.2.8 (20 May 2019)
31
+ # - Updated Git tag/commit behaviour -- now commit/tag/push by default
32
+ # - Updated deploy to remove existing targets and copy entire directory trees
33
+ #
8
34
  # Version 1.2.7 (17 May 2019)
9
35
  # - 'deploy' now expands '~' in paths
10
- #
36
+ #
11
37
  # Version 1.2.6 (17 May 2019)
12
38
  # - Updated deploy to use default dest from yaml (if specified)
13
- #
39
+ #
14
40
  # Version 1.2.5 (07 Nov 2018)
15
41
  # - Added 'deploy' command
16
- #
42
+ #
17
43
  # Version 1.2.4 (05 Sep 2018)
18
44
  # - Added commit message and tag details to `revision info`
19
45
  # - Minor refactoring
20
- #
46
+ #
21
47
  # Version 1.2.3 (03 Sep 2018)
22
48
  # - Tidied up `revision info` output formatting
23
- #
49
+ #
24
50
  # Version 1.2.2 (03 Sep 2018)
25
51
  # - Updated CLI to provide version info
26
- #
52
+ #
27
53
  # Version 1.2.1 (03 Sep 2018)
28
54
  # - Update to allow releasable without any artefacts
29
- #
55
+ #
30
56
  # Version 1.2.0 (06 Mar 2018)
31
57
  # - Build definition improvements (and new yaml structure)
32
58
  # - Added platform-agnostic environment variable definition (handles '~' replacement and :/; path separators)
33
59
  # - Added platform-agnostic packaging of binaries (i.e. appending .exe for windows when archiving)
34
- #
60
+ #
35
61
  # Version 1.1.10 (16 Feb 2018)
36
62
  # - Modified 'archive' command to just archive existing artefact -- i.e. skip build phase
37
63
  # - Added 'package' command that builds AND archives
38
- #
64
+ #
39
65
  # Version 1.1.9 (16 Feb 2018)
40
66
  # - Fixed bug when adding first changelog entry to file without existing placeholders
41
67
  # - Added standalone build command
42
- #
68
+ #
43
69
  # Version 1.1.8 (15 Dec 2017)
44
70
  # - Added .yardopts to build documentation
45
- #
71
+ #
46
72
  # Version 1.1.7 (15 Dec 2017)
47
73
  # - Corrected push -- was pushing tags without commit
48
- #
74
+ #
49
75
  # Version 1.1.6 (15 Dec 2017)
50
76
  # - Added full changelog entry as tag message
51
77
  # - Removed ruby-git dependency from gemspec
52
- #
78
+ #
53
79
  # Version 1.1.5 (15 Dec 2017)
54
80
  # - Replaced ruby-git library with shell calls, as wasn't handling submodules correctly
55
- #
81
+ #
56
82
  # Version 1.1.4 (14 Dec 2017)
57
83
  # - Minor message body reformatting
58
- #
84
+ #
59
85
  # Version 1.1.3 (14 Dec 2017)
60
86
  # - Eliminated duplication of version ID in commit message body
61
- #
87
+ #
62
88
  # Version 1.1.2 (14 Dec 2017)
63
89
  # - Removed redundant ':: ' from commit message headline
64
- #
90
+ #
65
91
  # Version 1.1.1 (14 Dec 2017)
66
92
  # - Added git connection failure handling
67
93
  # - Revision commit message now includes first line of changelog entry
68
94
  # - Updated configuration syntax for consistency (:revision: :file: -> :revision: :src:)
69
- #
95
+ #
70
96
  # Version 1.1.0 (13 Dec 2017)
71
97
  # - Updated to optionally push tags to the repo
72
- #
98
+ #
73
99
  # Version 1.0.1 (13 Dec 2017)
74
100
  # - Corrected revision placeholder handling when archiving build artefacts
75
101
  # - Added proper high-level usage documentation
76
- #
102
+ #
77
103
  # Version 1.0.0 (12 Dec 2017)
78
104
  # - First fully functional release with new config file
79
- #
105
+ #
80
106
  # Version 0.1.4 (12 Dec 2017)
81
107
  # - boo
82
108
  # - hoo
83
109
  # - hoo
84
- #
110
+ #
85
111
  # Version 0.1.3 (12 Dec 2017)
86
112
  # - boo
87
- #
113
+ #
88
114
  # Version 0.1.2 (12 Dec 2017)
89
115
  # - wahoo!
90
- #
116
+ #
91
117
  # Version 0.1.1 (12 Dec 2017)
92
118
  # - Wahey!
93
- # <END CHANGELOG>
119
+ # <END CHANGELOG>
@@ -2,7 +2,7 @@
2
2
  - :id: revision
3
3
  :revision:
4
4
  :src: lib/revision/version.rb
5
- :regex: (?<prefix>VERSION = ")(?<major>\d+)(?<sep1>\.)(?<minor>\d+)(?<sep2>\.)(?<patch>\d+)(?<postfix>")
5
+ :regex: (?<prefix>VERSION = ")(?<major>\d+)(?<sep1>\.)(?<minor>\d+)(?<sep2>\.)(?<patch>\d+)(?<postfix>".freeze)
6
6
  :comment_prefix: "#"
7
7
  :build_steps:
8
8
  - bundle exec rake install
@@ -6,20 +6,12 @@ Gem::Specification.new do |spec|
6
6
  spec.name = "revision"
7
7
  spec.version = Revision::VERSION
8
8
  spec.authors = ["Cormac Cannon"]
9
- spec.email = ["cormac.cannon@neuromoddevices.com"]
9
+ spec.licenses = ['MIT']
10
10
 
11
11
  spec.summary = %q{Language-agnostic revision management tool}
12
12
  spec.description = %q{Updates project revision identifiers in software source files and associated change log. Can also build and package project archives as a zip and optionally commit, tag and push to a Git repo.}
13
- # spec.homepage = "TBC"
14
-
15
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
- # to allow pushing to a single host or delete this section to allow pushing to any host.
17
- # if spec.respond_to?(:metadata)
18
- # spec.metadata["allowed_push_host"] = "http://gems.nmd.ie"
19
- # else
20
- # raise "RubyGems 2.0 or newer is required to protect against " \
21
- # "public gem pushes."
22
- # end
13
+ spec.homepage = 'https://rubygems.org/gems/revision'
14
+ spec.metadata = { "source_code_uri" => "https://github.com/cormacc/revision" }
23
15
 
24
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
25
17
  f.match(%r{^(test|spec|features)/})
@@ -29,11 +21,11 @@ Gem::Specification.new do |spec|
29
21
 
30
22
  spec.require_paths = ["lib"]
31
23
 
32
- spec.add_runtime_dependency 'thor', '~> 0.19.1'
33
- spec.add_runtime_dependency 'rubyzip'
24
+ spec.add_runtime_dependency 'thor', '~> 1.0'
25
+ spec.add_runtime_dependency 'rubyzip', '~> 2.0'
34
26
 
35
27
  spec.add_development_dependency "bundler", "~> 2.0"
36
- spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rake", "~> 13.0"
37
29
  spec.add_development_dependency "rspec", "~> 3.0"
38
30
  spec.add_development_dependency "pry"
39
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: revision
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.7
4
+ version: 1.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cormac Cannon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-17 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.19.1
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.19.1
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubyzip
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '2.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -97,8 +97,7 @@ dependencies:
97
97
  description: Updates project revision identifiers in software source files and associated
98
98
  change log. Can also build and package project archives as a zip and optionally
99
99
  commit, tag and push to a Git repo.
100
- email:
101
- - cormac.cannon@neuromoddevices.com
100
+ email:
102
101
  executables:
103
102
  - revision
104
103
  extensions: []
@@ -123,9 +122,11 @@ files:
123
122
  - lib/revision/version.rb
124
123
  - releasables.yaml
125
124
  - revision.gemspec
126
- homepage:
127
- licenses: []
128
- metadata: {}
125
+ homepage: https://rubygems.org/gems/revision
126
+ licenses:
127
+ - MIT
128
+ metadata:
129
+ source_code_uri: https://github.com/cormacc/revision
129
130
  post_install_message:
130
131
  rdoc_options: []
131
132
  require_paths:
@@ -141,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
142
  - !ruby/object:Gem::Version
142
143
  version: '0'
143
144
  requirements: []
144
- rubygems_version: 3.0.3
145
+ rubygems_version: 3.1.3
145
146
  signing_key:
146
147
  specification_version: 4
147
148
  summary: Language-agnostic revision management tool