Skip to content

Commit c6d12b7

Browse files
authored
feat: Use tags vX.Y.Z-<language> for JReleaser builders (#644)
Signed-off-by: laurentsimon <[email protected]>
1 parent 1778495 commit c6d12b7

File tree

4 files changed

+97
-10
lines changed

4 files changed

+97
-10
lines changed

verifiers/internal/gha/builder.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ import (
1515
)
1616

1717
var (
18-
trustedBuilderRepository = "slsa-framework/slsa-github-generator"
19-
e2eTestRepository = "slsa-framework/example-package"
20-
certOidcIssuer = "https://token.actions.githubusercontent.com"
21-
githubCom = "github.com/"
22-
httpsGithubCom = "https://" + githubCom
18+
trustedBuilderRepository = "slsa-framework/slsa-github-generator"
19+
e2eTestRepository = "slsa-framework/example-package"
20+
jReleaserActionRepository = "jreleaser/release-action"
21+
certOidcIssuer = "https://token.actions.githubusercontent.com"
22+
githubCom = "github.com/"
23+
httpsGithubCom = "https://" + githubCom
2324
// This is used in cosign's CheckOpts for validating the certificate. We
2425
// do specific builder verification after this.
2526
certSubjectRegexp = httpsGithubCom + "*"
@@ -40,6 +41,8 @@ var defaultBYOBReusableWorkflows = map[string]bool{
4041
common.GenericLowPermsDelegatorBuilderID: true,
4142
}
4243

44+
var JReleaserRepository = httpsGithubCom + jReleaserActionRepository
45+
4346
// VerifyCertficateSourceRepository verifies the source repository.
4447
func VerifyCertficateSourceRepository(id *WorkflowIdentity,
4548
sourceRepo string,

verifiers/internal/gha/provenance.go

+6
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ func isValidDelegatorBuilderID(prov iface.Provenance) error {
261261
if len(parts) != 2 {
262262
return fmt.Errorf("%w: %s", serrors.ErrorInvalidBuilderID, id)
263263
}
264+
265+
// Exception for JReleaser builders.
266+
// See https://github.com/slsa-framework/slsa-github-generator/issues/2035#issuecomment-1579963802.
267+
if strings.HasPrefix(parts[0], JReleaserRepository) {
268+
return utils.IsValidJreleaserBuilderTag(parts[1])
269+
}
264270
return utils.IsValidBuilderTag(parts[1], false)
265271
}
266272

verifiers/utils/builder.go

+23
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,26 @@ func IsValidBuilderTag(ref string, testing bool) error {
150150
}
151151
return nil
152152
}
153+
154+
func IsValidJreleaserBuilderTag(ref string) error {
155+
// Extract the pin.
156+
pin, err := TagFromGitRef(ref)
157+
if err != nil {
158+
return err
159+
}
160+
161+
// Valid semver of the form vX.Y.Z-<language> with no metadata.
162+
// NOTE: When adding a language, update the corresponding
163+
// unit test.
164+
languages := map[string]bool{
165+
"-java": true,
166+
}
167+
_, validLanguage := languages[semver.Prerelease(pin)]
168+
if !semver.IsValid(pin) ||
169+
len(strings.Split(pin, ".")) != 3 ||
170+
!validLanguage ||
171+
semver.Build(pin) != "" {
172+
return fmt.Errorf("%w: %s: not of the form vX.Y.Z-<language>", serrors.ErrorInvalidRef, pin)
173+
}
174+
return nil
175+
}

verifiers/utils/builder_test.go

+60-5
Original file line numberDiff line numberDiff line change
@@ -672,11 +672,6 @@ func Test_IsValidBuilderTag(t *testing.T) {
672672
ref: "refs/tags/v1",
673673
err: serrors.ErrorInvalidRef,
674674
},
675-
{
676-
name: "valid semver: no minor",
677-
ref: "refs/tags/v1",
678-
err: serrors.ErrorInvalidRef,
679-
},
680675
{
681676
name: "valid semver: pre-release",
682677
ref: "refs/tags/v1.2.3-rc.0",
@@ -770,3 +765,63 @@ func Test_IsValidBuilderTag(t *testing.T) {
770765
})
771766
}
772767
}
768+
769+
func Test_IsValidJreleaserBuilderTag(t *testing.T) {
770+
t.Parallel()
771+
tests := []struct {
772+
name string
773+
ref string
774+
err error
775+
}{
776+
{
777+
name: "valid full semver and language",
778+
ref: "refs/tags/v1.2.3-java",
779+
},
780+
{
781+
name: "valid semver: no patch",
782+
ref: "refs/tags/v1.2-java",
783+
err: serrors.ErrorInvalidRef,
784+
},
785+
{
786+
name: "valid semver: no minor",
787+
ref: "refs/tags/v1-java",
788+
err: serrors.ErrorInvalidRef,
789+
},
790+
{
791+
name: "valid semver: pre-release",
792+
ref: "refs/tags/v1.2.3-rc.0+java",
793+
err: serrors.ErrorInvalidRef,
794+
},
795+
{
796+
name: "valid semver: pre-release w/ build",
797+
ref: "refs/tags/v1.2.3-rc.0+build1",
798+
err: serrors.ErrorInvalidRef,
799+
},
800+
{
801+
name: "valid semver: build",
802+
ref: "refs/tags/v1.2.3-java+build1",
803+
err: serrors.ErrorInvalidRef,
804+
},
805+
{
806+
name: "invalid semver",
807+
ref: "refs/tags/1.2.3-java",
808+
err: serrors.ErrorInvalidRef,
809+
},
810+
{
811+
name: "invalid ref",
812+
ref: "refs/v1.2.3-java",
813+
err: serrors.ErrorInvalidRef,
814+
},
815+
}
816+
for _, tt := range tests {
817+
tt := tt // Re-initializing variable so it is not changed while executing the closure below
818+
819+
t.Run(tt.name, func(t *testing.T) {
820+
t.Parallel()
821+
err := IsValidJreleaserBuilderTag(tt.ref)
822+
if !cmp.Equal(err, tt.err, cmpopts.EquateErrors()) {
823+
t.Errorf(cmp.Diff(err, tt.err))
824+
}
825+
})
826+
}
827+
}

0 commit comments

Comments
 (0)