You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化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-2019 runner, 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-files to 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.
  • Verify your Publish Profiles are configured to output to the correct Deploy_* directories in the workflow workspace.
  • Uncomment the if condition in the deploy job if you want to skip deployment for PRs.

内容的提问来源于stack exchange,提问作者Vikram Giriraj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 21:40:21