NativeScript / android

NativeScript for Android using v8
https://docs.nativescript.org/guide/android-marshalling
Apache License 2.0
524 stars 135 forks source link

Detect which Runtime? #93

Closed NathanaelA closed 8 years ago

NathanaelA commented 9 years ago

Is their a command to get the current android runtime version, this would be very useful for add on. I've got a add-on that is going to require a patch that hasn't been deployed yet. This would be great if I could say if (__versionRuntime <= "1.02") then doSomething()

blagoev commented 9 years ago

Thanks for the suggestion, we will consider how this can be best done and what implications it has.

NathanaelA commented 8 years ago

Is their any news on this. Their is a nasty bug in v1.6.0 of the runtimes that I have to code around. 1.0-1.5.x works fine, and I'm sure it will be fixed in v1.6.1; but in my code their is no way to detect which runtime it is running on. This is something that would be VERY helpful to plugin developers.

If you have a preferred variable name, I might see if I can code up the Android side. Their is already a story/issue for doing this on the iOS side also.

Plamen5kov commented 8 years ago

Hi, @NathanaelA Can you say what particular problems you are having with v 1.6.0? And because you mention that having the version easily available would be very helpful to plugin developers, could you share what scenarios and user cases you have in mind. Having a version available in javascript is one possible solution but it might not be the best one, so IMHO we should explore what other options there are before committing to anything. Having a version of the runtime easily available in javascript seems like a slippery slope to me.

EDIT: If you wan't to use the version of the runtime as a workaround you can do:

var packageJson = require("./package.json");
var runtimeVersion = packageJson.version;
NathanaelA commented 8 years ago

Why would having access to the version be a slippery slope? changes occurs, bugs happen, being able to detect the version would allow me to code around them. This is not something I can easily "feature" detect if a bug that crashes the engine is present...

