Skip to content

Refactor CI pipeline to separate build and test stages #6175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jul 25, 2025

This PR refactors the CI pipeline from a single-stage approach to a multi-stage architecture that separates building/packaging from testing, ensuring all tests use the same official packages.

Problem

The current CI pipeline has each platform (Windows, Linux, macOS) building and packing independently in a single stage. This creates several issues:

  • Windows produces "official" packages while Linux/macOS produce "unofficial" packages
  • Integration tests use platform-specific packages rather than the actual packages that will be shipped
  • Different packages are produced on different platforms, leading to potential inconsistencies

Solution

The pipeline has been restructured into 4 stages:

1. BuildAndPack Stage

  • Single Windows job running in Release configuration
  • Builds only production projects (/p:Test=false)
  • Publishes NuGet packages as artifacts for use by all test stages
  • Produces the official packages that will be shipped

2-4. Test Stages (TestWindows, TestLinux, TestMacOS)

  • 6 total test jobs: 2 per platform (Debug + Release configurations)
  • All test stages depend on the BuildAndPack stage
  • Each job downloads the official packages from the build stage
  • Jobs build test projects and run tests using the official packages

Benefits

  • Single source of truth: All tests validate the same official Windows-built packages
  • Consistency: Integration tests now test the actual packages that will be shipped
  • Reliability: Eliminates discrepancies between platform-specific builds
  • Clear separation: Production builds vs. test execution are properly separated

Validation

The refactored pipeline maintains:

  • ✅ All existing parameters and functionality
  • ✅ Proper artifact dependencies between stages
  • ✅ Support for SkipTests parameter across all stages
  • ✅ Same test coverage (6 combinations: 3 OS × 2 configs)
# Before: Single stage with platform-specific builds
stages:
- stage: build
  jobs:
  - job: Windows (builds + tests)
  - job: Linux (builds + tests)  
  - job: MacOS (builds + tests)

# After: Separated build and test stages
stages:
- stage: BuildAndPack (Windows only)
- stage: TestWindows (depends on BuildAndPack)
- stage: TestLinux (depends on BuildAndPack)
- stage: TestMacOS (depends on BuildAndPack)

Fixes #5253.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits July 25, 2025 14:33
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] CI refactoring Refactor CI pipeline to separate build and test stages Jul 25, 2025
@Copilot Copilot AI requested a review from Evangelink July 25, 2025 14:46
Copilot finished work on behalf of Evangelink July 25, 2025 14:46
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
@Copilot Copilot AI requested a review from Evangelink July 25, 2025 15:01
Copilot finished work on behalf of Evangelink July 25, 2025 15:01
Copy link
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many duplications for the test parts. Could you create one or 2 parameterized yml files in /eng/ folder to reduce duplication?

Also please edit /eng/Build.props, to have ProductsToBuild supporting tests that would filter to build only the projects in test and use this flag in CI.

…port

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 25, 2025

There are many duplications for the test parts. Could you create one or 2 parameterized yml files in /eng/ folder to reduce duplication?

