@@ -149,18 +149,48 @@ test_slsa_provenance_attestations if {
149149 lib.assert_equal (lib.slsa_provenance_attestations, expected) with input.attestations as attestations
150150}
151151
152- test_pr_attestations if {
152+ test_pr_attestations_v1 if {
153+ # Test v1.0 PipelineRun attestation
154+ lib.assert_equal ([mock_pr_att], lib.pipelinerun_attestations) with input.attestations as [
155+ mock_tr_att,
156+ mock_pr_att,
157+ garbage_att,
158+ ]
159+ }
160+
161+ test_pr_attestations_v02 if {
162+ # Test v0.2 PipelineRun attestation
163+ lib.assert_equal ([mock_pr_att_legacy], lib.pipelinerun_attestations) with input.attestations as [
164+ mock_tr_att_legacy,
165+ mock_pr_att_legacy,
166+ garbage_att,
167+ ]
168+ }
169+
170+ test_pr_attestations_both if {
171+ # Test both v0.2 and v1.0 PipelineRun attestations together
172+ # Use properly structured v1.0 attestation
173+ v1_att := {" statement" : {
174+ " predicateType" : " https://slsa.dev/provenance/v1" ,
175+ " predicate" : {" buildDefinition" : {
176+ " buildType" : " https://tekton.dev/chains/v2/slsa-tekton" ,
177+ " externalParameters" : {" runSpec" : {" pipelineSpec" : {}}},
178+ }},
179+ }}
153180 lib.assert_equal (
154- [mock_pr_att, mock_pr_att_legacy ],
181+ [mock_pr_att_legacy, v1_att ],
155182 lib.pipelinerun_attestations,
156183 ) with input.attestations as [
157184 mock_tr_att,
158185 mock_tr_att_legacy,
159- mock_pr_att ,
186+ v1_att ,
160187 mock_pr_att_legacy,
161188 garbage_att,
162189 ]
190+ }
163191
192+ test_pr_attestations_empty if {
193+ # Test that no PipelineRun attestations returns empty list
164194 lib.assert_equal ([], lib.pipelinerun_attestations) with input.attestations as [
165195 mock_tr_att,
166196 mock_tr_att_legacy,
@@ -390,3 +420,202 @@ test_result_values if {
390420
391421 not lib.result_values (123 )
392422}
423+
424+ # Helper to create a build task (has IMAGE_URL and IMAGE_DIGEST)
425+ _build_task := {
426+ " name" : " buildah" ,
427+ " ref" : {" kind" : " Task" , " name" : " buildah" , " bundle" : trusted_bundle_ref},
428+ " results" : [
429+ {" name" : " IMAGE_URL" , " value" : " quay.io/test/image:tag" },
430+ {" name" : " IMAGE_DIGEST" , " value" : " sha256:abc123" },
431+ ],
432+ }
433+
434+ # Helper to create a non-build task (no IMAGE_URL/IMAGE_DIGEST)
435+ _non_build_task := {
436+ " name" : " git-clone" ,
437+ " ref" : {" kind" : " Task" , " name" : " git-clone" , " bundle" : trusted_bundle_ref},
438+ " results" : [
439+ {" name" : " url" , " value" : " https://github.com/test/repo" },
440+ {" name" : " commit" , " value" : " abc123" },
441+ ],
442+ }
443+
444+ # Helper to create SLSA v0.2 attestation with metadata
445+ _attestation_v02_with_metadata (build_finished_on, tasks) := {" statement" : {
446+ " predicateType" : " https://slsa.dev/provenance/v0.2" ,
447+ " predicate" : {
448+ " buildType" : lib.tekton_pipeline_run,
449+ " buildConfig" : {" tasks" : tasks},
450+ " metadata" : {
451+ " buildFinishedOn" : build_finished_on,
452+ " buildStartedOn" : " 2025-01-01T00:00:00Z" ,
453+ },
454+ },
455+ }}
456+
457+ # Helper to create SLSA v1.0 attestation with metadata
458+ _attestation_v1_with_metadata (build_finished_on, tasks) := {" statement" : {
459+ " predicateType" : " https://slsa.dev/provenance/v1" ,
460+ " predicate" : {
461+ " buildDefinition" : {
462+ " buildType" : lib.tekton_slsav1_pipeline_run,
463+ " externalParameters" : {" runSpec" : {" pipelineSpec" : {}}},
464+ " resolvedDependencies" : tekton_test.resolved_dependencies (tasks),
465+ },
466+ " runDetails" : {" metadata" : {
467+ " buildFinishedOn" : build_finished_on,
468+ " buildStartedOn" : " 2025-01-01T00:00:00Z" ,
469+ }},
470+ },
471+ }}
472+
473+ test_pipelinerun_attestations_single_v02 if {
474+ # Test single v0.2 attestation
475+ att := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [_build_task])
476+ expected := [att]
477+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as [att]
478+ }
479+
480+ test_pipelinerun_attestations_multiple_v02_latest_first if {
481+ # Multiple v0.2 attestations, latest is first in list
482+ att1 := _attestation_v02_with_metadata (" 2025-01-20T15:45:00Z" , [_build_task])
483+ att2 := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [_build_task])
484+ attestations := [att1, att2]
485+ expected := [att1]
486+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
487+ }
488+
489+ test_pipelinerun_attestations_multiple_v02_latest_last if {
490+ # Multiple v0.2 attestations, latest is last in list
491+ att1 := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [_build_task])
492+ att2 := _attestation_v02_with_metadata (" 2025-01-20T15:45:00Z" , [_build_task])
493+ attestations := [att1, att2]
494+ expected := [att2]
495+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
496+ }
497+
498+ test_pipelinerun_attestations_multiple_v02_middle if {
499+ # Multiple v0.2 attestations, latest is in the middle
500+ att1 := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [_build_task])
501+ att2 := _attestation_v02_with_metadata (" 2025-01-25T20:00:00Z" , [_build_task])
502+ att3 := _attestation_v02_with_metadata (" 2025-01-20T15:45:00Z" , [_build_task])
503+ attestations := [att1, att2, att3]
504+ expected := [att2]
505+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
506+ }
507+
508+ test_pipelinerun_attestations_multiple_v02_missing_timestamp if {
509+ # Multiple v0.2 attestations where at least one doesn't have a timestamp - should return empty
510+ att_with_metadata := _attestation_v02_with_metadata (" 2025-01-20T15:45:00Z" , [_build_task])
511+ att_without_metadata := json.patch (
512+ _attestation_v02_with_metadata (" 2025-01-25T20:00:00Z" , [_build_task]),
513+ [{" op" : " remove" , " path" : " /statement/predicate/metadata" }],
514+ )
515+ attestations := [att_with_metadata, att_without_metadata]
516+ expected := []
517+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
518+ }
519+
520+ test_pipelinerun_attestations_multiple_v1_missing_timestamp if {
521+ # Multiple v1.0 attestations where at least one doesn't have a timestamp - should return empty
522+ v1_task := tekton_test.slsav1_task_bundle (
523+ tekton_test.slsav1_task_result (
524+ " buildah" ,
525+ [
526+ {" name" : " IMAGE_URL" , " type" : " string" , " value" : " quay.io/test/image:tag" },
527+ {" name" : " IMAGE_DIGEST" , " type" : " string" , " value" : " sha256:abc123" },
528+ ],
529+ ),
530+ trusted_bundle_ref,
531+ )
532+ att_with_metadata := _attestation_v1_with_metadata (" 2025-01-20T15:45:00Z" , [v1_task])
533+ att_without_metadata := json.patch (
534+ _attestation_v1_with_metadata (" 2025-01-25T20:00:00Z" , [v1_task]),
535+ [{" op" : " remove" , " path" : " /statement/predicate/runDetails" }],
536+ )
537+ attestations := [att_with_metadata, att_without_metadata]
538+ expected := []
539+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
540+ }
541+
542+ test_pipelinerun_attestations_mixed_formats if {
543+ # Test with both v0.2 and v1.0 attestations - should return both (one per type)
544+ v02_task := _build_task
545+ v1_task := tekton_test.slsav1_task_bundle (
546+ tekton_test.slsav1_task_result (
547+ " buildah" ,
548+ [
549+ {" name" : " IMAGE_URL" , " type" : " string" , " value" : " quay.io/test/image:tag" },
550+ {" name" : " IMAGE_DIGEST" , " type" : " string" , " value" : " sha256:abc123" },
551+ ],
552+ ),
553+ trusted_bundle_ref,
554+ )
555+ att_v02 := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [v02_task])
556+ att_v1 := _attestation_v1_with_metadata (" 2025-01-20T15:45:00Z" , [v1_task])
557+ attestations := [att_v02, att_v1]
558+ expected := [att_v02, att_v1]
559+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
560+ }
561+
562+ test_pipelinerun_attestations_empty if {
563+ # No attestations should return empty list
564+ expected := []
565+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as []
566+ }
567+
568+ test_pipelinerun_attestations_single_no_timestamp if {
569+ # Single attestation without timestamp should still be returned
570+ att := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [_non_build_task])
571+ expected := [att]
572+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as [att]
573+ }
574+
575+ test_pipelinerun_attestations_multiple_per_type if {
576+ # Test scenario: 3 attestations where 2 are v0.2 and 1 is v1.0
577+ # Should return the latest v0.2 and the v1.0
578+ v02_att1 := _attestation_v02_with_metadata (" 2025-01-15T10:30:00Z" , [_build_task])
579+ v02_att2 := _attestation_v02_with_metadata (" 2025-01-20T15:45:00Z" , [_build_task])
580+ v1_att := _attestation_v1_with_metadata (" 2025-01-18T12:00:00Z" , [_build_task])
581+ attestations := [v02_att1, v02_att2, v1_att]
582+
583+ # Should return latest v0.2 (v02_att2) and the v1.0 (v1_att)
584+ expected := [v02_att2, v1_att]
585+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
586+ }
587+
588+ test_pipelinerun_attestations_v1_multiple if {
589+ # Test multiple v1.0 attestations - should return the latest
590+ v1_att1 := _attestation_v1_with_metadata (" 2025-01-15T10:30:00Z" , [_build_task])
591+ v1_att2 := _attestation_v1_with_metadata (" 2025-01-20T15:45:00Z" , [_build_task])
592+ attestations := [v1_att1, v1_att2]
593+ expected := [v1_att2]
594+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as attestations
595+ }
596+
597+ test_pipelinerun_attestations_v1_single_no_timestamp if {
598+ # Test single v1.0 attestation without timestamp - should still return it
599+ v1_task := tekton_test.slsav1_task_bundle (
600+ tekton_test.slsav1_task_result (
601+ " buildah" ,
602+ [
603+ {" name" : " IMAGE_URL" , " type" : " string" , " value" : " quay.io/test/image:tag" },
604+ {" name" : " IMAGE_DIGEST" , " type" : " string" , " value" : " sha256:abc123" },
605+ ],
606+ ),
607+ trusted_bundle_ref,
608+ )
609+
610+ # Create v1.0 attestation without runDetails.metadata.buildFinishedOn
611+ v1_att := {" statement" : {
612+ " predicateType" : " https://slsa.dev/provenance/v1" ,
613+ " predicate" : {" buildDefinition" : {
614+ " buildType" : lib.tekton_slsav1_pipeline_run,
615+ " externalParameters" : {" runSpec" : {" pipelineSpec" : {}}},
616+ " resolvedDependencies" : tekton_test.resolved_dependencies ([v1_task]),
617+ }},
618+ }}
619+ expected := [v1_att]
620+ lib.assert_equal (expected, lib.pipelinerun_attestations) with input.attestations as [v1_att]
621+ }
0 commit comments