Manage csproj file in CI/CD process - azure

I have an asp.net web forms application. To implement Continuous integration/deployment process:
TFS
Dev branch
Master branch
Azure: App service
Dev Slot
Staging Slot
Prod
The lifecycle is :
The developer add some features and commit it to Dev branch ==> the commit will be automatically deployed to Dev slot
The requestor or the client see, test and validate modifications
If it is Ok ==> the developer merge his changeset to master branch
when the changeset were merged with success, it will be ==>
deployed to Staging slot
Test some important Url in staging slot
If it is OK ==> Swap Staging and Production slots
So at the end, we will have the versions of the application:
Version N+1 in the dev slot
Version N-1 in the staging slot
Version N in the production
This process works fine. Because of the csproj file, in some it didn't
Example :
A Developer add a subsite A and B
site B is validated by the client but site A did not
when the site B's changeset were merged to the master branch, the csproj file will contains A and B pages references
So we will have a compilation error in master, because site A's pages are mentionned in the csproj but it doesn't exist in this master branch!
So I need to know how can I fix this issue ?
Thanks,

You have a continuously integrated dev branch. When it comes to deploying, you find yourself asking the question, "How do I deliver a subset of what's presently in the branch?" At this point, you're trying to essentially un-merge. You don't ever want to "unmerge".
Instead, consider adopting a feature toggle pattern. This is a developer-centric activity, not a branching/merging activity. Your developers wrap any new feature behind a toggle that can be conditionally enabled or disabled. If Site B is approved for deployment and Site A isn't, that's fine -- deploy with Site A's feature toggle disabled. It's still in the code, but there's no way for your end-users to access it.
Another possibility is to adopt a microservice architecture where there are fewer hard dependencies. Instead, your application is comprised of many, smaller, independently versioned and deployed services. This will probably end up involving feature toggles too, of course.
The above two thoughts are coming from a place of modern application design. To go back to an older way of thinking: If you need to "unmerge", it means you're merging too early. You may need to maintain multiple development branches and QA features independently, only merging them together once the changes have been approved. This, of course, requires a longer QA cycle because you'll have to QA both features a second time, after they are merged.

Related

What is the best approach for merging a feature branch into master when said feature branch is using a different build pipeline?

I am using Azure Devops in an IT environment with many different development teams and git repositories. Each development team owns one or more repositories. It's my job to work on various application components contained in said repositories. Because I do not own those repositories, I should not make any changes in build/release pipelines, build policies etc, all by myself because that can impact other people's work.
Now let's say I have a feature branch named UpgradedFeature in the repository FeatureRepository, containing my changes. Said changes also introduce a breaking change in the build pipeline used for that repository for the master branch. Let's say that pipeline is named MasterBuildPipeline.
So in order for my build based on the branch UpgradedFeature to succeed and not impact other people's work, I make a clone of the MasterBuildPipeline, name it UpgradedFeatureBuildPipeline and configure the breaking changes. This new build pipeline is used exclusively by me for the UpgradedFeature branch only.
The build, now using the new UpgradedFeatureBuildPipeline pipeline succeeds and now I want to merge into master , so I make a pull request to merge the changes contained in UpgradedFeature into master. The master branch has a branch policy in place named MasterBranchPolicy like described on https://learn.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops&tabs=browser. This branch policy contains the MasterBuildPipeline and prevents completion of that pull request when the build using that pipeline does not succeed.
So my problem is that my pull request triggers the MasterBranchPolicy containing the MasterBuildPipeline and not the UpgradedFeatureBuildPipeline containing the necessary breaking changes for the build to succeed. So the build fails and I cannot complete the pull request.
Of course I could edit the MasterBuildPipeline for a short time, introduce my breaking changes, run the build, then discard the breaking changes again. But there's a chance I may impact other people's work with that and somehow I have a feeling that's not the right approach. I could also edit or disable the MasterBranchPolicy for a short time but again, I may impact other people's work and I feel it's not the right approach.
How should I do this?
So the build fails and I cannot complete the pull request.
To complete the pull request even through the build fails, you could grant yourself Bypass permissions. Bypass permissions let you complete pull requests that don't satisfy branch policies. You can grant bypass permissions to yourself then complete the pull request. Here is Bypass branch policies for reference.
Please navigate to Project setting >> Repositories >> The repo >> Security >> user (yourself) >> Bypass policies when completing pull requests.
Then, you can Override branch policies and enable merge even the MasterBuildPipeline faild.
Please also note that use caution when granting the ability to bypass policies, especially at the repo and project levels. Policies are a cornerstone of secure and compliant source code management. In your scenario, it's suggested to edit the MasterBuildPipeline and the MasterBranchPolicy or disable the MasterBranchPolicy as you mentioned.
Generally, workflow of DevOps Branching Strategy as follows
Developer will create a feature or bugfix branch out of develop. One feature or bugfix branch usually stands for one JIRA bug or feature item. These branches are personal
The changes will be pushed into the developer's feature or bugfix branch.
When the new feature or bugfix is complete.A developer will create a pull request. Pull requests open a code review phase.
Once a pull request has been approved, the team lead or development team will move it into development.
When the development branch has all the epics and bug fixes, i.e., the content planned for the next release, the development team or team lead will create a release branch. This initiates the release regression testing phase.At this stage, only bug fixes are accepted for release, and the workflow is similar to that of the development branch.
Having a separate release branch will enable future development towards the next release in the development branch. Features for the next release are not included in this release. However, bug fixes for this release will be incorporated into the development of the next release as well.
When release content meets the criteria, the release branch will be frozen, which means that it ends. Content from releases will be merged to master and tagged there. For the next release, a new release branch is created when needed.
As per my experience, I would suggest creating branching policies like
A pull request is requested to merge the develop, release, and master branches.
Pull request approvers should be leads.
All developers can create feature branches.
All developers can push to hotfix and feature branches. Commit messages must include the JIRA issue id.

