Skip to content

Instantly share code, notes, and snippets.

@Dixzz
Created December 7, 2023 10:06
Show Gist options
  • Save Dixzz/412ac0019a40edcab468c2067cd3b65a to your computer and use it in GitHub Desktop.
Save Dixzz/412ac0019a40edcab468c2067cd3b65a to your computer and use it in GitHub Desktop.
Auto build, sign and upload to slack bot for further process (can be changed as per your favorite client)
// add to bottom of your app gradle config file
apply from: 'uploader.gradle'
// create new file in app directory
import java.nio.file.Files
// class can be put seperate file
class MultipartUtilityV2 {
private HttpURLConnection httpConn;
private DataOutputStream request;
private final int timeout = 120 * 1000;
private final String boundary = "//";
private final String crlf = "\r\n";
private final String charset = "UTF-8";
private final String twoHyphens = "--";
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
*
* @param requestURL
* @throws IOException
*/
MultipartUtilityV2(String requestURL)
throws IOException {
// creates a unique boundary based on time stamp
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
httpConn.setConnectTimeout(timeout)
httpConn.setChunkedStreamingMode(0)
registerHeader("Connection", "Keep-Alive");
registerHeader("Cache-Control", "no-cache");
registerHeader("Content-Type", "multipart/form-data;boundary=${this.boundary}");
}
void connect(){
request = new DataOutputStream(httpConn.getOutputStream());
}
void registerHeader(String key, String value) {
httpConn.setRequestProperty(key, value)
}
/**
* Adds a form field to the request
*
* @param name field name
* @param value field value
*/
void addFormField(String name, String value) throws IOException {
request.writeBytes(this.twoHyphens + this.boundary + this.crlf);
request.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"" + this.crlf);
request.writeBytes("Content-Type: text/plain; charset=${this.charset}" + this.crlf);
request.writeBytes(this.crlf);
request.writeBytes(value + this.crlf);
request.flush();
}
/**
* Adds a upload file section to the request
*
* @param fieldName name attribute in <input type="file" name="..." />
* @param uploadFile a File to be uploaded
* @throws IOException
*/
void addFilePart(String fieldName, File uploadFile)
throws IOException {
String fileName = uploadFile.getName();
request.writeBytes(this.twoHyphens + this.boundary + this.crlf);
request.writeBytes("Content-Disposition: form-data; name=\"" +
fieldName + "\";filename=\"" +
fileName + "\"" + this.crlf);
request.writeBytes(this.crlf);
// vm RAM goes poof +__+
try {
byte[] bytes = Files.readAllBytes(uploadFile.toPath());
request.write(bytes);
} catch (OutOfMemoryError ignored) {
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(uploadFile))
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
request.write(buffer, 0, bytesRead);
}
}
}
/**
* Completes the request and receives response from the server.
*
* @return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* @throws IOException
*/
String finish() throws IOException {
def response = ""
request.writeBytes(this.crlf);
request.writeBytes(this.twoHyphens + this.boundary + this.crlf);
request.flush();
request.close();
// checks server's status code first
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedInputStream responseStream = new BufferedInputStream(httpConn.getInputStream());
BufferedReader responseStreamReader =
new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
response = stringBuilder.toString();
httpConn.disconnect();
} else {
println("Server returned non-OK status: " + status)
}
return response;
}
}
ext.uploaderFiles = { uploadFile1 ->
def post = "https://slack.com/api/files.upload"
def flavorName = "debugStaging"
println("Checking file in ${uploadFile1.path}")
println("$flavorName, Last modified: ${new Date(uploadFile1.lastModified())}")
try {
MultipartUtilityV2 multipart = new MultipartUtilityV2(post);
def key = System.getenv("key")
def chatId = System.getenv("chatId")
multipart.registerHeader("Authorization", "Bearer $key");
multipart.connect()
multipart.addFormField("channels", "$chatId")
multipart.addFormField("filetype", "apk");
multipart.addFilePart("file", uploadFile1);
println("SERVER REPLIED: ${multipart.finish()}");
} catch (IOException ex) {
println("ERROR: " + ex.getMessage());
ex.printStackTrace();
}
}
println("Gawd ${tasks.getByName('build')} ${tasks.getByName('preBuild')}")
tasks.named('build') {
print("Found task ${it.name}, signing for ${rootProject.name}:${project.name} ${it.outputs.getFiles().getAsPath()}")
def final store_file = rootProject.file('X.jks')
android {
signingConfigs {
debugStaging {
storeFile store_file
storePassword 'XXXX'
keyAlias 'XXXX'
keyPassword 'XXXX'
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
debugStaging {
signingConfig signingConfigs.debugStaging
}
}
}
}
// Deferred task
tasks.register('uploadFile') {
def variant = 'DebugStaging'
mustRunAfter('assemble'+variant)
dependsOn('assemble'+variant)
final def firstChar = variant.charAt(0).toString()
variant = variant.replaceFirst(firstChar, firstChar.toLowerCase())
doLast {
def final apk = file("build/outputs/apk/${variant}/app-${variant}.apk")
if (!apk.exists()) throw GradleException("File not found at ${apk.absolutePath}")
uploaderFiles(apk)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment