Skip to content

Commit

Permalink
Add pristine? cli command
Browse files Browse the repository at this point in the history
related to #88
  • Loading branch information
thumbnail committed Dec 20, 2019
1 parent f5baad2 commit 41d4747
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 39 deletions.
46 changes: 38 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# Clojure CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-clojure/ for more details
#
version: 2
version: 2.1
jobs:
build:
docker:
Expand Down Expand Up @@ -50,7 +46,7 @@ jobs:

jfrog:
docker:
- image: circleci/clojure:lein-2.8.1-node
- image: circleci/clojure:lein-2.9.1-node

working_directory: ~/repo

Expand All @@ -73,8 +69,35 @@ jobs:
name: release to Clojars
command: lein deploy clojars

format-and-lint:
docker:
- image: circleci/clojure:lein-2.9.1-node

working_directory: ~/repo

steps:

- checkout

# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "project.clj" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-

- run: lein with-profile -dev,+ci,+pedantic deps

- save_cache:
paths:
- ~/.m2
key: v1-dependencies-{{ checksum "project.clj" }}

- run:
command: lein with-profile -dev,+ci run -m formatting-stack.branch-formatter pristine?

workflows:
version: 2
version: 2.1
CircleCI:
jobs:
- build:
Expand All @@ -83,7 +106,14 @@ workflows:
branches:
only: /.*/
tags:
only: /^v\d+\.\d+\.\d+(-alpha\d+)?$/
only: /^v\d+\.\d+\.\d+(-alpha\d+)?$/

- format-and-lint:
context: JFrog
filters:
branches:
ignore: master

- jfrog:
context: JFrog
requires:
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ That's by design, to avoid intrincate DSLs or data structures.
If you need something finer-grained, you are encouraged to copy the contents of the `formatting-stack.defaults` ns to your project, adapting things as needed.
That ns is a deliberately thin and data-only one, with the precise purpose of being forked at no cost.

## CI integration

**formatting-stack** can be used in a CI configuration to assert that there's no formatting errors or new warnings introduced.
```bash
lein with-profile -dev,+ci run -m formatting-stack.branch-formatter pristine?
```

will yield assertion errors if the build introduces new warnings / formatting changes in files touched against the `master`-branch.

## [FAQ](https://github.com/nedap/formatting-stack/wiki/FAQ)

## License
Expand Down
46 changes: 45 additions & 1 deletion src/formatting_stack/branch_formatter.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns formatting-stack.branch-formatter
"A set of defaults apt for formatting a git branch (namely, the files that a branch has modified, respective to another)."
(:require
[clojure.string :as str]
[formatting-stack.core]
[formatting-stack.formatters.cider :as formatters.cider]
[formatting-stack.formatters.clean-ns :as formatters.clean-ns]
Expand All @@ -15,7 +16,9 @@
[formatting-stack.linters.loc-per-ns :as linters.loc-per-ns]
[formatting-stack.linters.ns-aliases :as linters.ns-aliases]
[formatting-stack.strategies :as strategies]
[medley.core :refer [mapply]]))
[medley.core :refer [mapply]]
[nedap.speced.def :as speced])
(:gen-class))

(def third-party-indent-specs formatting-stack.indent-specs/default-third-party-indent-specs)

Expand Down Expand Up @@ -75,3 +78,44 @@
:compilers []
:linters linters
:in-background? in-background?)))

(speced/defn -main [command & _args]
(assert (#{"pristine?"} command)
(str "Command not recognised.\n\n"
"Available commands: pristine?.\n\n"
"You can refer to the documentation in: https://github.com/nedap/formatting-stack"))

(let [default-strategies [(fn [& {:as options}]
(mapply strategies/git-diff-against-default-branch (assoc options :target-branch "master")))]
opts {:third-party-indent-specs third-party-indent-specs}
linters [(formatters.cljfmt/map->Formatter opts)
(formatters.clean-ns/map->Formatter (assoc opts :strategies (conj default-strategies
strategies/files-with-a-namespace
strategies/exclude-cljc
strategies/exclude-cljs
strategies/exclude-edn
strategies/do-not-use-cached-results!)))]
results (formatting-stack.core/process! formatting-stack.protocols.linter/lint!
linters
nil
default-strategies
false)

print-results (fn [results] (->> (zipmap (map type linters) results)
(reduce-kv (fn reduce-linters [memo linter filenames]
(reduce (fn reduce-files [memo filename]
(update memo filename (fnil conj []) linter))
memo
filenames))
{})
(run! (fn print-violations [[filename linters]]
(println (str "📄" "\033[1m ./" filename "\033[0m\n"
(->> linters
(map #(str " - " (pr-str %) "\n"))
(apply str))))))))]
(when-not (every? empty? results)
(println "🚨 Violations found: \n")
(print-results results)
(System/exit 1)))

(println "👍🏻 No violations found"))
19 changes: 10 additions & 9 deletions src/formatting_stack/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@
files (memoize (fn [strategies]
(files-from-strategies strategies)))]
(with-serialized-output
(doseq [member members]
(let [{specific-strategies :strategies} member
strategies (or specific-strategies category-strategies default-strategies)]
(try
(->> strategies files (method member))
(catch Exception e
(println "Encountered an exception, which will be printed in the next line."
"formatting-stack execution has *not* been aborted.")
(-> e .printStackTrace))))))))
(map (fn [member]
(let [{specific-strategies :strategies} member
strategies (or specific-strategies category-strategies default-strategies)]
(try
(->> strategies files (method member))
(catch Exception e
(println "Encountered an exception, which will be printed in the next line."
"formatting-stack execution has *not* been aborted.")
(-> e .printStackTrace)))))
members))))