The main factor is that v1.6 of the Android runtime breaks the Application.context timing.

  1. If you attempt to use anything that attempts to get the App.Context the runtime will throw an error message about already being initialized on startup and CRASH!. This includes, if I attempt to use ANY straight Java calls to get the context. (https://github.com/NativeScript/NativeScript/issues/1577)

At this minute I am having to do a detection call on if the app contect variable doesn't exist, if it doesn't exists I have to a setTimeout loop until it exists. NASTY HACK, but their is no other solution that will work on all engines. If I had a version number, then I could say; if version >= "1.6.0" then use hack and put notice up, otherwise use the reliable method I've used since v1.00. (If you read the 1577 report you will see where this fix probably won't show up until 1.7) This hack I'm using is still not even totally foolproof as some of the calls to my plugin if they are done before App is initialized will still crash the engine with the same error. All those calls were direct data return calls; so I can't really change the api, any more than you can change the appSettings api (which will crash the engine if used before app.start(). The good news is odds are very low that any of my plugin calls will occur before the engine is initialized. I've also let everyone know that the safest to do any work in the app.js file is to do:

var app = require('application');
var screen_info = {moduleName: 'main-file'};
if (global.android) {
  app.start(screen_info);
}

// do all the work

if (!global.android) {
  app.start(screen_info);
}

Also pretty hacky, but at least it is very safe. iOS runtime doesn't run ANY code after the start. Android runtime we now need to do the start right away to eliminate any chance of crashing on startup.


\2. If you attempt to use clearHistory with navigation the navigation stack is corrupted (https://github.com/NativeScript/NativeScript/issues/1569) -- This one might be core modules, not sure yet who is the guilty party. But if I could detect the engine than I could easily make sure my login plugin doesn't use the clearHistory flag so that the poor developer isn't wondering why the app is randomly crashing with weird issues.

\3. Some plugins no longer function properly in v1.6 and have weird results (including crashing). (Like: https://github.com/NativeScript/NativeScript/issues/1585) Once a fix is found, the fix might be only relevant to v1.6x and may need to be flagged to be on in v1.6+; and flagged off in 1.5.x.

\4. It is a lot easier to do feature flagging when you know the engine actually supports the call. For example say I have a plugin that works perfectly fine in v1.2-1.5, but v1.6 adds the awesome new % sizes. I can start using that features in my plugin since I know it exists in v1.6, and continue using the old methods in the prior versions.

Please note I do realize I can do some of this by using the tns_modules/package.json and using that to detect which core modules I'm running. However, the core modules might not give me enough of the picture to know if it safe to do certain things that are only fixed (and won't crash) in the later versions of the runtimes.

If you look at the (https://github.com/NativeScript/NativeScript/issues/609) reference above you will see that ligaz also asked for a engine version constant; and if you check the iOS issues; you will see a story (https://github.com/NativeScript/ios-runtime/issues/123) for the same ability. I'm not an isolated case. :grinning:

NathanaelA commented 8 years ago

I should also mention Node.js has also included the versions of EVERYTHING in their process.versions (https://nodejs.org/api/process.html#process_process_versions) You would think that instead of making it more detailed if they thought this was a hindrance, they would mark it as depreciated. ;-) Node.JS has a way bigger JS community that NativeScript probably will ever have.

PHP Has http://php.net/manual/en/function.phpversion.php a way to get not only the version of the main php engine, but you can request the version for any extension.

ASP.Net has a couple ways to do it.

And of course the browser has the userAgent with the browser and version in it.

Plamen5kov commented 8 years ago

The main problem you are facing will be fixed with 1.6.2 release with this commit. As far as i know, although there is an issue on the version matter, it hasn't been accepted and as far as feature parity goes it won't be a good idea to have this feature present only in the android runtime. I never said your case is an isolated one and please try to understand that I want to find the best solution for the problem. I can't be convinced by the fact that everyone else is using versioning. By the same logic if everyone else were using feature detection it would be a good idea for us to do it as well.

slavchev commented 8 years ago

Hi @NathanaelA

I've read carefully your points and while I understand them I don't think versioning will help. Before I go into the details I would like to make it clear that whatever decision we take there will be a trade-off.

About 1) It is indeed a breaking change on our end. We did a change in modules and the runtime and It was hard to assess the impact of it. As a result we break some existing apps. We already committed the fix in the release branch and this morning we discussed to release a new version 1.6.2 tomorrow. I don't want people to use any versioning scheme in their plugins in order to provide a workaround for the breaking change we made. I prefer to fix the bug once. Also, suppose that this bug resurrects in a future version. It is not unheard, nobody's regression tests are perfect. I don't consider versioning a good tool in this scenario.

Points 2) and 3) are similar to 1) I guess this kind of issues will be eventually solved in different manner. I guess the npm builtin versioning comparability feature will be the preferred approach. Also, we can take a look at the guys from WordPress and see how they deal with the versioning/plugins issue. There is no silver bullet and in both cases there is always a testing step involved.

About 4) I think the explicit feature/API availability/discoverability is always proffered to version checks. I would love to discuss how this can be improved in {N} and implement a proper solution. Many of us remember the User-Agent horror and the problems it creates. I definitely don't want to go that way.

NathanaelA commented 8 years ago

@Plamen5kov - Feature parity is a horrible reason. If that is the case; then where is my cool non es5 "yield" in the android runtime? it has been present in iOS runtime since I think 1.4. If your going to quote feature parity, then I want that feature "parity" asap and then you can argue feature parity! :grinning: Oh, I way prefer feature detection over versioning, but even with feature detection you sometimes still needed versioning (see my question 4 to slavchev).

@slavchev - \1. Well that is awesome to see the fix will show up sooner rather than later. I fully understand how bugs occur, I wasn't complaining about the bugs -- those are a fact of the profession I've chosen to be in. What I am complaining about is you are handicapping ME in being able to provide a solution. If I had version detection ability since v1.5 then I could have totally worked around the issue in v1.6, without impacting ALL versions of my plugin because of a bad runtime. 2 & 3. Actually I would tend to disagree with you, the version would be the silver bullet. :grinning: \4 - I totally recall the versioning vs feature detection; I was developing JS code on Netscape Navigator. I've been around a while. :grinning: . On Feature Detection, can you explain to me how I can do feature detection on the following new features in v1.6? (https://github.com/NativeScript/NativeScript/pull/1355) (https://github.com/NativeScript/NativeScript/issues/1283) and (https://github.com/NativeScript/NativeScript/pull/1553)

