If you are not using Visual Studio to refresh your Nuget packages then you need to check them in to source control. In my case this is the version control in TFS. To solve the problem you just need to add a .tfignore file to the packages directory.
The easiest way to do this is to create a new .txt file in the packages directory and call it ".tfignore.". Notice it starts and ends with the period. The last period will be removed automatically and you will be left with a file called ".tfignore".
You can also use notepad.exe to create the file. The trick with this is to change the type to All File and just type the name ".tfignore".
Once you have a file created open it in notepad and add the following lines to it.
!*.exe
!*.dll
The ! tell the source control to NOT ignore the files with these extension.
Friday, April 22, 2016
TFS 2015 Build Highlights
Goals of new system
- Web based
- Simple customization
- Real-time output
- Versioning of build definition
- Build pools - share build agents across projects and collections
- Cross-platform - even Mac and Linux
- Full support for XAML-based builds
Build Overview
- Templates
- Web Applications
- Unit Testing
- Staging and drop locations
- Azure Deployment
- Powershell
Build Definitions
- Web based
- Several Templates
- No XAML templates, but still supports them
- My Dev Machine produces the same outputs as TFS will
- Task gallery
- Auditing (changes are logged with notes if desired).
- Web based diff tool.
Running a Build
- Real-time log view
- Project by project breakdown
- Build Outputs
Build Customization
- Settings
- Variables
- Triggers
- Versioning of build
- Draft (not published yet)
- Templates - reuse
Hosted Agent
- Visual Studio Online (not on premise)
- One build at a time (No XAM L Builds)
- < 1 hr
- < 10 GB storage
- No admin rights
- Can't log on
- Run on Visual Studio Online, not your agent
- No interactive mode
Configuration
- Options
- Multi-configuration
- Staging & build drop
- Templates
Deployment
- Deployment templates
- Azure
- PowerShell
Friday, April 15, 2016
Deployment Pipeline
Below are highlights from the chapter titled What is a Development Pipeline in the book Continuous Delivery.
What is a deployment pipeline is an automated manifestation of your process for getting software from version control into the hands of your users. It does not imply that no human interaction with the system through the release process, but instead ensures that the error-prone and complex steps are automated, reliable, and repeatable.
Goal: A deployment pipeline should allow you to create, test, deploy complex system of higher quality and at a significantly lower cot and risk than we could otherwise have done.
Deploy to any environment (Testing, Staging, Production, etc) with a click of a button
Repeatable deployment (deploy a previous version easily)
Minimum Stages of pipeline
The commit stage
Asserts that the system works at the technical. Meaning that it compiles, passes a suite of commit tests, and runs code analysis, creates binaries and prepare a test database for use by later stages. Commit tests are primarily unit tests, but should also include a small select of other types of tests such as BDD or integration tests to give a higher level of confidence that the build is working properly. The stage should take less than five minutes and definitely less than 10 minutes. Its purpose is to give quick feedback to the developer that something is not working and needs to be fixed before moving on to the next task.
Automated acceptance test stages
Asserts that the system works at the functional and nonfunctional level, and that it behaviorally meets the needs of its users and the specifications of the customers.
Manual test stages
Asserts that the system is usable and fulfills its requirements, detects any defects not caught by automated tests, and verifies that it provides value to its users. Typically, this would include exploratory testing environments, integration environments, and UAT (user acceptance testing).
Release stage
Delivers the system to users, either as packaged software or by deploying it into a production or staging environment (a staging environment is a testing environment identical to the production environment)
The process starts with the developers committing changes into their version control system. At this point, the continuous integration management system responds to the commit by triggering a new instance of our pipeline. This first (commit) stage of the pipeline compiles the code, runs unit tests, performs code analysis, and creates installers. If the unit tests all pass and the code is up to scratch, we assemble the executable code into binaries and store them in an artifact repository.
A application is comprised of three parts:
Principles
Deploy the same binaries to all environments. For example, the same binaries used in UAT should be used in production. This can be used by using hashes of the binaries to verify they are the same.
Store the binaries in a file system, not version control.
Configuration Data is not included in the binaries and should be kept separately. - Configuration data is data that is different between the environments such as ip address, urls, database connection strings, external services, etc. It can also include data that changes behavior of the application.
Use Configuration files and store in source control - Each environment should have its specific settings stored in a configuration file that is specific to that environment. This correct file can be determined by looking at the hostname of the local server if one server or in multi-server environments through the use of environment variable supplied to the deployment script. Alternatively the data could be stored in a database as well.
Binaries must be deployable to every environment
Deploy the same way to every environment - this ensures that the deployment process is tested effectively.
Test configuration settings - check to see if external services are actually available when deploying, Ideally if the service is not available the installation should not be.
Smoke test - after an installation run some very basic scenario to make sure the external services are accessible. Check particularly sensitive urls, hosts, etc, make sure certain pages come up that depend on configured information work .
Locked down environments - Production should only be changed once proper change management has been used for approval of the change. The same should be for test environments, but the approval process is easier.
Each change should propagate through the pipeline instantly - the first stage (commit) should be triggered upon every check-in and each stage should trigger the next one immediately upon successful completion of the previous one. The system needs to be smart enough to check for new changes before running tests. For example, if three people check-in before an integration test finishes the latest changes should be bundled into what is tested in the integration tests. For manually triggered stages (later ones) they need to wait for user interaction.
If any part of the pipeline fails, stop the line -
What is a deployment pipeline is an automated manifestation of your process for getting software from version control into the hands of your users. It does not imply that no human interaction with the system through the release process, but instead ensures that the error-prone and complex steps are automated, reliable, and repeatable.
Goal: A deployment pipeline should allow you to create, test, deploy complex system of higher quality and at a significantly lower cot and risk than we could otherwise have done.
Deploy to any environment (Testing, Staging, Production, etc) with a click of a button
Repeatable deployment (deploy a previous version easily)
Minimum Stages of pipeline
The commit stage
Asserts that the system works at the technical. Meaning that it compiles, passes a suite of commit tests, and runs code analysis, creates binaries and prepare a test database for use by later stages. Commit tests are primarily unit tests, but should also include a small select of other types of tests such as BDD or integration tests to give a higher level of confidence that the build is working properly. The stage should take less than five minutes and definitely less than 10 minutes. Its purpose is to give quick feedback to the developer that something is not working and needs to be fixed before moving on to the next task.
Automated acceptance test stages
Asserts that the system works at the functional and nonfunctional level, and that it behaviorally meets the needs of its users and the specifications of the customers.
Manual test stages
Asserts that the system is usable and fulfills its requirements, detects any defects not caught by automated tests, and verifies that it provides value to its users. Typically, this would include exploratory testing environments, integration environments, and UAT (user acceptance testing).
Release stage
Delivers the system to users, either as packaged software or by deploying it into a production or staging environment (a staging environment is a testing environment identical to the production environment)
The process starts with the developers committing changes into their version control system. At this point, the continuous integration management system responds to the commit by triggering a new instance of our pipeline. This first (commit) stage of the pipeline compiles the code, runs unit tests, performs code analysis, and creates installers. If the unit tests all pass and the code is up to scratch, we assemble the executable code into binaries and store them in an artifact repository.
A application is comprised of three parts:
- Binaries
- Data
- Configuration
Principles
- Keep the deployment pipeline efficient, so the team gets feedback as soon as possible.
- Build upon foundations known to be sound.
- Keep binary files independent from configuration information
- Keep configuration information in one place
Best Practices
Only build your binaries once - the binaries are the .NET assemblies and should only be compiled once in the Commit stage. The later stages use these binaries. Building at each stage or even for testing, code analysis, etc. is considered an anti-pattern.Deploy the same binaries to all environments. For example, the same binaries used in UAT should be used in production. This can be used by using hashes of the binaries to verify they are the same.
Store the binaries in a file system, not version control.
Configuration Data is not included in the binaries and should be kept separately. - Configuration data is data that is different between the environments such as ip address, urls, database connection strings, external services, etc. It can also include data that changes behavior of the application.
Use Configuration files and store in source control - Each environment should have its specific settings stored in a configuration file that is specific to that environment. This correct file can be determined by looking at the hostname of the local server if one server or in multi-server environments through the use of environment variable supplied to the deployment script. Alternatively the data could be stored in a database as well.
Binaries must be deployable to every environment
Deploy the same way to every environment - this ensures that the deployment process is tested effectively.
Test configuration settings - check to see if external services are actually available when deploying, Ideally if the service is not available the installation should not be.
Smoke test - after an installation run some very basic scenario to make sure the external services are accessible. Check particularly sensitive urls, hosts, etc, make sure certain pages come up that depend on configured information work .
Locked down environments - Production should only be changed once proper change management has been used for approval of the change. The same should be for test environments, but the approval process is easier.
Each change should propagate through the pipeline instantly - the first stage (commit) should be triggered upon every check-in and each stage should trigger the next one immediately upon successful completion of the previous one. The system needs to be smart enough to check for new changes before running tests. For example, if three people check-in before an integration test finishes the latest changes should be bundled into what is tested in the integration tests. For manually triggered stages (later ones) they need to wait for user interaction.
If any part of the pipeline fails, stop the line -
Tuesday, April 5, 2016
FeatureToggle Review
FeatureToggle
FeatureToggle is a popular feature toggle package that has a good architecture, regular updates, a training video, doesn't use magic strings, and is extensible. The documentation can be found here.
FeatureToggle Review
Multiple platforms: .NET Desktop/Server, Windows phone, Windows Store
No magic strings
No default fallback values - throws exception
Flexible provider model to allow for swapping out of parts.
Straight forward to use
Extensible via Providers and Custom Toggles.
Downside
I don't like that I have to specify the connection string that I want to use for each toggle. It would be nice if it could use a default connection string instead. It seems a bit clunky to specify a key for the feature toggle AND one to point to the database connection string. Perhaps that can be changed.
Support Configurations
FeatureToggle is a popular feature toggle package that has a good architecture, regular updates, a training video, doesn't use magic strings, and is extensible. The documentation can be found here.
FeatureToggle Review
Multiple platforms: .NET Desktop/Server, Windows phone, Windows Store
No magic strings
No default fallback values - throws exception
Flexible provider model to allow for swapping out of parts.
Straight forward to use
Extensible via Providers and Custom Toggles.
Downside
I don't like that I have to specify the connection string that I want to use for each toggle. It would be nice if it could use a default connection string instead. It seems a bit clunky to specify a key for the feature toggle AND one to point to the database connection string. Perhaps that can be changed.
Support Configurations
- Compiled
- Local configuration (app.config / web.config or App.xaml)
- Centralized SQL Server
Architecture
Built-in Toggle classes use providers to get configurations out specific sources such as database, configuration file, etc.
Strongly typed objects => Compile time checks to make sure it is completely removed.
Built-in Toggles
- AlwaysOnFeatureToggle
- AlwaysOffFeatureToggle
- SimpleFeatureToggle
- EnableOnOrAfterDateFeatureToggle
- EnableOnOrBeforeDateFeatureToggle
- EnableBetweenDatesFeatuerToggle
- EnableOnDaysOfWeekFeatureToggle
- RandomFeatureToggle - could use for random a/b testing
- SqlFeatureToggle - toggle from value in SQL Server database
Installation
Nuget: FeatureToggle
NOTE: FeatureToggle.Core is installed when FeatureToggle is installed.
Overview of Usage
For each feature that a feature toggle is required, a new class that inherits from one of the built-in Toggle classes is required.
Compiled Toggle Usage
public class MyFeature : AlwaysOnFeatureToggle {}
In place where want to use it, create a new instance of the MyFeature class.
i.e.
public MyFeature MyFeature1 = new MyFeature();
Can add to ViewModel to use on Razor page.
i.e.
@if (Model.MyFeature1.FeatureEnabled)
{
....html here
}
Config File Usage
In this example it would be the same as above, except we change the class we inherit from so that we can get the value from the config file. Note, the ViewModel and Razor page did not need to change even though we are changing what the logic is for hiding the feature.
i.e.
public class MyFeature : SimpleFeatureToggle{}
We do need to add it to the configuration file. We just need to add a new key to the appSetting. It must follow the convention such that the key starts with "FeatureToggle." and concatenated to the name of our class (MyFeature in this case).
i.e.
<appSetting>
<add key="FeatureToggle.MyFeature" value="true"/>
</appSettings>
SqlFeature Toggle Usage
We will continue our example as before, except we need to also tell the FeatureToggle where the database is.
In a database create a table called Toggles
ToggleName nvarchar(100) not null (primary key)
Value bit not null
NOTE: The table and column names or types are not important since we will write the SQL to access it later.
We need to add the connection string to the list of connection strings in the web.config.
<connectionString>
<add name="MyDB" connectionString="typical connection string here" />
</connectionString>
Insert a record with the ToggleName being the name of our class (MyFeature in this case) and value = True.
We need to specify the connection string in the web.config. We put it in as an appSetting key-value as
<appSettings>
<add key="FeatureToggle.MyFeature.ConnectionStringName" value="MyDB" />
<add key="FeatureToggle.MyFeature.SqlStatement" value="select value from Toggles where ToggleName = 'MyFeature'" />
</appSettings>
Removing a Toggle
Delete the class. Rebuild project. Review each compiler error. Remove from web.config.
Creating a Custom Toggle
Custom Toggles are good when the value is based on some business logic.
Continuing on the examples...
public class MyBusinessLogicToggle : IFeatureToggle
{
public bool FeatureEnabled { get { return businessLogicHere;}}
}
Change our Feature Toggle so that it inherits from the custom feature toggle. This can be reused with multiple feature toggles;
public class MyFeature : MyBusinessLogicToggle {}
Creating a Custom Provider
The base class for Feature Toggles has a property called ToggleValueProvider. Setting this value to a custom Provider allows us to change the default provider to a custom one.
We can create a custom provider by creating a subclass of a existing provider.
i.e.
public MyProvider : IBooleanToggleValueProvider
{
public bool EvaluateBooleanToggleValue(IFeature toggle)
{
return logicHere;
}
}
Some Alternatives
References
Most of the data is sourced from the Implementing Feature Toggles in .NET with FeatureToggle on PluralSight.
Labels:
Continuous Integration,
Product Review,
Programming
Monday, April 4, 2016
Feature Toggles
Release Feature Toggles
For the development team to manage release process instead of source control branches. Should be short lived and thus removed to keep technical debt low.
Business Feature Toggles
For the benefit of the business such that they tailor the user experience based on business requirements. Consider a regular edition vs pro edition of software. Typically long lived or forever.
Toggle value baked-in to assembly.
Features can only be enabled or disabled with new release
Multiple machines may need to be kept in sync
Local Configuration
Toggle values held in app/web.config
Can be changed without needing an new release
Multiple machines may need to be kept in sync
Centralized Configuration
Toggle values held in central location, database, network share, UI, etc.
Can be changed without needing a new release
Whole system can be managed centrally
Business can manage potentially via UI.
Toggle decision points
User interface element toggling
Toggle links to new page / screen
Number of decision points
Defaults
Don't set defaults for toggles. An exception should be thrown if state of toggle is unknown.
Alternatives to release toggles
Deliver smaller part of features (small releases and more often)
Build the backend first and then build user interface last. Delays testing of UI to end of cycle.
Suggested Open Source Solutions
FeatureToggle - Popular choice, actively developed, nice choice.
FeatureSwitch
FeatureSwitcher
For the development team to manage release process instead of source control branches. Should be short lived and thus removed to keep technical debt low.
Business Feature Toggles
For the benefit of the business such that they tailor the user experience based on business requirements. Consider a regular edition vs pro edition of software. Typically long lived or forever.
Configuration Types
Compiled ConfigurationToggle value baked-in to assembly.
Features can only be enabled or disabled with new release
Multiple machines may need to be kept in sync
Local Configuration
Toggle values held in app/web.config
Can be changed without needing an new release
Multiple machines may need to be kept in sync
Centralized Configuration
Toggle values held in central location, database, network share, UI, etc.
Can be changed without needing a new release
Whole system can be managed centrally
Business can manage potentially via UI.
Toggle decision points
User interface element toggling
Toggle links to new page / screen
Number of decision points
Defaults
Don't set defaults for toggles. An exception should be thrown if state of toggle is unknown.
Alternatives to release toggles
Deliver smaller part of features (small releases and more often)
Build the backend first and then build user interface last. Delays testing of UI to end of cycle.
Suggested Open Source Solutions
FeatureToggle - Popular choice, actively developed, nice choice.
FeatureSwitch
FeatureSwitcher
Friday, April 1, 2016
Branching Strategy for Agile team desiring continuous integration that must work with a restriction of a slow release cycle
Solution Requirements:
- Continuous Integration - Frequent integration of code changes to limit big scary merges. Avoid long periods without merging back for others to see.
- Changes to UAT - Allows for a release to stabilize at a slow pace than development.
- What is approved in UAT is what gets released to production.
- Hot fixes to Production - Allow for emergency changes to a production release
- Parallel UAT and Development - Development should be considered working, but not ready for production. UAT would a candidate for release to production pending user approval.
- Code Reviews - each feature should be code reviewed. Ideally any merging that is done by everyone is be done at the feature level, but the developer making the changes can commit changes more often. Thus once the feature is done, it can be bundled up, code reviewed, and merged and ultimately released.
Goal:
Deliver software with a high level of confidence. Confidence to be derived from unit tests, integration tests, BDD tests (End to End tests), and UAT user approval. This implies that what was approved in UAT is what should be moved to production.
A compromised Solution:
The solution we weretempted to implement is best described in the post A successful Git branching model by Vincent Driessen, but we are using TFS, not Git. It is basically says, each feature is done in a branch, though I would add that changes should be pulled from the develop branch DAILY. Ideally, we should be able to look at the develop branch and see features branches being merged in, not individual commits. The individual commits would have been done to the feature branch itself.This makes it easy to see what is in the develop branch and also when they are merged to the release branch and the main branch it is again at the feature level.
Once a feature passes all regression tests (unit tests, integration tests, BDD tests) and has been code reviewed it can then be merged into the develop branch. Ideally a feature branch would be only a few days. If it is longer than a few days the feature should be merged into the develop branch to avoid a big scary merge. If a feature is not finished by the end of a sprint and part of the feature has been merged to the develop branch, but part is unfinished a feature toggle (See Feature toggles note below on how these can be implemented) should be added so that it is not accessible to the user.
A feature should be merged into the release branch by the develop responsible for it once they are confident (passed unit tests, integration tests, BDD tests, and exploratory testing) it is ready for release (pending UAT approval). Unless a specific need comes up, we will only have one release branch and label each release in it when it is merged into master (main). A separate versioned release branch can be created if needed though.
If a change (bug fix, enhancement, etc) is need to the release branch because of something that needs to be changed in UAT the change should be made on the release branch and then merged to the develop branch.
Similarly, if an emergency change (hotfix) is needed on the production code, the change should be made on the master (main) branch. It should then be merged into the develop branch and eventually to the release branch (as part of the usual merging into release branch process).
A label should be created automatically or explicitly when merging from development to release and then to master (main).
In the end this may not work so well when trying to continuously integration. It can work if the branches are short lived enough. The real issue is the unknown time it takes to integration when the effort for the integration of branches is large and the unknown time needed to stabilize after the integration and before release. This tends to be needed at least once before a release. Smaller more frequent integrations has proven to be a more stable amount of effort required and the code base tends to keep the code base stable when using feature toggles (feature hiding).
Refactoring is an exception to this strategy and the changes should be merged immediately to minimize difficult merges. This make this strategy not as useful unfortunately.
NOTE: This strategy could probably work by merging branches (both to and from the develop branch) at least once a day. The question is what is the benefit of doing a branch then? Branching is for isolation of development and successful continuous integration demands not being isolated. A compromise may work as well such that the branching on the develop branch is removed and instead everyone develops on the develop branch. A branch should not live more than 3 days to be considered short lived.
In the end this may not work so well when trying to continuously integration. It can work if the branches are short lived enough. The real issue is the unknown time it takes to integration when the effort for the integration of branches is large and the unknown time needed to stabilize after the integration and before release. This tends to be needed at least once before a release. Smaller more frequent integrations has proven to be a more stable amount of effort required and the code base tends to keep the code base stable when using feature toggles (feature hiding).
Refactoring is an exception to this strategy and the changes should be merged immediately to minimize difficult merges. This make this strategy not as useful unfortunately.
NOTE: This strategy could probably work by merging branches (both to and from the develop branch) at least once a day. The question is what is the benefit of doing a branch then? Branching is for isolation of development and successful continuous integration demands not being isolated. A compromise may work as well such that the branching on the develop branch is removed and instead everyone develops on the develop branch. A branch should not live more than 3 days to be considered short lived.
A Better Approach:
Have one mainline (no other branches unless doing a bugfix for UAT or production). The key is that the mainline is ALWAYS deployable. Use feature toggles for every feature and enable or disable as needed to make current release stable or that what is enabled is deployable. Remove old feature toggles after not needed anymore. Use labels for each release or deployment. It has the advantage of always integrating, and only create a branch if needed in the case of an emergency hotfix or something. Alternatively, the mainline could be released for the hotfix if all previously unreleased feature toggles are still turned off, but that is a judgement call based on the situation. Note, the release label would be on the new branch in this case and then merged back into the mainline immediately. It is simple to manage and could work very well for open source or fast moving projects that can release as desired. It may be a bit difficult to use for processes where there is a lengthy UAT approval cycle by end users. This difficulty can be mitigated by making the change to the mainline, disabling the appropriate feature toggles and putting in UAT again. Could work well for a continuous deployment model too I would think. This entire model (as does any CI/CD model) relies on having automated regression tests.
Some guidelines:
Some guidelines:
- Avoid branches - Branches should only rarely used. For example, only use branches for things like releases or spikes. In general things that will not be used again.
- No long-lived branches - Long-lived branches are opposed to successful continuous integration and should be avoided at all costs. This includes things like refactoring, long term development, etc. Instead use feature toggles (feature hiding).
- Integration Daily - Get the latest from the mainline and Commit to the mainline at least once a day
- Pass tests - all tests should still work BEFORE (and after) checking in your changes. This helps keep the mainline deployable.
- Incremental changes - It may take a little longer to do a bigger change in smaller incremental changes, but the effort and time spent is worth the effort because the mainline is always deployable.
Optional:
- Label or Branch for releases - A branch or label can be created just before a release. Once created testing and validation of the release is done from this branch. New development is performed on the mainline. i.e. Only critical bug fixes are done on the release branch and immediately merged back to mainline. Branches are always off the mainline, not existing release branches.
References:
A successful Git branching model - what we are implementing here
Feature Toggles - enable / disable features using compile or runtime flags to make a feature visible to the end user. Pete Hodgson's perspective on how to implement / issues is here. Martin Fowler says this.
Branching and Merging: Ten Pretty-Good Practices
Continuous Delivery by Jez Humble and David Farley. See chapters on Chapter 13: Managing Components and Dependencies, and Chapter 14: Advanced Version Control.
Some different version control implementations - worth looking at since they are bit simpler than the successful git branching model.
Continuous Delivery by Jez Humble and David Farley. See chapters on Chapter 13: Managing Components and Dependencies, and Chapter 14: Advanced Version Control.
Some different version control implementations - worth looking at since they are bit simpler than the successful git branching model.
Subscribe to:
Posts (Atom)