C# Effective way to manage revision number - c#

C# 2008 SP1
I am wondering what is the best way to handle revision numbers.
I had always thought there is normally only 3 numbers. (Major, Minor, and Bug fixes).
However, I am left wondering what the build number is and the Revision number.
For example, in the past I have normally used only 3 numbers. I there is some very minor change or a bug fix I would increment the 3rd number (bug fixes).
Because I am new to this. What is normally done in the professional world?
Many thanks for any advice,
In my AssemblyInfo file I have the following:
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.2.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// 1.0.2 Added feature for detecting if a sound card is installed.

From MSDN:
Build : A difference in build number represents a recompilation of
the same source. This would be
appropriate because of processor,
platform, or compiler changes.
Revision : Assemblies with the same name, major, and minor version numbers
but different revisions are intended
to be fully interchangeable. This
would be appropriate to fix a security
hole in a previously released
assembly.
Phil Haack has a nice deconstruction of the .NET versioning system, but in practice I don't think his concerns really matter since in my experience the .NET/MS versioning system is only really used by technical for debugging/support/tracking purposes, the public and project management will often be date or made-up-marketing-version-number based.
FWIW every .NET project I've worked on ha been governed by "X.Y.*" i.e. we like to manually control what the major and minors are but let the system control the build and revision.

Try this:
http://autobuildversion.codeplex.com/