Please note I know several people who have either chosen to stay on the 1.5 runtimes or have reverted to the 1.5 runtimes because of issues. So their is no easy way for me to say; yeah these "new" features exist. So for me to have some way to detect version is critical for some cases.

slavchev commented 8 years ago

@NathanaelA

I do realize how my concerns about versioning may look hostile for many of the community. I have to say that I value your opinion and the great work you do for {N} :) Please don't take my unwillingness to introduce versioning as something set in stone. Yet, I am not convinced versioning is a good way to go. Once we introduced it will be very hard and painful to remove it if we revisit our decision. Also, please note that I don't want take this decision by myself and I would rather keep the discussion going.

I hope that all can see that for important and critical breaking changes, like https://github.com/NativeScript/android-runtime/issues/362, we try to provide a fix as fast as possible. In the concrete example our time to reaction is just a few days. I hope this gains the trust of the community. Also, as an active community member you have very quick time to react for every {N} release. Sometimes it may seem that we are holding you back but it is definitely not our intention. It is just the fact that we are trying to be more conservative when providing a new feature. I do realize this can be frustrating and I guess it is a matter of time until both sides learn to deal with such issue. We will try to act more quickly, that's for sure.

Now, about the versioning. We've all seen code full of version checks and it is not pretty. I don't mind if it is pretty or not but more importantly often these checks don't work for many scenarios. Bug regression is just one example. There are other alternatives to versioning. We can provide API contracts similar to the ones in Android or UWP for example. Also, maybe it is a good time to revisit our thinking about semver. As I said earlier I would love to help and dig deeper into the this and provide solutions starting with the most critical issues. Also, I would encourage everybody involved to look closely at solutions provided by npm and WordPress.

Besides, because the runtimes are npm modules we have the version info already. Look at the package.json which is located as a sibling to the app folder. It looks as follows:

{
    "nativescript": {
        "id": "org.nativescript.app",
        "tns-android": {
            "version": "1.6.1"
        }
    },
    "dependencies": {
        "tns-core-modules": "1.6.0"
    }
}

I will check with @teobugslayer and @rosen-vladimirov to see whether it is a good idea to merge its content with app/package.json file so that @Plamen5kov proposal can work.

In any way, I would kindly ask not to rush in providing versioning mechanism without thorough discussion.

NathanaelA commented 8 years ago

@slavchev - Don't worry I don't take any offense at a no, or any push back. I've been developing for a really long time and never take a no to mean I did anything wrong, it just means your wrong and you haven't figured it out yet.(:grinning: Joking!) But sufficed to say it doesn't affect my ego, in the slightest. :grinning: As long as you are upfront and straight with me I am good!

I wrote this to another Telerik Employee already on another issue. I am a very opinionated developer , and I am willing to speak my opinion. I am not offended in the least when you guys disagree with me. ;-) But try to understand I will overwhelm you with reasons to make you want to say yes. :grinning: But if the decision comes down to a no; then it is a no, and I will live with it. And I feel no hurt feelings over it. So pretend and treat me like I'm a member on your team and you told me that the direction you wanted to go was without versioning. I'm good with it!

I am really happy that the App.Context issue will be fixed/worked around shortly. clearHistory would be another one that should be patches asap.

I am confused about what proposal you are saying @Plamen5kov is talking about; I mentioned using the app/tns_modules/package.json to get the core_modules version. But the runtime package.json is not added to the apk, so I can't get it. And adding the main package.json is a very bad idea; those keys are often wrong because I can do "^1.6.0" and it could easily have v1.80 installed.

I guess in summary; I come down to:

  1. Attempt to do a feature check first, this is typically the safest check. And most features that you have added to v1.6 can be feature detected in one way or another. :grinning:
  2. At worst case do a version check. Without the ability in the COMPILED app to do a version check you do eliminate a valuable tool that I can use to work around issues or detect support that feature detection can't.
slavchev commented 8 years ago

@NathanaelA

I had a short discussion with @rosen-vladimirov and we analyzed the current state and how it can be improved. Part of the current problem is that we allow app upgrade and the user ends with old plugins + new runtime. It is important to state that while we use npm we don't take advantage of its full features and we treat versioning in a slightly different way. We realize that fixing this is part of the problem. Also, the idea of semver has very strong support and we consider to revisit our decision and adopt it. However, this will probably happen for 2.0 release.

