Skip to content

Commit

Permalink
Merge pull request #982 from DeveloperMetrics/UpgradeToDotNet8
Browse files Browse the repository at this point in the history
Upgraded to .NET 8 and replaced deprecated NuGet packages
  • Loading branch information
samsmithnz authored Nov 19, 2023
2 parents 9fbb102 + b076705 commit 88558a3
Show file tree
Hide file tree
Showing 35 changed files with 134 additions and 7,551 deletions.
9 changes: 0 additions & 9 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,6 @@ updates:
update-types: ["minor", "patch"]
assignees:
- "samsmithnz"
# - package-ecosystem: npm
# directory: /src/ProbotMetrics
# schedule:
# interval: daily
# time: "06:00"
# timezone: America/New_York
# open-pull-requests-limit: 10
# assignees:
# - "samsmithnz"
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
dotnet-version: 8.0.x

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
dotnet-version: 8.0.x

#Publish dotnet objects
- name: .NET Publish Web Service
Expand All @@ -44,12 +44,12 @@ jobs:
- name: .NET Publish functional tests
run: dotnet publish src/DevOpsMetrics.FunctionalTests/DevOpsMetrics.FunctionalTests.csproj --configuration Release --output ${{ github.workspace }}/functionalTests
- name: Copy chromedriver for functional test
run: copy "src/DevOpsMetrics.FunctionalTests/bin/Release/net7.0/chromedriver.exe" "${{ github.workspace }}/functionalTests"
run: copy "src/DevOpsMetrics.FunctionalTests/bin/Release/net8.0/chromedriver.exe" "${{ github.workspace }}/functionalTests"
shell: powershell
- name: DotNet restore functional tests to get correct NewtonSoft version
run: dotnet restore src/DevOpsMetrics.FunctionalTests/DevOpsMetrics.FunctionalTests.csproj
- name: Copy new NewtonSoft version for functional test
run: copy "src/DevOpsMetrics.FunctionalTests/bin/Release/net7.0/Newtonsoft.Json.dll" "${{ github.workspace }}/functionalTests"
run: copy "src/DevOpsMetrics.FunctionalTests/bin/Release/net8.0/Newtonsoft.Json.dll" "${{ github.workspace }}/functionalTests"
shell: powershell