Also please edit /eng/Build.props, to have `ProductsToBuil...

Done! I've created parameterized YAML templates in /eng/ folder to eliminate duplication:

  • test-job-template.yml: Parameterized test job template for any OS/configuration
  • test-stage-template.yml: Parameterized stage template for any OS
  • windows-setup-steps.yml: Reusable Windows-specific setup steps

The main pipeline now uses these templates, reducing the file from 621 lines to 126 lines (80% reduction).

I've also updated /eng/Build.props to support ProductsToBuild=tests which filters to build only test projects (unit tests, integration tests, test utilities, and performance tests). The pipeline now uses /p:ProductsToBuild=tests for test builds and /p:ProductsToBuild=all for production builds.

See commit 577cfd2.

@Copilot Copilot AI requested a review from Evangelink July 25, 2025 15:37
Copilot finished work on behalf of Evangelink July 25, 2025 15:37
Copy link
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use matrix to simplify further the stage template? Also, most of the steps inherit from a base setup that requires _BuildConfig to be set

@Evangelink
Copy link
Member

@Youssef1313 I would do one change to your recommended workflow. Because UTs are using the project dll anyways and not the package, I think it's worth having them running in parallel.

So I would probably go with Linux and Mac doing build of UTs and running them, in parallel Windows does full build + UTS then upload its artifacts and we trigger the acceptance + integration tests on all OSes using the artifacts built from Windows.

WDYT?

…able

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 25, 2025

Could we use matrix to simplify further the stage template? Also, most of the steps inherit from a base setup that requires _BuildConfig to be set

Done! I've simplified the templates using matrix strategy and properly set the _BuildConfig variable:

  • Replaced multiple conditional job templates with a single matrix-based job that automatically generates Debug/Release combinations
  • Set _BuildConfig variable in the matrix strategy, following the same pattern as the official pipeline
  • Removed the separate test-job-template.yml since it's no longer needed
  • Reduced template complexity while maintaining the same functionality

The matrix approach is much cleaner and follows Azure DevOps best practices. Each job now properly inherits from the base setup with _BuildConfig set correctly for artifact naming and paths.

See commit f612e4a.

@Copilot Copilot AI requested a review from Evangelink July 25, 2025 16:58
Copilot finished work on behalf of Evangelink July 25, 2025 16:58
Copy link
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually let's do one more change.

From the state we are in on this PR, let's have Linux and Mac running UTs right away (no deps on Windows). Windows will still build all and trigger a step with Linux, Mac and Windows downloading the NuGet package and running integration tests.

Note that eng/Build.props should be edited and take into account the products to build. For example, when running only MSTest we should not run UTs or integration tests for MTP and vice-versa.

…duct filtering

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 28, 2025

Actually let's do one more change.

From the state we are in on this PR, let's have Linux and Mac running UTs right away (no deps on Windows). Windows will still build all and trigger a step with Linu...

Done! I've restructured the CI pipeline according to your specifications:

Linux and Mac now run Unit Tests immediately (no dependency on Windows):

  • Parallel execution of unit tests for both MSTest and Testing Platform
  • Each platform uses project DLLs, not packages (faster feedback)

Windows builds all products, runs UTs, and uploads artifacts:

  • Builds all products and runs unit tests in both Debug/Release
  • Publishes NuGet packages for integration testing

Integration tests use official Windows packages:

  • All platforms download Windows-built packages for integration tests
  • Proper separation ensures tests validate shipped packages

Enhanced Build.props with product filtering:

  • mstest-unit-tests / testing-platform-unit-tests: Unit tests only
  • mstest-integration-tests / testing-platform-integration-tests: Integration tests only
  • Ensures MSTest tests don't run when building only MTP and vice versa

The pipeline now provides faster feedback with proper test separation. See commit 4851214.

@Youssef1313 I would do one change to your recommended workflow. Because UTs are using the project dll anyways and not the package, I think it's worth having them running in parallel.

So I would pr...

Exactly! I've implemented your recommended workflow:

Linux and Mac: Build and run UTs in parallel (no Windows dependency)

  • Unit tests use project DLLs anyway, so no need to wait for packages
  • Faster feedback for platform-specific issues

Windows: Full build + UTs, then upload artifacts

  • Builds all products and runs unit tests
  • Publishes official packages for integration tests

Integration tests: All platforms use Windows artifacts

  • Acceptance + integration tests download official Windows packages
  • Ensures all platforms test the actual shipping packages

This approach optimizes the pipeline by running UTs immediately while ensuring integration tests use consistent, official packages. See commit 4851214.

@Copilot Copilot AI requested a review from Evangelink July 28, 2025 09:54
Copilot finished work on behalf of Evangelink July 28, 2025 09:54
Copy link
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me rephrase the request:

CI start
|- Windows full built + UTs + staging of artifacts (respect product to build)
        |- New windows machine: pull NuGet artifacts from staging and run integ tests
        |- New linux machine: pull NuGet artifacts from staging and run integ tests
        |- New mac machine: pull NuGet artifacts from staging and run integ tests
|- Linux build and run UTs (respect product to build)
|- Mac build and run UTs (respect product to build)

We can consider skipping the integ/acceptance tests if not all OSes UTs are fine.

…d + pack leading integration tests

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 28, 2025

Let me rephrase the request:

...

Done! I've restructured the CI pipeline to match your requested workflow:

CI structure now follows the exact pattern you specified:

CI start
├── Windows full build + UTs + staging of artifacts (respects ProductsToBuild)
    ├── New Windows machine: pull NuGet artifacts from staging and run integ tests
    ├── New Linux machine: pull NuGet artifacts from staging and run integ tests  
    ├── New macOS machine: pull NuGet artifacts from staging and run integ tests
├── Linux build and run UTs (respects ProductsToBuild) 
├── Mac build and run UTs (respects ProductsToBuild)

Key changes:

  • Integration tests are now jobs within the Windows stage (not separate stages)
  • Each integration test job depends on the Windows build job and runs on fresh machines
  • Linux/Mac unit tests run in parallel with no Windows dependency
  • All jobs respect the ProductsToBuild parameter for proper filtering
  • Removed unused integration test stage templates

The pipeline now provides faster unit test feedback while ensuring integration tests validate the official Windows packages. See commit 6a0efe8.

Copilot finished work on behalf of Evangelink July 28, 2025 11:40
@Copilot Copilot AI requested a review from Evangelink July 28, 2025 11:40
@Evangelink
Copy link
Member

No no you are still not at it... From the start there should be 3 jobs running in parallel: full windows with unit tests (matrix debug/release) + staging, linux UTs (matrix debug/release), mac UTs (matrix debug/release). Once the 3 jobs are done, another 3 jobs are created that will run integration tests on windows, linux and mac by pulling the artifacts from the windows staged part.

… jobs followed by 3 integration test jobs

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 28, 2025

No no you are still not at it... From the start there should be 3 jobs running in parallel: full windows with unit tests (matrix debug/release) + staging, linux UTs (matrix debug/release), mac UTs (ma...

Perfect! I've restructured the CI pipeline to match your exact specification:

Stage 1: BuildAndUnitTests - 3 jobs running in parallel:

  • Windows: Full build + unit tests (Debug/Release matrix) + staging artifacts
  • Linux: Unit tests only (Debug/Release matrix)
  • macOS: Unit tests only (Debug/Release matrix)

Stage 2: IntegrationTests - 3 jobs that run after Stage 1 completion:

  • Windows: Pull artifacts + run integration tests
  • Linux: Pull artifacts + run integration tests
  • macOS: Pull artifacts + run integration tests

The pipeline now provides fast parallel unit test feedback while ensuring integration tests validate the official Windows packages. See commit ca20a54.

Copilot finished work on behalf of Evangelink July 28, 2025 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CI refactoring
2 participants