Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run tests on GitHub Actions #423

Merged
merged 1 commit into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Test

on:
push:
branches: ['master']
pull_request:

jobs:
build:
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
os: [ ubuntu, macos, windows ]

name: ${{ matrix.os }}

steps:

- uses: actions/checkout@v3

- name: Clojure deps cache
uses: actions/cache@v3
with:
path: |
~/.m2/repository
key: ${{ runner.os }}-cljdeps-${{ hashFiles('project.clj') }}
restore-keys: ${{ runner.os }}-cljdeps-

- name: "Setup Java"
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'

- name: Install Clojure Tools
uses: DeLaGuardo/[email protected]
with:
bb: 'latest'
lein: 'latest'

- name: Tools versions
run: bb tools-versions

- name: Bring down deps
run: lein deps

- name: Launch Virtual Display (ubuntu)
if: matrix.os == 'ubuntu'
run: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &

- name: Run Tests (unbuntu)
if: matrix.os == 'ubuntu'
run: lein test
env:
DISPLAY: :99.0

- name: Run Tests (macos, windows)
if: matrix.os != 'ubuntu'
run: lein test
3 changes: 3 additions & 0 deletions bb.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{:paths ["script"]
:deps {doric/doric {:mvn/version "0.9.0"}}
:tasks {tools-versions {:task tools-versions/report :doc "report on tools versions"}}}
146 changes: 146 additions & 0 deletions script/tools_versions.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
(ns tools-versions
(:require [babashka.fs :as fs]
[babashka.tasks :as tasks]
[clojure.string :as string]
[doric.core :as doric]
[cheshire.core :as json]))

(def tools
[;; earlier versions of java used -version and spit version info to stderr
{:oses :all :name "Java" :type :bin :app "java" :args "-version" :shell-opts {:out :string :err :string :continue true}}
{:oses :all :name "Leiningen" :type :bin :app "lein"}
{:oses :all :name "Babashka" :type :bin :app "bb"}

{:oses [:unix] :name "Chrome" :type :bin :app "google-chrome"} ;; only handling nix for now
{:oses [:mac] :name "Chrome" :type :mac-app :app "Google Chrome"}
{:oses [:win] :name "Chrome" :type :win-package :app "Google Chrome"}
{:oses :all :name "Chrome Webdriver" :type :bin :app "chromedriver"}

{:oses [:unix] :name "Firefox" :type :bin :app "firefox"} ;; only handling nix for now
{:oses [:mac] :name "Firefox" :type :mac-app :app "Firefox"}
{:oses [:win] :name "Firefox" :type :win-package :app #"Mozilla Firefox .*"}
{:oses :all :name "Firefox Webdriver" :type :bin :app "geckodriver" :version-post-fn #(->> % string/split-lines first)}

{:oses [:mac] :name "Edge" :type :mac-app :app "Microsoft Edge"}
{:oses [:win] :name "Edge" :type :win-package :app "Microsoft Edge"}
{:oses [:win :mac] :name "Edge Webdriver" :type :bin :app "msedgedriver"}

{:oses [:mac] :name "Safari" :type :mac-app :app "Safari"}
{:oses [:mac] :name "Safari Webdriver" :type :bin :app "safaridriver"}])

(def tool-defaults {:shell-opts {:out :string :continue true}
:args "--version"
:version-post-fn identity})

(defn- get-os []
(let [os-name (string/lower-case (System/getProperty "os.name"))]
(condp re-find os-name
#"win" :win
#"mac" :mac
#"(nix|nux|aix)" :unix
:unknown)))

(defn- expected-on-this-os [{:keys [oses]}]
(or (= :all oses)
(some #{(get-os)} oses)))

(defn- version-cmd-result [shell-opts {:keys [out err exit]}]
(if (not (zero? exit))
(format "<exit code %d>" exit)
(cond-> ""
(= :string (:out shell-opts)) (str out)
(= :string (:err shell-opts)) (str err))))

(defn- table-multilines->rows
"Convert a seq of maps from [{:a \"one\n\two\" :b \"a\nb\nc\"}]
to: [{:a \"one\" :b \"a\"}
{:a \"two\" :b \"b\"}
{:a \"\" :b \"c\"}]
in preparation for printing with doric."
[results]
(reduce (fn [acc n]
(let [n (reduce-kv (fn [m k v]
(assoc m k (string/split-lines v)))
{}
n)
max-lines (apply max (map #(count (val %)) n))]
(concat acc
(for [ln (range max-lines)]
(reduce-kv (fn [m k _v]
(assoc m k (get (k n) ln "")))
{}
n)))))
[]
results))

(defn- windows-software-list*
"One way to get a list of installed software on Windows.
Seems like there are many many ways, but this also often gets the install
location which is interesting to report."
[]
(let [reg-keys ["\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*"
"\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*"]]
(->> (mapcat (fn [reg-key]
(-> (tasks/shell {:out :string :continue true}
"powershell"
"-command"
(format "Get-ItemProperty HKLM:%s | Select-Object DisplayName, DisplayVersion, InstallLocation | ConvertTo-Json"
reg-key))
:out
json/parse-string))
reg-keys))))

(def windows-software-list (memoize windows-software-list*))

(defmulti resolve-tool :type)

(defmethod resolve-tool :win-package
[{:keys [app]}]
(if-let [found-package (->> (windows-software-list)
(filter (fn [p]
(when-let [pname (get p "DisplayName")]
(if (string? app)
(= app pname)
(re-matches app pname)))))
first)]
{:app (get found-package "InstallLocation" "?")
:version (get found-package "DisplayVersion" "?")}
{:error (format "<windows package not found: %s>" app)}))

(defmethod resolve-tool :mac-app
[{:keys [app shell-opts version-post-fn]}]
(let [app-dir (format "/Applications/%s.app" app)]
(if (fs/exists? app-dir)
{:app app-dir
:version
(->> (tasks/shell shell-opts (format "defaults read '%s/Contents/Info' CFBundleShortVersionString" app-dir))
(version-cmd-result shell-opts)
version-post-fn)}
{:error (format "<mac app not found: %s>" app)})))

(defmethod resolve-tool :bin
[{:keys [app shell-opts args version-post-fn]}]
(if-let [found-bin (some-> (fs/which app {:win-exts ["com" "exe" "bat" "cmd" "ps1"]})
str)]
{:app found-bin
:version (->> (if (string/ends-with? found-bin ".ps1")
(tasks/shell shell-opts "powershell" "-command" found-bin args)
(tasks/shell shell-opts found-bin args))
(version-cmd-result shell-opts)
version-post-fn)}
{:error (format "<bin not found: %s>" app)}))

(defn report
"Report on tools versions based the the OS the script it is run from.
Currently informational only, should always return 0 unless, of course,
something exceptional happens."
[]
(->> (for [{:keys [name] :as t} (map #(merge tool-defaults %) tools)
:when (expected-on-this-os t)
:let [{:keys [error app version]} (resolve-tool t)]]
(if error
{:name name :version error}
{:name name :app app :version version}))
table-multilines->rows
(doric/table [:name :version :app])
println))