Skip to content

Instantly share code, notes, and snippets.

@aviflax
Last active December 19, 2019 15:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aviflax/8645341be315d7f85ad415fe3614f277 to your computer and use it in GitHub Desktop.
Save aviflax/8645341be315d7f85ad415fe3614f277 to your computer and use it in GitHub Desktop.
Aborted attempt to simplify FC4 scripts that install sys deps for CI jobs — with ✨data✨!

System deps needed by scenario

Scenario Description Clojure? Java? Chrome/Chromium? Arch? Deb? Mac?
build Building the distribition package ✓ (11+)
lint Linting Clojure code ✓ (11+)
run Running dist pkg ✓ (8+)
test Testing from src ✓ (11+)
{;; Defines the set of packages that are supported in the scenarios, along with additional info.
:packages {:jre8 {}
:jre11 {}
:browser {}
:clojure {:version "1.10.1.492"}}
:stanzas {:install-clojure-linux
;; Steps copied from https://clojure.org/guides/getting_started#_installation_on_linux
["curl -O https://download.clojure.org/install/linux-install-1.10.1.492.sh"
"chmod +x linux-install-1.10.1.492.sh"
"sudo ./linux-install-1.10.1.492.sh"]}
;; Sequentials of sets of packages that are needed for each scenario, in the order they need to be
;; installed. Packages should be grouped together in a set if they can reasonably be installed at
;; the same time, i.e with a single command.
:packages-by-scenario {:testing [#{:browser :jre11} #{:clojure}]
:linting [#{:jre11} #{:clojure}]
:running [#{:browser :jre8}]} ;; TODO: this should be, somehow, jre8 OR jre11... hmm.
;; Specifications for how to install packages on various operating systems. nil means that we
;; don’t need it, so we can skip it.
:packages-by-os
{:mac {:jre8 nil ; already installed in CCI MacOS executors
:jre11 {:taps #{:AdoptOpenJDK/openjdk}
:casks #{:adoptopenjdk11-jre}}
:browser {:casks #{:chromium}}
:clojure {:packages #{:clojure}}}
:linux-arch {:jre8 nil ; we’re not currently using this configuration
:jre11 {:packages #{:jre11-openjdk-headless}}
:browser {:packages #{:chromium}}
:clojure {:stanzas #{:install-clojure-linux}}}
:linux-debian {:jre8 nil ; already installed in Docker image
:jre11 nil ; already installed in Docker image
:browser nil ; already installed in Docker image
:clojure {:stanza :install-clojure-linux}}}}
#!/usr/bin/env bb
;; This is an INCOMPLETE and UNTESTED [Babashka][babashka] script that generates shell scripts that install
;; all the packages, libraries, and apps needed by FC4 for a given scenario (CI job type) on a given OS.
;; [babashka]: https://github.com/borkdude/babashka
(ns fc4.ci.gen-install-sys-deps
(:require [clojure.edn :as edn]
[clojure.set :as set :refer [union]]
[clojure.string :as str :refer [join]]))
(def deps (edn/read-string (slurp "sys-deps.edn")))
(defn spec-sets
"Given an OS and a scenario, returns a sequential of spec-sets."
[os scenario]
; Using a list comprehension here rather than, say, select-keys, because we need to keep the specs
; in the order specified by packages-by-scenario.
(for [package-set (get-in deps [:packages-by-scenario scenario])]
(reduce
(fn [accum package] (conj accum (get-in deps [:packages-by-os os package])))
#{}
package-set)))
(defn kw->str
"Convert a keyword to a string, like name except preserves the namespace, if present; it just
removes the leading colon. e.g. :Foo/bar -> Foo/bar"
[kw]
(subs (str kw) 1))
(defn mac-spec-type->command
[t]
;; Using case rather than a map so it’ll blow up if something unexpected is encountered.
(case t :taps "tap"
:casks "cask"
:packages "install"))
(defn spec-set->mac-commands
[spec-set]
(->> (reduce #(merge-with union %1 %2) spec-set)
(map (fn [[spec-type vals]]
(format "brew %s %s"
(mac-spec-type->command spec-type)
(join " " (map kw->str vals)))))))
(defn spec-set->linux-arch-commands
[spec-set]
(->> (reduce #(merge-with union %1 %2) spec-set)
(map (fn [[spec-type vals]]
(case spec-type
:packages
(format "pacman --refresh --sync --needed --noconfirm --noprogressbar %s"
(join " " vals))
:stanzas
;; TODO: this `first` makes this brittle
(join "\n" (get-in deps [:stanzas (first vals)])))))))
(defn spec-set->linux-debian-commands [spec-set] "")
(defn spec-set->commands
"Given an os and :set-spec, returns a sequential of shell commands (as strings) for
installing the dependencies in the spec-set for the given os."
[os spec-set]
;; In regular Clojure this’d be a multimethod, but sci, the interpreter used by Babashka, does not
;; (yet) support multimethods. https://github.com/borkdude/sci
((case os
:mac spec-set->mac-commands
:linux-arch spec-set->linux-arch-commands
:linux-debian spec-set->linux-debian-commands)
spec-set))
(defn gen-script
[os scenario]
(->> (spec-sets os scenario)
(mapcat #(spec-set->commands os %))
(join "\n")))
(println (gen-script :linux-arch :running))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment