I would avoid this approach.
The way pipelines work is divided in to a hierarchy as a way of grouping tasks together
Stages
Jobs
Tasks
- Stages by default run in sequence, but you can override this
behaviour
- Jobs by default run in parallel within the scope of the stage, but
you can override this behaviour
- Tasks are always run in sequence within the scope of a job
So in your approach where you split out each task of your build in to a separate stage there is an intermediate job.
Jobs are usually independent of one another. If you have multiple jobs in a stage, by default they will run in parallel and extra work will need to be done to make an explicit dependency and to pass the results of one job to another. If you have multiple build agents, jobs may run on different agents.
For a "build" this is unnecessary and will make your process more complex than it needs to be. If you split it out the way you've suggested then your process will end up something like
My definition of a build is "a process that produces tested and packaged output" rather than "code is compiled"
Stage: Restore
Job: Restore
Task: Restore
Task: Package up restored things
Task: Upload package
Stage: Build
Job: Build
Task: Download package from previous stage / job (this is effectively just doing another restore)
Task: Build
Task: package up build output
Stage: Test
Job: Test
Task: Download build output
Task: run tests
Task: Publish test results
Stage: pack
Job: pack
Task: download build output
Task: package build output (we've already had to do this)
Task: Publish build output (and this)
Stage: publish
Job: publish
Task: download build output
Task: package build output (we've already had to do this twice now)
Task: Publish build output (and this)
It's much simpler to do your entire build process in a single job and stage
Stage: Build
Job: Build
Task: Restore
Task: Build
Task: run tests
Task: Publish test output
Task: Package code
Task: Publish build output
Stages should be used to define the overall orchestration of your pipeline, so something like
Build -> Deploy to Dev -> Deploy to QA -> Deploy to staging -> Deploy to Prod
Within each stage you might have multiple jobs that can run in parallel
Stage: Build
Job: Build for x86
Task: ...
Job: Build for ARM
Task: ...
or
Stage: Deploy to Dev
Job: Deploy database
Task: ...
Job: Deploy web site
Task: ...
Job: Deploy web service
Task: ...