如何优化GitHub Dotnet构建部署工作流,满足分阶段按需部署需求?
Optimized GitHub Workflow for Dotnet Project Build & Deployment
on: push: branches: - 'Quest_Cicd_Test' paths: - 'WBC.UI.Host.Web/**' - 'WBC.Services.WCFHost/**' - 'WBC.UI.Reporting.Web/**' pull_request: branches: - 'Quest_Cicd_Test' paths: - 'WBC.UI.Host.Web/**' - 'WBC.Services.WCFHost/**' - 'WBC.UI.Reporting.Web/**' jobs: build: runs-on: windows-2019 outputs: build_ui: ${{ steps.detect_changes.outputs.build_ui }} build_services: ${{ steps.detect_changes.outputs.build_services }} build_reports: ${{ steps.detect_changes.outputs.build_reports }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 with: vs-version: '15.0' - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '5.0.407' - name: Setup NuGet uses: NuGet/setup-nuget@v2 with: nuget-version: '6.0.2' - name: Enable long paths in Git run: git config --system core.longpaths true - name: Cache NuGet packages uses: actions/cache@v3 id: cache_nuget with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} restore-keys: | ${{ runner.os }}-nuget- - name: Restore NuGet packages if: steps.cache_nuget.outputs.cache-hit != 'true' run: nuget restore ./WBC.sln - name: Detect changed components id: detect_changes uses: tj-actions/changed-files@v41 with: files: | WBC.UI.Host.Web/** WBC.Services.WCFHost/** WBC.UI.Reporting.Web/** run: | # Determine which components need building $uiChanged = ${{ contains(steps.detect_changes.outputs.all_changed_files, 'WBC.UI.Host.Web/') }} $servicesChanged = ${{ contains(steps.detect_changes.outputs.all_changed_files, 'WBC.Services.WCFHost/') }} $reportsChanged = ${{ contains(steps.detect_changes.outputs.all_changed_files, 'WBC.UI.Reporting.Web/') }} # Set outputs for conditional builds echo "build_ui=$uiChanged" >> $env:GITHUB_OUTPUT echo "build_services=$servicesChanged" >> $env:GITHUB_OUTPUT echo "build_reports=$reportsChanged" >> $env:GITHUB_OUTPUT - name: Create deployment directories run: | mkdir -p "${{ github.workspace }}/Deploy_UI" mkdir -p "${{ github.workspace }}/Deploy_Services" mkdir -p "${{ github.workspace }}/Deploy_Reports" echo "Deployment directories created" - name: Build UI Component if: steps.detect_changes.outputs.build_ui == 'true' run: | msbuild ./WBC.UI.Host.Web/WBC.UI.Host.Web.csproj ` /p:GenerateSerializationAssemblies=Off ` /t:Build ` /p:DeployOnBuild=true ` /p:Configuration=Release ` /p:PublishProfile=FolderProfile - name: Build Services Component if: steps.detect_changes.outputs.build_services == 'true' run: | msbuild ./WBC.Services.WCFHost/WBC.Services.WCFHost.csproj ` /p:GenerateSerializationAssemblies=Off ` /t:Build ` /p:DeployOnBuild=true ` /p:Configuration=Release ` /p:PublishProfile=FolderProfile.pubxml - name: Build Reports Component if: steps.detect_changes.outputs.build_reports == 'true' run: | dotnet add package Microsoft.Report.Viewer --version 11.0.0 nuget install ./WBC.UI.Reporting.Web/packages.config -Source http://nuget.org/api/v2 msbuild ./WBC.UI.Reporting.Web/WBC.UI.Reporting.Web.csproj ` /p:GenerateSerializationAssemblies=Off ` /t:Build ` /p:DeployOnBuild=true ` /p:Configuration=Release ` /p:PublishProfile=NewProfile.pubxml - name: Upload UI Artifact if: steps.detect_changes.outputs.build_ui == 'true' uses: actions/upload-artifact@v4 with: name: ui-artifact path: ${{ github.workspace }}/Deploy_UI retention-days: 6 - name: Upload Services Artifact if: steps.detect_changes.outputs.build_services == 'true' uses: actions/upload-artifact@v4 with: name: services-artifact path: ${{ github.workspace }}/Deploy_Services retention-days: 6 - name: Upload Reports Artifact if: steps.detect_changes.outputs.build_reports == 'true' uses: actions/upload-artifact@v4 with: name: reports-artifact path: ${{ github.workspace }}/Deploy_Reports retention-days: 6 deploy: needs: build runs-on: self-hosted # Skip deployment for PRs if needed # if: github.event_name != 'pull_request' steps: - name: Download UI Artifact if: needs.build.outputs.build_ui == 'true' uses: actions/download-artifact@v4 with: name: ui-artifact path: ./UI_Deploy - name: Download Services Artifact if: needs.build.outputs.build_services == 'true' uses: actions/download-artifact@v4 with: name: services-artifact path: ./Services_Deploy - name: Download Reports Artifact if: needs.build.outputs.build_reports == 'true' uses: actions/download-artifact@v4 with: name: reports-artifact path: ./Reports_Deploy - name: Deploy UI to IIS if: needs.build.outputs.build_ui == 'true' run: | # Replace with your actual IIS UI app pool directory $iisDir = "C:\inetpub\wwwroot\UI_App" # Stop app pool to avoid file locks Stop-WebAppPool -Name "UI_AppPool" # Overwrite existing files Copy-Item -Path "./UI_Deploy/**" -Destination $iisDir -Recurse -Force # Restart app pool to apply changes Start-WebAppPool -Name "UI_AppPool" echo "UI component deployed successfully" - name: Deploy Services to IIS if: needs.build.outputs.build_services == 'true' run: | $iisDir = "C:\inetpub\wwwroot\Services_App" Stop-WebAppPool -Name "Services_AppPool" Copy-Item -Path "./Services_Deploy/**" -Destination $iisDir -Recurse -Force Start-WebAppPool -Name "Services_AppPool" echo "Services component deployed successfully" - name: Deploy Reports to IIS if: needs.build.outputs.build_reports == 'true' run: | $iisDir = "C:\inetpub\wwwroot\Reports_App" Stop-WebAppPool -Name "Reports_AppPool" Copy-Item -Path "./Reports_Deploy/**" -Destination $iisDir -Recurse -Force Start-WebAppPool -Name "Reports_AppPool" echo "Reports component deployed successfully"
Key Optimizations Explained
1. Split into Build & Deploy Stages
- Build Job: Runs on GitHub's managed
windows-2019runner, handling all compilation and artifact creation. Keeps the build environment consistent and isolated from your dev server. - Deploy Job: Runs on your self-hosted runner (dev server), depends on the build job succeeding, and executes IIS deployment steps. This separation ensures deployment only happens after successful builds.
2. Conditional Component Builds
- Uses
tj-actions/changed-filesto detect modified component directories in pushes/PRs. - Sets outputs to trigger only relevant build steps, reducing unnecessary computation.
- Uploads only artifacts for changed components, minimizing data transfer.
3. Artifact Transfer & IIS Deployment
- Each component's artifact is uploaded separately, enabling targeted deployment.
- In the deploy job:
- Downloads only artifacts that need updating.
- Stops corresponding IIS app pools to avoid file locks during file copy.
- Overwrites existing files in the IIS directory (replace paths with your actual app pool directories).
- Restarts app pools to apply changes immediately.
Critical Notes
- Ensure your self-hosted runner has:
- IIS Management PowerShell modules installed to run
Stop-WebAppPool/Start-WebAppPool. - Permissions to modify IIS directories and manage app pools.
- IIS Management PowerShell modules installed to run
- Verify your Publish Profiles are configured to output to the correct
Deploy_*directories in the workflow workspace. - Uncomment the
ifcondition in the deploy job if you want to skip deployment for PRs.
内容的提问来源于stack exchange,提问作者Vikram Giriraj
相关产品推荐
相关产品推荐

