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
18 changes: 18 additions & 0 deletions assets/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions controller/appcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1910,6 +1910,26 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
}
}
ts.AddCheckpoint("process_finalizers_ms")

// Update source hydrator currentOperation.hydratedSHA if sync revision differs
// This ensures the hydration operation reflects the current sync state
if app.Spec.SourceHydrator != nil && app.Status.SourceHydrator.CurrentOperation != nil &&
app.Status.SourceHydrator.CurrentOperation.Phase == appv1.HydrateOperationPhaseHydrated {
currentSyncRevision := compareResult.syncStatus.Revision
if len(compareResult.syncStatus.Revisions) > 0 {
currentSyncRevision = compareResult.syncStatus.Revisions[0]
}
if currentSyncRevision != "" && currentSyncRevision != app.Status.SourceHydrator.CurrentOperation.HydratedSHA {
app.Status.SourceHydrator.CurrentOperation.HydratedSHA = currentSyncRevision
// Also update LastSuccessfulOperation if it exists
if app.Status.SourceHydrator.LastSuccessfulOperation != nil {
app.Status.SourceHydrator.LastSuccessfulOperation.HydratedSHA = currentSyncRevision
}
// Persist the hydration status update separately to ensure it's saved
ctrl.PersistAppHydratorStatus(origApp, &app.Status.SourceHydrator)
}
}

patchDuration = ctrl.persistAppStatus(origApp, &app.Status)
// This is a partly a duplicate of patch_ms, but more descriptive and allows to have measurement for the next step.
ts.AddCheckpoint("persist_app_status_ms")
Expand Down
438 changes: 246 additions & 192 deletions pkg/apiclient/application/application.pb.go

Large diffs are not rendered by default.

107 changes: 73 additions & 34 deletions server/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,31 +816,8 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*v1a
) error {
source := app.Spec.GetSource()
repoURL := source.RepoURL
// When using sourceHydrator with different repos, use the stored config from Status
// (not Spec) because commits were created with that config at hydration time.
if app.Spec.SourceHydrator != nil {
// Check CurrentOperation first, then LastSuccessfulOperation for the correct repo URL
if op := app.Status.SourceHydrator.CurrentOperation; op != nil {
if op.SourceHydrator.SyncSource.RepoURL != "" {
repoURL = op.SourceHydrator.SyncSource.RepoURL
} else {
repoURL = op.SourceHydrator.DrySource.RepoURL
}
} else if op := app.Status.SourceHydrator.LastSuccessfulOperation; op != nil {
if op.SourceHydrator.SyncSource.RepoURL != "" {
repoURL = op.SourceHydrator.SyncSource.RepoURL
} else {
repoURL = op.SourceHydrator.DrySource.RepoURL
}
} else {
// Fallback to Spec if no Status operations exist yet
if app.Spec.SourceHydrator.SyncSource.RepoURL != "" {
repoURL = app.Spec.SourceHydrator.SyncSource.RepoURL
} else {
repoURL = app.Spec.SourceHydrator.DrySource.RepoURL
}
}
}
// Use explicit sourceType parameter instead of inference
repoURL = resolveSourceHydratorRepoURLWithSourceType(app, q.GetSourceType(), repoURL)
repo, err := s.db.GetRepository(ctx, repoURL, proj.Name)
if err != nil {
return fmt.Errorf("error getting repository: %w", err)
Expand Down Expand Up @@ -1623,7 +1600,6 @@ func (s *Server) WatchResourceTree(q *application.ResourcesQuery, ws application
})
}

// resolveSourceHydratorRepoURLWithSourceType determines the correct repository URL
// resolveSourceHydratorRepoURLWithSourceType determines the correct repository URL
// when using sourceHydrator. If sourceType is explicitly specified ("dry" or "hydrated"), it uses
// the corresponding repo URL directly. If sourceType is not specified, defaults to "dry".
Expand All @@ -1637,8 +1613,9 @@ func resolveSourceHydratorRepoURLWithSourceType(app *v1alpha1.Application, sourc
switch sourceType {
case "dry":
return app.Spec.SourceHydrator.DrySource.RepoURL
} else if sourceType == "hydrated" {
case "hydrated":
// Use sync source repo URL (or dry source if sync source has no different repo)
// Use GetHydrateToSource().RepoURL to ensure consistency with where hydrated commits are written
if app.Spec.SourceHydrator.SyncSource.RepoURL != "" {
return app.Spec.SourceHydrator.SyncSource.RepoURL
}
Expand All @@ -1647,8 +1624,6 @@ func resolveSourceHydratorRepoURLWithSourceType(app *v1alpha1.Application, sourc
// Default to "dry" when sourceType is not specified
return app.Spec.SourceHydrator.DrySource.RepoURL
}

return defaultRepoURL
}

func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMetadataQuery) (*v1alpha1.RevisionMetadata, error) {
Expand All @@ -1662,10 +1637,35 @@ func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMe
return nil, fmt.Errorf("error getting app source by source index and version ID: %w", err)
}

