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
11 changes: 4 additions & 7 deletions internal/sync/api/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ type SyncManifest struct {
Items []SyncManifestResource `json:"items"`
}

// SyncManifestResource is one versioned baseline entry.
// SyncManifestResource is one versioned baseline entry. The remote manifest
// records the fingerprint and the version of each entry. The descriptor
// metadata of a linked resource, such as its reference digest, lives in the
// sync.lock file only, and the API rejects it.
type SyncManifestResource struct {
ResourceKind syncdomain.Kind `json:"resourceKind"`
ResourceLookupKey string `json:"resourceLookupKey"`
Fingerprint string `json:"fingerprint"`
Version int `json:"version"`
FingerprintSchema string `json:"fingerprintSchema,omitempty"`
ReferenceDigest string `json:"referenceDigest,omitempty"`
AdapterBehavior string `json:"adapterBehavior,omitempty"`
}

// SyncManifestUpsert creates an entry, or updates the entry at Version.
Expand All @@ -35,9 +35,6 @@ type SyncManifestUpsert struct {
ResourceLookupKey string `json:"resourceLookupKey"`
Fingerprint string `json:"fingerprint"`
Version int `json:"version"`
FingerprintSchema string `json:"fingerprintSchema,omitempty"`
ReferenceDigest string `json:"referenceDigest,omitempty"`
AdapterBehavior string `json:"adapterBehavior,omitempty"`
}

// SyncManifestDeletion removes the entry at Version.
Expand Down
25 changes: 10 additions & 15 deletions internal/sync/manifest/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,11 @@ func (store Store) resourcesFromRemote(projectKey string, remote syncapi.SyncMan
)
}
resources = append(resources, Resource{
ResourceKind: item.ResourceKind,
ProjectKey: projectKey,
LookupKey: item.ResourceLookupKey,
Fingerprint: item.Fingerprint,
Version: item.Version,
FingerprintSchema: item.FingerprintSchema,
ReferenceDigest: item.ReferenceDigest,
AdapterBehavior: item.AdapterBehavior,
ResourceKind: item.ResourceKind,
ProjectKey: projectKey,
LookupKey: item.ResourceLookupKey,
Fingerprint: item.Fingerprint,
Version: item.Version,
})
}
return resources, nil
Expand All @@ -180,9 +177,6 @@ func changes(before, after []Resource) ([]syncapi.SyncManifestUpsert, []syncapi.
ResourceLookupKey: resource.LookupKey,
Fingerprint: resource.Fingerprint,
Version: current.Version,
FingerprintSchema: resource.FingerprintSchema,
ReferenceDigest: resource.ReferenceDigest,
AdapterBehavior: resource.AdapterBehavior,
})
}

Expand All @@ -199,11 +193,12 @@ func changes(before, after []Resource) ([]syncapi.SyncManifestUpsert, []syncapi.
return upserts, deletions
}

// sameManifestContent reports whether two entries are the same to the remote
// manifest, which records only the fingerprint. The descriptor metadata of a
// linked resource stays in the sync.lock file, so a change to it alone sends
// nothing.
func sameManifestContent(left, right Resource) bool {
return left.Fingerprint == right.Fingerprint &&
left.FingerprintSchema == right.FingerprintSchema &&
left.ReferenceDigest == right.ReferenceDigest &&
left.AdapterBehavior == right.AdapterBehavior
return left.Fingerprint == right.Fingerprint
}

// changesApplied reports whether the remote manifest contains every change.
Expand Down
41 changes: 27 additions & 14 deletions internal/sync/manifest/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,7 @@ func TestStoreUpdatesWithRemoteVersions(t *testing.T) {
client := &manifestClient{patchResponses: []syncapi.SyncManifest{{
Source: "git:example/repo",
Items: []syncapi.SyncManifestResource{
{
ResourceKind: syncdomain.KindVariation, ResourceLookupKey: "config/existing",
Fingerprint: fingerprint("c"), Version: 4,
FingerprintSchema: syncdomain.ProjectionFingerprintSchema, ReferenceDigest: fingerprint("e"),
AdapterBehavior: "markdown/1",
},
{ResourceKind: syncdomain.KindVariation, ResourceLookupKey: "config/existing", Fingerprint: fingerprint("c"), Version: 4},
{ResourceKind: syncdomain.KindTool, ResourceLookupKey: "search", Fingerprint: fingerprint("d"), Version: 1},
},
}}}
Expand All @@ -131,18 +126,36 @@ func TestStoreUpdatesWithRemoteVersions(t *testing.T) {
require.Len(t, client.patches, 1)
assert.Equal(t, []syncapi.SyncManifestUpsert{
{ResourceKind: syncdomain.KindTool, ResourceLookupKey: "search", Fingerprint: fingerprint("d"), Version: 0},
{
ResourceKind: syncdomain.KindVariation, ResourceLookupKey: "config/existing",
Fingerprint: fingerprint("c"), Version: 3,
FingerprintSchema: syncdomain.ProjectionFingerprintSchema, ReferenceDigest: fingerprint("e"),
AdapterBehavior: "markdown/1",
},
}, client.patches[0].upserts)
{ResourceKind: syncdomain.KindVariation, ResourceLookupKey: "config/existing", Fingerprint: fingerprint("c"), Version: 3},
}, client.patches[0].upserts, "the upsert carries the fingerprint and the version, and no descriptor metadata")
assert.Equal(t, []syncapi.SyncManifestDeletion{{
ResourceKind: syncdomain.KindSkill, ResourceLookupKey: "old", Version: 2,
}}, client.patches[0].deletions)
assert.Equal(t, 4, updated.Resources[1].Version)
assert.Equal(t, syncdomain.ProjectionFingerprintSchema, updated.Resources[1].FingerprintSchema)
assert.Empty(t, updated.Resources[1].FingerprintSchema, "the remote state has no descriptor metadata")
}

// The remote manifest records only the fingerprint, so a change to the
// descriptor metadata of a linked resource with the same fingerprint sends
// nothing. The sync.lock file keeps that metadata.
func TestStoreSendsNothingForADescriptorMetadataChange(t *testing.T) {
client := &manifestClient{patchResponses: []syncapi.SyncManifest{{Source: "git:example/repo"}}}
store := NewStore(client, "git:example/repo")
previous := Manifest{Resources: []Resource{{
ResourceKind: syncdomain.KindVariation, ProjectKey: "project", LookupKey: "config/linked",
Fingerprint: fingerprint("a"), Version: 3,
}}}
next := Manifest{Resources: []Resource{{
ResourceKind: syncdomain.KindVariation, ProjectKey: "project", LookupKey: "config/linked",
Fingerprint: fingerprint("a"), Version: 3,
FingerprintSchema: syncdomain.ProjectionFingerprintSchema, ReferenceDigest: fingerprint("e"),
AdapterBehavior: "markdown/1",
}}}

_, err := store.Update(previous, next)

require.NoError(t, err)
assert.Empty(t, client.patches, "no patch for a change that the remote manifest cannot record")
}

func TestStoreReportsOptimisticConflict(t *testing.T) {
Expand Down
Loading