Month: January 2020

A Realist’s Guide to Culture Change

The phrase “we need to change our culture to be successful” has become a punchline for any executive pitching ambitious visions and transformation initiatives, IT-related or otherwise. What is unfortunately less common is any mention of how such a change in culture will happen and how to know when this ideal future culture has been achieved.

Foci is by no means a change management firm nor do I profess any kind of expertise in human behaviour or organizational theory. We are however experts in helping organizations adopt new technologies and methods where culture is an unavoidable challenge. Based on our experience in the trenches, I would like to offer a realist’s perspective on what taking on “culture change” means and what one can expect when committing to this lofty goal.

Culture = People

We can’t talk about culture without defining it first. Culture is an abstraction of what the default behaviours and tendencies of a group of people are. Those behaviours and tendencies are either learned and developed in reaction to how an organization is built and managed, or inherent in the people that are being hired.

When an organization sets out to change its culture, it must accept the reality that it will likely result in a turnover in people. The culture that you desire won’t resonate with everyone in the organization. And a strong culture is built by people who naturally buy into it rather than by trying to hard sell it to someone. Therefore, it’s best to ensure that you are prepared to deal with an increase in turnover and hiring as a part of this commitment rather than assume that a new culture can be achieved without big changes to the workforce.

Culture Requires Nurturing

Executives can’t really dictate the culture of an organization the same way parents can’t really dictate the personalities of their children. An organization’s culture develops based on how people react to and are motivated by that organization’s structure, management style, processes, facilities, compensation model, other employees, and countless other factors. Any attempt to try to define a new culture without looking thoroughly at all aspects of the organization which enabled the current culture would be flawed.

Instead of asking how individuals can adopt the desired behaviours, the organization should ask what aspects of its current structure, policies, compensation, governance, rituals, and general work environment are contributing to the undesirable behaviours and then work to address those. For example, if an organization desires a culture of innovation, budget and approval processes will have to be updated to allow for more experimentation, frequent changes in project parameters, and faster decision making. This is a very organic and fluid process, so set realistic expectations and adapt the plan to how the people are reacting to the changes.

Stress = Negative Behaviours

High stress situations tend to push people to exhibit more basic survival instincts such as territorialism and combativeness. It is extremely difficult for people to adopt more desirable behaviours such as collaboration and transparency or take extra time to think about innovative solutions when timelines are aggressive and budget is tight.

People take time to learn new ways of working and making decisions. This means that efficiency and output will drop before recovering and even improving over the longer term. Project budgets and timelines must account for this and give people enough time to learn the new behaviours and repeat them enough times to become ingrained. It’s the classic “slow down to speed up” adage.

Change Starts at the Top

I am constantly surprised by the number of organizations treating culture change as an exercise whereby the executives look at how they can fix their workforce without also looking at their own behaviour. The culture of an organization is representative of how executives have made decisions over time.

If an organization wants to encourage a culture of taking responsibility, then executives must reflect this by taking actions such as increasing delegation of decision making and making their compensation more outcome-based. If more collaboration is desired, then open door policies must be adopted. Executives can’t just be the champions of change, but also become the examples of the desired culture themselves. The “do as I say and not as I do” philosophy doesn’t work here.

Achieving Success

We are extremely proud of the culture we’ve achieved at Foci. We’ve been deliberate in designing our organization and been very lucky in the type of people we’ve attracted and hired. Here are some of the things that we’ve done and learned about building a strong and innovative culture:

  1. Hire executives with diverse opinions and approaches, but very similar values. Your leadership should have different approaches to solving problems, but should see eye-to-eye on the organization’s core beliefs and philosophies;
  2. Hire for culture fit over pure technical acumen. It’s much easier to teach technical skills than modify behaviours;
  3. Constantly adjust and refine organizational processes and policies. Organizations and the people within them evolve over time. The processes and policies have to be tweaked to account for that;
  4. Create a relationship of mutual trust between our people and the company. Giving people the room to make decisions and exercise judgement encourages a sense of responsibility and ownership. Treat your staff like responsible adults who can make good decisions;
  5. Compensate people based on what you value in your employees. If you want a team that’s constantly upping their game, then compensate for personal growth and skills development;
  6. Invest in people. It’s not just training and some formalized mentorship program. Give people the time, resources, and the infrastructure needed to connect, collaborate, and share knowledge.

Culture change is hard, but by no means impossible. It takes a lot of commitment, attention, investment, time, and patience. By recognizing that the change is really building an organization that nurtures the desirable culture, “we need culture change” will become an achievable call to action rather than just an executive punchline.

  • Shan
  • Gu

Multi Stage Pipelines & Azure DevOps

Many years ago, I wrote a blog post about TFS and DevOps. A lot has changed since then, with multiple versions of the build pipeline being released, but it continues to be one of the most trafficked articles on our site.   Microsoft has worked hard to create a better experience for build automation and continuous integration – so I worked hard on updating this walkthrough. Recently, Microsoft released the idea of multi stage pipelines that work and feel much like how GitLab CI works.

