Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ssideleau committed Mar 12, 2019
0 parents commit dc6d8cf
Show file tree
Hide file tree
Showing 10 changed files with 3,355 additions and 0 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
parser: 'babel-eslint',
extends: 'airbnb-base',
rules: {
'class-methods-use-this': 0,
},
};
89 changes: 89 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@

# Created by https://www.gitignore.io/api/node
# Edit at https://www.gitignore.io/?templates=node

### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# End of https://www.gitignore.io/api/node

/build
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10.15
13 changes: 13 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const presets = [
[
"@babel/env",
{
targets: {
node: true,
},
useBuiltIns: "usage",
},
],
];

module.exports = { presets };
29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "react-native-set-version",
"version": "0.1.0",
"description": "Set the version in package.json, android/app/build.gradle",
"main": "index.js",
"author": "Novom Interactive",
"license": "UNLICENSED",
"scripts": {
"start": "node .src/index.js",
"build": "babel src --out-dir build"
},
"dependencies": {
"chalk": "^2.4.2",
"manifest-android": "^0.1.1"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"babel-eslint": "^10.0.1",
"eslint": "5.3.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "^2.14.0"
},
"bin": {
"setVersion": ".build/index.js",
"set-version": ".build/index.js"
}
}
78 changes: 78 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import AndroidManifest from 'manifest-android';
import chalk from 'chalk';
import fs from 'fs';

import { versionStringToVersion, versionToVersionCode } from './versionUtils';

const paths = {
packageJson: './package.json',
buildGradle: './android/app/build.gradle',
androidManifest: './android/app/src/main/AndroidManifest.xml',
};

const loadManifest = (manifest, path) => (
new Promise((resolve, reject) => {
manifest.load(path, (err, man) => {
if (err) {
return reject(err);
}
return resolve(man);
});
})
);

const changeVersion = async () => {
const display = console.log; // eslint-disable-line no-console

const versionText = process.argv[2];
const manifest = await loadManifest(new AndroidManifest(), { file: paths.androidManifest });
const currentVersionCode = +(manifest._xml.attributes['android:versionCode']); // eslint-disable-line no-underscore-dangle
const currentVersion = versionStringToVersion(manifest._xml.attributes['android:versionName']); // eslint-disable-line no-underscore-dangle
const version = versionStringToVersion(versionText, currentVersion, currentVersionCode);

const versionCode = versionToVersionCode(version);


display('');

display(chalk.yellow('Version info:'));
display(version); // eslint-disable-line no-console

display('');

display(chalk.yellow(`Will set version to ${chalk.bold.underline(versionText)}`));
display(chalk.yellow(`Will set version code to ${chalk.bold.underline(versionCode)}`));

display('');

const packageJSON = JSON.parse(fs.readFileSync(paths.packageJson));

packageJSON.version = versionText;

fs.writeFileSync(paths.packageJson, `${JSON.stringify(packageJSON, null, '\t')}\n`);
display(chalk.green(`Version replaced in ${chalk.bold('package.json')}`));

const buildGradle = fs.readFileSync(paths.buildGradle, 'utf8');

const newBuildGradle = buildGradle.replace(/versionCode \d+/g, `versionCode ${versionCode}`)
.replace(/versionName "[^"]*"/g, `versionName "${versionText}"`);

fs.writeFileSync(paths.buildGradle, newBuildGradle, 'utf8');
display(chalk.green(`Version replaced in ${chalk.bold('build.gradle')}`));

const androidManifest = fs.readFileSync(paths.androidManifest, 'utf8');

const newAndroidManifest = androidManifest.replace(/android:versionCode="\d*"/g, `android:versionCode="${versionCode}"`)
.replace(/android:versionName="[^"]*"/g, `android:versionName="${versionText}"`);

fs.writeFileSync(paths.androidManifest, newAndroidManifest, 'utf8');
display(chalk.green(`Version replaced in ${chalk.bold('AndroidManifest.xml')}`));

display('');

display(chalk.cyan.bold.underline('Do not forget to change your snapshots to reflect your new version number'));

display('');
};

changeVersion();
67 changes: 67 additions & 0 deletions src/tests/versionUtils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* eslint-disable no-undef */
/* eslint-disable camelcase */
import { versionStringToVersion, versionToVersionCode } from '../versionUtils';

const version0_4_0_2String = '0.4.0-alpha.2';
const version1_5_2String = '1.5.2';
const version10_12_3String = '10.12.3';

const version0_4_0 = {
major: 0,
minor: 4,
patch: 0,
build: 1,
};

const version0_4_0_2 = {
major: 0,
minor: 4,
patch: 0,
build: 2,
};

const version1_5_2 = {
major: 1,
minor: 5,
patch: 2,
build: 1,
};

const version10_12_3 = {
major: 10,
minor: 12,
patch: 3,
build: 1,
};

describe('versionStringToVersion:', () => {
it('Should match version0_4_0_2 object when version string is 0.4.0, current version is 0.4.0 and current version code is 4001', () => {
expect(versionStringToVersion(
version0_4_0_2String,
version0_4_0,
4001,
)).toEqual(version0_4_0_2);
});

it('Should match version1_5_2 object when version string is 1.5.2', () => {
expect(versionStringToVersion(version1_5_2String)).toEqual(version1_5_2);
});

it('Should match version10_12_3 object when version string is 10.12.3', () => {
expect(versionStringToVersion(version10_12_3String)).toEqual(version10_12_3);
});
});

describe('versionToVersionCode:', () => {
it('Should return 4002 when version is 0.4.0-alpha.2 and build number is 2', () => {
expect(versionToVersionCode(version0_4_0_2)).toBe(4002);
});

it('Should return 105021 when version is 1.5.2', () => {
expect(versionToVersionCode(version1_5_2)).toBe(105021);
});

it('Should return 1012031 when version is 10.12.3', () => {
expect(versionToVersionCode(version10_12_3)).toBe(1012031);
});
});
57 changes: 57 additions & 0 deletions src/versionUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const pad = (stringToPad, width, paddingCharacter) => {
const padChar = paddingCharacter || '0';
const toPad = stringToPad.toString();
return toPad.length >= width ?
toPad
:
new Array((width - toPad.length) + 1).join(padChar) + toPad;
};

const trimText = (s) => {
const indexOfString = s.search(/[^\d]/);
let result = s;

if (indexOfString > 0) {
result = s.substring(0, indexOfString);
}

return result;
};

const versionEquals = (versionA, versionB) => (
versionA.major === versionB.major &&
versionA.minor === versionB.minor &&
versionA.patch === versionB.patch
);

const versionStringToVersion = (versionString, currentVersion, currentVersionCode) => {
const versionParts = versionString.split('.');
let build = 1;
if (currentVersion && versionEquals(currentVersion, versionStringToVersion(versionString))) {
const newVersionCode = (currentVersionCode + 1).toString();
build = +(newVersionCode.substr(newVersionCode.length - 1));
if (build === 0) {
throw new Error('Sorry you have more than 10 builds using that version consider bumping version or change your version manually');
}
}

return {
major: +trimText(versionParts[0]),
minor: +trimText(versionParts[1]),
patch: +trimText(versionParts[2]),
build,
};
};

const versionToVersionCode = (version) => {
const major = pad(version.major, 2);
const minor = pad(version.minor, 2);
const patch = pad(version.patch, 2);
const build = version.build;
return +(`${major}${minor}${patch}${build}`);
};

module.exports = {
versionStringToVersion,
versionToVersionCode,
};
Loading

0 comments on commit dc6d8cf

Please sign in to comment.