revision 1.2.7 → 1.5.2

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: 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