mirror of
https://github.com/laurent22/joplin.git
synced 2024-11-24 08:12:24 +02:00
Automate building and deploying Android app
This commit is contained in:
parent
1a5c8d126d
commit
6ff67e0995
4
.gitignore
vendored
4
.gitignore
vendored
@ -35,4 +35,6 @@ _vieux/
|
||||
_mydocs
|
||||
.DS_Store
|
||||
Assets/DownloadBadges*.psd
|
||||
node_modules
|
||||
node_modules
|
||||
Tools/github_oauth_token.txt
|
||||
_releases
|
@ -75,7 +75,7 @@ apply from: "../../node_modules/react-native/react.gradle"
|
||||
* Upload all the APKs to the Play Store and people will download
|
||||
* the correct one based on the CPU architecture of their device.
|
||||
*/
|
||||
def enableSeparateBuildPerCPUArchitecture = true
|
||||
def enableSeparateBuildPerCPUArchitecture = false
|
||||
|
||||
/**
|
||||
* Run Proguard to shrink the Java bytecode in release builds.
|
||||
@ -137,11 +137,11 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':react-native-securerandom')
|
||||
compile project(':react-native-push-notification')
|
||||
compile project(':react-native-fs')
|
||||
compile project(':react-native-image-picker')
|
||||
compile project(':react-native-vector-icons')
|
||||
compile project(':react-native-securerandom')
|
||||
compile project(':react-native-push-notification')
|
||||
compile project(':react-native-fs')
|
||||
compile project(':react-native-image-picker')
|
||||
compile project(':react-native-vector-icons')
|
||||
compile project(':react-native-fs')
|
||||
compile fileTree(dir: "libs", include: ["*.jar"])
|
||||
compile "com.android.support:appcompat-v7:23.0.1"
|
||||
|
@ -36,7 +36,7 @@ class FsDriverRN {
|
||||
return {
|
||||
birthtime: r.ctime, // Confusingly, "ctime" normally means "change time" but here it's used as "creation time"
|
||||
mtime: r.mtime,
|
||||
isDirectory: () => return r.isDirectory(),
|
||||
isDirectory: () => r.isDirectory(),
|
||||
path: path,
|
||||
};
|
||||
}
|
||||
|
13
Tools/package-lock.json
generated
13
Tools/package-lock.json
generated
@ -73,6 +73,11 @@
|
||||
"is-stream": "1.1.0"
|
||||
}
|
||||
},
|
||||
"pct-encode": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pct-encode/-/pct-encode-1.0.2.tgz",
|
||||
"integrity": "sha1-uZt7BE1r18OeSDmnqAEirXUVyqU="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
@ -82,6 +87,14 @@
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
|
||||
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc="
|
||||
},
|
||||
"uri-template": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-template/-/uri-template-1.0.1.tgz",
|
||||
"integrity": "sha1-FKklo35Nk/diVDKqEWsF5Qyuga0=",
|
||||
"requires": {
|
||||
"pct-encode": "1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
"gettext-parser": "^1.3.0",
|
||||
"marked": "^0.3.7",
|
||||
"mustache": "^2.3.0",
|
||||
"node-fetch": "^1.7.3"
|
||||
"node-fetch": "^1.7.3",
|
||||
"uri-template": "^1.0.1"
|
||||
}
|
||||
}
|
||||
|
132
Tools/release-android.js
Normal file
132
Tools/release-android.js
Normal file
@ -0,0 +1,132 @@
|
||||
const fs = require('fs-extra');
|
||||
const { execCommand } = 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 githubOauthToken() {
|
||||
const r = await fs.readFile(rootDir + '/Tools/github_oauth_token.txt');
|
||||
return r.toString();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const oauthToken = await githubOauthToken();
|
||||
|
||||
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/joplin/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\/releases\/download\/.*?\.apk)/, downloadUrl);
|
||||
await fs.writeFile('README.md', readmeContent);
|
||||
|
||||
await execCommand('git add -A');
|
||||
await execCommand('git commit -m "Android release v' + version + '"');
|
||||
await execCommand('git tag ' + tagName);
|
||||
await execCommand('git push');
|
||||
await execCommand('git push --tags');
|
||||
|
||||
console.info('Creating GitHub release ' + tagName + '...');
|
||||
|
||||
const response = await fetch('https://api.github.com/repos/laurent22/joplin/releases', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
tag_name: tagName,
|
||||
name: tagName,
|
||||
draft: true,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'token ' + oauthToken,
|
||||
},
|
||||
});
|
||||
|
||||
const responseText = await response.text();
|
||||
const responseJson = JSON.parse(responseText);
|
||||
if (!responseJson.upload_url) throw new Error('No upload URL for release: ' + responseText);
|
||||
|
||||
const uploadUrlTemplate = uriTemplate.parse(responseJson.upload_url);
|
||||
const uploadUrl = uploadUrlTemplate.expand({ name: apkFilename });
|
||||
|
||||
const binaryBody = await fs.readFile(apkFilePath);
|
||||
|
||||
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);
|
||||
});
|
Loading…
Reference in New Issue
Block a user