add enterprise release publisher

master
Florian Schrofner 2023-01-19 18:16:15 +01:00
parent 08d8a290f1
commit f95b7ccd7d
2 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,73 @@
#! /usr/bin/bb
(require '[babashka.curl :as curl])
;;gets the working directory, but removes the new line in the end
(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]
"creates a os independent path string"
(str/join fs/file-separator segments))
(defn- get-output-folder [module variant]
"creates the path string of the output folder for the given 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))

View File

@ -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
```