diff --git a/enterprise-release-publisher/erp.clj b/enterprise-release-publisher/erp.clj new file mode 100755 index 0000000..42accbb --- /dev/null +++ b/enterprise-release-publisher/erp.clj @@ -0,0 +1,71 @@ +#! /usr/bin/bb + +(require '[babashka.curl :as curl]) + +(def wd (as-> (:out (shell/sh "pwd")) $ + (subs $ 0 (- (count $) 1)))) +(def metadata-file "output-metadata.json") +(def config-file "enterprise-releases.json") + +(defn- create-path-string [& segments] + (str/join fs/file-separator segments)) + +(defn- get-output-folder [module variant] + (create-path-string wd module "build" "outputs" "apk" variant)) + +(defn- create-enterprise-release [module variant] + "builds the app using the given module & variant and then returns the parsed metadata" + (println "building project..") + (shell/sh (create-path-string wd "gradlew") (str ":" module ":assemble" (str/capitalize variant))) + (json/parse-string (slurp (create-path-string (get-output-folder module variant) metadata-file)) true)) + +(defn- fetch-remote-config [server path file-name] + "fetches and parses the configuration on the remote server" + (let [remote-path (str server path "/" file-name ".json")] + (println "fetching remote config..") + (json/parse-string (:body (curl/get remote-path)) true))) + +(defn- upload-version [config metadata] + "uploads the built apk and updates the remote json to reflect the new version" + (let [info (second config) + server (:server info) + path (:path info) + file-name (:fileName info) + output-folder (get-output-folder (:module info) (:variant info)) + output-file (create-path-string output-folder (get-in metadata [:elements 0 :outputFile])) + remote-config (fetch-remote-config server path file-name) + new-version (get-in metadata [:elements 0 :versionCode]) + version-name (get-in metadata [:elements 0 :versionName])] + (if (<= new-version (get-in remote-config [:android :version_code])) + (println "warning: version on remote was higher or the same as uploaded version")) + (println "uploading apk..") + (curl/post (str server path "/" file-name ".apk") {:raw-args ["-T" output-file]}) + (println "updating version on remote..") + (let [updated-remote-file (create-path-string output-folder (str file-name ".json"))] + (as-> remote-config $ + (update-in $ [:android :version_code] (fn [x] new-version)) + (json/generate-string $ {:pretty true}) + (spit updated-remote-file $)) + (curl/post (str server path "/" file-name ".json") {:raw-args ["-T" updated-remote-file]})) + (println (str "new version " version-name " (" new-version ")" " successfully uploaded to " (name (first config)))))) + +(defn- build-and-upload [config] + "builds & uploads the application based on the handed over configuration" + (let [info (second config) + module (:module info) + variant (:variant info)] + (as-> (create-enterprise-release module variant) $ + (upload-version config $)))) + +(def config (json/parse-string (slurp (create-path-string wd config-file)) true)) + +;;if there's only one config, pick that one +;;otherwise get the one specified as argument +(def selected-config + (if + (= (count config) 1) (first config) + (first (filter #(= (first %) (keyword (first *command-line-args*))) config)))) + +(if (nil? selected-config) + (println "error: no matching config found") + (build-and-upload selected-config)) diff --git a/enterprise-release-publisher/readme.md b/enterprise-release-publisher/readme.md new file mode 100644 index 0000000..25c7b05 --- /dev/null +++ b/enterprise-release-publisher/readme.md @@ -0,0 +1,59 @@ +# Enterprise Release Publisher +A script that reads the configuration file in your Android project, builds the defined module/variant combination and then uploads it to the specified server using the defined file name and also updates the JSON file on the remote with the same file name. + +## Configuration +To use the script for your project, you have to add a configuration file called `enterprise-releases.json` in the root of your project directory. +This file can contain multiple release configurations and needs to specify a couple of key values: +```json +{ + "DEV": { + "module": "app", + "variant": "debug", + "server": "sftp://127.0.0.1", + "path": "/var/www/apps/projects/test", + "fileName": "Enterprise-Test" + }, + "INT": { + "module": "app", + "variant": "release", + "server": "sftp://127.0.0.1", + "path": "/var/www/apps/projects/test", + "fileName": "Enterprise-Test" + } +} +``` +- `module`: specifies the module built with Gradle +- `variant`: the variant that should be built. it's combined with the module from above to create the proper Gradle command, e.g. `:app:assembleDebug` +- `server`: the server (including protocol) to upload the files to +- `path`: the path on the remote server where the files should be placed +- `fileName`: the name to be used for the apk & json files on the remote + +If there's only one release configuration defined, it will automatically pick that one. In case there are multiple configurations you have to add the configuration name you want to build & upload as argument (see examples below). + +## Example Usage +Simply execute the script in the root directory of your project, optionally specifying the configuration to use if there are multiple. +```bash +erp.clj +erp.clj "INT" +``` + +## +### SSH Configuration +I'm assuming that you've properly defined your credentials in `~/.ssh/config`, so you don't have to specify any credentials in your configuration files. You can assign specific credentials to different hosts there. + +``` +Host SERVER + User USER + IdentityFile PATH_TO_KEY +``` + +### Fish +If you don't want to add the script itself to your path you can also create a fish function to use it from any directory. + +``` +function erp + PATH_TO_SCRIPT/erp.clj $argv[1] +end + +funcsave erp +```