diff --git a/.circleci/config.yml b/.circleci/config.yml index d9f0fe20..9147ad53 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -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: @@ -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 @@ -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: @@ -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: diff --git a/README.md b/README.md index 31af5fd5..e01d2203 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/formatting_stack/branch_formatter.clj b/src/formatting_stack/branch_formatter.clj index 44ce7f4c..0ec16271 100644 --- a/src/formatting_stack/branch_formatter.clj +++ b/src/formatting_stack/branch_formatter.clj @@ -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] @@ -15,7 +16,8 @@ [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])) (def third-party-indent-specs formatting-stack.indent-specs/default-third-party-indent-specs) @@ -75,3 +77,28 @@ :compilers [] :linters linters :in-background? in-background?))) + +(defn format-branch! [& {:keys [target-branch in-background?] + :or {target-branch "master" + in-background? (not (System/getenv "CI"))}}] + (let [default-strategies [(fn [& {:as options}] + (mapply strategies/git-diff-against-default-branch (assoc options :target-branch target-branch)))] + formatters (default-formatters default-strategies)] + (formatting-stack.core/format! :strategies default-strategies + :formatters formatters + :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")) + + (println "Running linter ...") + (let [output (-> (with-out-str (lint-branch! :in-background? false)) str/trim)] + (assert (#{""} output) (str "Linting yielded output: " output))) + + (println "Running formatter ...") + (let [output (-> (with-out-str (format-branch! :in-background? false)) str/trim)] + (assert (#{""} output) (str "Formatting yielded output: " output))) + + (println "Success!")) diff --git a/src/formatting_stack/linters/ns_aliases.clj b/src/formatting_stack/linters/ns_aliases.clj index 470eff57..b86dd0af 100644 --- a/src/formatting_stack/linters/ns_aliases.clj +++ b/src/formatting_stack/linters/ns_aliases.clj @@ -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))))))))))) diff --git a/src/formatting_stack/project_formatter.clj b/src/formatting_stack/project_formatter.clj index 8c93c713..dbb64f9f 100644 --- a/src/formatting_stack/project_formatter.clj +++ b/src/formatting_stack/project_formatter.clj @@ -14,7 +14,8 @@ [formatting-stack.linters.kondo :as linters.kondo] [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])) + [formatting-stack.strategies :as strategies]) + (:gen-class)) (def third-party-indent-specs formatting-stack.indent-specs/default-third-party-indent-specs) diff --git a/src/formatting_stack/util.clj b/src/formatting_stack/util.clj index 55facd48..d28f792e 100644 --- a/src/formatting_stack/util.clj +++ b/src/formatting_stack/util.clj @@ -1,5 +1,6 @@ (ns formatting-stack.util (:require + [clojure.java.shell :refer [sh]] [clojure.tools.namespace.file :as file] [clojure.tools.namespace.parse :as parse] [formatting-stack.project-parsing :refer [project-namespaces]]