We are going to create a proposal at https://github.com/NativeScript/nativescript-cli/issues because it is not Android specific and we consider there it will have much better visibility. I will provide a link once it is available.

EDIT: see https://github.com/NativeScript/nativescript-cli/issues/1530

NathanaelA commented 8 years ago

@slavchev & @rosen-vladimirov - SemVar is only part of the solution. That does not fix the reason I want a __runtimeVersion. :grinning:

Lets say I create AwesomePlugin (AP) in v1.50 of TNS and I have versions 1.0.0, 1.0.1, 1.0.2 all minor bugs/feature enhancements. I'm working on v2.0.0 as I have some really cool new feature that breaks how the plugin works. Really close to when I'm about to release 2.0.0 myself, you release v2.0.0 because you create a new breaking changes. Well my v2.0.0 COULD support 1.5 fine, however to be compatible with v2.0.0 only a small change is required that is incompatible with v1.5. My choices are:

  1. Abandon all my 1.5 clients
  2. Choose not to upgrade it to 2.0.0
  3. Create two separate packages with different patches
  4. Use __runtimeVersion to detect that this is 2.0.0 and have a simple if (ver < 2.0.0) { methodA(); } else { methodB(); }

Now, which of those situations do you really think I want to be in as a plugin developer? All four are valid options, but only one of them is a really great option.

slavchev commented 8 years ago

If it is a only matter of a simple if statements I would probably publish two versions of my AwesomePlugin. When the logic is more complex I would go for my own dependency, build two versions of it and then consume it from (two different versions of) my AwesomePlugin. I don't see publishing multiple versions a big price to pay as I am already doing it. But it is my way of thinking.

rosen-vladimirov commented 8 years ago

Hi @NathanaelA , Intersting example. However it means you want one version in your plugin to be used with two versions of the runtime, which have breaking changes. So this sounds really cool, but I do not feel it is correct in npm world. For example when nodejs released 4.0.0 there were tons of breaking changes. All npm packages that were using old API should have been upgraded no matter of their current release cycle. Of course the update made some packages to stop working with older nodejs versions, but that's fine as you have old versions of the package working with it. As I've been working on the support for different nodejs versions in nativescript-cli, I can tell you - you do not want to support different major versions in a single version of your product. Currently nativescript-cli can work with nodejs ~0.10.38, ~0.12.2, ^4.2.1, ^5.1.0 but this is really, really hard to achieve and support. So let me get back to your example - I would vote for releasing 2.0.0 compatible version with all your new features and make it work with newest runtime version. In case someone wants to use them - upgrade the runtime as well. In case you have to write a lot of code, you can just release 2.0.0 which is compatible with 1.5 and later, release 3.0.0 which is compatible with runtime 2.0.0 You'll always have a corner case when some change (in runtimes, modules, cli, plugin, nodejs, v8 or whatever) will prevent some users from upgrading. But I would definitely use the new features in all of my new versions and advise the users to upgrade.

NathanaelA commented 8 years ago

@slavchev - Why would you really want to maintain two code bases? When I release 2.0.1 I have to apply the patch to both version and release two different npm versions. If I have a runtime version, I am maintaining a single code base that works on both v1.5 & v2.0.

So applying your logic; when is the TNS-Core-Modules going to be split into two or more separate versions because version checking is not a good solution?

https://github.com/NativeScript/NativeScript/blob/master/utils/utils.android.ts#L29 https://github.com/NativeScript/NativeScript/blob/master/ui/core/view.ios.ts#L231 https://github.com/NativeScript/NativeScript/blob/master/ui/page/page.ios.ts#L51 https://github.com/NativeScript/NativeScript/blob/master/ui/styling/background.android.ts#L143

Please note I only pulled a couple places the team is using it in the TNS code modules. Are you really advocating having multiple different versions of TNS-Core-modules per release version?

slavchev commented 8 years ago

@NathanaelA

I think there is some misunderstanding. The (main) code base is one. You have two flavors. Does it really matter if you have