Azure DevOps - Restrict merging to branches

I'm looking to limit how merges are allowed to be done in Azure DevOps. I'm looking to replicate a setup that I had in Atlassian Bitbutcket.
So far I cannot see an easy or even a hard way to accomplish this in Azure DevOps. Right now the devs are merging directly into Master, and there are a number of internal devs and external contractors. I want to protect the main branch via hard limit policies. I know someone might suggest a solution to "just tell the devs to stop doing that", but unfortunately that never works. People are fallible, habits are hard to break, and "policies" go out the window when under a crunch or pressure to get something out quickly.
What I need to accomplish in DevOps:
Master cannot be deleted or rewritten
Nobody can push or merge directly to Master
Master can only be changed by a PR, preferably only from the Dev branch
Dev cannot be deleted or rewritten
Nobody can push or merge directly to Dev
Dev can only by change by a PR from an existing branch
Tagged branches cannot be deleted or rewritten
If someone has a suggestion how to accomplish this I'm all ears, and very thankful.
You need to setup a Branch Policy for the branches you want to do this on, this note is on that page
Branch Policies
Note: If any required policy is enabled, this branch cannot be deleted and changes must be made via pull request.
To get to Branch Policies -> in Project Settings choose Repositories then the particular Repository then Branch Policies are at the bottom - choose the branch.

Octopus Deploy and Multiple Branches/Release Candidates

