Skip to content

Fix: multi config sync#9958

Open
LudwigNordstrom wants to merge 3 commits intoGoogleContainerTools:mainfrom
LudwigNordstrom:fix-multi-config-sync
Open

Fix: multi config sync#9958
LudwigNordstrom wants to merge 3 commits intoGoogleContainerTools:mainfrom
LudwigNordstrom:fix-multi-config-sync

Conversation

@LudwigNordstrom
Copy link

Fixes: #7447
Related: N/A
Merge before/after: N/A

Description
When running skaffold dev with file sync enabled in a project with multiple configs, every file sync operation was being attempted N times (once per config). This happened because SyncerMux calls Sync on all registered syncers, and each syncer would attempt to find the corresponding image and sync the file, regardless of whether its deployer was actually responsible for deploying that image.

Solution
Introduced deployment-aware filtering for file syncing:

  1. New DeploymentAwareSyncer interface
    • Extends Syncer with RegisterDeployedArtifacts() and DeployedArtifacts() methods
    • Allows syncers to track which artifacts their associated deployer actually deployed
  2. Updated PodSyncer
    • Now stores deployed artifacts via RegisterDeployedArtifacts()
    • Before syncing, checks if the image being synced was deployed by this syncer
    • Skips sync (with an info log) if the image is not in its deployed artifacts list
  3. Updated deployers (kubectl, helm, kpt)
    • Register deployed artifacts with their syncer in TrackBuildArtifacts()
    • This ensures each syncer knows exactly which images it's responsible for

@LudwigNordstrom LudwigNordstrom requested a review from a team as a code owner January 23, 2026 13:06
@google-cla
Copy link

google-cla bot commented Jan 23, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @LudwigNordstrom, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue where file synchronization was inefficiently performed multiple times in multi-config projects. It introduces deployment-aware filtering to ensure each syncer only attempts to sync files for images it is responsible for, improving performance and reducing unnecessary operations. The changes include a new interface, updates to the pod syncer and deployers, and a new integration test to validate the fix.

Highlights

  • Fixes Multi-Config Sync Issue: Addresses a problem where file sync operations were being attempted multiple times in multi-config projects.
  • Introduces Deployment-Aware Filtering: Implements a new DeploymentAwareSyncer interface to allow syncers to track and filter artifacts based on deployment ownership.
  • Updates Deployers: Modifies kubectl, helm, and kpt deployers to register deployed artifacts with their respective syncers.
  • Adds Integration Test: Adds a new integration test TestDevSync_MultiConfig to verify the fix in a multi-config scenario.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses the issue of redundant file sync operations in multi-config Skaffold projects. The introduction of the DeploymentAwareSyncer interface and the corresponding updates to PodSyncer and deployers (kubectl, helm, kpt) ensure that each syncer only handles artifacts deployed by its associated deployer. This is a well-designed solution that improves efficiency and correctness for multi-config setups. The added integration and unit tests provide good coverage for the new functionality.

Comment on lines +42 to +49
// DeploymentAwareSyncer extends Syncer with the ability to track deployed artifacts.
// By tracking which artifacts each deployer deployed
// the syncer can skip sync operations for images it didn't deploy.
type DeploymentAwareSyncer interface {
Syncer
RegisterDeployedArtifacts([]graph.Artifact)
DeployedArtifacts() []graph.Artifact
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The DeploymentAwareSyncer interface is a good abstraction for the new filtering logic. It clearly separates the concerns of tracking deployed artifacts from the general sync operations.

Comment on lines +60 to 66
func NewPodSyncer(cli *pkgkubectl.CLI, namespaces *[]string, formatter logger.Formatter, deployedArtifacts []graph.Artifact) *PodSyncer {
return &PodSyncer{
kubectl: cli,
namespaces: namespaces,
formatter: formatter,
kubectl: cli,
namespaces: namespaces,
formatter: formatter,
deployedArtifacts: deployedArtifacts,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The NewPodSyncer constructor has been correctly updated to accept the deployedArtifacts parameter, ensuring proper initialization of the new filtering mechanism.

Comment on lines +282 to +289
// In multi-config projects, SyncerMux calls Sync on all syncers. To avoid
// syncing the same file N times, we check if this syncer's deployer actually
// deployed the image. If not, we skip and let the appropriate syncer handle it.
if !slices.ContainsFunc(s.DeployedArtifacts(), func(artifact graph.Artifact) bool {
return artifact.Tag == item.Image
}) {
log.Entry(ctx).Infof("Skipping sync for image %q: not in deployed artifacts", item.Image)
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block correctly implements the deployment-aware filtering. The slices.ContainsFunc check ensures that sync operations are only performed for images that the current syncer's deployer is responsible for, preventing redundant work in multi-config scenarios. The Infof log message is also helpful for debugging.

Comment on lines +189 to +192
// Register with syncer for multi-config sync filtering
if st, ok := k.syncer.(sync.DeploymentAwareSyncer); ok {
st.RegisterDeployedArtifacts(deployedImages)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The deployer correctly registers its deployed artifacts with the syncer, enabling the new filtering logic. This ensures that each syncer has the necessary context to determine if it should process a sync event.

Comment on lines +239 to +242
// Register with syncer for multi-config sync filtering
if st, ok := h.syncer.(sync.DeploymentAwareSyncer); ok {
st.RegisterDeployedArtifacts(deployedImages)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The deployer correctly registers its deployed artifacts with the syncer, enabling the new filtering logic. This ensures that each syncer has the necessary context to determine if it should process a sync event.

Comment on lines +172 to +175
// Register with syncer for multi-config sync filtering
if st, ok := k.syncer.(sync.DeploymentAwareSyncer); ok {
st.RegisterDeployedArtifacts(deployedImages)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The deployer correctly registers its deployed artifacts with the syncer, enabling the new filtering logic. This ensures that each syncer has the necessary context to determine if it should process a sync event.

Comment on lines +395 to +401
if strings.Count(stdErrStr, "Skipping sync for image") != 1 {
t.Error("Expected to see one 'Skipping sync for image' log message")
}

if strings.Count(stdErrStr, "Copying files:") != 1 {
t.Error("Expected to see one 'Copying files' log message")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The assertions for Skipping sync for image and Copying files log messages are crucial for verifying the new filtering behavior in a multi-config setup. This provides strong confidence that the fix is working as intended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Files are synched more times than needed when running skaffold dev

1 participant