if (version_check) {
  goLeft()
} else {
  goRight()
}

or two dependencies

// left flavor
goLeft()

and

// right flavor
goRight()
NathanaelA commented 8 years ago

@rosen-vladimirov - Long before nativescript, I have maintained several plugins across a parent plugin version (including several breaking changes). I do realize the difficulty. And sometimes it is a lot of work, but sometimes it is a necessary evil. Currently my fluentReports supports several different MAJOR versions of pdfKit. I realize it adds more work on my part; but I have no support issues because when I release a new version it supports the different versions that people use.

If I am I not mistaken, the CLI uses version detection to make sure it works properly on 0.10 as well as 5.1? Wouldn't your job be MUCH harder if you didn't even have version detection? Why aren't you releasing and maintaining 4 different versions of the CLI, that is exactly what you are proposing I do with my plugin? If the shoe fits for me, then why is the Telerik team not willing to swallow the same medicine?

Since emotion is not easy to convey via text, I am not at all upset; I am attempting to point out the logical inconsistency of your position, you have no problem using version detection to support your own project (and you could split the cli into 4 projects to support using the node engine semvar variable); but you are saying it is bad for me to use runtime versioning to support my project. :grinning:

NathanaelA commented 8 years ago

@slavchev but without the version check I can't detect to go left or right....

slavchev commented 8 years ago

OK, I let me be more precise

if (version_check) {
  goLeft();
} else {
  goRight()
}

And

// main code base
go()
// left flavor (npm dependency)
function go() {
   goLeft();
}
// right flavor (npm dependency)
function go() {
   goRight()
}
sitefinitysteve commented 8 years ago

IMO, I don't see why it totally matters, if you don't want to use it yourselves, don't, but if it helps @NathanaelA then let that slippery slope be his to traverse if he wants...

As long as exposing it doesn't cause undue burden to the {N} team... I think it can only help plugin developers.

I personally don't want to have nativescript-myplugin-v1 nativescript-myplugin-v2 ... nativescript-myplugin-v13 if there's just like a 1-3 line change\patch per version

slavchev commented 8 years ago

@sitefinitysteve

I think this one of those issues when we know we won't get it right in the first time. That's why we keep this discussion and try to find out a good compromise for most of us, hopefully for everyone.

Also, as I said if it is just a few if statements then I would just create a branch for the old version, build a package, publish it and continue to work in the master branch. You can back-port to the older version branch as long as you think it is feasible. Just my 2 cents.

sitefinitysteve commented 8 years ago

@slavchev Yeah thats fine, nobody is bent out of shape over it, it's your party :) But like @NathanaelA says, you guys are already internally doing these kinds of checks, what would it fundamentally hurt to expose this to us through the api so we could use it (even if you dont)

rosen-vladimirov commented 8 years ago

@NathanaelA , I'm expressing my own opinion what I would do in case I have to support a plugin. Btw nativescript-cli detects the nodejs version in order to stop execution in case some really not-working version is used (for example 4.2.0). We've added this check just to stop answering questions like: "Hey why I receive this error when I execute tns ". It's optimization of the support resources :smile_cat: Again, I would like to say that if I'm working on a plugin, I would not include such ifs in my code. But I like your arguments - the whole NativeScript project benefits from such discussions and real-world scenarios.

NathanaelA commented 8 years ago

@slavchev -- sorry guys city lost power at the most inconvenient time, we were having such a great conversation. :grinning:

I have several issue with your potential solution, if I understand it correctly.

