Skip to content

Commit

Permalink
Fix Changelog Verification (#19)
Browse files Browse the repository at this point in the history
This includes some fixes to the changelog tool including verification that no longer accepts everything, requiring the changelog file to have # Change Log at the top, restricting the arbitrary text at the top to be a single line, and adding tests for invalid changelog files. The command will also produce an exit code of 1 if it fails for any reason, unless it is called with zero arguments.
  • Loading branch information
Theodus authored and SeanTAllen committed Jan 6, 2018
1 parent 34e2f1b commit b8c2525
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 123 deletions.
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ deps:

bin/changelog-tool: deps
mkdir -p bin
stable env ponyc -o bin
stable env ponyc -V1 -o bin

install:
mkdir -p $(prefix)/bin
cp bin/changelog-tool $(prefix)/bin

test: deps
cd tests && \
stable env ponyc -d && ./tests && \
rm tests && cd ..
stable env ponyc -d -V1 && ./tests && \
rm tests && \
sh verification.sh && \
cd ..

clean:
rm -rf bin
Expand Down
20 changes: 17 additions & 3 deletions changelog.pony
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ class Changelog
let children = ast.children.values()
released = Array[Release]

heading = (children.next()? as Token).string()
heading =
if children.has_next() then
match children.next()?
| let t: Token => t.string()
| NotPresent => ""
else error
end
else
""
end

if ast.size() > 1 then
unreleased = try Release(children.next()? as AST)? end
for child in children do
Expand All @@ -32,8 +42,12 @@ class Changelog

fun string(): String iso^ =>
let str = (recover String end)
.> append(heading)
.> append("\n")
.> append("# Change Log\n\n")
if heading != "" then
str
.> append(heading)
.> append("\n\n")
end
if unreleased isnt None then str.append(unreleased.string()) end
for release in released.values() do
str.append(release.string())
Expand Down
6 changes: 3 additions & 3 deletions changelog_parser.pony
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use "peg"
primitive ChangelogParser
fun apply(): Parser val =>
recover
head() * release(false).opt() * release().many()
(head() * release(false).opt() * release().many()).eof()
end

fun head(): Parser val =>
recover
(not L("\n## [") * Unicode).many().term()
* -L("\n").opt()
let para = not L("#") * (not L("\n") * Unicode).many1().term()
-L("# Change Log\n\n") * para.opt() * -L("\n").many()
end

fun release(released: Bool = true): Parser val =>
Expand Down
48 changes: 20 additions & 28 deletions changelog_tool.pony
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use "debug"
use "files"
use "peg"
use "time"
Expand All @@ -10,39 +11,28 @@ class ChangelogTool
new create(env: Env, filename: String, filepath: FilePath) =>
(_env, _filename, _filepath) = (env, filename, filepath)

fun verify() =>
_env.out.print("verifying " + _filename + "...")
try
let ast = _parse()?

// TODO:
// let changelog = Changelog(ast)?
// _env.out.print(changelog.string())
// try changelog .> create_release("0.0.0", "0000-00-00")
// else _env.out.print("fail.")
// end
_env.out.print(_filename + " is a valid changelog")
end
fun verify() ? =>
let ast = _parse()?
let changelog = Changelog(ast)?
Debug(recover Printer(ast) end)
Debug(changelog.string())

fun release(version: String, edit: Bool) =>
try
_check_version(version)?
let date = Date(Time.seconds()).format("%Y-%m-%d")
let changelog: String =
Changelog(_parse()?)?
.> create_release(version, date)
.string()
_edit_or_print(edit, changelog)
else
_env.err.print("unable to perform release prep")
end
fun release(version: String, edit: Bool) ? =>
_check_version(version)?
let date = Date(Time.seconds()).format("%Y-%m-%d")
let changelog: String =
Changelog(_parse()?)?
.> create_release(version, date)
.string()
_edit_or_print(edit, changelog)

fun _check_version(version: String) ? =>
let source = Source.from_string(version)
match recover val ChangelogParser.version().parse(source) end
| (_, let t: Token) => None
else
_env.err.print("invalid version number: '" + version + "'")
_env.out.print("invalid version number: '" + version + "'")
_env.exitcode(1)
error
end

Expand Down Expand Up @@ -77,9 +67,11 @@ class ChangelogTool
ast
| (let offset: USize, let r: Parser val) =>
let e = recover val SyntaxError(source, offset, r) end
_env.err.writev(PegFormatError.console(e))
_env.out.writev(PegFormatError.console(e))
_env.exitcode(1)
error
else
_env.err.print("unable to parse file: " + _filename)
_env.out.print("unable to parse file: " + _filename)
_env.exitcode(1)
error
end
112 changes: 69 additions & 43 deletions main.pony
Original file line number Diff line number Diff line change
@@ -1,57 +1,83 @@
use "files"
use "options"
use "itertools"

actor Main
let help_text: String =
"""
changelog-tool COMMAND <changelog file> [...]
Commands:
verify Verify that the given changelog is valid.
release Print a changelog that is prepared for release.
Example: `changelog-tool release CHANGELOG.md 0.13.1`
unreleased Add unreleased section to changelog if none exists.
Options:
--edit, -e Edit the changelog file (release and unreleased only).
"""

new create(env: Env) =>
// TODO use the cli package instead of options
let options =
Options(env.args)
.> add("edit", "e", None)

try
var edit = false
for option in options do
match option
| ("edit", None) => edit = true
| let err: ParseError =>
err.report(env.err)
error
end
// TODO use the cli package

if env.args.size() == 1 then
env.out.print(help_text)
return
end

(let cmd, let filename) =
try (env.args(1)?, env.args(2)?)
else
env.out.print(help_text)
env.exitcode(1)
return
end

let filepath =
try
FilePath(env.root as AmbientAuth, filename)?
else
env.out.print("unable to open: " + filename)
env.exitcode(1)
return
end
let tool = ChangelogTool(env, filename, filepath)

let args = Array[String]
for arg in options.remaining().values() do
args.push(arg.clone())
var edit = false
for arg in Iter[String](env.args.values()).skip(3) do
if (arg == "-e") or (arg == "--edit") then
edit = true
break
end
end

let filename = args(2)?
let filepath =
try
FilePath(env.root as AmbientAuth, filename)?
match cmd
| "verify" =>
env.out.print("Verifying " + filename + "...")
try
tool.verify()?
env.out.print(filename + " is a valid changelog.")
else
env.out.print(filename + " is not a valid changelog.")
env.exitcode(1)
return
end
| "release" =>
let version =
try env.args(3)?
else
env.err.print("unable to open: " + filename)
env.out.print("A release version must be provided.")
env.exitcode(1)
return
end
let tool = ChangelogTool(env, filename, filepath)

match args(1)?
| "verify" => tool.verify()
| "release" => tool.release(args(3)?, edit)
| "unreleased" => tool.unreleased(edit)
else error
try tool.release(version, edit)?
else
env.out.print("Unable to perform release prep.")
env.exitcode(1)
return
end
| "unreleased" => tool.unreleased(edit)
else
env.out.print(
"""
changelog-tool COMMAND <changelog file> [...]
Commands:
verify Verify that the given changelog is valid.
release Print a changelog that is prepared for release.
Example: `changelog-tool release CHANGELOG.md 0.13.1`
unreleased Add unreleased section to changelog if none exists.
Options:
--edit, -e Edit the changelog file (release and unreleased only).
""")
env.out.print(help_text)
env.exitcode(1)
return
end
Empty file added tests/bad-changelogs/empty.md
Empty file.
8 changes: 8 additions & 0 deletions tests/bad-changelogs/malformed-version.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Change Log

## [unreleased] - unreleased

### Fixed
- things

## [0.1.] - 2017-04-07
1 change: 1 addition & 0 deletions tests/bad-changelogs/no-changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## [unreleased] - unreleased
17 changes: 17 additions & 0 deletions tests/bad-changelogs/unreleased-sub-heading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Change Log

Stuff

## [unreleased] - unreleased

### Fixed
- things

### Adde
- stuff

## [0.13.0] - 2017-04-07

### Fixed

- Do not allow capability subtyping when checking constraint subtyping. ([PR #1816](https://github.com/ponylang/ponyc/pull/1816))
Loading

0 comments on commit b8c2525

Please sign in to comment.