Skip to content

Feature Flags CI/CD #10126

Feature Flags CI/CD

Feature Flags CI/CD #10126

Workflow file for this run

name: "Feature Flags CI/CD"
on:
push:
schedule:
- cron: '0 5 * * *'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
dotNetVersion: net8.0
dotNetConfiguration: Release
dotNetSDKVersion: 8.0.x
dotNetSDKIncludePrerelease: false
runtimeTarget: win-x86
jobs:
build:
runs-on: windows-latest
outputs: # https://stackoverflow.com/questions/59175332/using-output-from-a-previous-job-in-a-new-one-in-a-github-action
Version: ${{ steps.gitversion.outputs.nuGetVersionV2 }}
CommitsSinceVersionSource: ${{ steps.gitversion.outputs.CommitsSinceVersionSource }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 #fetch-depth is needed for GitVersion
# install and calculate the new version with GitVersion
- name: Install GitVersion
uses: gittools/actions/gitversion/setup@v1.2.0
with:
versionSpec: '5.x'
- name: Determine Version
uses: gittools/actions/gitversion/execute@v1.2.0
id: gitversion # step id used as reference for output values
- name: Display GitVersion outputs
run: |
echo "MajorMinorPatch: ${{ steps.gitversion.outputs.majorMinorPatch }}"
echo "NuGetVersionV2: ${{ steps.gitversion.outputs.nuGetVersionV2 }}"
echo "CommitsSinceVersionSource: ${{ steps.gitversion.outputs.CommitsSinceVersionSource }}"
# install dependencies, build, and test
- name: Setup Dotnet for use with actions
uses: actions/setup-dotnet@v4.0.1
with:
dotnet-version: ${{ env.dotNetSDKVersion }}
include-prerelease: ${{ env.dotNetSDKIncludePrerelease }}
#Publish web and web service projects
- name: DotNet Publish Web Service
run: dotnet publish src/FeatureFlags.Service/FeatureFlags.Service.csproj --configuration ${{ env.dotNetConfiguration }} -p:Version=${{ steps.gitversion.outputs.nuGetVersionV2 }} --output ${{ github.workspace }}/webservice --runtime ${{env.runtimeTarget}} --self-contained false # --self-contained true --runtime ${{env.runtimeTarget}}
- name: DotNet Publish Web Site
run: dotnet publish src/FeatureFlags.Web/FeatureFlags.Web.csproj --configuration ${{ env.dotNetConfiguration }} -p:Version=${{ steps.gitversion.outputs.nuGetVersionV2 }} --output ${{ github.workspace }}/web --runtime ${{env.runtimeTarget}} --self-contained false # --self-contained true --runtime ${{env.runtimeTarget}}
- name: DotNet Publish Demo Web Site
run: dotnet publish src/FeatureFlagsDemo.Web/FeatureFlagsDemo.Web.csproj --configuration ${{ env.dotNetConfiguration }} -p:Version=${{ steps.gitversion.outputs.nuGetVersionV2 }} --output ${{ github.workspace }}/webDemo --runtime ${{env.runtimeTarget}} --self-contained false # --self-contained true --runtime ${{env.runtimeTarget}}
#Publish functional tests
- name: DotNet build functional tests
run: dotnet build src/FeatureFlags.FunctionalTests/FeatureFlags.FunctionalTests.csproj --configuration ${{ env.dotNetConfiguration }} --runtime ${{env.runtimeTarget}} #--self-contained false #--self-contained true --runtime ${{env.runtimeTarget}}
- name: DotNet Publish functional tests
run: dotnet publish src/FeatureFlags.FunctionalTests/FeatureFlags.FunctionalTests.csproj --configuration ${{ env.dotNetConfiguration }} --output ${{ github.workspace }}/functionalTests --runtime ${{env.runtimeTarget}} --self-contained false # --self-contained true --runtime ${{env.runtimeTarget}}
- name: Copy chromedriver for functional test
run: copy "src/FeatureFlags.FunctionalTests/bin/${{ env.dotNetConfiguration }}/${{ env.dotNetVersion }}/${{env.runtimeTarget}}/chromedriver.exe" "${{ github.workspace }}/functionalTests"
shell: powershell
- name: DotNet restore functional tests to get correct Newtonsoft version
run: dotnet restore src/FeatureFlags.FunctionalTests/FeatureFlags.FunctionalTests.csproj
- name: Copy new NewtonSoft version for functional test
run: copy "src/FeatureFlags.FunctionalTests/bin/${{ env.dotNetConfiguration }}/${{ env.dotNetVersion }}/${{env.runtimeTarget}}/Newtonsoft.Json.dll" "${{ github.workspace }}/functionalTests"
shell: powershell
#Publish build artifacts to GitHub
- name: Upload web service build artifacts back to GitHub
uses: actions/upload-artifact@v4
with:
name: serviceapp
path: ${{ github.workspace }}/webservice
- name: Upload website build artifacts back to GitHub
uses: actions/upload-artifact@v4
with:
name: webapp
path: ${{ github.workspace }}/web
- name: Upload website build artifacts back to GitHub
uses: actions/upload-artifact@v4
with:
name: webappDemo
path: ${{ github.workspace }}/webDemo
- name: Upload function test build artifacts back to GitHub
uses: actions/upload-artifact@v4
with:
name: functionaltests
path: ${{ github.workspace }}/functionalTests
test:
runs-on: windows-latest
permissions:
actions: read
steps:
- uses: actions/checkout@v4
# install dependencies, build, and test
- name: Setup Dotnet for use with actions
uses: actions/setup-dotnet@v4.0.1
with:
dotnet-version: ${{ env.dotNetSDKVersion }}
include-prerelease: ${{ env.dotNetSDKIncludePrerelease }}
# Test service
- name: Variable Substitution appsettings file for tests
uses: microsoft/variable-substitution@v1
with:
files: 'src/FeatureFlags.Tests/appsettings.json'
env:
AppSettings.ClientSecret: "${{ secrets.ClientSecret }}"
- name: Build automated tests project
run: dotnet build src/FeatureFlags.Tests/FeatureFlags.Tests.csproj --configuration ${{ env.dotNetConfiguration }}
- name: Run automated unit and integration tests
run: dotnet test src/FeatureFlags.Tests/FeatureFlags.Tests.csproj --configuration ${{ env.dotNetConfiguration }} --settings:./src/FeatureFlags.Tests/CodeCoverage.runsettings #/p:CollectCoverage=true /p:CoverletOutput=TestResults/ /p:CoverletOutputFormat=lcov
- name: Publish coverage report to coveralls.io
uses: coverallsapp/github-action@master
if: 0 == 1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: src/FeatureFlags.Tests/TestResults/coverage.info
#Deploy the artifacts to Azure
deploy:
runs-on: windows-2022
needs: [build, test]
steps:
# Install SDK for Selenium/Functional tests
- name: Setup Dotnet for use with actions
uses: actions/setup-dotnet@v4.0.1
with:
dotnet-version: ${{ env.dotNetSDKVersion }}
include-prerelease: ${{ env.dotNetSDKIncludePrerelease }}
# Login with the secret SP details
- name: Log into Azure
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_SP }}
- name: Deployment setup PowerShell script
run: |
Write-Host "Starting deployment"
Write-Host "Continuing deployment"
shell: powershell
#Download the artifacts from GitHub
- name: Download serviceapp artifact
uses: actions/download-artifact@v4
with:
name: serviceapp
path: serviceapp
- name: Download webapp artifact
uses: actions/download-artifact@v4
with:
name: webapp
path: webapp
- name: Download webappDemo artifact
uses: actions/download-artifact@v4
with:
name: webappDemo
path: webappDemo
- name: Download functionaltests artifact
uses: actions/download-artifact@v4
with:
name: functionaltests
path: functionaltests
#Deploy service and website to Azure staging slots
- name: Deploy web service to Azure WebApp
uses: Azure/webapps-deploy@v3
with:
app-name: featureflags-prod-eu-service
package: serviceapp
#slot-name: staging
- name: Set service secrets
run: az webapp config appsettings set --name "featureflags-prod-eu-service" --resource-group "FeatureFlags" --settings "AppSettings:ClientSecret=${{ secrets.ClientSecret }}" #--slot staging
- name: Deploy website to Azure WebApp
uses: Azure/webapps-deploy@v3
with:
app-name: featureflags-prod-eu-web
package: webapp
#slot-name: staging
- name: Deploy website demo to Azure WebApp
uses: Azure/webapps-deploy@v3
with:
app-name: featureflagsdemo-prod-eu-web
package: webappDemo
#slot-name: staging
# Run functional tests on staging slots
- name: Functional Tests
if: 1 == 0
run: |
$vsTestConsoleExe = "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Common7\\IDE\\Extensions\\TestPlatform\\vstest.console.exe"
$targetTestDll = "functionaltests\FeatureFlags.FunctionalTests.dll"
$testRunSettings = "/Settings:`"functionaltests\test.runsettings`" "
$parameters = " -- ServiceUrl=""https://featureflags-prod-eu-service.azurewebsites.net/"" WebsiteUrl=""https://featureflags-prod-eu-web.azurewebsites.net/"" "
#Note that the `" is an escape character to quote strings, and the `& is needed to start the command
$command = "`& `"$vsTestConsoleExe`" `"$targetTestDll`" $testRunSettings $parameters "
Write-Host "$command"
Invoke-Expression $command
shell: powershell
sonarCloud:
name: Run SonarCloud analysis
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Run Sonarcloud test
uses: samsmithnz/SamsDotNetSonarCloudAction@v2
with:
projects: 'src/FeatureFlags.Service/FeatureFlags.Service.csproj,src/FeatureFlags.ConsoleApp/FeatureFlags.ConsoleApp.csproj,src/FeatureFlags.FunctionalTests/FeatureFlags.FunctionalTests.csproj,src/FeatureFlags.Models/FeatureFlags.Models.csproj,src/FeatureFlags.Tests/FeatureFlags.Tests.csproj,src/FeatureFlags.Web/FeatureFlags.Web.csproj,src/FeatureFlagsDemo.Web/FeatureFlagsDemo.Web.csproj'
dotnet-version: '8.0.x'
sonarcloud-organization: samsmithnz-github
sonarcloud-project: samsmithnz_SamsFeatureFlags
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
#Deploy the artifacts to Azure
release:
runs-on: ubuntu-latest # Note, Azure CLI requires a Linux runner...
needs:
- build
- deploy
- sonarCloud
#Only deploy if running off the main branch - we don't want to deploy off feature branches
if: github.ref == 'refs/heads/main'
steps:
- name: Display GitVersion outputs
run: |
echo "Version: ${{ needs.build.outputs.Version }}"
echo "CommitsSinceVersionSource: ${{ needs.build.outputs.CommitsSinceVersionSource }}"
- name: Create Release
id: create_release
uses: actions/create-release@v1
if: needs.build.outputs.CommitsSinceVersionSource > 0 #Only create a release if there has been a commit change
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: "v${{ needs.build.outputs.Version }}"
release_name: "v${{ needs.build.outputs.Version }}"
# Login with the secret SP details
- name: Log into Azure
if: 0==1
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_SP }}
#Swap staging slots with prod
- name: Swap web service staging slot to production
if: 0==1
uses: Azure/cli@v2.0.0
with:
inlineScript: az webapp deployment slot swap --resource-group FeatureFlags --name featureflags-prod-eu-service --slot staging --target-slot production
- name: Swap web site staging slot to production
if: 0==1
uses: Azure/cli@v2.0.0
with:
inlineScript: az webapp deployment slot swap --resource-group FeatureFlags --name featureflags-prod-eu-web --slot staging --target-slot production