Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: "Copilot Setup Steps"

# Allow testing of the setup steps from your repository's "Actions" tab.
on:
workflow_dispatch:

pull_request:
branches:
- master
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

This workflow’s pull_request trigger is restricted to master. Since this file is being backported to release/v7.5, PRs targeting release/** (including this branch) won’t run the workflow to validate changes. Consider adding release/** (matching other CI workflows here) or removing the branch filter so edits are validated on release branches too.

Suggested change
- master
- master
- release/**

Copilot uses AI. Check for mistakes.
paths:
- ".github/workflows/copilot-setup-steps.yml"

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
# See https://docs.github.com/en/copilot/customizing-copilot/customizing-the-development-environment-for-copilot-coding-agent
copilot-setup-steps:
runs-on: ubuntu-latest

permissions:
contents: read

# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 1000

- name: Bootstrap
if: success()
run: |-
$title = 'Import Build.psm1'
Write-Host "::group::$title"
Import-Module ./build.psm1 -Verbose -ErrorAction Stop
Write-LogGroupEnd -Title $title

$title = 'Switch to public feed'
Write-LogGroupStart -Title $title
Switch-PSNugetConfig -Source Public
Write-LogGroupEnd -Title $title

$title = 'Bootstrap'
Write-LogGroupStart -Title $title
Start-PSBootstrap -Scenario DotNet
Write-LogGroupEnd -Title $title

$title = 'Install .NET Tools'
Write-LogGroupStart -Title $title
Start-PSBootstrap -Scenario Tools
Write-LogGroupEnd -Title $title

$title = 'Sync Tags'
Write-LogGroupStart -Title $title
Sync-PSTags -AddRemoteIfMissing
Write-LogGroupEnd -Title $title

$title = 'Setup .NET environment variables'
Write-LogGroupStart -Title $title
Find-DotNet -SetDotnetRoot
Write-LogGroupEnd -Title $title
shell: pwsh
106 changes: 98 additions & 8 deletions build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2282,7 +2282,12 @@ function Start-PSBootstrap {
[switch]$BuildLinuxArm,
[switch]$Force,
[Parameter(Mandatory = $true)]
[ValidateSet("Package", "DotNet", "Both")]
# Package: Install dependencies for packaging tools (fpm, rpmbuild, WiX)
# DotNet: Install the .NET SDK
# Both: Package and DotNet scenarios
# Tools: Install .NET global tools (e.g., dotnet-format)
# All: Install all dependencies (packaging, .NET SDK, and tools)
[ValidateSet("Package", "DotNet", "Both", "Tools", "All")]
Comment on lines +2289 to +2290
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Scenario = 'All' is documented as installing packaging + .NET SDK + tools, but several dependency-install branches earlier in Start-PSBootstrap still only check for Both/Package (e.g., OS package deps, WiX on Windows). As-is, All won't actually include all packaging dependencies. Update the other $Scenario -eq 'Both' -or $Scenario -eq 'Package' checks to include All (or switch them to the same -in 'All','Both','Package' pattern used below).

Suggested change
# All: Install all dependencies (packaging, .NET SDK, and tools)
[ValidateSet("Package", "DotNet", "Both", "Tools", "All")]
[ValidateSet("Package", "DotNet", "Both", "Tools")]

Copilot uses AI. Check for mistakes.
[string]$Scenario = "Package"
)

Expand Down Expand Up @@ -2402,15 +2407,15 @@ function Start-PSBootstrap {

# Install [fpm](https://github.com/jordansissel/fpm)
# Note: fpm is now only needed for DEB and macOS packages; RPM packages use rpmbuild directly
if ($Scenario -eq 'Both' -or $Scenario -eq 'Package') {
if ($Scenario -in 'All', 'Both', 'Package') {
# Install fpm on Debian-based systems, macOS, and Mariner (where DEB packages are built)
if (($environment.IsLinux -and ($environment.IsDebianFamily -or $environment.IsMariner)) -or $environment.IsMacOS) {
Install-GlobalGem -Sudo $sudo -GemName "dotenv" -GemVersion "2.8.1"
Install-GlobalGem -Sudo $sudo -GemName "ffi" -GemVersion "1.16.3"
Install-GlobalGem -Sudo $sudo -GemName "fpm" -GemVersion "1.15.1"
Install-GlobalGem -Sudo $sudo -GemName "rexml" -GemVersion "3.2.5"
}

# For RPM-based systems, ensure rpmbuild is available
if ($environment.IsLinux -and ($environment.IsRedHatFamily -or $environment.IsSUSEFamily -or $environment.IsMariner)) {
Write-Verbose -Verbose "Checking for rpmbuild..."
Expand All @@ -2422,7 +2427,7 @@ function Start-PSBootstrap {
}
}

if ($Scenario -eq 'DotNet' -or $Scenario -eq 'Both') {
if ($Scenario -in 'All', 'Both', 'DotNet') {

Write-Verbose -Verbose "Calling Find-Dotnet from Start-PSBootstrap"

Expand Down Expand Up @@ -2479,6 +2484,19 @@ function Start-PSBootstrap {
}
}

if ($Scenario -in 'All', 'Tools') {
Write-Log -message "Installing .NET global tools"

# Ensure dotnet is available
Find-Dotnet

# Install dotnet-format
Write-Verbose -Verbose "Installing dotnet-format global tool"
Start-NativeExecution {
dotnet tool install --global dotnet-format
}
Comment on lines +2493 to +2497
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The .NET global tools install uses dotnet tool install --global dotnet-format, which is not idempotent (it fails if the tool is already installed). Consider switching to dotnet tool update --global or checking dotnet tool list --global first so Start-PSBootstrap can be safely re-run.

Suggested change
# Install dotnet-format
Write-Verbose -Verbose "Installing dotnet-format global tool"
Start-NativeExecution {
dotnet tool install --global dotnet-format
}
# Ensure dotnet-format is installed as a global tool (idempotent)
Write-Verbose -Verbose "Ensuring dotnet-format global tool is installed"
$dotnetToolListOutput = Start-NativeExecution -IgnoreExitcode {
dotnet tool list --global
}
$dotnetFormatInstalled = $false
if ($LASTEXITCODE -eq 0 -and $dotnetToolListOutput -match '^\s*dotnet-format\b') {
$dotnetFormatInstalled = $true
}
if ($dotnetFormatInstalled) {
Write-Verbose -Verbose "dotnet-format is already installed. Updating global tool."
Start-NativeExecution {
dotnet tool update --global dotnet-format
}
}
else {
Write-Verbose -Verbose "dotnet-format is not installed. Installing global tool."
Start-NativeExecution {
dotnet tool install --global dotnet-format
}
}

Copilot uses AI. Check for mistakes.
}

if ($env:TF_BUILD) {
Write-Verbose -Verbose "--- Start - Capturing nuget sources"
dotnet nuget list source --format detailed
Expand Down Expand Up @@ -2646,6 +2664,63 @@ function Start-ResGen
}
}

function Add-PSEnvironmentPath {
<#
.SYNOPSIS
Adds a path to the process PATH and persists to GitHub Actions workflow if running in GitHub Actions
.PARAMETER Path
Path to add to PATH
.PARAMETER Prepend
If specified, prepends the path instead of appending
#>
param (
[Parameter(Mandatory)]
[string]$Path,

[switch]$Prepend
)

# Set in current process
if ($Prepend) {
$env:PATH = $Path + [IO.Path]::PathSeparator + $env:PATH
} else {
$env:PATH += [IO.Path]::PathSeparator + $Path
}

# Persist to GitHub Actions workflow if running in GitHub Actions
if ($env:GITHUB_ACTIONS -eq 'true') {
Write-Verbose -Verbose "Adding $Path to GITHUB_PATH"
Add-Content -Path $env:GITHUB_PATH -Value $Path
}
}

function Set-PSEnvironmentVariable {
<#
.SYNOPSIS
Sets an environment variable in the process and persists to GitHub Actions workflow if running in GitHub Actions
.PARAMETER Name
The name of the environment variable
.PARAMETER Value
The value of the environment variable
#>
param (
[Parameter(Mandatory)]
[string]$Name,

[Parameter(Mandatory)]
[string]$Value
)

# Set in current process
Set-Item -Path "env:$Name" -Value $Value

# Persist to GitHub Actions workflow if running in GitHub Actions
if ($env:GITHUB_ACTIONS -eq 'true') {
Write-Verbose -Verbose "Setting $Name in GITHUB_ENV"
Add-Content -Path $env:GITHUB_ENV -Value "$Name=$Value"
}
}

function Find-Dotnet {
param (
[switch] $SetDotnetRoot
Expand Down Expand Up @@ -2676,25 +2751,40 @@ function Find-Dotnet {
if ($dotnetCLIInstalledVersion -ne $chosenDotNetVersion) {
Write-Warning "The 'dotnet' in the current path can't find SDK version ${dotnetCLIRequiredVersion}, prepending $dotnetPath to PATH."
# Globally installed dotnet doesn't have the required SDK version, prepend the user local dotnet location
$env:PATH = $dotnetPath + [IO.Path]::PathSeparator + $env:PATH
Add-PSEnvironmentPath -Path $dotnetPath -Prepend

if ($SetDotnetRoot) {
Write-Verbose -Verbose "Setting DOTNET_ROOT to $dotnetPath"
$env:DOTNET_ROOT = $dotnetPath
Set-PSEnvironmentVariable -Name 'DOTNET_ROOT' -Value $dotnetPath
}
} elseif ($SetDotnetRoot) {
Write-Verbose -Verbose "Expected dotnet version found, setting DOTNET_ROOT to $dotnetPath"
$env:DOTNET_ROOT = $dotnetPath
Set-PSEnvironmentVariable -Name 'DOTNET_ROOT' -Value $dotnetPath
}
}
else {
Write-Warning "Could not find 'dotnet', appending $dotnetPath to PATH."
$env:PATH += [IO.Path]::PathSeparator + $dotnetPath
Add-PSEnvironmentPath -Path $dotnetPath

if ($SetDotnetRoot) {
Write-Verbose -Verbose "Setting DOTNET_ROOT to $dotnetPath"
Set-PSEnvironmentVariable -Name 'DOTNET_ROOT' -Value $dotnetPath
}
}

if (-not (precheck 'dotnet' "Still could not find 'dotnet', restoring PATH.")) {
# Give up, restore original PATH. There is nothing to persist since we didn't make a change.
$env:PATH = $originalPath
}
Comment on lines +2754 to 2778
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Find-Dotnet now persists PATH/DOTNET_ROOT to GitHub Actions via Add-PSEnvironmentPath/Set-PSEnvironmentVariable before the final precheck succeeds. If precheck fails, the code restores only $env:PATH, but any prior writes to $GITHUB_PATH/$GITHUB_ENV (and DOTNET_ROOT in-process) remain, leaving the job environment inconsistent. Persist only after the final precheck passes, or stage changes locally and write to GitHub env files conditionally on success.

Copilot uses AI. Check for mistakes.
elseif ($SetDotnetRoot) {
# If we found dotnet, also add the global tools path to PATH
# Add .NET global tools to PATH when setting up the environment
$dotnetToolsPath = Join-Path $dotnetPath "tools"
Comment on lines +2781 to +2782
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The global tools PATH being added uses Join-Path $dotnetPath "tools". On Windows, dotnet tool install --global typically installs to $env:USERPROFILE\.dotnet\tools, not under $env:LocalAppData\Microsoft\dotnet\tools, so this may not put global tools on PATH. Consider computing the tools path per-platform (or from DOTNET_CLI_HOME/USERPROFILE) to ensure dotnet-format is discoverable.

Suggested change
# Add .NET global tools to PATH when setting up the environment
$dotnetToolsPath = Join-Path $dotnetPath "tools"
# Compute .NET global tools path based on DOTNET_CLI_HOME/USERPROFILE/HOME
$dotnetCliHome = if (-not [string]::IsNullOrWhiteSpace($env:DOTNET_CLI_HOME)) {
$env:DOTNET_CLI_HOME
}
elseif ($environment.IsWindows) {
$env:USERPROFILE
}
else {
$env:HOME
}
$dotnetToolsRoot = Join-Path $dotnetCliHome ".dotnet"
$dotnetToolsPath = Join-Path $dotnetToolsRoot "tools"

Copilot uses AI. Check for mistakes.
if (Test-Path $dotnetToolsPath) {
Write-Verbose -Verbose "Adding .NET tools path to PATH: $dotnetToolsPath"
Add-PSEnvironmentPath -Path $dotnetToolsPath
}
}
}

<#
Expand Down
Loading