diff --git a/scripts/release.js b/scripts/release.js index 86a81591..9a5db066 100755 --- a/scripts/release.js +++ b/scripts/release.js @@ -1,157 +1,76 @@ require("dotenv").config() +// dependencies const packagejson = require("../package.json") - const path = require("path") const fs = require("fs") const child_process = require("child_process") const { Octokit } = require("@octokit/rest") -const sevenzip = require("7zip-min") -const axios = require("axios") +// utils +const compressDistBundle = require("./utils/compressDistBundle") +const buildAppDist = require("./utils/buildAppDist") +const createGithubRelease = require("./utils/createGithubRelease") +const uploadAssets = require("./utils/uploadAssets") +const composeChangelog = require("./utils/composeChangelog") +const bumpVersion = require("./utils/bumpVersion") + +// constants & paths const repo = "ragestudio/comty" const appSrcPath = path.resolve(process.cwd(), "packages/app/src") const appDistPath = path.resolve(process.cwd(), "packages/app/dist") const changelogsPath = path.resolve(process.cwd(), "changelogs") - -const octokit = new Octokit({ - auth: process.env.GITHUB_TOKEN -}) - -const composeChangelog = require("./utils/composeChangelog") -const bumpVersion = require("./utils/bumpVersion") - -async function createGithubRelease(payload) { - if (process.argv.includes("--noPublish")) { - console.log("🔥 Skipping release creation due to `noPublish` argument") - return true - } - - const { version, changelog } = payload - - const response = await axios({ - method: "post", - url: `https://api.github.com/repos/${repo}/releases`, - headers: { - "Authorization": `token ${process.env.GITHUB_TOKEN}`, - "Content-Type": "application/json" - }, - data: { - tag_name: version, - name: `v${version}`, - body: changelog - } - }) - - console.log("⚒ Creating release done!") - - return response.data -} - -async function createAppDistBundle() { - // check if has `noBuild` argument - if (process.argv.includes("--noBuild")) { - console.log("🔥 Skipping build due to `noBuild` argument") - return true - } - - // build app for production - console.log("⚒ Building app...") - await child_process.execSync("yarn build", { - cwd: appSrcPath, - stdio: "inherit" - }) - console.log("⚒ Building app done!") - - return appDistPath -} - -async function compressDistBundle() { - const outPath = path.resolve(appDistPath, "../app_dist.7z") - - if (process.argv.includes("--noCompress") || process.argv.includes("--noBuild")) { - console.log("🔥 Skipping compress due to `noBuild` or `noCompress` argument") - return outPath - } - - // compress with 7zip - console.log("⚒ Compressing app...") - - // check if out file exists - if (fs.existsSync(outPath)) { - fs.unlinkSync(outPath) - } - - await new Promise((resolve, reject) => { - sevenzip.pack(appDistPath, outPath, (err) => { - if (err) { - return reject(err) - } - - return resolve(outPath) - }) - }) - - console.log("⚒ Compressing app done! > " + outPath) - - return outPath -} - -async function uploadAssets({ release, bundlePath, changelogFilepath }) { - // check if has `noPublish` argument, if true, skip uploading assets - if (process.argv.includes("--noPublish")) { - console.log("🔥 Skipping upload assets due to `noPublish` argument") - return true - } - - console.log("⚒ Uploading assets...") - - console.log(`ReleaseID: ${release.id}`) - - const appDistAsset = await octokit.repos.uploadReleaseAsset({ - release_id: release.id, - owner: repo.split("/")[0], - repo: repo.split("/")[1], - name: "app_dist.7z", - data: fs.readFileSync(bundlePath) - }) - - const changelogAsset = await octokit.repos.uploadReleaseAsset({ - release_id: release.id, - owner: repo.split("/")[0], - repo: repo.split("/")[1], - name: "changelog.md", - data: fs.readFileSync(changelogFilepath) - }) - - if (!appDistAsset) { - return false - } - - if (!changelogAsset) { - return false - } - - console.log("⚒ Uploading assets done!") - - return true -} +const packedDistPath = path.resolve(appDistPath, "dist.zip") async function main() { - // check if no GITHUB_TOKEN env if (!process.env.GITHUB_TOKEN) { console.error("🆘 Missing GITHUB_TOKEN env") return false } - // check if is any changes pending to commit - const gitStatus = child_process.execSync("git status --porcelain", { - cwd: process.cwd() - }).toString().trim() + const octokit = new Octokit({ + auth: process.env.GITHUB_TOKEN + }) - if (gitStatus.length > 0 && !process.argv.includes("--ignore-commits")) { - console.error("🆘 There are pending changes to commit, please commit first.") - return false + let steps = { + build: true, + bundle: true, + publish: true, + ignoreCommits: false, + ignoreVersion: false, + changelog: true, + } + + if (process.argv.includes("--no-pack")) { + steps.bundle = false + } + + if (process.argv.includes("--no-publish")) { + steps.publish = false + } + + if (process.argv.includes("--no-build")) { + steps.build = false + } + + if (process.argv.includes("--ignore-commits")) { + steps.ignoreCommits = true + } + + if (process.argv.includes("--ignore-version")) { + steps.ignoreVersion = true + } + + // check if is any changes pending to commit + if (!steps.ignoreCommits) { + const gitStatus = child_process.execSync("git status --porcelain", { + cwd: process.cwd() + }).toString().trim() + + if (gitStatus.length > 0) { + console.warn("There are pending changes to commit, please commit first.") + return false + } } let currentVersion = packagejson.version @@ -165,76 +84,111 @@ async function main() { return false }) - if (latestRelease && latestRelease.data.tag_name === currentVersion && !process.argv.includes("--force")) { - if (process.argv.includes("--bump")) { - const bumpType = process.argv[process.argv.indexOf("--bump") + 1] + if (!latestRelease) { + console.error("🆘 Failed to get latest release") + return false + } - const newVersion = await bumpVersion({ - root: process.cwd(), - type: bumpType, - count: 1 - }).catch((error) => { - console.error(`🆘 Failed to bump version >`, error) - return false - }) + if (!steps.ignoreVersion) { + if (latestRelease && latestRelease.data.tag_name === currentVersion) { + if (process.argv.includes("--bump")) { + const bumpType = process.argv[process.argv.indexOf("--bump") + 1] - if (!newVersion) { - throw new Error("Failed to bump version") + const newVersion = await bumpVersion({ + root: process.cwd(), + type: bumpType, + count: 1 + }).catch((error) => { + console.error(`🆘 Failed to bump version >`, error) + return false + }) + + if (!newVersion) { + throw new Error("Failed to bump version") + } + + currentVersion = newVersion + + // create new commit + await child_process.execSync(`git add . && git commit -m "Bump version to ${currentVersion}"`, { + cwd: process.cwd(), + stdio: "inherit" + }) + + // push to remote + await child_process.execSync(`git push`, { + cwd: process.cwd(), + stdio: "inherit" + }) + } else { + console.log("🚫 Current version is already latest version, please bump version first. \n - use --bump to automatically bump version. \n - use --ignore-version to force release.") + return true } - - currentVersion = newVersion - - // create new commit - await child_process.execSync(`git add . && git commit -m "Bump version to ${currentVersion}"`, { - cwd: process.cwd(), - stdio: "inherit" - }) - - // push to remote - await child_process.execSync(`git push`, { - cwd: process.cwd(), - stdio: "inherit" - }) - } else { - console.log("🚫 Current version is already latest version, please bump version first. \n - use --bump to automatically bump version. \n - use --force to force release.") - return true } } - if (!latestRelease) return + if (steps.build) { + steps.build = await buildAppDist(appSrcPath) + } - await createAppDistBundle() + if (steps.bundle) { + steps.bundle = await compressDistBundle(appDistPath, packedDistPath) + } - const bundlePath = await compressDistBundle() + if (steps.changelog) { + const changelog = await composeChangelog() - const changelog = await composeChangelog() + steps.changelog = path.resolve(changelogsPath, `v${currentVersion.split(".").join("-")}.md`) - const changelogFilepath = path.resolve(changelogsPath, `v${currentVersion.split(".").join("-")}.md`) + console.log(`📝 Writing changelog to file > ${steps.changelog}`) - console.log(`📝 Writing changelog to file > ${changelogFilepath}`) + // write changelog to file + fs.writeFileSync(steps.changelog, changelog) + } - // write changelog to file - fs.writeFileSync(changelogFilepath, changelog) + if (steps.publish) { + const release = await createGithubRelease( + repo, + { + version: currentVersion, + changelog, + }, + process.env.GITHUB_TOKEN, + ).catch((err) => { + console.error(`🆘 Failed to create release: ${err}`) + return false + }) - const release = await createGithubRelease({ - version: currentVersion, - changelog, - }).catch((err) => { - console.error(`🆘 Failed to create release: ${err}`) - return false - }) + console.log("🎉 Release done!") - if (!release) return + if (!release) { + return false + } - const assets = await uploadAssets({ release, bundlePath, changelogFilepath }).catch((err) => { - console.error(`🆘 Failed to upload asset: ${err}`, err.response) - return false - }) + const assets = await uploadAssets( + octokit, + repo, + release, + [ + { + name: packedDistPath, + data: fs.readFileSync(packedDistPath) + }, + { + name: "changelog.md", + data: fs.readFileSync(steps.changelog) + } + ], + ) - if (!assets) return + console.log("🎉 Assets uploaded! >", assets) - console.log("🎉 Release done!") - console.log(`🔗 ${release.html_url}`) + console.log(`🔗 ${release.html_url}`) + } + + console.log("All Done!") + + return true } main().catch((err) => { diff --git a/scripts/utils/buildAppDist.js b/scripts/utils/buildAppDist.js new file mode 100644 index 00000000..10c10f5c --- /dev/null +++ b/scripts/utils/buildAppDist.js @@ -0,0 +1,15 @@ +const child_process = require("child_process") + +async function buildAppDist(srcPath) { + // build app for production + console.log("⚒ Building app...") + await child_process.execSync("yarn build", { + cwd: srcPath, + stdio: "inherit" + }) + console.log("⚒ Building app done!") + + return srcPath +} + +module.exports = buildAppDist \ No newline at end of file diff --git a/scripts/utils/compressDistBundle.js b/scripts/utils/compressDistBundle.js new file mode 100644 index 00000000..44fa77c1 --- /dev/null +++ b/scripts/utils/compressDistBundle.js @@ -0,0 +1,28 @@ +const fs = require("fs") +const sevenzip = require("7zip-min") + +async function compressDistBundle(origin, output) { + // compress with 7zip + console.log("⚒ Compressing app...") + + // check if out file exists + if (fs.existsSync(output)) { + fs.unlinkSync(output) + } + + await new Promise((resolve, reject) => { + sevenzip.pack(origin, output, (err) => { + if (err) { + return reject(err) + } + + return resolve(output) + }) + }) + + console.log("⚒ Compressing app done! > " + output) + + return output +} + +module.exports = compressDistBundle \ No newline at end of file diff --git a/scripts/utils/createGithubRelease.js b/scripts/utils/createGithubRelease.js new file mode 100644 index 00000000..f3c43ae0 --- /dev/null +++ b/scripts/utils/createGithubRelease.js @@ -0,0 +1,25 @@ +const axios = require("axios") + +async function createGithubRelease(repo, payload, token) { + const { version, changelog } = payload + + const response = await axios({ + method: "post", + url: `https://api.github.com/repos/${repo}/releases`, + headers: { + "Authorization": `token ${token}`, + "Content-Type": "application/json" + }, + data: { + tag_name: version, + name: `v${version}`, + body: changelog + } + }) + + console.log("⚒ Creating release done!") + + return response.data +} + +module.exports = createGithubRelease \ No newline at end of file diff --git a/scripts/utils/uploadAssets.js b/scripts/utils/uploadAssets.js new file mode 100644 index 00000000..1b4837ba --- /dev/null +++ b/scripts/utils/uploadAssets.js @@ -0,0 +1,23 @@ +async function uploadAssets(octokit, repo, release, assets, { release, bundlePath, changelogFilepath }) { + console.log("⚒ Uploading assets...") + + console.log(`ReleaseID: ${release.id}`) + + for await (const asset of assets) { + console.log(`Uploading Asset: ${asset.name}`) + + await octokit.repos.uploadReleaseAsset({ + release_id: release.id, + owner: repo.split("/")[0], + repo: repo.split("/")[1], + name: asset.name, + data: asset.data + }) + } + + console.log("⚒ Uploading assets done!") + + return true +} + +module.exports = uploadAssets \ No newline at end of file