Skip to content

Commit 94e19ff

Browse files
committed
add explicit check that hash is set for components
1 parent 15dcea7 commit 94e19ff

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

internal/fingerprint/fingerprint.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,18 @@ func ComputeIdentity(
7373
DistroVersion: distroRef.Version,
7474
}
7575

76-
// 1. Hash the resolved config struct (excluding fingerprint:"-" fields).
76+
// 1. Verify all source files have a hash. Without a hash the fingerprint
77+
// cannot detect content changes, so we refuse to compute one.
78+
for i := range component.SourceFiles {
79+
if component.SourceFiles[i].Hash == "" {
80+
return nil, fmt.Errorf(
81+
"source file %#q has no hash; cannot compute a deterministic fingerprint",
82+
component.SourceFiles[i].Filename,
83+
)
84+
}
85+
}
86+
87+
// 2. Hash the resolved config struct (excluding fingerprint:"-" fields).
7788
configHash, err := hashstructure.Hash(component, hashstructure.FormatV2, &hashstructure.HashOptions{
7889
TagName: hashstructureTagName,
7990
})
@@ -83,15 +94,15 @@ func ComputeIdentity(
8394

8495
inputs.ConfigHash = configHash
8596

86-
// 2. Hash overlay source file contents.
97+
// 3. Hash overlay source file contents.
8798
overlayHashes, err := hashOverlayFiles(fs, component.Overlays)
8899
if err != nil {
89100
return nil, fmt.Errorf("hashing overlay files:\n%w", err)
90101
}
91102

92103
inputs.OverlayFileHashes = overlayHashes
93104

94-
// 3. Combine all inputs into the overall fingerprint.
105+
// 4. Combine all inputs into the overall fingerprint.
95106
return &ComponentIdentity{
96107
Fingerprint: combineInputs(inputs),
97108
Inputs: inputs,

internal/fingerprint/fingerprint_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,26 @@ func TestComputeIdentity_SourceFileOriginExcluded(t *testing.T) {
368368
assert.Equal(t, fp1, fp2, "changing source file origin URL must NOT change fingerprint")
369369
}
370370

371+
func TestComputeIdentity_SourceFileNoHash_Error(t *testing.T) {
372+
ctx := newTestFS(t, map[string]string{
373+
"/specs/test.spec": "Name: testpkg\nVersion: 1.0",
374+
})
375+
376+
comp := baseComponent()
377+
comp.SourceFiles = []projectconfig.SourceFileReference{
378+
{
379+
Filename: "source.tar.gz",
380+
Origin: projectconfig.Origin{Type: "download", Uri: "https://example.com/source.tar.gz"},
381+
},
382+
}
383+
distro := baseDistroRef()
384+
385+
_, err := fingerprint.ComputeIdentity(ctx.FS(), comp, distro, fingerprint.IdentityOptions{})
386+
require.Error(t, err)
387+
assert.Contains(t, err.Error(), "source.tar.gz")
388+
assert.Contains(t, err.Error(), "no hash")
389+
}
390+
371391
func TestComputeIdentity_InputsBreakdown(t *testing.T) {
372392
ctx := newTestFS(t, map[string]string{
373393
"/specs/test.spec": "Name: testpkg\nVersion: 1.0",

0 commit comments

Comments
 (0)