(defn format! [& {:keys [strategies
third-party-indent-specs
Expand Down
13 changes: 12 additions & 1 deletion src/formatting_stack/formatters/clean_ns.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
[formatting-stack.formatters.clean-ns.impl :as impl]
[formatting-stack.formatters.how-to-ns]
[formatting-stack.protocols.formatter]
[formatting-stack.protocols.linter]
[formatting-stack.util :refer [process-in-parallel! try-require without-aliases]]
[medley.core :refer [deep-merge]]
[refactor-nrepl.config]))
[refactor-nrepl.config])
(:import
(java.io File)))

(defn clean! [how-to-ns-opts refactor-nrepl-opts namespaces-that-should-never-cleaned libspec-whitelist filename]
(let [buffer (slurp filename)
Expand Down Expand Up @@ -50,6 +53,14 @@
#{'user 'dev})

(defrecord Formatter [how-to-ns-opts refactor-nrepl-opts namespaces-that-should-never-cleaned libspec-whitelist]
formatting-stack.protocols.linter/Linter
(lint! [this files]
(let [changed-files (atom [])]
(with-redefs [spit (fn [f & _]
(swap! changed-files conj (if (string? f) f (.getPath ^File f))))]
(with-out-str (formatting-stack.protocols.formatter/format! this files))
@changed-files)))

formatting-stack.protocols.formatter/Formatter
(format! [this files]
(let [refactor-nrepl-opts (deep-merge refactor-nrepl.config/*config*
Expand Down
10 changes: 10 additions & 0 deletions src/formatting_stack/formatters/cljfmt.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@
[clojure.java.io :as io]
[formatting-stack.formatters.cljfmt.impl :as impl]
[formatting-stack.protocols.formatter]
[formatting-stack.protocols.linter]
[formatting-stack.util :refer [process-in-parallel!]]
[medley.core :refer [deep-merge]]))

(defrecord Formatter [options third-party-indent-specs]
formatting-stack.protocols.linter/Linter
(lint! [this files]
(->> files
(process-in-parallel! (fn [filename]
(let [indents (impl/cljfmt-indents-for filename third-party-indent-specs)]
(#'cljfmt.main/check-one {:indents indents} filename))))
(remove (fn [{{:keys [incorrect error]} :counts}] (zero? (+ incorrect error))))
(map :file)))

formatting-stack.protocols.formatter/Formatter
(format! [this files]
(let [cljfmt-opts (deep-merge cljfmt.main/default-options
Expand Down
36 changes: 17 additions & 19 deletions src/formatting_stack/linters/ns_aliases.clj
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,20 @@
(let [acceptable-aliases-whitelist (or acceptable-aliases-whitelist
default-acceptable-aliases-whitelist)]
(->> filenames
(process-in-parallel! (fn [filename]
(let [bad-require-clauses (->> filename
file/read-file-ns-decl
formatting-stack.util/require-from-ns-decl
(rest)
(remove (partial acceptable-require-clause?
acceptable-aliases-whitelist)))]
(when (seq bad-require-clauses)
(let [formatted-bad-requires (->> bad-require-clauses
(map (fn [x]
(str " " x)))
(string/join "\n"))]
(-> (str "Warning for "
filename
": the following :require aliases are not derived from their refered namespace:"
"\n"
formatted-bad-requires
". See https://stuartsierra.com/2015/05/10/clojure-namespace-aliases\n")
(println)))))))))))
(process-in-parallel!
(fn [filename]
(let [bad-require-clauses (->> filename
file/read-file-ns-decl
formatting-stack.util/require-from-ns-decl
(rest)
(remove (partial acceptable-require-clause?
acceptable-aliases-whitelist)))]
(when (seq bad-require-clauses)
(let [formatted-bad-requires (->> bad-require-clauses
(map (fn [x]
(str " " x)))
(string/join "\n"))]
(-> (str "Warning for " filename
": the following :require aliases are not derived from their referred namespace:\n"
formatted-bad-requires ". See https://stuartsierra.com/2015/05/10/clojure-namespace-aliases\n")
(println)))))))))))
3 changes: 2 additions & 1 deletion src/formatting_stack/protocols/linter.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

(defprotocol Linter
(lint! [this filenames]
"Lints `filenames` according to a linter of your choice: e.g. Eastwood, or Kibit, lein-dependency-check, etc."))
"Lints `filenames` according to a linter of your choice: e.g. Eastwood, or Kibit, lein-dependency-check, etc.
returns a seq of filenames with violations"))

0 comments on commit 41d4747

Please sign in to comment.