// Resolve the correct repo URL for sourceHydrator apps
// If sourceType is explicitly specified, use the corresponding repo URL directly.
// If sourceType is not specified, defaults to "dry".
repoURL := resolveSourceHydratorRepoURLWithSourceType(a, q.GetSourceType(), source.RepoURL)
// Determine the correct repo URL to use
// Priority: sourceType > versionId > default
var repoURL string
switch {
case q.GetSourceType() != "":
// When sourceType is explicitly provided, use it to determine the repo URL
// based on the CURRENT app spec, not the historical source. This ensures
// we always use the current repository configuration, even if historical
// sources reference old removed repositories.
var defaultRepoURL string
if a.Spec.SourceHydrator != nil {
// Use the current spec's dry source as the default when sourceType is provided
defaultRepoURL = a.Spec.SourceHydrator.DrySource.RepoURL
} else {
// Fallback to historical source if no sourceHydrator
defaultRepoURL = source.RepoURL
}
repoURL = resolveSourceHydratorRepoURLWithSourceType(a, q.GetSourceType(), defaultRepoURL)
case q.VersionId != nil:
// For historical revisions without explicit sourceType, use the repository URL
// directly from the historical source. This ensures we fetch commits from the
// repository that was actually used at that time, even if the app configuration
// has changed (e.g., SyncSource.repoURL was removed).
repoURL = source.RepoURL
default:
// For current revisions without versionId or sourceType, resolve based on current spec
// If sourceType is not specified, defaults to "dry".
repoURL = resolveSourceHydratorRepoURLWithSourceType(a, q.GetSourceType(), source.RepoURL)
}

repo, err := s.db.GetRepository(ctx, repoURL, proj.Name)
if err != nil {
Expand All @@ -1676,9 +1676,48 @@ func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMe
return nil, fmt.Errorf("error creating repo server client: %w", err)
}
defer utilio.Close(conn)

// Determine which revision to use
revisionToFetch := q.GetRevision()

// If sourceType is provided and we're using a different repo than the historical source,
// and the revision is a commit SHA (from the old repo), we need to resolve the branch/revision
// from the CURRENT app spec in the new repo to get the current commit SHA.
if q.GetSourceType() != "" && repoURL != source.RepoURL && git.IsCommitSHA(revisionToFetch) {
// The revision is an old commit SHA from the old repo, but we're using the new repo.
// Get the current app spec's target revision (branch/tag) and resolve it in the new repo.
var targetRevision string
switch {
case a.Spec.SourceHydrator != nil:
if q.GetSourceType() == "hydrated" {
targetRevision = a.Spec.SourceHydrator.SyncSource.TargetBranch
} else {
targetRevision = a.Spec.SourceHydrator.DrySource.TargetRevision
}
case a.Spec.HasMultipleSources() && len(a.Spec.Sources) > 0:
targetRevision = a.Spec.Sources[0].TargetRevision
case a.Spec.Source != nil:
targetRevision = a.Spec.Source.TargetRevision
}

if targetRevision != "" {
// Resolve the branch/tag from the current spec in the new repo
resolveResp, err := repoClient.ResolveRevision(ctx, &apiclient.ResolveRevisionRequest{
Repo: repo,
App: a,
AmbiguousRevision: targetRevision,
SourceIndex: 0,
})
if err == nil && resolveResp.Revision != "" {
// Successfully resolved the branch to a commit SHA in the new repo
revisionToFetch = resolveResp.Revision
}
}
}

return repoClient.GetRevisionMetadata(ctx, &apiclient.RepoServerRevisionMetadataRequest{
Repo: repo,
Revision: q.GetRevision(),
Revision: revisionToFetch,
CheckSignature: len(proj.Spec.SignatureKeys) > 0,
})
}
Expand Down
Loading