In this post I’ll walk through a basic YAML file and show how you can get a C# project up, built, and tested quickly.

Setup

We need to have a project that is checked into DevOps before we begin. I have a repository that I made for this blog up on DevOps. that is a basic dotnet core console application and a unit test project that goes along with it. At the time of writing this blog post you will also need to turn on the multi-stage pipelines Preview Feature in order to get the best view for these pipelines. You can do that by clicking on the user settings button

User Settings

Then click on preview features

Preview Features

Then ensure that multi-stage pipelines are enabled

Multi stage pipelines enabled

First Steps

First we need to add a YAML file into our project. I tend to put this file directly at root and name it azure-pipelines.yaml. Then we need to define our stages. A stage is a collection of jobs and can be run concurrently or can be dependent on another stage successfully completing. For this quick project we will have two different stages

  • Build
  • Test

In order to define these stages in our pipeline we need to write some YAML like

stages:
  - stage: build
    displayName: Build
  - stage: test
    displayName: Test
    dependsOn:
    - build

this will give us building blocks to add our jobs. If you check this file into DevOps and navigate to pipelines you can see that we have a pipeline defined without any runs associated to it.

multi stage pipeline showing in dashboard

Adding a Job

A job runs on a build agent. By default DevOps provides hosted build agents. These agents are a pre-configured VM that have a lot of different development tools pre-installed. I’ll be using the hosted agents for this post.

Let’s add in some YAML to add a job that will build our dotnet solution. We can do this in one of two ways, we can use a DevOps “task” or we can write a script. Tasks can provide a lot of features that you would normally need to script yourself. These can be very helpful, however it also hides a lot of what is being run. I tend to try and use tasks as they get updated regularly to add additional features and fix bugs. Microsoft hasn’t made tasks to solve every problem however so you will need to write some scripts eventually.

Example as Task

variables:
  buildConfiguration: "Release"
  
stages:
- stage: build
  displayName: Build
  pool:
    vmImage: "Ubuntu 16.04"    
  jobs:
  - job: build_dotnet_solution
    displayName: build dotnet solution
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: build
        arguments: '--configuration $(buildConfiguration)'
- stage: test
  displayName: Test
  dependsOn:
  - build

Example as script

variables:
  buildConfiguration: "Release"
  
stages:
- stage: build
  displayName: Build
  pool:
    vmImage: "Ubuntu 16.04"    
  jobs:
  - job: build_dotnet_solution
    displayName: build dotnet solution
    steps:
    - script: |
      dotnet build --configuration $(buildConfiguration)
- stage: test
  displayName: Test
  dependsOn:
  - build

In both examples I have added a variable to set the build configuration setting for the pipeline. Variables are very helpful and DevOps also provides a lot of pre-defined variables for you. You can ready about them here.

Artifacts

Now that we have our job running and our solution is being built. We will probably want to retain these files. We will need to artifact these files if we want to use them in a different job, or we can download them later for manually testing the build.

variables:
  buildConfiguration: "Release"
  
stages:
- stage: build
  displayName: Build
  pool:
    vmImage: "Ubuntu 16.04"    
  jobs:
  - job: build_dotnet_solution
    displayName: build dotnet solution
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: build
        arguments: '--configuration $(buildConfiguration)'
    - publish: $(System.DefaultWorkingDirectory)/src/demo-project/bin/$(buildConfiguration)/netcoreapp3.0/
      artifact: source
- stage: test
  displayName: Test
  dependsOn:
  - build

Once the build is completed you should see the artifacts on the build page. You can download them and use them in different jobs now.

multi stage pipeline artifacts published

Testing

Now that we have our code built, we can go ahead and run the tests for our application. DevOps also has the ability to show us test results through its dashboards. It’s easiest to use the task for this, as the task has capabilities to upload the tests results for us.

variables:
  buildConfiguration: "Release"
  
stages:
- stage: build
  displayName: Build
  pool:
    vmImage: "Ubuntu 16.04"    
  jobs:
  - job: build_dotnet_solution
    displayName: build dotnet solution
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: build
        arguments: '--configuration $(buildConfiguration)'
    - publish: $(System.DefaultWorkingDirectory)/src/demo-project/bin/$(buildConfiguration)/netcoreapp3.0/
      artifact: source
- stage: test
  displayName: Test
  dependsOn:
  - build
  jobs:
  - job: test_dotnet_solution
    displayName: test dotnet solution
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: test        
        arguments: '--configuration $(buildConfiguration)'
multi stage pipeline tests successful

With this, you now have a basic build and test pipeline that will run with every check-in to your repository. There is a lot more that can be done, such as managing environments and performing releases. I hope that this is a good starting block to get you moving with DevOps.

  • Dan
  • McCrady