Skip to content
Draft
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
2 changes: 1 addition & 1 deletion internal/app/azldev/cmds/component/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func BuildComponent(

var preparerOpts []sources.PreparerOption
if options.WithGitRepo {
preparerOpts = append(preparerOpts, sources.WithGitRepo(env.Config().Project.DefaultAuthorEmail))
preparerOpts = append(preparerOpts, sources.WithGitRepo(env))
}

sourcePreparer, err := sources.NewPreparer(sourceManager, env.FS(), env, env, preparerOpts...)
Expand Down
2 changes: 1 addition & 1 deletion internal/app/azldev/cmds/component/preparesources.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func PrepareComponentSources(env *azldev.Env, options *PrepareSourcesOptions) er

var preparerOpts []sources.PreparerOption
if options.WithGitRepo {
preparerOpts = append(preparerOpts, sources.WithGitRepo(env.Config().Project.DefaultAuthorEmail))
preparerOpts = append(preparerOpts, sources.WithGitRepo(env))
}

if options.AllowNoHashes {
Expand Down
2 changes: 1 addition & 1 deletion internal/app/azldev/cmds/component/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func prepareComponentSources(
// WithSkipLookaside avoids expensive tarball downloads — only spec +
// sidecar files are needed for rendering.
preparerOpts := []sources.PreparerOption{
sources.WithGitRepo(env.Config().Project.DefaultAuthorEmail),
sources.WithGitRepo(env),
sources.WithSkipLookaside(),
}

Expand Down
43 changes: 24 additions & 19 deletions internal/app/azldev/core/sources/sourceprep.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ type PreparerOption func(*sourcePreparerImpl)
// requires the project configuration to reside inside a git repository.
// Without this option, no dist-git is created and synthetic history is skipped.
//
// The defaultAuthorEmail is used for synthetic changelog entries and commits
// when no author email is available from git history.
func WithGitRepo(defaultAuthorEmail string) PreparerOption {
// The cmdFactory is used to shell out to git for fingerprint change detection.
func WithGitRepo(
cmdFactory opctx.CmdFactory,
) PreparerOption {
return func(p *sourcePreparerImpl) {
p.withGitRepo = true
p.defaultAuthorEmail = defaultAuthorEmail
p.cmdFactory = cmdFactory
}
}

Expand Down Expand Up @@ -118,9 +119,9 @@ type sourcePreparerImpl struct {
// source preparation. Git-tracked files are still fetched.
skipLookaside bool

// defaultAuthorEmail is the email address used for synthetic changelog
// entries and commits when no author email is available from git history.
defaultAuthorEmail string
// cmdFactory is used to shell out to git for fingerprint change detection
// in the project repository. Set via [WithGitRepo].
cmdFactory opctx.CmdFactory

// allowNoHashes, when true, allows source file references without hash
// values. Missing hashes are computed from the downloaded files.
Expand Down Expand Up @@ -220,7 +221,7 @@ func (p *sourcePreparerImpl) PrepareSources(

// Record the changes as synthetic git history when dist-git creation is enabled.
if p.withGitRepo {
if err := p.trySyntheticHistory(component, outputDir); err != nil {
if err := p.trySyntheticHistory(ctx, component, outputDir); err != nil {
return fmt.Errorf("failed to generate synthetic history for component %#q:\n%w",
component.GetName(), err)
}
Expand Down Expand Up @@ -350,37 +351,41 @@ func initSourcesRepo(sourcesDirPath string) (*gogit.Repository, error) {
}

// trySyntheticHistory attempts to create synthetic git commits on top of the
// component's sources directory. If no .git directory exists, one is initialized
// with an initial commit so Affects commits can be layered on uniformly for all
// component types.
// component's sources directory. Synthetic commits are derived from lock file
// fingerprint changes in the project repository and interleaved into the
// upstream dist-git history. If no .git directory exists, one is initialized
// with an initial commit so synthetic commits can be layered on uniformly.
//
// Returns a non-nil error if history generation fails.
func (p *sourcePreparerImpl) trySyntheticHistory(
ctx context.Context,
component components.Component,
sourcesDirPath string,
) error {
config := component.GetConfig()
componentName := component.GetName()

// Build commit metadata from Affects commits.
commits, err := buildSyntheticCommits(config, component.GetName(), p.defaultAuthorEmail)
// Build commit metadata from lock file fingerprint changes.
changes, importCommit, err := buildSyntheticCommits(
ctx, p.cmdFactory, config, componentName,
)
if err != nil {
return fmt.Errorf("failed to build synthetic commits:\n%w", err)
}

if len(commits) == 0 {
if len(changes) == 0 {
slog.Debug("No synthetic commits to create; skipping history generation",
"component", component.GetName())
"component", componentName)

return nil
}

// Adjust the Release tag before staging changes. See [tryBumpStaticRelease]
// for the handling of %autorelease, static integers, and non-standard values.
if err := p.tryBumpStaticRelease(component, sourcesDirPath, len(commits)); err != nil {
if err := p.tryBumpStaticRelease(component, sourcesDirPath, len(changes)); err != nil {
return fmt.Errorf("failed to apply release bump:\n%w", err)
}

// Use os.Stat (not p.fs) because go-git always operates on the real filesystem.
gitDirPath := filepath.Join(sourcesDirPath, ".git")

_, statErr := os.Stat(gitDirPath)
Expand All @@ -391,7 +396,7 @@ func (p *sourcePreparerImpl) trySyntheticHistory(

if os.IsNotExist(statErr) {
slog.Info("No .git directory in sources; initializing repository",
"component", component.GetName())
"component", componentName)

if _, err := initSourcesRepo(sourcesDirPath); err != nil {
return fmt.Errorf("failed to initialize sources repository:\n%w", err)
Expand All @@ -404,7 +409,7 @@ func (p *sourcePreparerImpl) trySyntheticHistory(
return fmt.Errorf("failed to open sources repository at %#q:\n%w", sourcesDirPath, err)
}

if err := CommitSyntheticHistory(sourcesRepo, commits); err != nil {
if err := CommitInterleavedHistory(sourcesRepo, changes, importCommit); err != nil {
return fmt.Errorf("failed to commit synthetic history:\n%w", err)
}

Expand Down
Loading
Loading