dotnet build/test precursor #69
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD Build, Test and Deploy | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| paths: | |
| - .github/workflows/gtc-rg-semkernel-api-ci-cd.yml | |
| - src/** | |
| - .github/workflows/gtc-rg-semkernel-iac.yml | |
| - .azure/**/*.bicep | |
| - .azure/**/*.bicepparams | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - .github/workflows/gtc-rg-semkernel-api-ci-cd.yml | |
| - src/** | |
| - .github/workflows/gtc-rg-semkernel-iac.yml | |
| - .azure/**/*.bicep | |
| - .azure/**/*.bicepparams | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Environment to run' | |
| required: true | |
| default: 'development' | |
| mode: | |
| description: 'Running mode' | |
| permissions: | |
| actions: read | |
| id-token: write | |
| contents: read | |
| security-events: write | |
| jobs: | |
| ci: | |
| name: 'CI Build, Test, Code QL, Publish' | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' | |
| environment: development | |
| strategy: | |
| matrix: | |
| DOTNET_VERSION: ['9.x'] | |
| env: | |
| AZURE_WEBAPP_NAME: api-semkernel-dev-001 | |
| AZURE_WEBAPP_PACKAGE_PATH: '.' | |
| AZURE_RG_NAME: 'gtc-rg-devtest-semkernel-dev-001' | |
| RUNTIME_ENV: 'Development' | |
| SRC_PATH: './src' | |
| SRC_SLN: 'SemanticKernelMicroservice.sln' | |
| API_PATH: 'Presentation.WebApi' | |
| API_PROJECT: 'Presentation.WebApi.csproj' | |
| TEST_PATH: 'Tests.Specs.Integration' | |
| TEST_PROJECT: 'Tests.Specs.Integration.csproj' | |
| SCRIPTS_PATH: './.github/scripts' | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@v3 | |
| - name: dotnet version ${{ matrix.DOTNET_VERSION }} | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ matrix.DOTNET_VERSION }} | |
| - name: Set-Version.ps1 | |
| run: | | |
| $version = ${{ env.SCRIPTS_PATH }}/Set-Version.ps1 -Path ${{ env.SRC_PATH }} -VersionToReplace 1.0.0 | |
| echo $version | |
| echo "VERSION=$version" >> $GITHUB_ENV | |
| shell: pwsh | |
| - name: pipeline configuration secrets | |
| run: | | |
| echo "ASPNETCORE_ENVIRONMENT=${{ env.RUNTIME_ENV }}" >> $GITHUB_ENV | |
| echo "AZURE_FUNCTIONS_ENVIRONMENT=${{ env.RUNTIME_ENV }}" >> $GITHUB_ENV | |
| echo "OpenAI:ApiKey=${{ secrets.OPENAI_APIKEY }}" >> $GITHUB_ENV | |
| shell: pwsh | |
| - name: App Settings Variable Substitution | |
| uses: microsoft/variable-substitution@v1 | |
| with: | |
| files: '${{ env.SRC_PATH }}/${{ env.API_PATH }}/appsettings.json, ${{ env.SRC_PATH }}/${{ env.API_PATH }}/appsettings.${{ env.RUNTIME_ENV }}.json, ${{ env.SRC_PATH }}/${{ env.TEST_PATH }}/appsettings.test.json' | |
| env: | |
| OpenAI.ApiKey: ${{ secrets.OPENAI_APIKEY }} | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v3 | |
| with: | |
| languages: csharp | |
| - name: Build | |
| run: | | |
| dotnet build ${{ env.SRC_PATH }}/${{ env.SRC_SLN }} --configuration Release | |
| shell: pwsh | |
| - name: Test | |
| run: | | |
| mkdir -p TestResults-${{ matrix.DOTNET_VERSION }} | |
| dotnet test ${{ env.SRC_PATH }}/${{ env.TEST_PATH }}/${{ env.TEST_PROJECT }} --logger "trx;LogFileName=test_results.trx" --results-directory TestResults-${{ matrix.DOTNET_VERSION }} --verbosity normal | |
| shell: pwsh | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-dotnet-${{ matrix.DOTNET_VERSION }} | |
| path: TestResults-${{ matrix.DOTNET_VERSION }} | |
| if: ${{ always() }} | |
| - name: Run Coverage Script | |
| run: | | |
| pwsh ${{ env.SRC_PATH }}/Get-CodeCoverage.ps1 ` | |
| -TestProjectFilter '${{ env.TEST_PROJECT }}' ` | |
| -ProdPackagesOnly ` | |
| -ProductionAssemblies Cannery.Insights.Core.Application Cannery.Insights.Presentation.WebApi Cannery.Insights.Presentation.Blazor | |
| shell: pwsh | |
| - name: Upload Coverage Report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report-${{ matrix.DOTNET_VERSION }} | |
| path: ${{ env.SRC_PATH }}/TestResults/Reports/**/index.html | |
| if: ${{ always() }} | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v3 | |
| cd: | |
| name: 'CD Deploy .NET' | |
| runs-on: ubuntu-latest | |
| needs: ci | |
| if: | | |
| github.event_name == 'push' && | |
| contains(github.ref, 'refs/tags/deploy') | |
| environment: development | |
| strategy: | |
| matrix: | |
| DOTNET_VERSION: ['9.x'] | |
| env: | |
| AZURE_WEBAPP_NAME: api-semkernel-dev-001 | |
| AZURE_WEBAPP_PACKAGE_PATH: '.' | |
| AZURE_RG_NAME: 'gtc-rg-devtest-semkernel-dev-001' | |
| RUNTIME_ENV: 'Development' | |
| SRC_PATH: './src' | |
| SRC_SLN: 'SemanticKernelMicroservice.sln' | |
| API_PATH: 'Presentation.WebApi' | |
| API_PROJECT: 'Presentation.WebApi.csproj' | |
| APPI_NAME: 'appi-semkernel-dev-001' | |
| INFRA_PATH: 'Infrastructure.SqlServer' | |
| INFRA_PROJECT: 'Infrastructure.SqlServer.csproj' | |
| INFRA_DBCONTEXT: 'SemanticKernelContext' | |
| TEST_PATH: 'Tests.Specs.Integration' | |
| TEST_PROJECT: 'Tests.Specs.Integration.csproj' | |
| SCRIPTS_PATH: './.github/scripts' | |
| SQL_NAME: 'sql-semkernel-dev-001' | |
| SQLDB_NAME: 'sqldb-semkernel-dev-001' | |
| AZURE_CRED: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","subscriptionId":"${{ secrets.SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}' | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@v3 | |
| - name: dotnet version ${{ matrix.DOTNET_VERSION }} | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ matrix.DOTNET_VERSION }} | |
| - name: Set-Version.ps1 | |
| run: | | |
| $version = ${{ env.SCRIPTS_PATH }}/Set-Version.ps1 -Path ${{ env.SRC_PATH }} -VersionToReplace 1.0.0 | |
| echo $version | |
| echo "VERSION=$version" >> $GITHUB_ENV | |
| shell: pwsh | |
| - name: pipeline configuration secrets | |
| run: | | |
| echo "ASPNETCORE_ENVIRONMENT=${{ env.RUNTIME_ENV }}" >> $GITHUB_ENV | |
| echo "AZURE_FUNCTIONS_ENVIRONMENT=${{ env.RUNTIME_ENV }}" >> $GITHUB_ENV | |
| echo "OpenAI:ApiKey=${{ secrets.OPENAI_APIKEY }}" >> $GITHUB_ENV | |
| shell: pwsh | |
| - name: App Settings Variable Substitution | |
| uses: microsoft/variable-substitution@v1 | |
| with: | |
| files: '${{ env.SRC_PATH }}/${{ env.API_PATH }}/appsettings.json, ${{ env.SRC_PATH }}/${{ env.API_PATH }}/appsettings.${{ env.RUNTIME_ENV }}.json, ${{ env.SRC_PATH }}/${{ env.TEST_PATH }}/appsettings.test.json' | |
| env: | |
| OpenAI.ApiKey: ${{ secrets.OPENAI_APIKEY }} | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v3 | |
| with: | |
| languages: csharp | |
| - name: Build | |
| run: | | |
| dotnet build ${{ env.SRC_PATH }}/${{ env.SRC_SLN }} --configuration Release | |
| shell: pwsh | |
| - name: Test | |
| run: | | |
| mkdir -p TestResults-${{ matrix.DOTNET_VERSION }} | |
| dotnet test ${{ env.SRC_PATH }}/${{ env.TEST_PATH }}/${{ env.TEST_PROJECT }} --logger "trx;LogFileName=test_results.trx" --results-directory TestResults-${{ matrix.DOTNET_VERSION }} --verbosity normal | |
| shell: pwsh | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-dotnet-${{ matrix.DOTNET_VERSION }} | |
| path: TestResults-${{ matrix.DOTNET_VERSION }} | |
| if: ${{ always() }} | |
| - name: Run Coverage Script | |
| run: | | |
| pwsh ${{ env.SRC_PATH }}/Get-CodeCoverage.ps1 ` | |
| -TestProjectFilter '${{ env.TEST_PROJECT }}' ` | |
| -ProdPackagesOnly ` | |
| -ProductionAssemblies Cannery.Insights.Core.Application Cannery.Insights.Presentation.WebApi Cannery.Insights.Presentation.Blazor | |
| shell: pwsh | |
| - name: Upload Coverage Report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report-${{ matrix.DOTNET_VERSION }} | |
| path: ${{ env.SRC_PATH }}/TestResults/Reports/**/index.html | |
| if: ${{ always() }} | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v3 | |
| - name: Publish | |
| run: | | |
| dotnet publish ${{ env.SRC_PATH }}/${{ env.API_PATH }}/${{ env.API_PROJECT }} --configuration Release -o ${{ env.AZURE_WEBAPP_NAME }} | |
| shell: pwsh | |
| - name: az login | |
| uses: azure/login@v1 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: get publish profile | |
| id: publishprofile | |
| uses: aliencube/publish-profile-actions@v1 | |
| env: | |
| AZURE_CREDENTIALS: ${{ env.AZURE_CRED }} | |
| with: | |
| resourceGroupName: ${{ env.AZURE_RG_NAME }} | |
| appName: ${{ env.AZURE_WEBAPP_NAME }} | |
| - name: functionapp deploy | |
| uses: Azure/functions-action@v1 | |
| with: | |
| app-name: ${{ env.AZURE_WEBAPP_NAME }} | |
| package: '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/${{ env.AZURE_WEBAPP_NAME }}' | |
| publish-profile: ${{ steps.publishprofile.outputs.profile }} | |
| if: ${{ false }} | |
| - name: webapps deploy | |
| uses: azure/webapps-deploy@v2 | |
| with: | |
| app-name: ${{ env.AZURE_WEBAPP_NAME }} | |
| publish-profile: ${{ steps.publishprofile.outputs.profile }} | |
| package: '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/${{ env.AZURE_WEBAPP_NAME }}' | |
| #slot-name: staging | |
| - name: Reset publish profile | |
| uses: aliencube/publish-profile-actions@v1 | |
| env: | |
| AZURE_CREDENTIALS: ${{ secrets.AZURE_CRED }} | |
| with: | |
| resourceGroupName: ${{ env.AZURE_RG_NAME }} | |
| appName: ${{ env.AZURE_WEBAPP_NAME }} | |
| reset: true | |
| # Get instrumentation key: az monitor app-insights component show --app <app-name> -g <rg-name> | |
| # Get connection: az monitor app-insights component show -g ${{ env.AZURE_RG_NAME }} --app ${{ env.APPI_NAME }} | |
| - name: ${{ env.AZURE_WEBAPP_NAME }} app settings | |
| run: | | |
| az config set extension.use_dynamic_install=yes_without_prompt | |
| $TEMP_JSON = az monitor app-insights component show -g ${{ env.AZURE_RG_NAME }} --app ${{ env.APPI_NAME }} | ConvertFrom-Json | |
| $INSTR_KEY = $TEMP_JSON.instrumentationKey | |
| $CONN_STR = $TEMP_JSON.connectionString | |
| az webapp config appsettings set -g ${{ env.AZURE_RG_NAME }} -n ${{ env.AZURE_WEBAPP_NAME }} --settings APPINSIGHTS_INSTRUMENTATIONKEY=$INSTR_KEY | |
| az webapp config appsettings set -g ${{ env.AZURE_RG_NAME }} -n ${{ env.AZURE_WEBAPP_NAME }} --settings APPLICATIONINSIGHTS_CONNECTION_STRING=$CONN_STR | |
| az webapp config appsettings set -g ${{ env.AZURE_RG_NAME }} -n ${{ env.AZURE_WEBAPP_NAME }} --settings ASPNETCORE_ENVIRONMENT=${{ env.RUNTIME_ENV }} | |
| shell: pwsh | |
| # Get Azure SQL DB Conenction: az sql db show-connection-string --client ado.net --server ${{ env.SQL_NAME }} --name ${{ env.SQLDB_NAME }} -o tsv | |
| - name: ${{ env.AZURE_WEBAPP_NAME }} connection strings | |
| run: | | |
| $TEMP_STR=az sql db show-connection-string --client ado.net --server ${{ env.SQL_NAME }} --name ${{ env.SQLDB_NAME }} -o tsv | |
| $TEMP_STR=$TEMP_STR.replace("<username>", "${{ secrets.SQL_ADMIN_USER }}") | |
| $TEMP_STR=$TEMP_STR.replace("<password>", "${{ secrets.SQL_ADMIN_PASSWORD }}") | |
| az webapp config connection-string set -g ${{ env.AZURE_RG_NAME }} -n ${{ env.AZURE_WEBAPP_NAME }} -t SQLServer --settings DefaultConnection=$TEMP_STR | |
| shell: pwsh | |
| - name: ${{ env.AZURE_WEBAPP_NAME }} dotnet ef migrations | |
| run: | | |
| $TEMP_STR=az sql db show-connection-string --client ado.net --server ${{ env.SQL_NAME }} --name ${{ env.SQLDB_NAME }} -o tsv | |
| $TEMP_STR=$TEMP_STR.replace("<username>", "${{ secrets.SQL_ADMIN_USER }}") | |
| $TEMP_STR=$TEMP_STR.replace("<password>", "${{ secrets.SQL_ADMIN_PASSWORD }}") | |
| dotnet tool install --global dotnet-ef | |
| dotnet tool restore | |
| dotnet ef migrations add v${{ env.VERSION }} --project ${{ env.SRC_PATH }}/${{ env.INFRA_PATH }}/${{ env.INFRA_PROJECT }} --startup-project ${{ env.SRC_PATH }}/${{ env.API_PATH }}/${{ env.API_PROJECT }} --context ${{ env.INFRA_DBCONTEXT }} | |
| dotnet ef migrations script --project ${{ env.SRC_PATH }}/${{ env.INFRA_PATH }}/${{ env.INFRA_PROJECT }} --startup-project ${{ env.SRC_PATH }}/${{ env.API_PATH }}/${{ env.API_PROJECT }} --context ${{ env.INFRA_DBCONTEXT }} --output ${{ github.workspace }}/sql/migrations.sql --idempotent | |
| dotnet ef database update --project ${{ env.SRC_PATH }}/${{ env.INFRA_PATH }}/${{ env.INFRA_PROJECT }} --startup-project ${{ env.SRC_PATH }}/${{ env.API_PATH }}/${{ env.API_PROJECT }} --context ${{ env.INFRA_DBCONTEXT }} --connection $TEMP_STR | |
| shell: pwsh | |
| - name: Swap to production slot | |
| run: | | |
| az webapp deployment slot swap --resource-group ${{ env.AZURE_RG_NAME }} --name ${{ env.AZURE_WEBAPP_NAME }} --slot staging --target-slot production | |
| echo "Swap finished. App Service Application URL: https://$(az webapp show --resource-group ${{ env.AZURE_RG_NAME }} --name ${{ env.AZURE_WEBAPP_NAME }} --query hostNames[0] -o tsv)" | |
| if: ${{ false }} |