First we are assuming the NS is will start using SemVar version for all breaking changes (which it currently doesn't).

Lets go back to my scenario; I have AP 1.00 project; works on runtime (RT) v1.0-1.9 fine. But it won't work on RT 2.0 because lets say a constructor in RT v2.0 is the breaking change. RT 2.0 comes out; I was already going to push a AP2.0 but I waited a couple days for 2.0 to come out to make sure everything works. I find out the only reason AP2.0 doesn't work out of the box on RT 2.x is because of a constructor call breaking change. So now the scenario should be as clear as mud. :grinning:

Now my "BEST" solution is to do a simple:

var newAP;
if (_version <= "2.0.0") {
  newAP = someConstructor(  x,  y  );
} else {
  newAp = someConstructor(   t, y,  x   );
}

And later in AP v2.2 I mark v1 as depreciated in the readme, and AP v2.5 I remove support for v1.x of the RT. But initially I want to support both version since a lot of people will stay on the stable 1.x branch until the 2.x branch is stabilized. You know how many versions of Node are still in the wild. I also assume that at some point in the future you will actually decided to have a "stable" branch (i.e. lets say the 1.x versions) and a beta branch (the current release v2.x version) and maybe even a canary branch (master!) Chrome & v8 have 4 branches! (Release, beta, dev, canary). Every 6 weeks or so the branches are promoted (i.e. Beta becomes release. etc).

So let me make sure I understand in this example you are saying that your "best" solution is to:

Am I following your recommendation correctly so far? (If not, what did I misunderstand?)

So assuming I am following your proposal;

I don't believe this is even remotely possible with TNS & NPM currently. :grinning:

  1. The AP plugin itself can run on all versions so it needs be tagged NativeScript.Platforms.Android="~1.0.0".
  2. The AP plugin package.json has to depend on the APC package, so it has to have a key dependancies.APC = "????" -- Which version do I put, v1 ONLY runs on RT 1, v2 only runs on RT v2. I can't put a hard dependencies on a version here, because APC is specific to a Runtime version.
  3. If I put something like "^1.0" then it will think APC v1 will work on RT 2, which is false. (Problem 1)
  4. Assuming I can put inside the APC NativeScript.platforms.android="~1.0.0" and "~2.0.0" how does NPM know which APC to use since NPM also has no concept of {N} RT versions. (Problem 2).

So let assume that you guys spend countless days getting this scenario working and we figure out how to make TNS & NPM work together and have it automatically figure out which version of APC to pull based on RT version; you have now created additional work for me. :frowning: Not only do I have to split my code into three files; but I have to create a whole new plugin (APC) with its own package.json file and make sure I publish it properly on two separate branches (after all I need to make sure I have a v1.0x branch and a v2.0x branch). If you thrown in trying to support the canary/master branch now I potentially have THREE separate APC versions. Any mistakes and the whole house of cards falls for several versions.

In my scenario; I continue publishing a single package and it just works everywhere I want it too. Which makes more sense really?

NathanaelA commented 8 years ago

@rosen-vladimirov that maybe the case, and as you can see it is VERY useful to do the version checking in some cases. :grinning:

According to my quick grep of the source you reference some variation of "version" 483 times in the TNS CLI. I don't have time to look at them, but you are checking versions of all sorts of things to verify the environment will work; and it would NOT surprise me if in at least one of those cases there is a if/else based on version number of some component that uses one path over another based on the results. (BTW: The 483 does NOT include node_modules, just the telerik TNS-CLI lib directory. if you include node_modules, you have and additional 4,368 references to version of some sort. :grinning: ) Neither of these counts will include any sub-checks on things like: var currentVer = process.version; And then having multiple checks on currentVer to decide what to do...

slavchev commented 8 years ago

TL;DR I describe how I use the standard version branches

First thing first. Current tns doesn't use the full npm functionality but all described scenarios are supported in npm.

OK, I am a plugin author and I work on AwesomePlugin (AP). The current version of the runtime (RT) is version A. I work in master branch and I am ready with my AP and there comes RT version B.

Scenario 1

My AP is compatible with both RT version A and B so I tag my current commit, declare my compatatibility (with A and B), build and publish my AP.

Scenario 2

There is a breaking change in RT version B and my AP doesn't work anymore. Say a simple if would suffice to fix the compatibility. I would not go for this option but rather for the next one.

Scenario 3

There is a breaking change in RT version B and my AP doesn't work anymore. I branch from c1 as shown below

------(c1)---------- [master branch]
         \
          \
           \--------(c2) [VESION_A branch]

In commit c2 I set my dependency to RT version A, tag the commit, build and publish VERSION_A of my AP.

Then I continue work in master branch and adapt my code for RT version B in commit c3

------(c1)------------------(c3)------ [master branch]
         \
          \
           \--------(c2) [VESION_A branch]

Once I am ready, I branch from c3 and follow the same steps.

------(c1)------------------(c3)------ [master branch]
         \                   \ 
          \                   \------(c4) [VERSION_B branch]
           \
            \--------(c2) [VESION_A branch]

In commit c4 I set my dependency to RT version B, tag the commit, build and publish VERSION_B of my AP.

I continue to work in master branch and I create a handy feature with commit c5

------(c1)------------------(c3)---------------(c5)--- [master branch]
         \                   \ 
          \                   \------(c4) [VERSION_B branch]
           \
            \--------(c2) [VESION_A branch]

I want to provide this feature to my existing versions of AP (VERSION_A and VERSION_B) so I back-port it with commits c6 and c7 accordingly.

------(c1)------------------(c3)---------------(c5)--- [master branch]
         \                   \ 
          \                   \------(c4)-----(c6)--- [VERSION_B branch]
           \
            \--------(c2)----(c7)--- [VESION_A branch]

I tag c6 and c7 commit, build and publish new versions, VERSION_A1 and VESION_B1, of my AP.

I support a old version branches as long as I find it feasible, For example, I may decide to back-port my new feature only to VERSION_A of my AP.

At that point a bug in RT version A is discovered. It turned out the bug in fixed in RT version B. I switch to VERSION_A branch and fix the bug with commit c8.

------(c1)------------------(c3)---------------(c5)--- [master branch]
         \                   \ 
          \                   \------(c4)-----(c6)--- [VERSION_B branch]
           \
            \--------(c2)----(c7)--------------------------(c8)---- [VESION_A branch]

I tag c8 commit, build and publish new version of my AP.

Scenario 4

There is a breaking change in RT version B and my AP doesn't work anymore. The change in RT version B is a big one and I decide to abstract it in a new dependency. I will keep it short this time but I am going to apply the same approach from scenario 3.

I build my AwesomePlugin component (APC). I branch where I have to and build and publish to versions VERSION_APCA and VERSION_APCB. Then I use APC in two different branches of my AP, build and publish two of it VERSION_A and VERSION_A and I set VERSION_A to have dependency to RT version A and VERSION_APCA. Next, I set VERSION_B to have dependency to RT version B and VERSION_APCB. This is really a variation of the previous scenario.

Again, this is what I would do, YMMV.

EDIT: As far for the V8, they use the described approach https://github.com/v8/v8/network

blagoev commented 8 years ago

There are example of both worlds. For example Chrome does not allow you to detect the v8 runtime version. At least is not easy and totally hacky. Also note that there are people trying to do just that.

On the other hand Android is good example of promoting version checks for multiple platforms support. You can also detect if it is art or dalvik runtime executing your code.

Also .NET have very easy version checking. https://msdn.microsoft.com/en-us/library/system.environment.version.aspx

I am not opposed to the idea of having version exposed if that will make someone life easy. Having the version information can help someone shoot himself in the foot, but that's fine if that's what he wants/needs to do. Stopping someone from messing something by hiding information will only make them make even more hacks to get what they need. For example including build hooks in plugins to hard code the package.json version to be available at runtime.

So in short my vote is inclined towards what @NathanaelA have requested.

NathanaelA commented 8 years ago

@slavchev - Ah, I get what you are saying now thank you very much for that detailed post; that is different idea than what I got the first time.

I still dislike that publishing strategy for small things because of future changes. If I'm working in the master branch, and make new feature X change now I need to push that change to two (or more) other branches; (i.e. version_1 and Version_2 branches). If I made some fixes in version_1 or version_2 that is in the same diff path, then I have to do conflict resolution. It just adds more work, and I'm all about avoiding work. ;-) My time is valuable enough (at least imho :grinning:) I don't need to be wasting it conflict resolution, multiple merges and multiple npm publishes and the potential errors those can cause. Please understand I fully think this (your method) is a VALID way of doing things, and I do think there are several good reasons to do it. But in a lot of cases the extra work and potential errors isn't worth it.