#Publish build artifacts to GitHub
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
dotnet-version: 8.0.x
#Run automated .NET tests
- name: Variable Substitution appsettings file for tests
uses: microsoft/variable-substitution@v1
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x #Not a typo, the function is locked to a LTS version of .NET
dotnet-version: 8.0.x #Not a typo, the function is locked to a LTS version of .NET
- name: .NET Publish Function
run: dotnet publish src/DevOpsMetrics.Function/DevOpsMetrics.Function.csproj --configuration Debug --output ${{ github.workspace }}/function
- name: Upload function build artifacts back to GitHub
Expand All @@ -135,7 +135,7 @@ jobs:
uses: samsmithnz/[email protected]
with:
projects: 'src/DevOpsMetrics.Core/DevOpsMetrics.Core.csproj,src/DevOpsMetrics.Function/DevOpsMetrics.Function.csproj,src/DevOpsMetrics.FunctionalTests/DevOpsMetrics.FunctionalTests.csproj,src/DevOpsMetrics.Service/DevOpsMetrics.Service.csproj,src/DevOpsMetrics.Tests/DevOpsMetrics.Tests.csproj,src/DevOpsMetrics.Web/DevOpsMetrics.Web.csproj,src/DevOpsMetrics.Cmd/DevOpsMetrics.Cmd.csproj'
dotnet-version: '7.0.x'
dotnet-version: '8.0.x'
sonarcloud-organization: samsmithnz-github
sonarcloud-project: samsmithnz_DevOpsMetrics
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
next-version: 1.9.0
next-version: 1.10.0
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
[![Current Release](https://img.shields.io/github/release/samsmithnz/DevOpsMetrics/all.svg)](https://github.com/samsmithnz/DevOpsMetrics/releases)


**Why should we care about DevOps Metrics and what are they?** All engineering, including software, needs metrics to track performance, but many metrics when measured individually, can be 'gamed', or don't encourage the right behaviors or incentives. This has been an issue with metrics for many years. The [DORA metrics](https://services.google.com/fh/files/misc/state-of-devops-2019.pdf) are a step in the right direction, combining several metrics that encourage the behaviors and incentives - and hence that encourage DevOps teams to perform at a high level of performance.
**Why should we care about DevOps Metrics and what are they?** All engineering, including software, needs metrics to track performance, but many metrics when measured individually, can be 'gamed', or don't encourage the right behaviors or incentives. This has been an issue with metrics for many years. The [DORA metrics](https://services.google.com/fh/files/misc/state-of-devops-2019.pdf) are a step in the right direction, combining several metrics that encourage the behaviors and incentives - and hence that encourage DevOps teams to perform at a high level of performance. DORA metrics aren't perfect, but are still the best we have available today.
- A [demo website displaying these metrics can be viewed here](https://devops-prod-eu-web.azurewebsites.net/).
- Insights I've noted about implementing DORA DevOps metrics can be found in a [blog post here](https://samlearnsazure.blog/2020/04/30/high-performing-devops-metrics/)

This project is focused on helping you collect and analyze four key high performing DevOps metrics from GitHub and Azure DevOps. [DORA's "State of DevOps" research](https://cloud.google.com/blog/products/devops-sre/announcing-dora-2021-accelerate-state-of-devops-report) and [Accelerate](https://www.amazon.com/Accelerate-Software-Performing-Technology-Organizations/dp/1942788339) highlighted four driving indicators of high performing DevOps teams. While these four metrics are widely used in DevOps discussion, it's challenging to implement and capture all of the metrics.

Expand All @@ -16,12 +18,10 @@ This project is focused on helping you collect and analyze four key high perform
- **Change failure rate: After a production deployment, was it successful? Or was a fix or rollback required after the fact?** How often is a change we made 'successful'? This ties in well with deployment frequency and lead time for changes, but is challenging to measure - as it requires a signoff off of success. Not just that the code deployed correctly, but that there weren't adverse effects or degradation of the deployment to the system

![High performing metrics](https://user-images.githubusercontent.com/8389039/212061370-6984b2c3-bc13-4d92-8afc-0068be4cdde1.png)
(Chart from [page 11 of state of DevOps 2022 report](https://cloud.google.com/devops/state-of-devops))
A [demo website displaying the metrics can be viewed here](https://devops-prod-eu-web.azurewebsites.net/).
More information about high performing DevOps metrics can be found in a [blog post here](https://samlearnsazure.blog/2020/04/30/high-performing-devops-metrics/)
[^1]

## The current solution:
**We currently have all four of the metrics implemented and undergoing a pilot. There is a Probot for GitHub. (The Azure DevOps widget is on hold to focus on GitHub).**
**We currently have all four of the metrics implemented and undergoing a pilot. (The Azure DevOps widget is currently not planned - but is possible if someone wants to build it!).**

- **Deployment Frequency**, in both Azure DevOps and GitHub:
- How does it work? We look at the number of successful pipeline runs.
Expand Down Expand Up @@ -63,12 +63,11 @@ More information about high performing DevOps metrics can be found in a [blog po
![Change failure rate](https://github.com/samsmithnz/DevOpsMetrics/blob/main/ReadmeImages/ChangeFailureRate.png)

# Architecture
Developed in .NET 7. A GitHub action runs the CI/CD process.
Developed in .NET 8. A GitHub action runs the CI/CD process.

Currently the CI/CD process:
1. Builds the code
2. Runs the unit tests
3. ~~Deploys the Probot code to a Azure web app (http://devops-prod-eu-probot.azurewebsites.net/)~~ (Currently disabled)
3. Deploys the webservice to a Azure web app (https://devops-prod-eu-service.azurewebsites.net)
4. Deploys the demo website to a Azure web app (https://devops-prod-eu-web.azurewebsites.net)
4. Deploys the function website to a Azure function
Expand All @@ -78,7 +77,7 @@ Dependabot runs daily to check for dependency upgrades.
![Architecture diagram](https://github.com/samsmithnz/DevOpsMetrics/blob/main/ReadmeImages/Architecture.png)

## Badges
The API can generate a URL for static badges, but more work is needed. Some current samples are shown below:
The API can generate a URL for static badges, some samples are shown below:
[![Build](https://img.shields.io/badge/Lead%20time%20for%20changes-High-green)](https://img.shields.io/badge/Lead%20time%20for%20changes-High-green) [![Build](https://img.shields.io/badge/Time%20to%20restore%20service-Medium-orange)](https://img.shields.io/badge/Time%20to%20restore%20service-Medium-orange) [![Build](https://img.shields.io/badge/Change%20failure%20rate-Low-red)](https://img.shields.io/badge/Change%20failure%20rate-Low-red)

# Setup
Expand All @@ -94,11 +93,12 @@ The API can generate a URL for static badges, but more work is needed. Some curr
# What's next?
- Upgrades to packaging and setup (in progress)
- Upgrades to store data in CosmosDB (currently in Azure storage)
- Reviewing the current GitHub probot approach, to find a better target than issues (perhaps a metrics readme.md file?)
- Support for more scenarios, releases, etc
- ~~Azure DevOps marketplace integrations, so you can see the changes real time on your project/repo.~~ (lower priority to focus on GitHub)

# References

- GitHub API: https://developer.GitHub.com/v3/actions/workflow-runs/
- Azure DevOps API: https://docs.microsoft.com/en-us/rest/api/azure/devops/build/builds/list?view=azure-devops-rest-5.1

[^1]: Chart from [page 11 of state of DevOps 2022 report](https://cloud.google.com/devops/state-of-devops)
7 changes: 5 additions & 2 deletions src/DevOpsMetrics.Cmd/DevOpsMetrics.Cmd.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>dc96f8ff-2de5-4ed3-b124-89a134688b66</UserSecretsId>
Expand All @@ -19,7 +19,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Azure.Identity" Version="1.10.4" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.5.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
29 changes: 20 additions & 9 deletions src/DevOpsMetrics.Cmd/Program.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using DevOpsMetrics.Core.DataAccess.TableStorage;
using Azure.Identity;
using DevOpsMetrics.Core.DataAccess.TableStorage;
using DevOpsMetrics.Core.Models.AzureDevOps;
using DevOpsMetrics.Core.Models.Common;
using DevOpsMetrics.Core.Models.GitHub;
using DevOpsMetrics.Service;
using DevOpsMetrics.Service.Controllers;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Azure.Core;
using Azure.Identity;

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

Check warning on line 11 in src/DevOpsMetrics.Cmd/Program.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Identity' appeared previously in this namespace

namespace DevOpsMetrics.Cmd
{
Expand All @@ -28,12 +29,22 @@ static async Task Main()
IConfigurationRoot Configuration = builder.Build();
ILogger log = new Logger<Program>(new LoggerFactory());

string keyVaultURL = Configuration["AppSettings:KeyVaultURL"];
string keyVaultId = Configuration["AppSettings:KeyVaultClientId"];
string keyVaultSecret = Configuration["AppSettings:KeyVaultClientSecret"];
AzureServiceTokenProvider azureServiceTokenProvider = new();
KeyVaultClient keyVaultClient = new(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault(keyVaultURL, keyVaultId, keyVaultSecret);
string? keyVaultURL = Configuration["AppSettings:KeyVaultURL"];
string? keyVaultId = Configuration["AppSettings:KeyVaultClientId"];
string? keyVaultSecret = Configuration["AppSettings:KeyVaultClientSecret"];
string? tenantId = Configuration["AppSettings:TenantId"];
//AzureServiceTokenProvider azureServiceTokenProvider = new();
//KeyVaultClient keyVaultClient = new(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
//builder.AddAzureKeyVault(keyVaultURL, keyVaultId, keyVaultSecret);
if (keyVaultURL != null && keyVaultId != null && keyVaultSecret != null && tenantId != null)
{
TokenCredential tokenCredential = new ClientSecretCredential(tenantId, keyVaultId, keyVaultSecret);
builder.AddAzureKeyVault(new(keyVaultURL), tokenCredential);
}
else
{
throw new System.Exception("Missing configuration for Azure Key Vault");
}
Configuration = builder.Build();
ServiceApiClient serviceApiClient = new(Configuration);

Expand Down
3 changes: 2 additions & 1 deletion src/DevOpsMetrics.Cmd/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"WebServiceURL": "https://devops-prod-eu-service.azurewebsites.net/",
"KeyVaultURL": "https://devops-prod-eu-vault.vault.azure.net/",
"KeyVaultClientId": "",
"KeyVaultClientSecret": ""
"KeyVaultClientSecret": "",
"TenantId": "40244aae-8aee-4af5-b221-b480db24698b"
},
"ApplicationInsights": {
"InstrumentationKey": "dc3fb590-3612-4f09-8c95-e9378cba8654"
Expand Down
5 changes: 2 additions & 3 deletions src/DevOpsMetrics.Core/DevOpsMetrics.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Data.Tables" Version="12.8.1" />
<PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="1.0.8" />
<PackageReference Include="Azure.Data.Tables" Version="12.8.2" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
Expand Down
7 changes: 4 additions & 3 deletions src/DevOpsMetrics.Function/DevOpsMetrics.Function.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- This needs to stay as a LTS .NET version, otherwise the function needs to be rewritten as an isolated process -->
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<UserSecretsId>ed162474-1392-455c-b088-8b07e5438062</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.24" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
<PackageReference Include="Azure.Identity" Version="1.10.4" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DevOpsMetrics.Core\DevOpsMetrics.Core.csproj" />
Expand Down
22 changes: 17 additions & 5 deletions src/DevOpsMetrics.Function/NightlyProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Azure.Core;
using DevOpsMetrics.Core.DataAccess.TableStorage;
using DevOpsMetrics.Core.Models.AzureDevOps;
using DevOpsMetrics.Core.Models.Common;
using DevOpsMetrics.Core.Models.GitHub;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Azure.Core;

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / buildFunction

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace

Check warning on line 13 in src/DevOpsMetrics.Function/NightlyProcessor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The using directive for 'Azure.Core' appeared previously in this namespace
using Azure.Identity;

namespace DevOpsMetrics.Function
{
Expand All @@ -36,9 +37,20 @@ public static async Task Run(
string keyVaultURL = Configuration["AppSettings:KeyVaultURL"];
string keyVaultId = Configuration["AppSettings:KeyVaultClientId"];
string keyVaultSecret = Configuration["AppSettings:KeyVaultClientSecret"];
AzureServiceTokenProvider azureServiceTokenProvider = new();
KeyVaultClient keyVaultClient = new(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault(keyVaultURL, keyVaultId, keyVaultSecret);
string tenantId = Configuration["AppSettings:TenantId"];
//AzureServiceTokenProvider azureServiceTokenProvider = new();
//KeyVaultClient keyVaultClient = new(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
//builder.AddAzureKeyVault(keyVaultURL, keyVaultId, keyVaultSecret);

if (keyVaultURL != null && keyVaultId != null && keyVaultSecret != null && tenantId != null)
{
TokenCredential tokenCredential = new ClientSecretCredential(tenantId, keyVaultId, keyVaultSecret);
builder.AddAzureKeyVault(new(keyVaultURL), tokenCredential);
}
else
{
throw new System.Exception("Missing configuration for Azure Key Vault");
}
Configuration = builder.Build();
ServiceApiClient serviceApiClient = new(Configuration);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
Expand Down
Loading

0 comments on commit 88558a3

Please sign in to comment.