const fs = require("fs-extra"); const { execCommand, githubRelease, githubOauthToken } = require("./tool-utils.js"); const path = require("path"); const fetch = require("node-fetch"); const uriTemplate = require("uri-template"); const rnDir = __dirname + "/../ReactNativeClient"; const rootDir = path.dirname(__dirname); const releaseDir = rootDir + "/_releases"; function increaseGradleVersionCode(content) { const newContent = content.replace(/versionCode\s+(\d+)/, function(a, versionCode, c) { const n = Number(versionCode); if (isNaN(n) || !n) throw new Error("Invalid version code: " + versionCode); return "versionCode " + (n + 1); }); if (newContent === content) throw new Error("Could not update version code"); return newContent; } function increaseGradleVersionName(content) { const newContent = content.replace(/(versionName\s+"\d+?\.\d+?\.)(\d+)"/, function(match, prefix, buildNum) { const n = Number(buildNum); if (isNaN(n) || !n) throw new Error("Invalid version code: " + versionCode); return prefix + (n + 1) + '"'; }); if (newContent === content) throw new Error("Could not update version name"); return newContent; } function updateGradleConfig() { let content = fs.readFileSync(rnDir + "/android/app/build.gradle", "utf8"); content = increaseGradleVersionCode(content); content = increaseGradleVersionName(content); fs.writeFileSync(rnDir + "/android/app/build.gradle", content); return content; } function gradleVersionName(content) { const matches = content.match(/versionName\s+"(\d+?\.\d+?\.\d+)"/); if (!matches || matches.length < 1) throw new Error("Cannot get gradle version name"); return matches[1]; } async function main() { const projectName = "joplin-android"; const newContent = updateGradleConfig(); const version = gradleVersionName(newContent); const tagName = "android-v" + version; const apkFilename = "joplin-v" + version + ".apk"; const apkFilePath = releaseDir + "/" + apkFilename; const downloadUrl = "https://github.com/laurent22/" + projectName + "/releases/download/" + tagName + "/" + apkFilename; process.chdir(rootDir); console.info("Running from: " + process.cwd()); console.info("Building APK file..."); const output = await execCommand('/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat assembleRelease -PbuildDir=build --console plain"'); console.info(output); await fs.mkdirp(releaseDir); console.info("Copying APK to " + apkFilePath); await fs.copy("ReactNativeClient/android/app/build/outputs/apk/app-release.apk", apkFilePath); console.info("Updating Readme URL..."); let readmeContent = await fs.readFile("README.md", "utf8"); readmeContent = readmeContent.replace(/(https:\/\/github.com\/laurent22\/joplin-android\/releases\/download\/.*?\.apk)/, downloadUrl); await fs.writeFile("README.md", readmeContent); console.info(await execCommand("git pull")); console.info(await execCommand("git add -A")); console.info(await execCommand('git commit -m "Android release v' + version + '"')); console.info(await execCommand("git tag " + tagName)); console.info(await execCommand("git push")); console.info(await execCommand("git push --tags")); console.info("Creating GitHub release " + tagName + "..."); const release = await githubRelease(projectName, tagName, false); const uploadUrlTemplate = uriTemplate.parse(release.upload_url); const uploadUrl = uploadUrlTemplate.expand({ name: apkFilename }); const binaryBody = await fs.readFile(apkFilePath); const oauthToken = await githubOauthToken(); console.info("Uploading " + apkFilename + " to " + uploadUrl); const uploadResponse = await fetch(uploadUrl, { method: "POST", body: binaryBody, headers: { "Content-Type": "application/vnd.android.package-archive", Authorization: "token " + oauthToken, "Content-Length": binaryBody.length, }, }); const uploadResponseText = await uploadResponse.text(); console.info(uploadResponseText); } main().catch(error => { console.error("Fatal error"); console.error(error); });