Add Copilot event manager tests and deduplication fixes #242
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: Release build | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - dev | |
| paths: | |
| - src/** | |
| - reports/** | |
| - .github/** | |
| workflow_dispatch: | |
| env: | |
| Solution_Directory: src\AnalyticsEngine\ | |
| Build_Platform: Any CPU | |
| Build_ProcessorArchitecture: x86 | |
| ClientID: ${{ secrets.APP_CLIENTID }} | |
| ClientSecret: ${{ secrets.APP_CLIENTSECRET }} | |
| TenantGUID: ${{ secrets.APP_TENANTGUID }} | |
| TenantDomain: ${{ secrets.APP_TENANTDOMAIN }} | |
| CognitiveEndpoint: ${{ secrets.APP_COGNITIVEENDPOINT }} | |
| CognitiveKey: ${{ secrets.APP_COGNITIVEKEY}} | |
| CosmosDbTestContainerCurrent: stats | |
| CosmosDbTestContainerHistory: history | |
| CosmosDbTestDatabaseName: UnitTestDevOps | |
| CosmosDb: ${{ secrets.APP_COSMOSDB }} | |
| redis: ${{ secrets.CONNECTIONSTRINGS_REDIS }} | |
| ServiceBus: ${{ secrets.CONNECTIONSTRINGS_SERVICEBUS }} | |
| Storage: ${{ secrets.CONNECTIONSTRINGS_STORAGE }} | |
| SoftwareDownloadURL: ${{ secrets.SOFTWAREDOWNLOADURL }} | |
| StatsApiSecret: ${{ secrets.STATSAPISECRET }} | |
| StatsApiUrl: ${{ secrets.STATSAPIURL }} | |
| jobs: | |
| setup_build: | |
| # This step will calculate the build number with an offset | |
| # so that build numbers will follow the ones from Azure DevOps. | |
| # It will also check that the important folders have been updated. | |
| runs-on: ubuntu-latest | |
| outputs: | |
| build_number: ${{ steps.build_number.outputs.number }} | |
| steps: | |
| - name: Calculate build number | |
| id: build_number | |
| run: echo "number=$((${{ vars.BUILD_NUMBER_OFFSET }} + ${{ github.run_number }}))" >> "$GITHUB_OUTPUT" | |
| build_dotnet: | |
| # Preparation: | |
| # - Get signing certificate | |
| # - Transform configuration files | |
| # - Restore dependencies | |
| # Build: | |
| # - Build .Net projects | |
| # Output: | |
| # - Clean .Net builds | |
| # - Copy PS scripts | |
| # - Zip files | |
| # - Publish artifacts | |
| runs-on: windows-latest | |
| needs: setup_build | |
| strategy: | |
| matrix: | |
| configuration: [Release] # [Debug, Release] | |
| project: | |
| - name: WebJob.AppInsightsImporter | |
| file: WebJob.AppInsightsImporter.csproj | |
| outDir: AppInsightsImporter | |
| compressFolder: AppInsightsImporter | |
| - name: WebJob.Office365ActivityImporter | |
| file: WebJob.Office365ActivityImporter.csproj | |
| outDir: Office365ActivityImporter | |
| compressFolder: Office365ActivityImporter | |
| - name: Web | |
| file: Web.csproj | |
| outDir: Website | |
| compressFolder: Website\_PublishedWebsites\Web | |
| - name: App.ControlPanel | |
| file: App.ControlPanel.WinForms.csproj | |
| outDir: ControlPanelApp | |
| compressFolder: ControlPanelApp | |
| env: | |
| BuildId: ${{ needs.setup_build.outputs.build_number }} | |
| BuildLabel: Build ${{ needs.setup_build.outputs.build_number }} | |
| steps: | |
| - name: This is ${{ env.BuildLabel }} | |
| run: echo ${{ env.BuildId }} | |
| - name: Prepare build | |
| id: prep | |
| shell: bash | |
| run: | | |
| mkdir -p "${{ env.Zips_Folder }}" | |
| echo "ZIPS_FOLDER=${{ env.Zips_Folder }}" >> "$GITHUB_OUTPUT" | |
| echo "PFX_PATH=${{ env.Pfx_Path }}" >> "$GITHUB_OUTPUT" | |
| env: | |
| Zips_Folder: ${{ runner.temp }}/zips/ | |
| Pfx_Path: ${{ runner.temp }}/SPOInsightsBinaries.pfx | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| - name: Setup MSBuild | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Cache NuGet Packages | |
| id: nuget-packages | |
| uses: actions/cache@v4 | |
| if: false | |
| env: | |
| cache-name: nuget-package-cache | |
| with: | |
| path: ~\.nuget\packages | |
| key: ${{ runner.os }}-${{ env.cache-name }} | |
| # Configuration files | |
| - name: Year substitution | |
| shell: bash | |
| run: | | |
| year=$(date +%Y) | |
| find ./src -name AssemblyInfo.cs | xargs sed -i "s/© __year__/© $year/" | |
| - name: Config substitutions | |
| uses: devops-actions/variable-substitution@v1.2 | |
| with: | |
| files: '${{ env.Solution_Directory }}\*\App.Release.config, ${{ env.Solution_Directory }}\Web\Web.Release.config' | |
| # Build the project | |
| - name: Restore the application | |
| run: msbuild ${{ env.Solution_Directory }}\${{ matrix.project.name }}\${{ matrix.project.file }} -t:Restore ` | |
| -p:Configuration=${{ matrix.configuration }} ` | |
| -p:Platform="${{ env.Build_Platform }}" ` | |
| -p:ProcessorArchitecture=${{ env.Build_ProcessorArchitecture }} | |
| - name: Build ${{ matrix.project.name }} | |
| run: msbuild ${{ env.Solution_Directory }}\${{ matrix.project.name }}\${{ matrix.project.file }} ` | |
| -p:Configuration=${{ matrix.configuration }} ` | |
| -p:Platform="${{ env.Build_Platform }}" ` | |
| -p:ProcessorArchitecture=${{ env.Build_ProcessorArchitecture }} ` | |
| -p:OutDir=${{ runner.temp }}\${{ matrix.project.outDir }} ` | |
| -p:OutputPath=${{ matrix.configuration }} ` | |
| -p:AllowedReferenceRelatedFileExtensions=none ` | |
| -p:EmitCompilerGeneratedFiles=false | |
| - name: Copy Automation scripts (WebJob.Office365ActivityImporter only) | |
| if: matrix.project.name == 'WebJob.Office365ActivityImporter' | |
| run: | | |
| Copy-Item -Verbose -Force -Recurse ` | |
| -Path "src/AnalyticsEngine/WebJob.Office365ActivityImporter/AutomationPS" ` | |
| -Destination "${{ runner.temp }}\Office365ActivityImporter\" | |
| - name: Setup SignTool | |
| uses: KamaranL/add-signtool-action@v1 | |
| id: signtool | |
| - name: Decode the PFX | |
| if: matrix.project.name == 'App.ControlPanel' | |
| run: | | |
| $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.PFX_BASE64 }}") | |
| [IO.File]::WriteAllBytes("${{ steps.prep.outputs.PFX_PATH }}", $pfx_cert_byte) | |
| - name: Debug SignTool Outputs | |
| if: matrix.project.name == 'App.ControlPanel' | |
| run: | | |
| Write-Host "Available SignTool outputs:" | |
| Write-Host "signtool-x64: '${{ steps.signtool.outputs.signtool-x64 }}'" | |
| Write-Host "signtool-x86: '${{ steps.signtool.outputs.signtool-x86 }}'" | |
| Write-Host "Runner Arch: ${{ runner.arch }}" | |
| Write-Host "ENV RUNNER_ARCH: $env:RUNNER_ARCH" | |
| - name: Sign installer | |
| if: matrix.project.name == 'App.ControlPanel' | |
| run: | | |
| $signtoolPath = "${{ steps.signtool.outputs.signtool-x64 }}" | |
| if ([string]::IsNullOrEmpty($signtoolPath)) { | |
| # Fallback to PATH | |
| Write-Host "SignTool output is empty, using PATH" | |
| $signtoolPath = "signtool.exe" | |
| } else { | |
| Write-Host "Using SignTool from output: $signtoolPath" | |
| } | |
| & $signtoolPath sign /fd SHA256 /a /t http://timestamp.digicert.com /v ` | |
| /f "${{ steps.prep.outputs.PFX_PATH }}" /p "${{ secrets.PFX_KEY}}" ` | |
| "${{ runner.temp }}\ControlPanelApp\AnalyticsInstaller.exe" | |
| - name: Remove the PFX | |
| if: matrix.project.name == 'App.ControlPanel' | |
| run: | | |
| Remove-Item -Path "${{ steps.prep.outputs.PFX_PATH }}" | |
| - name: Archive ${{ matrix.project.name }} | |
| run: | | |
| Remove-Item -Force -Recurse -ErrorAction SilentlyContinue "${{ runner.temp }}\AppInsightsImporter\_PublishedWebsites" | |
| Remove-Item -Force -Recurse -ErrorAction SilentlyContinue "${{ runner.temp }}\Office365ActivityImporter\_PublishedWebsites" | |
| Remove-Item -Force -Recurse -ErrorAction SilentlyContinue "${{ runner.temp }}\Website\_PublishedWebsites\Web\bin\Scripts" | |
| Compress-Archive -Force -Path "${{ runner.temp }}\${{ matrix.project.compressFolder }}" ` | |
| -DestinationPath "${{ steps.prep.outputs.ZIPS_FOLDER }}\${{ matrix.project.outDir }}.zip" | |
| # Wrap up | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: ${{ steps.prep.outputs.ZIPS_FOLDER }} | |
| name: drop_${{ matrix.project.name }} | |
| if-no-files-found: error | |
| build_aitracker: | |
| # NPM ai tracker | |
| # Build: | |
| # - Build AI Tracker | |
| # Output: | |
| # - Clean AI Tracker | |
| # - Zip files | |
| # - Publish artifacts | |
| runs-on: ubuntu-latest | |
| needs: setup_build | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| - name: Build AITracker | |
| run: | | |
| cd src/SPO/AITracker/TypeScript | |
| npm ci | |
| npm run build:prod | |
| cd ../.. | |
| rm -rf AITracker/TypeScript | |
| zip -r AITrackerInstaller.zip AITracker | |
| # Wrap up | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: src/SPO/AITrackerInstaller.zip | |
| name: drop_aitracker | |
| if-no-files-found: error | |
| build_reports: | |
| runs-on: windows-latest | |
| needs: setup_build | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| - name: Archive Reports | |
| run: | | |
| Get-ChildItem '.\reports\Usage Analytics\*' ` | |
| -Exclude "*_base.pbit" -Include "*.pbit","Readme.txt" | Compress-Archive ` | |
| -Force -DestinationPath "${{ runner.temp }}\Analytics_Reports.zip" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| path: ${{ runner.temp }}/Analytics_Reports.zip | |
| name: drop_Reports | |
| if-no-files-found: error | |
| release: | |
| runs-on: ubuntu-latest | |
| needs: | |
| - setup_build | |
| - build_dotnet | |
| - build_aitracker | |
| - build_reports | |
| permissions: | |
| # Required to create tags in the repo | |
| contents: write | |
| env: | |
| BuildId: ${{ needs.setup_build.outputs.build_number }} | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| if: false | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Changelog Generator | |
| if: false | |
| run: sudo gem install github_changelog_generator | |
| - name: Generate Changelog | |
| if: false | |
| run: | | |
| git branch | |
| last_tag="" | |
| extra="" | |
| if ( git describe --tags --abbrev=0 ); then | |
| last_tag=$(git describe --tags --abbrev=0) | |
| extra="--since-tag $last_tag" | |
| fi | |
| echo $extra | xargs github_changelog_generator -u pnp -p Microsoft365-Analytics-Insights \ | |
| --token ${{ github.token }} \ | |
| --release-branch ${{ github.ref_name }} | |
| sed -i '/\[Unreleased\]/,+1d' CHANGELOG.md | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| id: artifacts | |
| - name: Generate release label | |
| run: | | |
| if [ "${{ github.ref_name }}" != "main" ]; then | |
| echo "LABEL=Testing build ${{ env.BuildId }}" >> $GITHUB_ENV | |
| else | |
| echo "LABEL=Stable build ${{ env.BuildId }}" >> $GITHUB_ENV | |
| fi | |
| - name: Create release | |
| uses: ncipollo/release-action@v1.14.0 | |
| id: create_release | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| BASE: ${{ steps.artifacts.outputs.download-path }} | |
| with: | |
| draft: ${{ vars.PUBLISH_RELEASES != 'true' }} | |
| prerelease: ${{ github.ref_name != 'main' }} | |
| makeLatest: ${{ github.ref_name == 'main' }} | |
| name: ${{ env.LABEL }} | |
| tag: ${{ env.BuildId }} | |
| commit: ${{ github.sha }} | |
| # bodyFile: CHANGELOG.md | |
| generateReleaseNotes: true | |
| artifacts: "${{ env.BASE }}/**/*.zip" | |
| artifactContentType: application/zip |