S⚠️ ◾ Automated Package Update#818
Conversation
This script updates NuGet package versions in the Directory.Packages.props file by querying the latest available versions and updating the Version attributes accordingly, while respecting the PreserveMajor attribute and pre-release version detection.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Changed the trigger for package updates to a scheduled cron job.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Initial plan * Gate PR creation on changes detection flag Co-authored-by: neilr81 <49037171+neilr81@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: neilr81 <49037171+neilr81@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Removed GitHub CLI installation step from workflow.
Removed the 'powershell' label from the automated package update PR.
PR Metrics✔ Thanks for keeping your pull request small.
Metrics computed by PR Metrics. Add it to your Azure DevOps and GitHub PRs! |
There was a problem hiding this comment.
Pull request overview
Adds GitHub-based automation to update centrally-managed NuGet package versions, including a new workflow + PowerShell updater script, and applies the latest automated package updates in the repo’s Directory.Packages.props.
Changes:
- Add a scheduled GitHub Actions workflow to run a package-version update script and open an automated PR.
- Add a PowerShell script that scans
Directory.Packages.propsAutoUpdate groups and updates package versions viadotnet package search. - Update
Directory.Packages.props(notably MSTest packages) and apply formatting/encoding changes produced by the script.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| Directory.Packages.props | Applies automated package version updates and rewrites formatting/encoding. |
| .github/workflows/package-update.yml | Introduces the scheduled workflow that runs the updater, commits, pushes, and opens a PR. |
| .github/scripts/Update-NuGetPackageVersions.ps1 | Adds the updater implementation that searches and updates versions in the props file. |
| if ($updateCount -gt 0) { | ||
| Write-Host "##[section]Saving $updateCount package updates to $propsFile" | ||
| $xml.Save($propsFile) | ||
| Write-Host "Successfully updated $updateCount packages" |
There was a problem hiding this comment.
Saving via XmlDocument.Save() is reformatting the props file (BOM, attribute spacing, etc.), which makes automated PRs much noisier than necessary. Consider updating only the Version attribute values in-place without reserializing the full XML (or use an XML writer/settings approach that preserves the original formatting/encoding).
| @@ -1,59 +1,59 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
There was a problem hiding this comment.
The file now starts with a UTF-8 BOM (the invisible character before <?xml ...?>) and the automation also rewrote many self-closing tags (spacing before />). This creates noisy diffs that are unrelated to the actual version bump; consider keeping the original encoding/formatting stable (e.g., ensure the update script preserves formatting and encoding).
| <?xml version="1.0" encoding="utf-8"?> | |
| <?xml version="1.0" encoding="utf-8"?> |
| if (git diff --cached --quiet) { | ||
| echo "No changes detected; skipping commit and PR creation." | ||
| echo "has-changes=false" >> $env:GITHUB_OUTPUT | ||
| exit 0 | ||
| } |
There was a problem hiding this comment.
git diff --cached --quiet doesn’t produce output; in PowerShell the if (git diff --cached --quiet) condition won’t reflect the exit code, so this block won’t correctly detect the no-change case (and the workflow will attempt git commit and fail when there are no changes). Capture and check $LASTEXITCODE (0 = no changes, 1 = changes) instead.
| on: | ||
| schedule: | ||
| - cron: "0 6 * * 1" | ||
| pull_request: | ||
| branches: [ "main" ] | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
There was a problem hiding this comment.
This workflow runs on pull_request but also creates and pushes branches and opens PRs. That combination can cause PR-triggered runs to create additional automation branches/PRs (or fail due to token restrictions) and adds unnecessary write permissions to PR runs. Consider limiting PR creation/push steps to schedule/manual triggers (e.g., remove pull_request trigger or add if: github.event_name == 'schedule' guards).
| gh pr create ` | ||
| --title "Automated Package Update" ` | ||
| --body "This PR was created automatically by the workflow run ${{ github.run_id }}." ` | ||
| --base main ` | ||
| --head "automation/package-update-${{ github.run_id }}" ` | ||
| --label automation ` | ||
| --assignee "${{ github.actor }}" |
There was a problem hiding this comment.
On schedule runs, github.actor is typically github-actions[bot], so --assignee "${{ github.actor }}" will assign the PR to the bot rather than a maintainer. Consider omitting the assignee, using a fixed assignee, or deriving it from CODEOWNERS/team config.
| # Prefer NuGet-GitHub.Config (used on GitHub runners) when present, otherwise fall back to NuGet.config | ||
| $nugetGithubConfigPath = Join-Path $SourcesDirectory "NuGet-GitHub.Config" | ||
| $nugetConfigPath = Join-Path $SourcesDirectory "NuGet.config" | ||
| $configSourceFlag = "" |
There was a problem hiding this comment.
The repo root contains NuGet.Config (capital C). This script falls back to NuGet.config, which will fail on case-sensitive filesystems (and won’t match the repo’s actual filename). Update the fallback path/message to use NuGet.Config.
| Write-Host " [VERBOSE] Executing: $searchCmd" | ||
| } | ||
|
|
||
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, ($MajorVersion ? ('(major version {0}.*)' -f $MajorVersion) : '')) |
There was a problem hiding this comment.
This uses the PowerShell 7+ ternary operator ($MajorVersion ? ... : ...). If this script is intended to be runnable from Windows PowerShell 5.1 as well (the examples imply it might), it will fail to parse. Either add a #requires -Version 7.0 (or #requires -PSEdition Core) to make the requirement explicit, or rewrite this expression using if/else.
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, ($MajorVersion ? ('(major version {0}.*)' -f $MajorVersion) : '')) | |
| $majorVersionSuffix = "" | |
| if ($MajorVersion) { | |
| $majorVersionSuffix = '(major version {0}.*)' -f $MajorVersion | |
| } | |
| Write-Host ("Searching for package: {0} {1}" -f $PackageId, $majorVersionSuffix) |
This PR was created automatically by the workflow run 21805884507.