I do have one other issue with this technique. TNS platforms.android key only check against ONE version (I believe the runtime version) -- I might need to do the patch against because of the TNS-Core not the Runtime. For those who do like your design, you need to think of how to handle this correctly also!

@blagoev - LOL, I've been found out, I mentioned to @sitefinitysteve that I had figured out a way to get the RT version outside of this issue a couple days ago, but I would much rather have the version built in instead having to create a plugin. And yes, it creates slightly more work right this second (creating a plugin); but on the flip side I would get to increase my plugin count, Eddy is killing us out there... :grinning:

slavchev commented 8 years ago

I tried to analyze the reasons behind this issue. I tried to answer questions like why it was open last June and why it resurfaces now. I think this is mainly because we did a breaking change, namely https://github.com/NativeScript/NativeScript/issues/1577.

Also, there is another important thing. While tns is build around npm we don't take full advantage of npm and even break some of its assumptions. As I said this was discussed with @rosen-vladimirov and this results in https://github.com/NativeScript/nativescript-cli/issues/1530.

I looked deeper in npm and found the following pages

Here is a short excerpt.

In some cases, you want to express the compatibility of your package with a host tool or library, while not necessarily doing a require of this host. This is usually referred to as a plugin.

Currently we have tns-android module but we treat it in a special way. My idea is to treat tns-android as an ordinary plugin (some months ago I created a plugin that containes *.so files, not to be mistaken with native module so I know it is possible). Then it will be possible to use peerDependencies and set dependency to the runtime. In short, the more I think about the problem the more I am convinced that providing proper dependency mechanism is preferred to runtime version checking.

