Skip to content

Commit

Permalink
Release automation (#164)
Browse files Browse the repository at this point in the history
* add auto-release script

* Add auto-release script

* more verbose output

* add script to package.json

* fix message text

* remove extra console.log

* fix: make script more readable

* add comment

* Update scripts/auto-release/index.mjs

Co-authored-by: IlyaIzr <[email protected]>

Co-authored-by: IlyaIzr <[email protected]>
  • Loading branch information
Akiyamka and IlyaIzr authored Sep 15, 2022
1 parent 3163b8a commit 8cb74ab
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 1 deletion.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"auto:cosmos:export": "patch-package && cosmos-export --config cosmos.config.export.json",
"auto:cosmos:renderer": "vite --config cosmos.vite.config.ts --force serve --port=8080",
"auto:cosmos:renderer:export": "vite build --config cosmos.vite.config.ts",
"link:ui-kit": "npm link @konturio/ui-kit @konturio/default-theme @konturio/default-icons"
"link:ui-kit": "npm link @konturio/ui-kit @konturio/default-theme @konturio/default-icons",
"release": "node ./scripts/auto-release/index.mjs"
},
"lint-staged": {
"*/**/*.{ts,tsx}": [
Expand Down
10 changes: 10 additions & 0 deletions scripts/auto-release/git-utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { execSync as exec } from 'child_process';

export default {
currentBrunch: () => exec('git rev-parse --abbrev-ref HEAD').toString().trim(),
status: () => exec('git status').toString(),
createAndCheckoutToBranch: (branch) => exec(`git checkout -b ${branch}`).toString(),
add: () => exec(`git add .`),
commit: (message) => exec(`git commit -m "${message}"`),
push: () => exec(`git push`),
};
70 changes: 70 additions & 0 deletions scripts/auto-release/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import chalk from 'chalk';
import git from './git-utils.mjs';
import prompts from './prompts.mjs';
import npm from './npm-utils.mjs';

/**
* This script allows you to create release branch by npm run release command only when
* • you're on main
* • main is sync with remote
* • no unmerged releases right now
* also it:
* • creates branch
* • increases version in package.lock and package.json
* • creates commit
* • pushes branch
*/
async function createRelease() {
// Check branch
if (git.currentBrunch() !== 'main')
throw new Error('You should create release from main branch');
// Check status
if (!git.status().includes('nothing to commit, working tree clean'))
throw new Error('You should pull/push changes before');
// Check PR
if (!(await prompts.askConfirmation('The repository has an unmerged release?'))) {
throw new Error('You should merge or close previous release');
}
// Ask new version
const packageJSON = npm.readPackageJSON();

const version = await prompts.askVersion(
'New version is:',
[
{ title: 'major', value: 'major', description: 'Add breaking changes' },
{ title: 'minor', value: 'minor', description: 'Add new features' },
{ title: 'patch', value: 'patch', description: 'Add bugfix' },
],
{ currentVersion: packageJSON.version, default: 'minor' },
);

// Create release branch
console.log('Creating release branch, please wait\n');
const branchName = `${release}-version`;
git.createAndCheckoutToBranch(branchName);

// Update package.json
npm.savePackageJSON({
...packageJSON,
version,
});

// Update package.lock.json
npm.fixLockFile();

// Git push
git.add('.');
git.commit(`Version ${version}`);
git.push();

// Final message
console.log(
chalk.greenBright(`Success! You can now open a pull request by the link above`),
);
}

try {
await createRelease();
} catch (e) {
console.log(chalk.redBright(e.message));
}
9 changes: 9 additions & 0 deletions scripts/auto-release/npm-utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { execSync as exec } from 'child_process';
import { readFileSync, writeFileSync } from 'node:fs';
import { resolve } from 'node:path';

export default {
readPackageJSON: () => JSON.parse(readFileSync(resolve('package.json'))),
savePackageJSON: (json) => writeFileSync(resolve('package.json'), JSON.stringify(json, null, 2)),
fixLockFile: () => exec('npm i --package-lock-only')
};
45 changes: 45 additions & 0 deletions scripts/auto-release/prompts.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import prompts from 'prompts';
import semver from 'semver';
import chalk from 'chalk';

async function askConfirmation(question) {
const answers = await prompts([
{
type: 'confirm',
name: 'haveUnmergedRelease',
message: question,
},
]);
return answers.haveUnmergedRelease
}

async function askVersion(question, variants, options) {
const { version, versionConfirmed } = await prompts([
{
type: 'select',
name: 'version',
message: question,
initial: options.variants.find(v => v.value === options.default) ?? 0,
choices: variants,
format: (releaseType) => semver.inc(options.currentVersion, releaseType),
},
{
type: 'confirm',
name: 'versionConfirmed',
message: (nextVersion) =>
`Update version from ${chalk.yellowBright(
options.currentVersion,
)} to ${chalk.yellowBright(nextVersion)} ?`,
},
]);
if (versionConfirmed) {
throw new Error('Canceled by user');
}

return version;
}

export default {
askConfirmation,
askVersion
}

0 comments on commit 8cb74ab

Please sign in to comment.