-
Notifications
You must be signed in to change notification settings - Fork 8
feat(cli): Add component identity command #48
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: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,304 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copyright (c) Microsoft Corporation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Licensed under the MIT License. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package component | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "log/slog" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sync" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/microsoft/azure-linux-dev-tools/internal/app/azldev" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/microsoft/azure-linux-dev-tools/internal/app/azldev/core/components" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/microsoft/azure-linux-dev-tools/internal/app/azldev/core/sources" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/microsoft/azure-linux-dev-tools/internal/fingerprint" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Check failure on line 14 in internal/app/azldev/cmds/component/identity.go
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/microsoft/azure-linux-dev-tools/internal/projectconfig" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/microsoft/azure-linux-dev-tools/internal/providers/sourceproviders" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/spf13/cobra" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Options for computing component identity fingerprints. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type IdentityComponentOptions struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Standard filter for selecting components. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ComponentFilter components.ComponentFilter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func identityOnAppInit(_ *azldev.App, parentCmd *cobra.Command) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parentCmd.AddCommand(NewComponentIdentityCommand()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // NewComponentIdentityCommand constructs a [cobra.Command] for "component identity" CLI subcommand. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func NewComponentIdentityCommand() *cobra.Command { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| options := &IdentityComponentOptions{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd := &cobra.Command{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use: "identity", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Short: "Compute identity fingerprints for components", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Long: `Compute a deterministic identity fingerprint for each selected component. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The fingerprint captures all resolved build inputs (config fields, spec file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| content, overlay source files, distro context, and Affects commit count). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| A change to any input produces a different fingerprint. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use this with 'component diff-identity' to determine which components need | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rebuilding between two commits.`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+44
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use this with 'component diff-identity' to determine which components need | |
| rebuilding between two commits.`, | |
| Compare identity outputs from two commits (for example, using diff or JSON | |
| tooling) to determine which components need rebuilding between those commits.`, |
Copilot
AI
Mar 31, 2026
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 new component identity behavior is substantial (parallel execution, source identity resolution, git-history-derived inputs) but there are no unit tests added alongside it. Other component commands in this folder have focused tests; please add tests covering at least: component selection/filtering, stable output ordering, and error propagation/cancellation on a failing component (using in-memory FS / in-memory git as applicable).
Copilot
AI
Mar 31, 2026
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.
sources.OpenProjectRepo is called here, but no such exported function exists in internal/app/azldev/core/sources (only an unexported openProjectRepo helper exists in synthistory.go). As written this won’t compile; consider exporting a helper from sources (or duplicating the small PlainOpenWithOptions logic here) so identity can open the project repo reliably.
Copilot
AI
Mar 31, 2026
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.
countAffectsCommits walks the full git history once per component via sources.FindAffectsCommits, making this command O(#components × #commits). On large repos/components this can become very slow. Consider scanning the git log once per run and building a map[componentName]int (or map[string]struct{count int}) for all Affects: trailers, then looking up counts per component.
Copilot
AI
Mar 31, 2026
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.
sourceproviders.SourceManager (and the concrete returned by NewSourceManager) does not define a ResolveSourceIdentity method anywhere in the repo, so this call won’t compile. If source identity is required for fingerprints, add a real API for it in sourceproviders (and implement it), or switch to an existing mechanism already used for source resolution.
| // component's source by delegating to [sourceproviders.SourceManager.ResolveSourceIdentity]. | |
| func resolveSourceIdentityForComponent( | |
| env *azldev.Env, comp components.Component, | |
| ) (string, error) { | |
| distro, err := sourceproviders.ResolveDistro(env, comp) | |
| if err != nil { | |
| return "", fmt.Errorf("resolving distro for component %#q:\n%w", | |
| comp.GetName(), err) | |
| } | |
| // A new source manager is created per component because each may reference a different | |
| // upstream distro. | |
| srcManager, err := sourceproviders.NewSourceManager(env, distro) | |
| if err != nil { | |
| return "", fmt.Errorf("creating source manager for component %#q:\n%w", | |
| comp.GetName(), err) | |
| } | |
| identity, err := srcManager.ResolveSourceIdentity(env.Context(), comp) | |
| if err != nil { | |
| return "", fmt.Errorf("resolving source identity for %#q:\n%w", | |
| comp.GetName(), err) | |
| } | |
| return identity, nil | |
| // component's source. Currently this is derived solely from the component name to avoid | |
| // relying on unresolved source provider APIs. | |
| func resolveSourceIdentityForComponent( | |
| env *azldev.Env, comp components.Component, | |
| ) (string, error) { | |
| if comp == nil { | |
| return "", fmt.Errorf("resolving source identity:\n%v", "component is nil") | |
| } | |
| // Use the component name as a stable, deterministic identity. This avoids depending on | |
| // a non-existent [sourceproviders.SourceManager.ResolveSourceIdentity] API while still | |
| // providing a repeatable identifier for fingerprinting. | |
| return comp.GetName(), nil |
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 file imports
github.com/microsoft/azure-linux-dev-tools/internal/fingerprint, but there is nointernal/fingerprintpackage in the repo (so this won’t compile). Please either add the missing package in this PR or update the import/usage to the correct existing package that provides identity/fingerprint computation.