What do you think?

NathanaelA commented 8 years ago

@slavchev - Peer dependancies would solve that part of this, for some issues. And that might meet most needs.

However, you are still assuming I want to maintain two (or more) forks of my project, I really dislike having two active branches, if I can avoid it. ;-) Too many additional complications -- even Telerik has made the same mistake (I think in v1.3) and forgot to port a nasty bug fix from Release back to master until I mentioned it. It is VERY easy to make that mistake and get them out of sync. I personally prefer simpler and for me simpler is having all code is in the exact same branch...

var support;
if (version < x) { 
  support = require('./v1Support.js');
} else {
  support = require('./v2Support.js;);
}
var x = new support.Constructor();

I think we have hashed this to death. :grinning: Please note, I'm not saying your way is wrong; it just doesn't match my development style and slows me down. So either let this old man have his preferred working style or don't. :grinning: Just like the other things that were no's -- I have ways around it, so I'm not really worried about it. :grinning:

sitefinitysteve commented 8 years ago

+1 for letting us choose and avoid branch complexity... If we want to for plugin X. If it's a TINY change i just want a simple if statement...

slavchev commented 8 years ago

Guys, the more we discuss the more I get confused :smile:

I described what git workflow I use, I never meant that you should do the same. I guess it is my fault that I haven't been more clear about that. Everybody uses some workflow that works for him/her and it is not my business to tell the people what to do :smile:

If you don't want to have multiple branches that is fine with me. Nevertheless I would like to understand what do you think about the following suggestion. The same scenario as before. You are about to ship your plugin and we release a new version of the runtime with a breaking change that you can easily workaround with an if statement. Here is my suggestion:

Is it a high price to pay? Do you want to avoid having your plugin published twice?

All we want is to make it easier for you guys. We did a mistake by using npm in a wrong way and now we are trying to fix that. And as far as I can see we have your support https://github.com/NativeScript/nativescript-cli/issues/1530#issuecomment-187707996. It is important for us to understand your scenarios.

NathanaelA commented 8 years ago

@slavchev - I'm glad that {N} will support npm properly in the future; that is awesome!++

The issue for me is not really the first release and creating two plugins. That would be annoying but do-able as a one time hack; what concerns me about this workflow/design is the continued support.

Lets say I have a bug in my own library (I know I'm so perfect, you want to discount that right. :grinning:) ; then I have to push two more plugins again. That is the part I want to eliminate; I don't want to have to create two plugins for each change. The next part is that eventually I hope you have both a LTS and a Next Gen branch. (i.e. like Node 4 & 5). I will want my plugin to support both 4 & 5, but I don't really want to keep pushing 2 plugins each time I create new features in a plugin.

NathanaelA commented 8 years ago

@slavchev @valentinstoychev - Did you guys come to a consensuses on this; will this be added to the runtime or not?