I think Paul Alexander's answer is the correct one but I'd like to add the following remark to your AssemblyInfo file:
If you use 1.0.2.* remember that the last bit (replaced by the *) is a random number So if you build 1.0.2.*` this evening, and you build it again tomorrow morning, the second version could have a lower version number than the build you did earlier.

You'll want to consider versioning your assembly and file differently. When you change the assembly version number it's possible, but extremely difficult, for existing code to use it without recompiling. We only change the assembly version when there are breaking changes so we can release minor bug fixes easily.
Read more on our Assembly Versioning policy.

We use the Bug-fix number in increments of two. Odd numbers mean released minor bug fixes and even numbers mean working on bug fixes. Apparently this is common in some businesses, i.e., the one I am in.
The idea is to identify accidental releases, and somehow I like the idea. Doing things so that you easily see things that are wrong. This does not say that an odd number necessarily is a non-accidental release, only that it is with a quite high probability.

Thanks for all your suggestions.
I have decided to use the following.
My project has the following version number: 1.0.2.20.
1. :Major changes
0. :Minor changes
2. :Bug fixes
20 :Subversion revision number
So I have changed the following in my assemblyinfo.c file
[assembly: AssemblyVersion("1.0.2.20")]
Any suggestions on this idea, I would be happy to hear.
Many thanks,

Related

How to handle your code that later versions of the framework include?

I have to work with an old version of Mono in Unity projects. I find myself recreating some classes and extension methods that exist in later versions of .NET. Should I be marking these with an attribute that will make it easy to take them out at a later point, just wait for the inevitable errors, and delete the duplicate code, or take some other approach I'm not familiar with yet? If the attribute route is the way to go, is there already an appropriate attribute created for this kind of thing?
Here's what I'd like:
[PresentInDotNET(3.5)]
I fill in the version and get alerted when the framework is at that level or higher.
Split them off to a separate assembly, and change the set of assemblies that make up the final delivery based on the .NET version. You need to rebuild your main assembly to refer to the correct assemblies (depending on whether Foo is in MySystem or System), but as long as you keep namespaces identical, that's all. If you are not even interested in keeping compatibility with older versions, you can simply delete classes from this assembly as they become available.
Alternatively, if the classes/extension methods you are recreating are not interesting (in the sense that you gain nothing by having .NET supply them for you), simply put them in their separate namespace and accept that you are duplicating code already present in newer versions. It doesn't matter a whole lot which assembly gets the job done, after all, as long as it happens.
Whatever you do, try to avoid going the route of #ifdefs, runtime discovery, and other conditional code, as this is much harder to maintain.
How about adding "// TODO" comments for places like this? Visual Studio will display these in the Task window and you can get at them pretty easily.

Source code not changed, but everytime I rebuild the project(Visual Studio C#), the output exe file content is different [duplicate]

I'm using a build script to compile several C# projects. The binary output is copied to a result folder, overwriting the previous version of the files, and then added/committed to subversion.
I noticed that the binary output of the compilation are different even when there was no change to the source or environment at all. How is this possible? Isn't the binary result supposed to be exactly equal for the same input?
I'm not intentionally using any kind of special timestamps anywhere, but does the compiler (Microsoft, the one included in .NET 4.0) possibly add timestamps itself?
The reason I'm asking is I'm committing the output to subversion, and due to the way our build server works the checked in changes trigger a rebuild, causing the once again modified binary files to be checked in in a circle.
ANOTHER UPDATE:
Since 2015 the compiler team has been making an effort to get sources of non-determinism out of the compiler toolchain, so that identical inputs really do produce identical outputs. See the "Concept-determinism" tag on the Roslyn github for more details.
UPDATE: This question was the subject of my blog in May 2012. Thanks for the great question!
How is this possible?
Very easily.
Isn't the binary result supposed to be exactly equal for the same input?
Absolutely not. The opposite is true. Every time you run the compiler you should get a different output. Otherwise how could you know that you'd recompiled?
The C# compiler embeds a freshly generated GUID in an assembly on every compilation, thereby guaranteeing that no two compilations produce exactly the same result.
Moreover -- even without the GUID, the compiler makes no guarantees whatsoever that two "identical" compilations will produce the same results.
In particular, the order in which the metadata tables are populated is highly dependent on details of the file system; the C# compiler starts generating metadata in the order in which the files are given to it, and that can be subtly changed by a variety of factors.
due to the way our build server works the checked in changes trigger a rebuild, causing the once again modified binary files to be checked in in a circle.
I'd fix that if I were you.
Yes, the compiler includes a timestamp. Additionally, in some cases the compiler will auto-increment the assembly version number. I haven't seen any guarantee anywhere that the binary result is meant to be identical.
(Note that if the source is already in Subversion, I'd generally steer clear of also adding the binary files in there. I'd usually only include releases of third-party libraries. It depends on exactly what you're doing though.)
As mentioned by others, the compiler does generate a distinct build hence the different result. What you are looking for is the ability to create deterministic builds and now this is included as part of the roslyn compiler.
Roslyn command line options
/deterministic Produce a deterministic assembly (including module
version GUID and timestamp)
Read more about this feature
https://github.com/dotnet/roslyn/blob/master/docs/compilers/Deterministic%20Inputs.md
As far as I know, only MS binaries are different on every compile. 20 or so years ago, it wasn't like that. The MS binaries were the same after every compile (assuming the source code was the same).

Repeatable builds from same C# source code on different machines

I am trying to produce a tool which is smart enough to programmtically examine release version binaries produced by identical C# code compiled on two seperate machinces at different times and conclude that the code was identical while being able to pick up any code changes if present in the c# code used to produce these binaries.
I have tried using a number of approaches but in order to keep this short i'll just stick to the latest attempt.
I run ildasm with the /text option on the binaries and replace the GUIDs for anonymous fields etc in text, but when the binaries come from different pcs i find that the text produced by ILDASM /text option is reordered. The binaries originating from the same code but compiled by same setup on different machines also appear heavily reordered. Any suggestion how one may be able to control this reordering of IL would be much appreciated ?
Cheers
PS: Any alternative strategies of reliably accomplishing this are also most welcome.
Waiting for Eric Lippert to wake up :) - community wiki out of #mikez 's comment:
When a principal developer (Eric Lippert) on the compiler team speaks, you should listen: http://ericlippert.com/2012/05/31/past-performance-is-no-guarantee-of-future-results/ contains detailed explanation and strong recommendation for not doing it (likely in response to this precise question):
Is compiling the same C# program twice guaranteed to produce the same binary output?
No.
I found that a solution in accordance to what Eric Lippert's mentioned in his post what his client ended up settling for can be reached by setting the processor affinity for the compilation process to 01. After this the executables/ dlls produced are almost identical in excpetion to som mvid and guids used. Running ILDASM on these binaries with the text mode and building a simple hashing tool to strip away this random stuff provides such a solution. I am just providing this for the sake of completion and to help others who may face this problem.

Develop Version Numbering for an Application

Firstly, I think this forum is not appropriate for my question, so if it is in wrong place, kindly forgive and place wherever appropriate. I didn't find proper forum for my question.
I have developed a C# application (Win Forms). Now I need to handle its version numbering. I can't make out what is the best way to do. I want the version number to be simple something like 1.2 or 1.2.1. I read about SVN Version, but that also seems little confusing at this stage. There are different version types for the application - 1 with the installer , and 1 without installer.
I think the release version and the development version should be the same - please correct me if I am wrong. Should it be handled automatically or change manually? What are the best, simple and easy way to handle version numbering of an application.
We use major.minor[.build[.revision]]. And we give the semantics of:
major = major version. (Kind of big changes, maybe even with UI refresh).
minor = as medium set of changes. (maybe new internal processes or engines' refactoring).
As for build and revision:
0 - Means its alpha stage.
1 - Beta.
2 - Release candidate.
3 - Production.
So, if your app its on 3.2.1.0. You know you're at the alpha stage of the 3.2 version. And so on.
NOTE: Although it may seems kinda large to include the revision we found it to be a good practice because if we found some bug or unexpected behavior we just fix and increment revision and not build.
I think - and this comes from my experience, not just an idea - that you should use 4 part version numbering - very much along the lines of #Randolf. However I would make a different definition of the parts and the versioning.
major - this should be incremented when the version is a new build, is not compatible with previous versions without an upgrade process, or when the build/development platform changes ( so moving from .net 2.0 to .net 4.0 would count.
minor - this should be incremented when the data structures underlying your application change ( whether this is a db or not ). This means that a data build or update will be needed, which for clients indicates the level of work that may be needed for an upgrade.
build - this should always be incremented whenever a full production build is made, as a release candidate.
revision - this should be updated for every build, and used for bug fixes on a release candidate.
This means that you can identify with the version number exactly which changes and fixes are in that release, which is crucial for support.
Manual or automatic - this route would imply a manual update, and this is important to enable you to identify what a release contains.
Release and development version numbers should generally be the same, becasue the version number should only be incremented when a build for potential release is made. Having said that, you should also make sure that you can do development on any supported version, which may be lower than current development version, if a new release is in testing.
Frustratingly, .Net seems to consider build numbers the 'wrong' way round, according to many people. AssemblyInfo specifies build number as [Major][Minor][Build][Revision], which to me doesn't make any sense. Surely a nightly build happens more often than a revision of the spec, and is therefore the 'smallest' change? I'm not going to fight against the framework though, so I'm just going to have to tolerate it.
Maybe it's the same root cause as the phenomenon of Americans specifying dates in the wrong order. Again, common sense would dictate large->small consistently.
With regards to organising this conceptually, I would say that each part of a four-part build number should indicate the most recent change of the appropriate magnitude; i.e:
Major: A major upgrade of the application, which you expect users to pay for if it's a commercial project. Users should expect to face infrastructure concerns, such as service packs and new .Net versions;
Minor: A significant rollup of bug fixes and change requests that would fulfil the description of 'small feature'. Anything that should arguably have been in the program already can be rolled into a minor version;
Build: Personal choice, but for me this would be the unique build number. If you get your binaries from an integration server, this could run into the tens of thousands. Likely to be a nightly build, but could also be built on demand when the PM says 'go'. The build number should uniquely correspond to an event that kicked off a full production build on the integration server.
Revision: Should correspond to an amendment to the specification, at least conceptually. Would typically match an item in the changelog i.e. all incremental changes up to and including change request x.
In BuildMaster, we consider the #.#.#.# release number format to represent:
[major version].[minor version].[maintenance version].[build number]
Since mostly I would be regurgitating information from our blog, I'll just give you a link to the article written by a colleague of mine: http://blog.inedo.com/2011/03/15/release-numbering-best-practices/
When it comes to updating your release numbers, I would just leave the local development version at 0.0.0.0 and let your automated build process worry about the numbering.

Best practices for assembly naming and versioning?

I am looking out for some good practices on naming assemblies and versioning them. How often do you increment the major or minor versions?
In some cases, I have seen releases going straight from version 1.0 to 3.0. In other cases, it seems to be stuck at version 1.0.2.xxxx.
This will be for a shared assembly used in multiple projects across the company. Looking forward to some good inputs.
Some good information from this article on Suzanne Cook's blog on MSDN (posted 2003-05-30):
When to Change File/Assembly Versions
First of all, file versions and assembly versions need not coincide
with each other. I recommend that file versions change with each
build. But, don’t change assembly versions with each build just so
that you can tell the difference between two versions of the same
file; use the file version for that. Deciding when to change assembly
versions takes some discussion of the types of builds to consider:
shipping and non-shipping.
Non-Shipping Builds In general, I recommend keeping non-shipping assembly versions the same between shipping builds. This
avoids strongly-named assembly loading problems due to version
mismatches. Some people prefer using publisher policy to redirect new
assembly versions for each build. I recommend against that for
non-shipping builds, however: it doesn’t avoid all of the loading
problems. For example, if a partner x-copies your app, they may not
know to install publisher policy. Then, your app will be broken for
them, even though it works just fine on your machine.
But, if there are cases where different applications on the same
machine need to bind to different versions of your assembly, I
recommend giving those builds different assembly versions so that the
correct one for each app can be used without having to use
LoadFrom/etc.
Shipping Builds As for whether it’s a good idea to change that version for shipping builds, it depends on how you want the binding to
work for end-users. Do you want these builds to be side-by-side or
in-place? Are there many changes between the two builds? Are they
going to break some customers? Do you care that it breaks them (or do
you want to force users to use your important updates)? If yes, you
should consider incrementing the assembly version. But, then again,
consider that doing that too many times can litter the user’s disk
with outdated assemblies.
When You Change Your Assembly Versions To change hardcoded versions to the new one, I recommend setting a variable to the version
in a header file and replacing the hardcoding in sources with the
variable. Then, run a pre-processor during the build to put in the
correct version. I recommend changing versions right after shipping,
not right before, so that there's more time to catch bugs due to the
change.
One way to define your versioning is to give semantic meaning to each portion:
Go from N.x to N+1.0 when compatibility breaks with the new relase
Go from N.M to N.M+1 when new features are added which do not break compatibility
Go from N.M.X to N.M.X+1 when bug fixes are added
The above is just an example -- you'd want to define the rules that make sense for you. But it is very nice for users to quickly tell if incompatibilities are expected just by looking at the version.
Oh, and don't forget to publish the rules you come up with so people know what to expect.
Semantic Versioning has a set of guidelines and rules as to how to apply this (and when). Very simple to follow and it just works.
http://semver.org/
The first thing I would recommend is to become familiar with the differences between the Assembly version and the File version. Unfortunately, .NET tends to treat these as the same when it comes to the AssemblyInfo files in that it usually only puts AssemblyVersion and allows the FileVersion to default to the same value.
Since you said this is a shared assembly, I'm assuming you mean it's shared at a binary level (not by including the project in the various solutions). If that's the case you want to be very deliberate about changing the Assembly version as that is what .NET uses to strong name the assembly (to allow you to put it in the GAC) and also makes up the "assembly full name". When the assembly version changes, it can have breaking changes for the applications that use it without adding assembly redirect entries in the app.config file.
As for naming, I think it depends on what your company naming rules are (if any) and the purpose of the library. For exmaple, if this library provides "core" (or system level) functionality that isn't specific to any particular product or line of business, you could name it as:
CompanyName.Framework.Core
if it's part of a larger library, or simply
CompanyName.Shared
CompanyName.Core
CompanyName.Framework
As far as when to increment version numbers, it's still rather subjective and depends on what you consider each portion of the build number to represent. The default Microsoft scheme is Major.Minor.Build.Revision, but that doesn't mean you can't come up with your own definitions. The most important thing is to be consistent in your strategy and make sure that the definitions and rules make sense across all of your products.
In almost every version scheme I've seen the first two portions are Major.Minor. The major version number usually increments when there are large changes and/or breaking changes, while the minor version number usually increments to indicate that something changed which did was not a breaking change. The other two numbers are considerably more subjective and can be the "build" (which is often times a serial date value or a sequentially updating number that changes each day) and the "revision" or patch number. I've also seen them reversed (giving Major.Minor.Revision.Build) where build is a sequentially incrementing number from an automated build system.
Keep in mind that the assembly major and minor versions are used as the type library version number when the assembly is exported.
Finally, take a look at some of these resources for more information:
http://msdn.microsoft.com/en-us/library/51ket42z.aspx
http://msdn.microsoft.com/en-us/library/system.reflection.assemblyversionattribute.aspx
http://blogs.msdn.com/suzcook/archive/2003/05/29/57148.aspx

Categories