distribute.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/local/bin/node
  2. const ora = require("ora");
  3. const request = require("request");
  4. const fs = require("fs");
  5. const path = require("path");
  6. const ProgressBar = require("progress");
  7. const spawn = require("cross-spawn");
  8. const parser = require("fast-xml-parser");
  9. const config = parser.parse(
  10. fs.readFileSync(path.resolve(__dirname, "config.xml")).toString(),
  11. { ignoreAttributes: false }
  12. );
  13. const post = (url, data) => {
  14. return new Promise((resolve, reject) => {
  15. request.post({ url, ...data }, (err, httpResponse, body) => {
  16. if (err) {
  17. reject(err);
  18. } else {
  19. resolve(body);
  20. }
  21. });
  22. });
  23. };
  24. const apkDir = path.resolve(
  25. __dirname,
  26. "platforms/android/app/build/outputs/apk/release/app-release.apk"
  27. );
  28. let spinner;
  29. function exec(cmd, args, options) {
  30. return new Promise((resolve, reject) => {
  31. var s = spawn(cmd, args, options);
  32. s.stdout.on("data", function (s) {});
  33. s.stderr.on("data", function (s) {
  34. //console.error(s.toString());
  35. //reject(s.toString())
  36. });
  37. s.on("close", (code) => {
  38. if (code == 0) {
  39. resolve();
  40. } else {
  41. reject();
  42. }
  43. });
  44. });
  45. }
  46. const cwd = path.resolve(__dirname);
  47. const vueDir = path.resolve(__dirname, "vue");
  48. spinner = ora("prepare").start();
  49. exec("cordova", ["prepare"], { cwd: cwd })
  50. .then((res) => {
  51. spinner.succeed("prepare success");
  52. spinner.start("building android apk");
  53. return exec(
  54. "cordova",
  55. [
  56. "build",
  57. "android",
  58. "--release",
  59. "--",
  60. `--keystore=${(path.resolve(__dirname), "zouma.jks")}`,
  61. "--storePassword=zouma123",
  62. "--password=zouma123",
  63. "--alias=zouma",
  64. ],
  65. { cwd: cwd }
  66. );
  67. })
  68. .then((res) => {
  69. spinner.succeed("apk build success");
  70. var bar = new ProgressBar(
  71. " uploading apk [:bar] :rateKb/s :percent :etas",
  72. {
  73. complete: "=",
  74. incomplete: " ",
  75. width: 20,
  76. total: fs.statSync(apkDir).size / 1000,
  77. clear: true,
  78. }
  79. );
  80. return post("http://api.bq04.com/apps/", {
  81. json: {
  82. type: "android",
  83. bundle_id: config.widget["@_id"],
  84. api_token: "b25f2b5fe65704df8b8b1fe866aaea05",
  85. },
  86. }).then((res) => {
  87. return Promise.all([
  88. post(res.cert.icon.upload_url, {
  89. formData: {
  90. key: res.cert.icon.key,
  91. token: res.cert.icon.token,
  92. file: fs.createReadStream(
  93. path.resolve(__dirname, "res/icon/android/icon-xxxhdpi.png")
  94. ),
  95. },
  96. }),
  97. post(res.cert.binary.upload_url, {
  98. formData: {
  99. key: res.cert.binary.key,
  100. token: res.cert.binary.token,
  101. file: fs
  102. .createReadStream(apkDir)
  103. .on("data", (chunk) => {
  104. bar.tick(chunk.length / 1000);
  105. }),
  106. "x:name": config.widget.name,
  107. "x:version": config.widget["@_version"],
  108. "x:build": config.widget["@_android-versionCode"],
  109. },
  110. }),
  111. ]);
  112. });
  113. })
  114. .then((res) => {
  115. spinner.succeed("apk upload success");
  116. console.log(res);
  117. })
  118. .catch((e) => {
  119. console.log(e);
  120. spinner.fail("fail");
  121. spinner.stop();
  122. });