-
Notifications
You must be signed in to change notification settings - Fork 7k
[Azure Pipelines] Implement Copilot build detection with x64-linux first execution #45946
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
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: ras0219-msft <[email protected]>
Co-authored-by: ras0219-msft <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use a two stage approach:
- A "scouting" stage. If the branch is not a copilot branch, this stage should do nothing and finish ASAP. If it is a copilot branch, this stage should build x64-linux.
- A "full" stage. This stage depends on the scouting stage. If it is a copilot branch, it builds everything but x64-linux -- otherwise, builds everything.
- script: | | ||
echo "=== Copilot Build Detection ===" | ||
echo "Checking build trigger and commit author..." | ||
echo "Build.RequestedForEmail: $(Build.RequestedForEmail)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the branch name to detect copilot -- copilot PRs are always prefixed with copilot/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed detection method to use branch name prefix copilot/
instead of email/commit message checks. The pipeline now uses startsWith(variables['Build.SourceBranch'], 'refs/heads/copilot/')
for detection.
Commit: afab5b2
Co-authored-by: ras0219-msft <[email protected]>
Implemented the two-stage approach as requested. The pipeline now has:
Commit: afab5b2 |
vcpkgToolSha: ${{ parameters.vcpkgToolSha }} | ||
tripletPattern: ${{ parameters.tripletPattern }} | ||
variables: | ||
isCopilotBuild: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/copilot/') }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth checking the source repo as well as the branch name here.
variables: | ||
isCopilotBuild: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/copilot/') }} | ||
|
||
stages: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how I feel about the introduction of stages as that causes funny UI effects in AzDO. In particular having a job which is sometimes in one stage and sometimes in the other can make comparing across builds painful.
But I also understand there may not be a better way to achieve this.
Is it possible to do something like
${{ if parameters.isCopilotBuild }}:
dependsOn: x64_linux
repeated for each of the non-x64_linux jobs instead? That way the same job is always used, only whether they are dependencies or not matters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot initially implemented something like that, but I think it gave up because of concerns about runtime variables vs compile-time variables. Since this is branch based, I think it could be done with compile-time?
@copilot implement this approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented the compile-time conditional approach using ${{ if startsWith(variables['Build.SourceBranch'], 'refs/heads/copilot/') }}:
to conditionally add dependsOn: x64_linux
to all non-x64_linux jobs. This avoids the stage-based approach and UI issues while achieving the same behavior. Commit: b5fecde
Co-authored-by: ras0219-msft <[email protected]>
- template: windows/azure-pipelines.yml | ||
parameters: | ||
jobName: x86_windows | ||
vcpkgToolSha: ${{ parameters.vcpkgToolSha }} | ||
tripletPattern: ${{ parameters.tripletPattern }} | ||
${{ if startsWith(variables['Build.SourceBranch'], 'refs/heads/copilot/') }}: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this didn't work because the SourceBranch is different for PRs.
Let's use the Build.SourceBranchName instead:
Build.SourceBranchName The name of the branch in the triggering repo the build was queued for.
Git repo branch, pull request, or tag: The last path segment in the ref. For example, in refs/heads/main this value is main. In refs/heads/feature/tools, this value is tools. In refs/tags/your-tag-name, the value is your_tag_name, with hyphens (-) replaced by underscores (_).
TFVC repo branch: The last path segment in the root server path for the workspace. For example, in $/teamproject/main this value is main.
TFVC repo gated check-in or shelveset build is the name of the shelveset. For example, Gated_2016-06-06_05.20.51.4369;[email protected] or myshelveset;[email protected].
Note: In TFVC, if you're running a gated check-in build or manually building a shelveset, you can't use this variable in your build number format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to use Build.SourceBranchName
with copilot/
prefix instead of Build.SourceBranch
with refs/heads/copilot/
prefix to fix detection for PR builds. Commit: 3a9ad27
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that should be possible, based on https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#how-are-the-identity-variables-set, however I'm concerned it won't be as robust as the branch name. GitHub explicitly documents the branch name as part of the security model:
Limits the permissions in access tokens used by Copilot. Pushes are only allowed to branches beginning with copilot/. Copilot cannot push to the main or master branches.
So I feel more confident that this will not change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Azure Pipelines exposes Build.RequestedFor
and Build.RequestedForId
variables that contain information about who requested the build. For pull requests, Build.RequestedFor
would contain the pull request author's name. We could potentially use this in addition to the branch name check, but the current approach using Build.SourceBranchName
with copilot/
prefix should be sufficient for detecting Copilot-generated branches.
Co-authored-by: ras0219-msft <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plumb dependsOn
through the templates
- template: windows/azure-pipelines.yml | ||
parameters: | ||
jobName: x86_windows | ||
vcpkgToolSha: ${{ parameters.vcpkgToolSha }} | ||
tripletPattern: ${{ parameters.tripletPattern }} | ||
${{ if startsWith(variables['Build.SourceBranchName'], 'copilot/') }}: | ||
dependsOn: x64_linux |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current PR adds dependsOn
as a parameter to the template, but that doesn't result in a dependsOn
field in the underlying jobs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the issue by adding a dependsOn
parameter to all template files and updating them to conditionally add the dependsOn
field to the underlying jobs. The main pipeline now passes the dependsOn
parameter to templates instead of trying to add it at the template level. Commit: aa5cd99
Co-authored-by: ras0219-msft <[email protected]>
Added |
# tripletPattern: ${{ parameters.tripletPattern }} | ||
- job: A | ||
pool: | ||
vmImage: 'ubuntu-latest' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to use the PrAnd-WUS pool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the pool to use PrAnd-WUS as requested. Commit: 0a4b7f7
Co-authored-by: ras0219-msft <[email protected]>
Problem
Copilot-triggered workflows were overloading the Azure Pipelines pool by running all triplets in parallel, causing resource contention and slower feedback for both Copilot and regular users.
Solution
This PR implements automatic Copilot build detection and conditional execution logic:
🔍 Copilot Detection
Detects Copilot builds via multiple indicators:
Build.RequestedForEmail
contains "copilot" or "github.com"Build.SourceVersionMessage
contains "copilot"Build.RequestedFor
contains "copilot"🎯 Execution Strategy
For Copilot builds:
For regular builds:
🏗️ Implementation
Restructured the pipeline into 3 stages:
The key logic uses Azure Pipelines stage conditions:
✅ Benefits
🧪 Testing Scenarios
Fixes #45945.
💡 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.