Skip to content

Commit

Permalink
Add check command (#79)
Browse files Browse the repository at this point in the history
* Add check command

* Document check function:

* Bump version

* [Format] Auto-formatting

---------

Co-authored-by: nnichols <nnichols@users.noreply.github.com>
  • Loading branch information
nnichols and nnichols authored May 3, 2024
1 parent 3cda595 commit 0974697
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 4 deletions.
11 changes: 11 additions & 0 deletions .sealog/changes/1-5-0.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{:version {:major 1
:minor 5
:patch 0}
:version-type :semver3
:changes {:added ["`check` command to [verify the current configuration, changelog entries, and project version.](https://github.com/Wall-Brew-Co/lein-sealog#check-sealog-configuration)"]
:changed []
:deprecated []
:removed []
:fixed []
:security []}
:timestamp "2024-05-03T00:46:45.488497Z"}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## Table of Contents

* [1.5.0 - 2024-05-03](#150---2024-05-03)
* [1.4.0 - 2024-05-01](#140---2024-05-01)
* [1.3.0 - 2024-03-13](#130---2024-03-13)
* [1.2.1 - 2024-03-10](#121---2024-03-10)
Expand All @@ -15,6 +16,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* [1.0.1 - 2022-10-23](#101---2022-10-23)
* [1.0.0 - 2022-10-23](#100---2022-10-23)

## 1.5.0 - 2024-05-03

* Added
* `check` command to [verify the current configuration, changelog entries, and project version.](https://github.com/Wall-Brew-Co/lein-sealog#check-sealog-configuration)

## 1.4.0 - 2024-05-01

* Added
Expand Down
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ From the root of your project directory, you may invoke the following commands:
* `render` - To compile all changelog entry files into a markdown Changelog
* `insert` - To update the most recent changelog entry file with new notes
* `version` - To print the current project versions from Leiningen and sealog
* `check` - To validate Sealog's configuration, changelog entry files, the changelog, and the project version
* `help` - To view the help text of sealog or any command

Most commands will accept several options, which can be configured by the command line arguments passed in or by a configuration file located at `.sealog/config.edn`.
Expand Down Expand Up @@ -228,6 +229,55 @@ Reading from .sealog/changes/1-3-0.edn
1.3.0
```

### Check Sealog Configuration

Sealog relies on convention to produce sane changelogs.
To validate that Sealog is configured appropriately, you may run a series of introspective checks.

```sh
$ lein sealog check
Reading from .sealog/config.edn
Sealog configuration is valid.
Reading from .sealog/config.edn
Changelog entry directory contains at least one file.
Reading from .sealog/changes/1-0-1.edn
Reading from .sealog/changes/1-2-0.edn
Reading from .sealog/changes/1-3-0.edn
All changelog entries are valid.
Reading from .sealog/changes/1-0-1.edn
Reading from .sealog/changes/1-2-0.edn
Reading from .sealog/changes/1-3-0.edn
All changelog entries use the same version type.
Reading from .sealog/changes/1-0-1.edn
Reading from .sealog/changes/1-2-0.edn
Reading from .sealog/changes/1-3-0.edn
All changelog entries have distinct versions.
Reading from .sealog/changes/1-0-1.edn
Reading from .sealog/changes/1-2-0.edn
Reading from .sealog/changes/1-3-0.edn
Project version matches latest changelog entry.
Reading from .sealog/changes/1-0-1.edn
Reading from .sealog/changes/1-2-0.edn
Reading from .sealog/changes/1-3-0.edn
Rendered changelog contains all changelog entries.
All checks passed
```

Checks:

* If a configuration file exists, it must be valid.
* If no configuration file exists, sealog will assume its default configuration
* The changelog directory must contain at least one file.
* The changelog directory must contain only valid changelog entries.
* If invalid files are found, the issues will be printed to STDERR with `clojure.spec/explain-str`
* All changelog entry files must use the same version type.
* If mismatched version types are found, all version types will be printed to STDERR
* All changelog entry files must have a distinct version.
* If duplicate versions are found, all versions will be printed to STDERR
* The project.clj version must match the latest changelog entry.
* If mismatched versions are found, both will be printed to STDERR
* The rendered changelog must contain all changelog entries.

### Render Changelog

Finally, Sealog can aggregate and render your change entries into a clean, Markdown format.
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<groupId>com.wallbrew</groupId>
<artifactId>lein-sealog</artifactId>
<packaging>jar</packaging>
<version>1.4.0</version>
<version>1.5.0</version>
<name>lein-sealog</name>
<description>A Leiningen plugin for managing your changelog.</description>
<url>https://github.com/Wall-Brew-Co/common-beer-format</url>
Expand All @@ -20,7 +20,7 @@
<url>https://github.com/Wall-Brew-Co/lein-sealog</url>
<connection>scm:git:git://github.com/Wall-Brew-Co/lein-sealog.git</connection>
<developerConnection>scm:git:ssh://git@github.com/Wall-Brew-Co/lein-sealog.git</developerConnection>
<tag>35a7a6065f42d677e414db4f75a379a1422e82f2</tag>
<tag>0d6214fa1dbfa0929d716b29eff63aee1082fb2a</tag>
</scm>
<build>
<sourceDirectory>src</sourceDirectory>
Expand Down
2 changes: 1 addition & 1 deletion project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject com.wallbrew/lein-sealog "1.4.0"
(defproject com.wallbrew/lein-sealog "1.5.0"
:description "A Leiningen plugin for managing your changelog."
:url "https://github.com/Wall-Brew-Co/common-beer-format"
:license {:name "MIT"
Expand Down
23 changes: 22 additions & 1 deletion src/leiningen/sealog.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
(defn unknown-command
"Formats an error message for an unknown command."
[command]
(str "Unknown command: " command "\nAvailable commands: init, bump, render, insert, version, and help"))
(str "Unknown command: " command "\nAvailable commands: init, bump, render, insert, version, check, and help"))


(defn top-level-help
Expand All @@ -27,6 +27,7 @@
(main/info " render - Render the changelog to the target file.")
(main/info " insert - Insert a note of a specified change type into the most current change file.")
(main/info " version - Display information about the current version.")
(main/info " check - Check the current configuration, changelog etries, and the current project version.")
(main/info " help - Display this help message.")
(main/info "")
(main/info "Run `lein sealog help <command>` for more information on a specific command."))
Expand Down Expand Up @@ -96,6 +97,24 @@
(main/info " If no value is provided, the process will load all sources to compare."))


(defn check-help
"Display help text for the check command"
[]
(main/info "Usage: lein sealog check")
(main/info "")
(main/info "Check the current configuration, changelog etries, and the current project version.")
(main/info "Will exit abnormally if any issues are found.")
(main/info "")
(main/info "Checks:")
(main/info " - If a configuration file exists, it must be valid.")
(main/info " - The changelog directory must contain at least one file.")
(main/info " - The changelog directory must contain only valid changelog entries.")
(main/info " - All changelog entry files must use the same version type.")
(main/info " - All changelog entry files must have a distinct version.")
(main/info " - The project version must match the latest changelog entry.")
(main/info " - The rendered changelog must contain all changelog entries."))


(defn help
"Display help text for a specific command."
[options]
Expand All @@ -107,6 +126,7 @@
"render" (render-help)
"insert" (insert-help)
"version" (version-help)
"check" (check-help)
"help" (main/info "Run `lein sealog help <command>` for more information on a specific command.")
(main/info (unknown-command command)))))

Expand All @@ -125,5 +145,6 @@
"render" (sealog/render-changelog options)
"insert" (sealog/insert-entry options)
"version" (sealog/display-version project options)
"check" (sealog/check project options)
"help" (help options)
(main/warn "Unknown command: %s" command))))
22 changes: 22 additions & 0 deletions src/leiningen/sealog/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,25 @@
(do (main/info (str "project.clj: " leiningen-version))
(main/info (str "sealog: " sealog-version)))))
(System/exit 1))))


(defn check
"Check the current configuration, changelog entries, and the current project version."
[project _opts]
(if (impl/valid-configuration?)
(let [configuration (impl/load-config!)
some-changelog-entries? (impl/changelog-entry-directory-is-not-empty? configuration)
all-changelog-entries-valid? (impl/changelog-directory-only-contains-valid-files? configuration)
same-version-type? (impl/all-changelog-entries-use-same-version-type? configuration)
distinct-versions? (impl/all-changelog-entries-have-distinct-versions? configuration)]
(if (and some-changelog-entries?
all-changelog-entries-valid?
same-version-type?
distinct-versions?)
(let [versions-match? (impl/project-version-matches-latest-changelog-entry? project configuration)
changelog-rendered? (impl/rendered-changelog-contains-all-changelog-entries? configuration)]
(if (and versions-match? changelog-rendered?)
(main/info "All checks passed")
(System/exit 1)))
(System/exit 1)))
(System/exit 1)))
105 changes: 105 additions & 0 deletions src/leiningen/sealog/impl.clj
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,108 @@
[_opts]
(io/make-parents (io/file config/config-file))
(write-file! config/config-file config/default-config))


(defn valid-configuration?
"Returns true if the configuration is valid."
[]
(let [configuration-contents (if (file-exists? config/config-file)
(edn/read-string (read-file! config/config-file))
config/default-config)
contents (st/coerce ::config/config configuration-contents st/string-transformer)
valid? (spec/valid? ::config/config contents)]
(if valid?
(do (main/info "Sealog configuration is valid.")
true)
(do (main/warn (format "Invalid configuration file contents: %s" (spec/explain-str ::config/config contents)))
false))))


(defn changelog-entry-directory-is-not-empty?
"Returns true if the changelog entry directory is not empty."
[{:keys [changelog-entry-directory] :as _configuration}]
(let [has-files? (boolean (seq (list-all-files changelog-entry-directory)))]
(if has-files?
(do (main/info "Changelog entry directory contains at least one file.")
true)
(do (main/warn "Changelog entry directory is empty.")
false))))


(defn changelog-directory-only-contains-valid-files?
"Returns true if the changelog entry directory only contains valid files."
[{:keys [changelog-entry-directory] :as _configuration}]
(let [files (list-all-files changelog-entry-directory)
valid? (fn [filepath]
(let [file-content (edn/read-string (read-file! filepath))
contents (st/coerce ::changelog/entry file-content st/string-transformer)]
(if (spec/valid? ::changelog/entry contents)
true
(do (main/warn (format "Invalid changelog file contents at path `%s`: %s"
filepath
(spec/explain-str ::changelog/entry contents)))
false))))
all-valid? (every? valid? files)]
(if all-valid?
(do (main/info "All changelog entries are valid.")
true)
false)))


(defn all-changelog-entries-use-same-version-type?
"Returns true if all changelog entries use the same version type."
[{:keys [changelog-entry-directory] :as _configuration}]
(let [files (list-all-files changelog-entry-directory)
reducer (fn [acc filepath]
(let [content (edn/read-string (read-file! filepath))]
(conj acc (:version-type content))))
version-types (vec (distinct (reduce reducer [] files)))]
(if (= 1 (count version-types))
(do (main/info "All changelog entries use the same version type.")
true)
(do (main/warn (format "Changelog entries use multiple version types: %s" version-types))
false))))


(defn all-changelog-entries-have-distinct-versions?
"Returns true if all changelog entries have distinct versions."
[{:keys [changelog-entry-directory] :as _configuration}]
(let [files (list-all-files changelog-entry-directory)
reducer (fn [acc filepath]
(let [content (edn/read-string (read-file! filepath))]
(conj acc (:version content))))
versions (vec (distinct (reduce reducer [] files)))]
(if (= (count files) (count versions))
(do (main/info "All changelog entries have distinct versions.")
true)
(do (main/warn (format "Changelog entries have non-distinct versions: %s" versions))
false))))


(defn project-version-matches-latest-changelog-entry?
"Returns true if the project version matches the latest changelog entry."
[project configuration]
(let [changelog (load-changelog-entry-directory! configuration)
latest-changelog-entry (changelog/max-version changelog)
sealog-version (changelog/render-version latest-changelog-entry)
leiningen-version (:version project)]
(if (= leiningen-version sealog-version)
(do (main/info "Project version matches latest changelog entry.")
true)
(do (main/warn (format "Project version `%s` does not match latest changelog entry `%s`"
leiningen-version
sealog-version))
false))))


(defn rendered-changelog-contains-all-changelog-entries?
"Returns true if the rendered changelog contains all changelog entries."
[{:keys [changelog-filename] :as configuration}]
(let [changelog (load-changelog-entry-directory! configuration)
rendered-changelog (render-changelog changelog)
rendered-changelog-contents (slurp changelog-filename)]
(if (= (count rendered-changelog) (count rendered-changelog-contents))
(do (main/info "Rendered changelog contains all changelog entries.")
true)
(do (main/warn "Rendered changelog does not contain all changelog entries. Please run `lein sealog render`.")
false))))

0 comments on commit 0974697

Please sign in to comment.