We have currently released our code to Production, and as a result have cut and branched to ensure we can support our current release, whilst still supporting hot-fixes without breaking the current release from any on-going development.
Here is our current structure:
Project-
/Development
/RC1
Until recently using Octopus we have had the following process:
Dev->Staging/Dev Test->UAT
Which works fine as we didn't have an actual release.
My question is how can Octopus support our new way of working?
Do we create a new/clone project in Octopus named RC1 and have CI from our RC1 branch into that? Then add/remove as appropriate as this RC's are no longer required?
Or is there another method that we've clearly missed out on?
It seems that most organisations that are striving for continuous something end up with a CI server and continuous deployment up to some manual sign off environment and then require continuous delivery to production. This generally leads to a branching strategy in order to isolate the release candidate to allow hot fixing.
I think a question like this raises more points for discussion, before trying to provide a one size fits all answer IMHO.
The kind of things that spring to mind are:
Do you have "source code" dependencies or binary ones for any shared components.
What level of integration / automated regression testing do you have.
Is your deployment orchestrated by TFS, or driven by a user in Octopus.
Is there a database as part of the application that needs consideration.
How is your application version numbering controlled.
What is your release cycle.
In the past where I've encountered this scenario, I would look towards a code promotion branching strategy which provides you with one branch to maintain in production - This has worked well where continuous deployment to production is not an option. You can find more branching strategies discussed on the ALM Rangers page on CodePlex
Developers / Testers can continually push code / features / bug fixes through staging / uat. At the point of release the Dev branch is merged to Release branch, which causes a release build and creates a nuget package. This should still be released to Octopus in exactly the same way, only it's a brand new release and not a promotion of a previous release. This would need to ensure that there is no clash on version numbering and so a strategy might be to have a difference in the major number - This would depend on your current setup. This does however, take an opinionated view that the deployment is orchestrated by the build server rather than Octopus Deploy. Primarily TeamCity / TFS calls out to the Ocotpus API, rather than a user choosing the build number in Octopus (we have been known to make mistakes)
ocoto.exe create-release --version GENERATED_BY_BUILD_SERVER
To me, the biggest question I ask clients is "What's the constraint that means you can't continuously deploy to production". Address that constraint (see theory of constraints) and you remove the need to work round an issue that needn't be there in the first place (not always that straight forward I know)
I would strongly advise that you don't clone projects in Octopus for different environments as it's counter intuitive. At the end of the day you're just telling Octopus to go and get this nuget package version for this app, and deploy it to this environment please. If you want to get the package from a different NuGet feed for release, then you could always make use of the custom binding on the NuGet field in Octopus and drive that by a scoped variable depending on the environment you're deploying to.
Step 1 - Setup two feeds
Step 2 - Scope some variables for those feeds
Step 3 - Consume the feed using a custom expression
I hope this helps
This is unfortunately something Octopus doesn't directly have - true support for branching (yet). It's on their roadmap for 3.1 under better branching support. They have been talking about this problem for some time now.
One idea that you mentioned would be to clone your project for each branch. You can do this under the "Settings" tab (on the right-hand side) in your project that you want to clone. This will allow you to duplicate your project and simply rename it to one of your branches - so one PreRelease or Release Candidate project and other is your mainline Dev (I would keep the same name of the project). I'm assuming you have everything in the same project group.
Alternatively you could just change your NuSpec files in your projects in different branches so that you could clearly see what's being deployed at the overview project page or on the dashboard. So for your RC branch, you could just add the suffix -release within the NuSpec in your RC branch which is legal (rules on Semantic Versioning talk about prereleases at rule #9). This way, you can use the same project but have different packages to deploy. If your targeted servers are the same, then this may be the "lighter" or simpler approach compared to cloning.
I blogged about how we do this here:
http://www.alexjamesbrown.com/blog/development/working-branch-deployments-tfs-octopus/
It's a bit of a hack, but in summary:
Create branch in TFS Create branch specific build definition
Create branch specific drop location for Octopack
Create branch specific Octopus Deployment Project (by cloning your ‘main’ deployment
Edit the newly cloned deployment, re-point the nuget feed location to your
branch specific output location, created in step 3

git deploy to an Azure website has stopped working

I've been successfully using Git deploy (via Kudu) to a couple of Azure websites (e.g., beta/prod) for several months, and it's worked quite well. Starting today, I noticed that when I push to the appropriate respective git branch, my Azure websites will supposedly deploy - i.e., the deploy kicks off, everything builds, all my tests run, and the Azure management portal swears up and down that it's deployed my website - but ... nothing happens. My websites don't change. (Beta and prod pull from different branches of the same git repo, but no matter which I push to, none of the changes included in the latest push show up on either website.)
There are no errors or any other indication of a problem in the logs. The Azure portal detects the git pushes, runs the deployments, and swears that they've happened successfully. But the changes - some very simple ones, i.e., text on a certain page - simply aren't there.
This is the sort of thing that I'd normally contact Azure support for, but my subscription doesn't include tech support :-(. The Azure site recommends asking here on SO, and hence my post.
Any suggestions for further troubleshooting this?
Well, I don't know what was triggering the problem, but resetting the website - by adding a bogus key/value pair to the configuration, and saving it - triggers the website(s) to pick up the changes. Apparently the underlying issue is that the Kudu deploy doesn't seem to be triggering the website to reset itself. I'll add more details in the future if I run into the problem again.
[Edit 2013-10-15 - Today, deploys seem to be working normally again. My guess is that it was some sort of transient Azure bug that's now fixed.]

Using mercurial branches for automatic deployment of website

I am currently thinking of a way to nicely structure my web project with mercurial. I was thinking of having two branches default (for development & testing) and release (the finished code which gets published). I would develop and test on the default branch until I have a stable application running. Then I would merge into the release branch. When I push the code to my central repository (on the server where my web application lives) I would want the code to be automatically published.
Is this the right way to go and if yes can this automatic publishing of the release branch be achieved with hooks?
Have you considered the git-flow branching model? I would recommend it and also hgflow by yujiewu. The latter is an implementation of the git-flow idea for mercurial.
Instead of a "release" branch, you should name it 'stable' as several projects do.
Do you use Continuous integration yet? Maybe, you should. In Jenkins, you could create a post-build step to publish the release if everything went well. It's better than a changegroup hook.

Resources