-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New UniversalPackagesV1 #21590
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?
New UniversalPackagesV1 #21590
Conversation
1d61b25 to
823e196
Compare
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.
Pull request overview
This PR introduces UniversalPackagesV1, a new major version of the Universal Packages task that adds support for Workload Identity Federation (WIF) authentication and Azure DevOps service connections. This enables downloading and publishing Universal Packages to/from Azure Artifacts feeds using build identities and WIF without requiring Personal Access Tokens (PATs).
Key Changes:
- Added new
adoServiceConnectioninput for WIF-based authentication with service connections - Implemented provenance session support for publish operations when using service connections
- Restructured task code with clearer separation between download, publish, and helper modules
- Added comprehensive L0 test suite with mocking infrastructure
Reviewed changes
Copilot reviewed 19 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| make-options.json | Registers UniversalPackagesV1 in build system task lists |
| task.json / task.loc.json | Task definition with new inputs for service connection and organization |
| universalMain.ts | Main entry point with validation and command routing logic |
| universalDownload.ts | Download command implementation using ArtifactTool |
| universalPublish.ts | Publish command with provenance session support |
| universalPackageHelpers.ts | Authentication, feed validation, and artifact tool management |
| UniversalPackageContext.ts | Context object for passing state between functions |
| Tests/*.ts | Comprehensive L0 test suite with mock infrastructure |
| Strings/resources.resjson | Localized strings for messages and help text |
| package.json | Task dependencies and build scripts |
| CODEOWNERS | Ownership assignment to azure-artifacts-packages team |
Files not reviewed (1)
- Tasks/UniversalPackagesV1/package-lock.json: Language not supported
| "Error_UnexpectedErrorArtifactToolDownload": "An unexpected error occurred while trying to download the package. Exit code(%s) and error(%s)", | ||
| "Error_UnexpectedErrorArtifactToolPublish": "An unexpected error occurred while trying to push the package. Exit code(%s) and error(%s)", | ||
| "Error_UniversalPackagesNotSupportedOnPrem": "Universal Packages are not supported in Azure DevOps Server.", | ||
| "Success_PackagesDownloaded": "Package were downloaded successfully", |
Copilot
AI
Dec 17, 2025
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 error message "Package were downloaded successfully" contains a grammatical error. It should be "Packages were downloaded successfully" (plural form).
| "Success_PackagesDownloaded": "Package were downloaded successfully", | |
| "Success_PackagesDownloaded": "Packages were downloaded successfully", |
| "loc.messages.Error_UnexpectedErrorArtifactToolDownload": "An unexpected error occurred while trying to download the package. Exit code(%s) and error(%s)", | ||
| "loc.messages.Error_UnexpectedErrorArtifactToolPublish": "An unexpected error occurred while trying to push the package. Exit code(%s) and error(%s)", | ||
| "loc.messages.Error_UniversalPackagesNotSupportedOnPrem": "Universal Packages are not supported in Azure DevOps Server.", | ||
| "loc.messages.Success_PackagesDownloaded": "Package were downloaded successfully", |
Copilot
AI
Dec 17, 2025
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 error message "Package were downloaded successfully" contains a grammatical error. It should be "Packages were downloaded successfully" (plural form).
| "loc.messages.Success_PackagesDownloaded": "Package were downloaded successfully", | |
| "loc.messages.Success_PackagesDownloaded": "Packages were downloaded successfully", |
|
|
||
| function parseFeedInput(feed: string): { feedName: string; projectName: string | null } { | ||
| let feedName: string; | ||
| let projectName: string = null; |
Copilot
AI
Dec 17, 2025
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 variable projectName is initialized as a string but should be initialized to null (not the string "null") to match the type annotation. This could cause issues when checking if projectName is truthy.
| let projectName: string = null; | |
| let projectName: string | null = null; |
| "type": "string", | ||
| "label": "Package name", | ||
| "required": true, | ||
| "helpMarkDown": "The name of the Universal Package. Package names must be lower case and can only use letters, numbers, and dashes(-)." |
Copilot
AI
Dec 17, 2025
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 help text contains a typo: "dashes(-)" should include a space before the parenthesis for better readability: "dashes (-)". This appears in both the regular and localized versions.
| "helpMarkDown": "The name of the Universal Package. Package names must be lower case and can only use letters, numbers, and dashes(-)." | |
| "helpMarkDown": "The name of the Universal Package. Package names must be lower case and can only use letters, numbers, and dashes (-)." |
| "loc.input.label.feed": "Feed", | ||
| "loc.input.help.feed": "The feed name. For project-scoped feeds, use 'project/feed' format.", | ||
| "loc.input.label.packageName": "Package name", | ||
| "loc.input.help.packageName": "The name of the Universal Package. Package names must be lower case and can only use letters, numbers, and dashes(-).", |
Copilot
AI
Dec 17, 2025
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 help text contains a typo: "dashes(-)" should include a space before the parenthesis for better readability: "dashes (-)". This appears in both the regular and localized versions.
| "loc.input.help.packageName": "The name of the Universal Package. Package names must be lower case and can only use letters, numbers, and dashes(-).", | |
| "loc.input.help.packageName": "The name of the Universal Package. Package names must be lower case and can only use letters, numbers, and dashes (-).", |
| { | ||
| "id": "e0b79640-8625-11e8-91be-db2878ff888a", | ||
| "name": "UniversalPackages", | ||
| "friendlyName": "Universal packages", |
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.
should this be Universal Packages
|
|
||
| "execution": { | ||
| "Node10": { | ||
| "target": "universalMain.js", |
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.
do we need to support all these node versions ? are there any active node migrations we can get ahead of ?
| @@ -0,0 +1,33 @@ | |||
| { | |||
| "name": "universalpackages", | |||
| "version": "1.267.0", | |||
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.
is this version used at all in this repo? should it be a simple 1.0.0 ?
| if (context.adoServiceConnection) { | ||
| tl.debug(tl.loc('Debug_UsingWifAuth', context.adoServiceConnection)); | ||
| try { | ||
| accessToken = await getFederatedWorkloadIdentityCredentials(context.adoServiceConnection); |
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 see we are not passing the tenant id to the getFederatedWorkloadIdentityCredentials. This will be needed for cross tenant feeds.
Can we use the getfeedTentantId if available?
|
|
||
| tl.debug(tl.loc('Debug_UsingServiceUri', serviceUri)); | ||
|
|
||
| toolRunnerOptions.env.UNIVERSAL_AUTH_TOKEN = accessToken; |
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.
if this variable is set in the pipeline from a previous step or process are we overwritting? Do we want to enable this env being set by another process ?
| } | ||
|
|
||
| // This will throw if the feed doesn't exist or token doesn't have access | ||
| const data = await webApi.vsoClient.getVersioningData(ApiVersion, PackagingAreaName, PackageAreaId, routeValues); |
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.
is this validate feed access just testing read ? Because it seems like this could pass but then fail for publish if they do not have write access. Do we care? In this case does it make sense to do this check still ?
| "packageName": tl.getInput("packageName"), | ||
| "adoServiceConnection": tl.getInput("adoServiceConnection"), | ||
| "System.TeamFoundationCollectionUri": tl.getVariable("System.TeamFoundationCollectionUri"), | ||
| "verbosity": tl.getInput("verbosity"), |
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 have a question about versbosity - can we determine if the system.debug predifined variable is set and set the verbosity to debug if true?
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.
this is more for the context than just the telemetery
| "command": tl.getInput("command"), | ||
| "organization": tl.getInput("organization"), | ||
| "feed": tl.getInput("feed"), | ||
| "packageName": tl.getInput("packageName"), |
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.
would package version be helpful here too ?
Context
This PR includes a new Major version of the UniversalPackages task. There are many modifications (mostly reductions) to now obsolete inputs, plus implementation of the adoServiceConnection input. This will allow build identities and WIF to be used for downloading and publishing of Universal Packages (UPack) to and from Azure Artifacts feeds, without the use of PATs.
AB#2327595
Task Name
UniversalPackagesV1
Description
Files:
Task:
Tests:
Risk Assessment (Low / Medium / High)
Medium. There is no backward compatibility, and it is a new task. However, it does not break existing usage of the V0 task.
Change Behind Feature Flag (Yes / No)
No. It's a new task.
Tech Design / Approach
Documentation Changes Required (Yes/No)
Yes -- once the task reaches public availability docs will need to be updated to include the new major version.
Unit Tests Added or Updated (Yes / No)
Yes
Additional Testing Performed
Extensive end-to-end testing in pipelines, including both download and publish commands, varied feed scopes, windows/macOS/linux environments, error validation, etc.
Logging Added/Updated (Yes/No)
Yes
Telemetry Added/Updated (Yes/No)
No telemetry beyond logging and that which is included in the framework.
Rollback Scenario and Process (Yes/No)
N/A - it's a new task.
Dependency Impact Assessed and Regression Tested (Yes/No)
Yes
Checklist