Skip to content

Commit

Permalink
fix(ios): deal with the latest cli breaking change
Browse files Browse the repository at this point in the history
I've also:
* made platform props access lazy
* moved the important cli code to ts
* added required arguments checks
* fixed some test snapshots
* exposed the package types
  • Loading branch information
Grohden committed Jun 30, 2022
1 parent 599b297 commit 3a5801c
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 74 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-cli-bump-version",
"version": "1.4.0",
"version": "1.5.0",
"main": "src/index.ts",
"types": "lib/index.d.ts",
"license": "MIT",
Expand Down
26 changes: 1 addition & 25 deletions react-native.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,7 @@ module.exports = {
commands: [{
name: "bump-version",
func: (_, config, args) => {
if (args.skipCodeFor === "all" && args.skipSemverFor === "all") {
// https://i.kym-cdn.com/photos/images/newsfeed/001/240/075/90f.png
console.log("My work here is done.");
return;
}

const appGradlePath = path.join(
config.project.android.sourceDir,
config.project.android.appName,
"build.gradle",
);

versioner({
root: config.root,
pbxprojPath: config.project.ios.pbxprojPath,
buildGradlePath: appGradlePath,
type: args.type,
semver: args.semver,
skipCodeFor: args.skipCodeFor
? args.skipCodeFor.split(" ")
: [],
skipSemVerFor: args.skipSemverFor
? args.skipSemverFor.split(" ")
: [],
});
versioner(config, args).run();
},
options: [
{
Expand Down
138 changes: 109 additions & 29 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ type Configs = {
skipSemVerFor: Platforms[];
skipCodeFor: Platforms[];
root: string;
pbxprojPath: string;
buildGradlePath: string;
pbxprojPath: () => string;
buildGradlePath: () => string;
};

// -- FP
Expand All @@ -30,7 +30,7 @@ const pipe2 = <A1, A2, R>(

const replace = (expr: string | RegExp, replacement: string, str: string) => {
return str.replace(expr, replacement);
}
};

// -- Specializations

Expand All @@ -42,11 +42,12 @@ const writeFile = (fPath: string, file: string) => {
fs.writeFileSync(fPath, file, "utf8");
};

const matchFirst = (reg: RegExp) => (value: string) => {
const [, first] = ([] as string[]).concat(reg.exec(value)!);
const matchFirst = (reg: RegExp) =>
(value: string) => {
const [, first] = ([] as string[]).concat(reg.exec(value)!);

return first;
}
return first;
};

const incrementSemVer = (current: string, type: SemVer | undefined) => {
const [major, minor, patch] = parseSemVer(current);
Expand All @@ -66,28 +67,27 @@ const incrementSemVer = (current: string, type: SemVer | undefined) => {
throw new Error(`'${type}' is not a semver type`);
};


// -- Managers

abstract class BaseFileManager {
private readonly basePath: string;
private readonly basePath: () => string;
protected content: string | null = null;

constructor(basePath: string) {
constructor(basePath: () => string) {
this.basePath = basePath;
}

protected read() {
if (this.content === null) {
this.content = fs.readFileSync(this.basePath, "utf8");
this.content = fs.readFileSync(this.basePath(), "utf8");
}

return this.content;
}

write() {
if (this.content) {
return writeFile(this.basePath, this.content);
return writeFile(this.basePath(), this.content);
}
}
}
Expand Down Expand Up @@ -170,18 +170,24 @@ class BuildGradleManager extends BaseFileManager {
}

class PackageJSONManager {
private readonly basePath: string;
private content: {
private readonly basePath: () => string;
public content: {
version: string;
} | null = null;

constructor(basePath: string) {
constructor(basePath: () => string) {
this.basePath = basePath;
}

private read() {
if (this.content === null) {
this.content = require(this.basePath);
// Avoid direct require as it caches
// resolved modules and changes to them
// are going to be persisted in the same process
const raw = fs.readFileSync(require.resolve(this.basePath()), {
encoding: "utf8",
});
this.content = JSON.parse(raw);
}

return this.content!;
Expand All @@ -190,7 +196,7 @@ class PackageJSONManager {
write() {
if (this.content) {
return writeFile(
this.basePath,
this.basePath(),
JSON.stringify(this.content, null, 2),
);
}
Expand All @@ -208,26 +214,24 @@ class PackageJSONManager {
}
}

export class ProjectFilesManager {
class ProjectFilesManager {
readonly configs: Configs;
readonly pbx: PBXManager;
readonly buildGradle: BuildGradleManager;
readonly packageJSON: PackageJSONManager;

constructor(configs: Configs) {
const {
root,
pbxprojPath,
buildGradlePath,
} = configs;
const { root, pbxprojPath, buildGradlePath } = configs;

this.configs = configs;
this.buildGradle = new BuildGradleManager(buildGradlePath);
this.pbx = new PBXManager(pbxprojPath);
this.packageJSON = new PackageJSONManager(path.join(
root,
"package.json",
));
this.packageJSON = new PackageJSONManager(() =>
path.join(
root,
"package.json",
)
);
}

syncSemver(semverString: string) {
Expand Down Expand Up @@ -309,6 +313,82 @@ export class ProjectFilesManager {
}
}

export const versioner = (configs: Configs) => {
new ProjectFilesManager(configs).run();
// if you want a simple version to use as api
export const apiVersioner = (configs: Configs) => {
return new ProjectFilesManager(configs);
};

export const versioner = (
cliConfigs: {
root?: string;
project?: {
ios?: {
sourceDir?: string;
pbxprojPath?: string;
xcodeProject?: {
name: string;
};
};
android?: {
sourceDir?: string;
appName?: string;
};
};
},
cliArgs: {
skipCodeFor?: string;
skipSemverFor?: string;
semver?: string;
type?: string;
},
) => {
if (cliArgs.skipCodeFor === "all" && cliArgs.skipSemverFor === "all") {
// https://i.kym-cdn.com/photos/images/newsfeed/001/240/075/90f.png
console.log("My work here is done.");
return;
}

const required = <T>(value: T, name: string): NonNullable<T> => {
if (!value) {
throw new Error(
`Value for ${name} is '${value}', maybe RN cli broke compatibility?`,
);
}

return value!;
};

return apiVersioner({
root: required(cliConfigs.root, "root"),
pbxprojPath: () => {
const iosProject = required(cliConfigs?.project?.ios, "project.ios");

return iosProject.pbxprojPath || path.join(
required(iosProject.sourceDir, "project.ios.sourceDir"),
required(iosProject.xcodeProject, "project.ios.xcodeProject")
.name
.replace(".xcworkspace", ".xcodeproj"),
"project.pbxproj",
);
},
buildGradlePath: () => {
const androidProject = required(cliConfigs?.project?.android, "project.android");

return path.join(
required(androidProject.sourceDir, "project.android.sourceDir"),
required(androidProject.appName, "project.android.appName"),
"build.gradle",
);
},
// code validates these casts, we cast to make api above allow only valid values
// for type checked usages
type: cliArgs.type as SemVer,
semver: cliArgs.semver,
skipCodeFor: cliArgs.skipCodeFor
? cliArgs.skipCodeFor.split(" ") as Platforms[]
: [],
skipSemVerFor: cliArgs.skipSemverFor
? cliArgs.skipSemverFor.split(" ") as Platforms[]
: [],
});
};
2 changes: 1 addition & 1 deletion tests/__snapshots__/android.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ exports[`preserve quotes style 1`] = `
"android {
defaultConfig {
versionCode 2
versionName '1.2.0'
versionName '1.1.0'
}
}
"
Expand Down
27 changes: 27 additions & 0 deletions tests/__snapshots__/ios.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ exports[`skip semVer when asked 1`] = `
"
`;

exports[`successfully bump version (pre 0.69.x) 1`] = `
"// !$*UTF8*$!
{
objects = {
/* Begin XCBuildConfiguration section */
13B07F941A680F5B01A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
MARKETING_VERSION = 1.1.0;
CURRENT_PROJECT_VERSION = 32;
};
name = Debug;
};
13B07F951A680F5B01A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
MARKETING_VERSION = 1.1.0;
CURRENT_PROJECT_VERSION = 32;
};
name = Release;
};
/* End XCBuildConfiguration section */
};
}
"
`;

exports[`successfully bump version 1`] = `
"// !$*UTF8*$!
{
Expand Down
24 changes: 15 additions & 9 deletions tests/android.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
const path = require("path");
const { ProjectFilesManager } = require("../lib/index");
const { versioner } = require("../lib/index");

const makeDefaultManager = ({
semver,
type = "minor",
skipSemVerFor = "ios",
skipSemverFor = "ios",
skipCodeFor = "ios",
gradleFileName = "double.gradle",
appName = "double",
} = {}) =>
new ProjectFilesManager({
versioner({
root: path.join(__dirname, "android"),
project: {
android: {
appName: appName,
sourceDir: path.join(__dirname, "android"),
},
},
}, {
type,
semver,
skipSemVerFor,
skipSemverFor,
skipCodeFor,
root: path.join(__dirname, "android"),
buildGradlePath: path.join(__dirname, "android", gradleFileName),
});

test("successfully bump version", () => {
Expand All @@ -24,13 +30,13 @@ test("successfully bump version", () => {
});

test("skip semVer when asked", () => {
const manager = makeDefaultManager({ skipSemVerFor: "all" }).dryRun();
const manager = makeDefaultManager({ skipSemverFor: "all" }).dryRun();

expect(manager.buildGradle.content).toMatchSnapshot();
});

test("preserve quotes style", () => {
const manager = makeDefaultManager({ gradleFileName: "single.gradle" }).dryRun();
const manager = makeDefaultManager({ appName: "single" }).dryRun();

expect(manager.buildGradle.content).toMatchSnapshot();
});
Expand Down
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 3a5801c

Please sign in to comment.