BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
65ad11b4
Commit
65ad11b4
authored
Aug 10, 2017
by
Robert Speicher
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '21949-add-type-to-changelog' into 'master'
Let's start labeling our CHANGELOG entries Closes #21949 See merge request !11579
parents
130c369a
eb2b895a
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
215 additions
and
75 deletions
+215
-75
changelog
bin/changelog
+99
-35
21949-add-type-to-changelog.yml
changelogs/unreleased/21949-add-type-to-changelog.yml
+4
-0
changelog.md
doc/development/changelog.md
+46
-8
changelog_spec.rb
spec/bin/changelog_spec.rb
+66
-32
No files found.
bin/changelog
View file @
65ad11b4
...
...
@@ -14,54 +14,107 @@ Options = Struct.new(
:dry_run
,
:force
,
:merge_request
,
:title
:title
,
:type
)
INVALID_TYPE
=
-
1
class
ChangelogOptionParser
def
self
.
parse
(
argv
)
options
=
Options
.
new
Type
=
Struct
.
new
(
:name
,
:description
)
TYPES
=
[
Type
.
new
(
'added'
,
'New feature'
),
Type
.
new
(
'fixed'
,
'Bug fix'
),
Type
.
new
(
'changed'
,
'Feature change'
),
Type
.
new
(
'deprecated'
,
'New deprecation'
),
Type
.
new
(
'removed'
,
'Feature removal'
),
Type
.
new
(
'security'
,
'Security fix'
),
Type
.
new
(
'other'
,
'Other'
)
].
freeze
TYPES_OFFSET
=
1
class
<<
self
def
parse
(
argv
)
options
=
Options
.
new
parser
=
OptionParser
.
new
do
|
opts
|
opts
.
banner
=
"Usage:
#{
__FILE__
}
[options] [title]
\n\n
"
# Note: We do not provide a shorthand for this in order to match the `git
# commit` interface
opts
.
on
(
'--amend'
,
'Amend the previous commit'
)
do
|
value
|
options
.
amend
=
value
end
opts
.
on
(
'-f'
,
'--force'
,
'Overwrite an existing entry'
)
do
|
value
|
options
.
force
=
value
end
opts
.
on
(
'-m'
,
'--merge-request [integer]'
,
Integer
,
'Merge Request ID'
)
do
|
value
|
options
.
merge_request
=
value
end
opts
.
on
(
'-n'
,
'--dry-run'
,
"Don't actually write anything, just print"
)
do
|
value
|
options
.
dry_run
=
value
end
opts
.
on
(
'-u'
,
'--git-username'
,
'Use Git user.name configuration as the author'
)
do
|
value
|
options
.
author
=
git_user_name
if
value
end
opts
.
on
(
'-t'
,
'--type [string]'
,
String
,
"The category of the change, valid options are:
#{
TYPES
.
map
(
&
:name
).
join
(
', '
)
}
"
)
do
|
value
|
options
.
type
=
parse_type
(
value
)
end
opts
.
on
(
'-h'
,
'--help'
,
'Print help message'
)
do
$stdout
.
puts
opts
exit
end
end
parser
=
OptionParser
.
new
do
|
opts
|
opts
.
banner
=
"Usage:
#{
__FILE__
}
[options] [title]
\n\n
"
parser
.
parse!
(
argv
)
# Note: We do not provide a shorthand for this in order to match the `git
# commit` interface
opts
.
on
(
'--amend'
,
'Amend the previous commit'
)
do
|
value
|
options
.
amend
=
value
end
# Title is everything that remains, but let's clean it up a bit
options
.
title
=
argv
.
join
(
' '
).
strip
.
squeeze
(
' '
).
tr
(
"
\r\n
"
,
''
)
opts
.
on
(
'-f'
,
'--force'
,
'Overwrite an existing entry'
)
do
|
value
|
options
.
force
=
value
end
options
end
opts
.
on
(
'-m'
,
'--merge-request [integer]'
,
Integer
,
'Merge Request ID'
)
do
|
value
|
options
.
merge_request
=
value
end
def
read_type
read_type_message
opts
.
on
(
'-n'
,
'--dry-run'
,
"Don't actually write anything, just print"
)
do
|
value
|
options
.
dry_run
=
value
end
type
=
TYPES
[
$stdin
.
getc
.
to_i
-
TYPES_OFFSET
]
assert_valid_type!
(
type
)
opts
.
on
(
'-u'
,
'--git-username'
,
'Use Git user.name configuration as the author'
)
do
|
value
|
options
.
author
=
git_user_name
if
value
end
type
.
name
end
private
opts
.
on
(
'-h'
,
'--help'
,
'Print help message'
)
do
$stdout
.
puts
opts
exit
def
parse_type
(
name
)
type_found
=
TYPES
.
find
do
|
type
|
type
.
name
==
name
end
type_found
?
type_found
.
name
:
INVALID_TYPE
end
parser
.
parse!
(
argv
)
# Title is everything that remains, but let's clean it up a bit
options
.
title
=
argv
.
join
(
' '
).
strip
.
squeeze
(
' '
).
tr
(
"
\r\n
"
,
''
)
def
read_type_message
$stdout
.
puts
"
\n
>> Please specify the index for the category of your change:"
TYPES
.
each_with_index
do
|
type
,
index
|
$stdout
.
puts
"
#{
index
+
TYPES_OFFSET
}
.
#{
type
.
description
}
"
end
$stdout
.
print
"
\n
?> "
end
options
end
def
assert_valid_type!
(
type
)
unless
type
$stderr
.
puts
"Invalid category index, please select an index between 1 and
#{
TYPES
.
length
}
"
exit
1
end
end
def
self
.
git_user_name
%x{git config user.name}
.
strip
def
git_user_name
%x{git config user.name}
.
strip
end
end
end
...
...
@@ -72,8 +125,12 @@ class ChangelogEntry
@options
=
options
assert_feature_branch!
assert_new_file!
assert_title!
assert_new_file!
# Read type from $stdin unless is already set
options
.
type
||=
ChangelogOptionParser
.
read_type
assert_valid_type!
$stdout
.
puts
"
\e
[32mcreate
\e
[0m
#{
file_path
}
"
$stdout
.
puts
contents
...
...
@@ -90,7 +147,8 @@ class ChangelogEntry
yaml_content
=
YAML
.
dump
(
'title'
=>
title
,
'merge_request'
=>
options
.
merge_request
,
'author'
=>
options
.
author
'author'
=>
options
.
author
,
'type'
=>
options
.
type
)
remove_trailing_whitespace
(
yaml_content
)
end
...
...
@@ -129,6 +187,12 @@ class ChangelogEntry
" to use the title from the previous commit."
end
def
assert_valid_type!
return
unless
options
.
type
&&
options
.
type
==
INVALID_TYPE
fail_with
'Invalid category given!'
end
def
title
if
options
.
title
.
empty?
last_commit_subject
...
...
changelogs/unreleased/21949-add-type-to-changelog.yml
0 → 100644
View file @
65ad11b4
---
title
:
Added type to CHANGELOG entries
merge_request
:
author
:
Jacopo Beschi @jacopo-beschi
doc/development/changelog.md
View file @
65ad11b4
...
...
@@ -15,11 +15,14 @@ following format:
title
:
"
Going
through
change[log]s"
merge_request
:
1972
author
:
Ozzy Osbourne
type
:
added
```
The
`merge_request`
value is a reference to a merge request that adds this
entry, and the
`author`
key is used to give attribution to community
contributors.
**Both are optional**
.
The
`type`
field maps the category of the change,
valid options are: added, fixed, changed, deprecated, removed, security, other.
**Type field is mandatory**
.
Community contributors and core team members are encouraged to add their name to
the
`author`
field. GitLab team members
**should not**
.
...
...
@@ -94,6 +97,19 @@ Its simplest usage is to provide the value for `title`:
$ bin/changelog 'Hey DZ, I added a feature to GitLab!'
```
At this point the script would ask you to select the category of the change (mapped to the
`type`
field in the entry):
```
text
>> Please specify the category of your change:
1. New feature
2. Bug fix
3. Feature change
4. New deprecation
5. Feature removal
6. Security fix
7. Other
```
The entry filename is based on the name of the current Git branch. If you run
the command above on a branch called
`feature/hey-dz`
, it will generate a
`changelogs/unreleased/feature-hey-dz.yml`
file.
...
...
@@ -106,26 +122,29 @@ create changelogs/unreleased/my-feature.yml
title: Hey DZ, I added a feature to GitLab!
merge_request:
author:
type:
```
If you're working on the GitLab EE repository, the entry will be added to
`changelogs/unreleased-ee/`
instead.
#### Arguments
| Argument | Shorthand | Purpose |
| ----------------- | --------- | --------------------------------------------- |
|
[
`--amend`
]
| | Amend the previous commit |
|
[
`--force`
]
|
`-f`
| Overwrite an existing entry |
|
[
`--merge-request`
]
|
`-m`
| Set merge request ID |
|
[
`--dry-run`
]
|
`-n`
| Don't actually write anything, just print |
|
[
`--git-username`
]
|
`-u`
| Use Git user.name configuration as the author |
|
[
`--help`
]
|
`-h`
| Print help message |
| Argument | Shorthand | Purpose |
| ----------------- | --------- | ---------------------------------------------------------------------------------------------------------- |
|
[
`--amend`
]
| | Amend the previous commit |
|
[
`--force`
]
|
`-f`
| Overwrite an existing entry |
|
[
`--merge-request`
]
|
`-m`
| Set merge request ID |
|
[
`--dry-run`
]
|
`-n`
| Don't actually write anything, just print |
|
[
`--git-username`
]
|
`-u`
| Use Git user.name configuration as the author |
|
[
`--type`
]
|
`-t`
| The category of the change, valid options are: added, fixed, changed, deprecated, removed, security, other |
|
[
`--help`
]
|
`-h`
| Print help message |
[
`--amend`
]:
#-amend
[
`--force`
]:
#-force-or-f
[
`--merge-request`
]:
#-merge-request-or-m
[
`--dry-run`
]:
#-dry-run-or-n
[
`--git-username`
]:
#-git-username-or-u
[
`--type`
]:
#-type-or-t
[
`--help`
]:
#-help
##### `--amend`
...
...
@@ -147,6 +166,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Added an awesome new feature to GitLab
merge_request:
author:
type:
```
##### `--force` or `-f`
...
...
@@ -164,6 +184,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Hey DZ, I added a feature to GitLab!
merge_request: 1983
author:
type:
```
##### `--merge-request` or `-m`
...
...
@@ -178,6 +199,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Hey DZ, I added a feature to GitLab!
merge_request: 1983
author:
type:
```
##### `--dry-run` or `-n`
...
...
@@ -192,6 +214,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Added an awesome new feature to GitLab
merge_request:
author:
type:
$ ls changelogs/unreleased/
```
...
...
@@ -211,6 +234,21 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Hey DZ, I added a feature to GitLab!
merge_request:
author: Jane Doe
type:
```
##### `--type` or `-t`
Use the
**`--type`**
or
**`-t`**
argument to provide the
`type`
value:
```
text
$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -t added
create changelogs/unreleased/feature-hey-dz.yml
---
title: Hey DZ, I added a feature to GitLab!
merge_request:
author:
type: added
```
### History and Reasoning
...
...
spec/bin/changelog_spec.rb
View file @
65ad11b4
...
...
@@ -4,56 +4,90 @@ load File.expand_path('../../bin/changelog', __dir__)
describe
'bin/changelog'
do
describe
ChangelogOptionParser
do
it
'parses --ammend'
do
options
=
described_class
.
parse
(
%w[foo bar --amend]
)
describe
'.parse'
do
it
'parses --amend'
do
options
=
described_class
.
parse
(
%w[foo bar --amend]
)
expect
(
options
.
amend
).
to
eq
true
end
expect
(
options
.
amend
).
to
eq
true
end
it
'parses --force and -f'
do
%w[--force -f]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
bar]
)
it
'parses --force and -f'
do
%w[--force -f]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
bar]
)
expect
(
options
.
force
).
to
eq
true
expect
(
options
.
force
).
to
eq
true
end
end
end
it
'parses --merge-request and -m'
do
%w[--merge-request -m]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
1234 bar]
)
it
'parses --merge-request and -m'
do
%w[--merge-request -m]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
1234 bar]
)
expect
(
options
.
merge_request
).
to
eq
1234
expect
(
options
.
merge_request
).
to
eq
1234
end
end
end
it
'parses --dry-run and -n'
do
%w[--dry-run -n]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
bar]
)
it
'parses --dry-run and -n'
do
%w[--dry-run -n]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
bar]
)
expect
(
options
.
dry_run
).
to
eq
true
expect
(
options
.
dry_run
).
to
eq
true
end
end
end
it
'parses --git-username and -u'
do
allow
(
described_class
).
to
receive
(
:git_user_name
).
and_return
(
'Jane Doe'
)
it
'parses --git-username and -u'
do
allow
(
described_class
).
to
receive
(
:git_user_name
).
and_return
(
'Jane Doe'
)
%w[--git-username -u]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
bar]
)
%w[--git-username -u]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
bar]
)
expect
(
options
.
author
).
to
eq
'Jane Doe'
expect
(
options
.
author
).
to
eq
'Jane Doe'
end
end
it
'parses --type and -t'
do
%w[--type -t]
.
each
do
|
flag
|
options
=
described_class
.
parse
(
%W[foo
#{
flag
}
security]
)
expect
(
options
.
type
).
to
eq
'security'
end
end
end
it
'parses -h'
do
expect
do
expect
{
described_class
.
parse
(
%w[foo -h bar]
)
}.
to
output
.
to_stdout
end
.
to
raise_error
(
SystemExit
)
it
'parses -h'
do
expect
do
expect
{
described_class
.
parse
(
%w[foo -h bar]
)
}.
to
output
.
to_stdout
end
.
to
raise_error
(
SystemExit
)
end
it
'assigns title'
do
options
=
described_class
.
parse
(
%W[foo -m 1 bar
\n
-u baz
\r\n
--amend]
)
expect
(
options
.
title
).
to
eq
'foo bar baz'
end
end
it
'assigns title'
do
options
=
described_class
.
parse
(
%W[foo -m 1 bar
\n
-u baz
\r\n
--amend]
)
describe
'.read_type'
do
let
(
:type
)
{
'1'
}
expect
(
options
.
title
).
to
eq
'foo bar baz'
it
'reads type from $stdin'
do
expect
(
$stdin
).
to
receive
(
:getc
).
and_return
(
type
)
expect
do
expect
(
described_class
.
read_type
).
to
eq
(
'added'
)
end
.
to
output
.
to_stdout
end
context
'invalid type given'
do
let
(
:type
)
{
'99'
}
it
'shows error message and exits the program'
do
allow
(
$stdin
).
to
receive
(
:getc
).
and_return
(
type
)
expect
do
expect
do
expect
{
described_class
.
read_type
}.
to
raise_error
(
SystemExit
)
end
.
to
output
(
"Invalid category index, please select an index between 1 and 7
\n
"
).
to_stderr
end
.
to
output
.
to_stdout
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment