Skip to content

Commit 39075e5

Browse files
committed
Add last.patched timestamp
Signed-off-by: robert-cronin <[email protected]>
1 parent 3cb6678 commit 39075e5

File tree

2 files changed

+13
-30
lines changed

2 files changed

+13
-30
lines changed

integration/multiarch/patch_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,8 @@ func verifyAnnotations(t *testing.T, patchedRef string, platforms []string, repo
387387
err = json.Unmarshal(out, &manifest)
388388
require.NoError(t, err, "failed to parse manifest JSON")
389389

390-
// Check index-level annotations (Copa metadata)
390+
// Check index-level annotations
391391
assert.NotEmpty(t, manifest.Annotations, "index-level annotations should not be empty")
392-
assert.Equal(t, "true", manifest.Annotations["sh.copa.patched"], "should have Copa patched annotation")
393-
assert.NotEmpty(t, manifest.Annotations["sh.copa.patched.timestamp"], "should have Copa timestamp annotation")
394392
assert.NotEmpty(t, manifest.Annotations["org.opencontainers.image.created"], "should have created annotation")
395393

396394
t.Logf("found %d index-level annotations", len(manifest.Annotations))
@@ -411,6 +409,12 @@ func verifyAnnotations(t *testing.T, patchedRef string, platforms []string, repo
411409
t.Logf("platform %s has updated created timestamp: %s", platformStr, createdTime)
412410
}
413411

412+
// Check for Copa last.patched annotation on patched platforms
413+
lastPatched, exists := manifestEntry.Annotations["sh.copa.last.patched"]
414+
assert.True(t, exists, "patched platform %s should have sh.copa.last.patched annotation", platformStr)
415+
assert.NotEmpty(t, lastPatched, "sh.copa.last.patched timestamp should not be empty for patched platform %s", platformStr)
416+
t.Logf("platform %s has Copa last.patched timestamp: %s", platformStr, lastPatched)
417+
414418
t.Logf("platform %s has %d manifest-level annotations", platformStr, len(manifestEntry.Annotations))
415419

416420
// Verify that ALL original annotations are preserved
@@ -446,7 +450,11 @@ func verifyAnnotations(t *testing.T, patchedRef string, platforms []string, repo
446450

447451
t.Logf("verified %d original annotations are preserved for platform %s", len(originalAnnotations), platformStr)
448452
} else {
449-
t.Logf("skipping platform %s (no vulnerability report, not patched)", platformStr)
453+
t.Logf("checking platform %s (no vulnerability report, not patched)", platformStr)
454+
455+
// Non-patched platforms should NOT have the Copa last.patched annotation
456+
_, exists := manifestEntry.Annotations["sh.copa.last.patched"]
457+
assert.False(t, exists, "non-patched platform %s should not have sh.copa.last.patched annotation", platformStr)
450458
}
451459
}
452460
}

pkg/patch/patch.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ const (
5252
defaultRegistry = "docker.io"
5353
defaultTag = "latest"
5454
LINUX = "linux"
55-
trueString = "true"
5655
ARM64 = "arm64"
5756
copaAnnotationKeyPrefix = "sh.copa"
5857
)
@@ -156,19 +155,6 @@ func createMultiPlatformManifest(
156155
}
157156
}
158157

159-
// add a custom annotation to indicate this image was patched by Copa
160-
patchedKey := exptypes.AnnotationKey{
161-
Type: exptypes.AnnotationIndex,
162-
Key: copaAnnotationKeyPrefix + ".patched",
163-
}
164-
annotations[patchedKey] = trueString
165-
166-
patchedTimestampKey := exptypes.AnnotationKey{
167-
Type: exptypes.AnnotationIndex,
168-
Key: copaAnnotationKeyPrefix + ".patched.timestamp",
169-
}
170-
annotations[patchedTimestampKey] = time.Now().UTC().Format(time.RFC3339)
171-
172158
log.Debugf("Preserving %d annotations from original image", len(annotations))
173159
} else {
174160
log.Info("No annotations found in original image, adding Copa annotations only")
@@ -178,18 +164,6 @@ func createMultiPlatformManifest(
178164
Key: "org.opencontainers.image.created",
179165
}
180166
annotations[createdKey] = time.Now().UTC().Format(time.RFC3339)
181-
182-
patchedKey := exptypes.AnnotationKey{
183-
Type: exptypes.AnnotationIndex,
184-
Key: copaAnnotationKeyPrefix + ".patched",
185-
}
186-
annotations[patchedKey] = trueString
187-
188-
patchedTimestampKey := exptypes.AnnotationKey{
189-
Type: exptypes.AnnotationIndex,
190-
Key: copaAnnotationKeyPrefix + ".patched.timestamp",
191-
}
192-
annotations[patchedTimestampKey] = time.Now().UTC().Format(time.RFC3339)
193167
}
194168
}
195169

@@ -494,6 +468,7 @@ func patchSingleArchImage(
494468
// determine which attributes to set for the export
495469
attrs := map[string]string{
496470
"name": patchedImageName,
471+
"annotation." + copaAnnotationKeyPrefix + ".last.patched": time.Now().UTC().Format(time.RFC3339),
497472
}
498473
if shouldExportOCI {
499474
attrs["oci-mediatypes"] = "true"

0 commit comments

Comments
 (0)