Skip to content

Commit 13c1258

Browse files
lpusokgodrei
andauthored
Move export to v2/codesigngroup (#310)
* Renamed export package to 'codesigngroup' made internal only * Use v2 logger * Added codesigngroup printer, removed extraneous log usages * Use slices.ContainsFunc in containsCertificate * Use slices.Sortfunc instead of sort.Sort * Removed empty literal slice inits * removed unused CodeSignGroup interface * moved codesigngroup.iOS constructer after type init --------- Co-authored-by: Krisztián Gödrei <krisztian.godrei@bitrise.io>
1 parent 08bf8f4 commit 13c1258

8 files changed

Lines changed: 560 additions & 49 deletions

File tree

exportoptionsgenerator/codesign_group_provider.go

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,32 @@ package exportoptionsgenerator
33
import (
44
"github.com/bitrise-io/go-utils/v2/log"
55
"github.com/bitrise-io/go-xcode/certificateutil"
6-
"github.com/bitrise-io/go-xcode/export"
76
"github.com/bitrise-io/go-xcode/exportoptions"
87
"github.com/bitrise-io/go-xcode/profileutil"
8+
codesigngroup "github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/internal/codesigngroup"
99
"github.com/bitrise-io/go-xcode/v2/plistutil"
1010
)
1111

1212
// CodeSignGroupProvider ...
1313
type CodeSignGroupProvider interface {
14-
DetermineCodesignGroup(certificates []certificateutil.CertificateInfoModel, profiles []profileutil.ProvisioningProfileInfoModel, defaultProfile *profileutil.ProvisioningProfileInfoModel, bundleIDEntitlementsMap map[string]plistutil.PlistData, exportMethod exportoptions.Method, teamID string, xcodeManaged bool) (*export.IosCodeSignGroup, error)
14+
DetermineCodesignGroup(certificates []certificateutil.CertificateInfoModel, profiles []profileutil.ProvisioningProfileInfoModel, defaultProfile *profileutil.ProvisioningProfileInfoModel, bundleIDEntitlementsMap map[string]plistutil.PlistData, exportMethod exportoptions.Method, teamID string, xcodeManaged bool) (*codesigngroup.Ios, error)
1515
}
1616

1717
type codeSignGroupProvider struct {
18-
logger log.Logger
18+
logger log.Logger
19+
printer *codesigngroup.Printer
1920
}
2021

2122
// NewCodeSignGroupProvider ...
2223
func NewCodeSignGroupProvider(logger log.Logger) CodeSignGroupProvider {
23-
return &codeSignGroupProvider{logger: logger}
24+
return &codeSignGroupProvider{
25+
logger: logger,
26+
printer: codesigngroup.NewPrinter(logger),
27+
}
2428
}
2529

2630
// DetermineCodesignGroup ....
27-
func (g codeSignGroupProvider) DetermineCodesignGroup(certificates []certificateutil.CertificateInfoModel, profiles []profileutil.ProvisioningProfileInfoModel, defaultProfile *profileutil.ProvisioningProfileInfoModel, bundleIDEntitlementsMap map[string]plistutil.PlistData, exportMethod exportoptions.Method, teamID string, xcodeManaged bool) (*export.IosCodeSignGroup, error) {
31+
func (g codeSignGroupProvider) DetermineCodesignGroup(certificates []certificateutil.CertificateInfoModel, profiles []profileutil.ProvisioningProfileInfoModel, defaultProfile *profileutil.ProvisioningProfileInfoModel, bundleIDEntitlementsMap map[string]plistutil.PlistData, exportMethod exportoptions.Method, teamID string, xcodeManaged bool) (*codesigngroup.Ios, error) {
2832
g.logger.Println()
2933
g.logger.Printf("Target Bundle ID - Entitlements map")
3034
var bundleIDs []string
@@ -38,9 +42,6 @@ func (g codeSignGroupProvider) DetermineCodesignGroup(certificates []certificate
3842
g.logger.Printf("%s: %s", bundleID, entitlementKeys)
3943
}
4044

41-
g.logger.Println()
42-
g.logger.Printf("Resolving CodeSignGroups...")
43-
4445
g.logger.Debugf("Installed certificates:")
4546
for _, certInfo := range certificates {
4647
g.logger.Debugf(certInfo.String())
@@ -51,76 +52,65 @@ func (g codeSignGroupProvider) DetermineCodesignGroup(certificates []certificate
5152
g.logger.Debugf(profileInfo.String(certificates...))
5253
}
5354

54-
g.logger.Printf("Resolving CodeSignGroups...")
55-
codeSignGroups := export.CreateSelectableCodeSignGroups(certificates, profiles, bundleIDs)
55+
g.logger.Println()
56+
g.logger.Printf("Resolving code signing groups...")
57+
codeSignGroups := codesigngroup.BuildFilterableList(certificates, profiles, bundleIDs)
5658
if len(codeSignGroups) == 0 {
5759
g.logger.Errorf("Failed to find code signing groups for specified export method (%s)", exportMethod)
5860
}
5961

6062
g.logger.Debugf("\nGroups:")
61-
for _, group := range codeSignGroups {
62-
g.logger.Debugf(group.String())
63-
}
63+
g.logger.Debugf("%s", g.printer.ListToDebugString(codeSignGroups))
6464

6565
if len(bundleIDEntitlementsMap) > 0 {
66-
g.logger.Warnf("Filtering CodeSignInfo groups for target capabilities")
66+
g.logger.Printf("Filtering code signing groups for target capabilities")
6767

68-
codeSignGroups = export.FilterSelectableCodeSignGroups(codeSignGroups, export.CreateEntitlementsSelectableCodeSignGroupFilter(convertToV1PlistData(bundleIDEntitlementsMap)))
68+
codeSignGroups = codesigngroup.Filter(codeSignGroups, codesigngroup.CreateEntitlementsSelectableCodeSignGroupFilter(convertToV1PlistData(bundleIDEntitlementsMap)))
6969

7070
g.logger.Debugf("\nGroups after filtering for target capabilities:")
71-
for _, group := range codeSignGroups {
72-
g.logger.Debugf(group.String())
73-
}
71+
g.logger.Debugf("%s", g.printer.ListToDebugString(codeSignGroups))
7472
}
7573

76-
g.logger.Warnf("Filtering CodeSignInfo groups for export method")
74+
g.logger.Printf("Filtering code signing groups for export method %s", exportMethod)
7775

78-
codeSignGroups = export.FilterSelectableCodeSignGroups(codeSignGroups, export.CreateExportMethodSelectableCodeSignGroupFilter(exportMethod))
76+
codeSignGroups = codesigngroup.Filter(codeSignGroups, codesigngroup.CreateExportMethodSelectableCodeSignGroupFilter(exportMethod))
7977

8078
g.logger.Debugf("\nGroups after filtering for export method:")
81-
for _, group := range codeSignGroups {
82-
g.logger.Debugf(group.String())
83-
}
79+
g.logger.Debugf("%s", g.printer.ListToDebugString(codeSignGroups))
8480

8581
if teamID != "" {
86-
g.logger.Warnf("ExportDevelopmentTeam specified: %s, filtering CodeSignInfo groups...", teamID)
82+
g.logger.Printf("Development team specified: %s, filtering groups...", teamID)
8783

88-
codeSignGroups = export.FilterSelectableCodeSignGroups(codeSignGroups, export.CreateTeamSelectableCodeSignGroupFilter(teamID))
84+
codeSignGroups = codesigngroup.Filter(codeSignGroups, codesigngroup.CreateTeamSelectableCodeSignGroupFilter(teamID))
8985

9086
g.logger.Debugf("\nGroups after filtering for team ID:")
91-
for _, group := range codeSignGroups {
92-
g.logger.Debugf(group.String())
93-
}
87+
g.logger.Debugf("%s", g.printer.ListToDebugString(codeSignGroups))
9488
}
9589

9690
if !xcodeManaged {
97-
g.logger.Warnf("App was signed with NON Xcode managed profile when archiving,\n" +
98-
"only NOT Xcode managed profiles are allowed to sign when exporting the archive.\n" +
99-
"Removing Xcode managed CodeSignInfo groups")
91+
g.logger.Printf("App was signed with NON Xcode managed profile when archiving,\n" +
92+
"only NON Xcode managed profiles are allowed to sign when exporting the archive.\n" +
93+
"Removing Xcode managed code signing groups")
10094

101-
codeSignGroups = export.FilterSelectableCodeSignGroups(codeSignGroups, export.CreateNotXcodeManagedSelectableCodeSignGroupFilter())
95+
codeSignGroups = codesigngroup.Filter(codeSignGroups, codesigngroup.CreateNotXcodeManagedSelectableCodeSignGroupFilter())
10296

103-
g.logger.Debugf("\nGroups after filtering for NOT Xcode managed profiles:")
104-
for _, group := range codeSignGroups {
105-
g.logger.Debugf(group.String())
106-
}
97+
g.logger.Debugf("\nGroups after filtering for NON Xcode managed profiles:")
98+
g.logger.Debugf("%s", g.printer.ListToDebugString(codeSignGroups))
10799
}
108100

109101
if teamID == "" && defaultProfile != nil {
110102
g.logger.Debugf("\ndefault profile: %v\n", defaultProfile)
111-
filteredCodeSignGroups := export.FilterSelectableCodeSignGroups(codeSignGroups,
112-
export.CreateExcludeProfileNameSelectableCodeSignGroupFilter(defaultProfile.Name))
103+
filteredCodeSignGroups := codesigngroup.Filter(codeSignGroups,
104+
codesigngroup.CreateExcludeProfileNameSelectableCodeSignGroupFilter(defaultProfile.Name))
113105
if len(filteredCodeSignGroups) > 0 {
114106
codeSignGroups = filteredCodeSignGroups
115-
107+
g.logger.Printf("Removed default profile '%s' from code signing groups", defaultProfile.Name)
116108
g.logger.Debugf("\nGroups after removing default profile:")
117-
for _, group := range codeSignGroups {
118-
g.logger.Debugf(group.String())
119-
}
109+
g.logger.Debugf("%s", g.printer.ListToDebugString(codeSignGroups))
120110
}
121111
}
122112

123-
var iosCodeSignGroups []export.IosCodeSignGroup
113+
var iosCodeSignGroups []codesigngroup.Ios
124114

125115
for _, selectable := range codeSignGroups {
126116
bundleIDProfileMap := map[string]profileutil.ProvisioningProfileInfoModel{}
@@ -132,7 +122,7 @@ func (g codeSignGroupProvider) DetermineCodesignGroup(certificates []certificate
132122
}
133123
}
134124

135-
iosCodeSignGroups = append(iosCodeSignGroups, *export.NewIOSGroup(selectable.Certificate, bundleIDProfileMap))
125+
iosCodeSignGroups = append(iosCodeSignGroups, *codesigngroup.NewIOSGroup(selectable.Certificate, bundleIDProfileMap))
136126
}
137127

138128
g.logger.Debugf("\nFiltered groups:")
@@ -144,12 +134,12 @@ func (g codeSignGroupProvider) DetermineCodesignGroup(certificates []certificate
144134
}
145135

146136
if len(iosCodeSignGroups) < 1 {
147-
g.logger.Errorf("Failed to find Codesign Groups")
137+
g.logger.Errorf("Failed to find code signing groups")
148138
return nil, nil
149139
}
150140

151141
if len(iosCodeSignGroups) > 1 {
152-
g.logger.Warnf("Multiple code signing groups found! Using the first code signing group")
142+
g.logger.Warnf("Multiple code signing groups found! Using the first code signing group.")
153143
}
154144

155145
return &iosCodeSignGroups[0], nil

exportoptionsgenerator/exportoptionsgenerator.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import (
55
"slices"
66

77
"github.com/bitrise-io/go-utils/v2/log"
8-
"github.com/bitrise-io/go-xcode/export"
98
"github.com/bitrise-io/go-xcode/exportoptions"
109
"github.com/bitrise-io/go-xcode/profileutil"
10+
"github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/internal/codesigngroup"
1111
"github.com/bitrise-io/go-xcode/v2/plistutil"
1212
"github.com/bitrise-io/go-xcode/v2/xcodeversion"
1313
)
@@ -128,7 +128,7 @@ func (g ExportOptionsGenerator) GenerateApplicationExportOptions(
128128

129129
// determineCodesignGroup finds the best codesign group (certificate + profiles)
130130
// based on the installed Provisioning Profiles and Codesign Certificates.
131-
func (g ExportOptionsGenerator) determineCodesignGroup(bundleIDEntitlementsMap map[string]plistutil.PlistData, exportMethod exportoptions.Method, teamID string, xcodeManaged bool) (*export.IosCodeSignGroup, error) {
131+
func (g ExportOptionsGenerator) determineCodesignGroup(bundleIDEntitlementsMap map[string]plistutil.PlistData, exportMethod exportoptions.Method, teamID string, xcodeManaged bool) (*codesigngroup.Ios, error) {
132132
certs, err := g.certificateProvider.ListCodesignIdentities()
133133
if err != nil {
134134
return nil, fmt.Errorf("failed to get installed certificates: %w", err)
@@ -268,7 +268,7 @@ func addTestFlightInternalTestingOnly(exportOpts exportoptions.ExportOptions, te
268268
return exportOpts
269269
}
270270

271-
func addManualSigningFields(exportOpts exportoptions.ExportOptions, codeSignGroup *export.IosCodeSignGroup, archivedWithXcodeManagedProfiles bool, logger log.Logger) exportoptions.ExportOptions {
271+
func addManualSigningFields(exportOpts exportoptions.ExportOptions, codeSignGroup *codesigngroup.Ios, archivedWithXcodeManagedProfiles bool, logger log.Logger) exportoptions.ExportOptions {
272272
exportCodeSignStyle := ""
273273
exportProfileMapping := map[string]string{}
274274

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package codesigngroup
2+
3+
import (
4+
"slices"
5+
6+
"github.com/bitrise-io/go-xcode/certificateutil"
7+
"github.com/bitrise-io/go-xcode/profileutil"
8+
"github.com/ryanuber/go-glob"
9+
)
10+
11+
// SelectableCodeSignGroup ...
12+
type SelectableCodeSignGroup struct {
13+
Certificate certificateutil.CertificateInfoModel
14+
BundleIDProfilesMap map[string][]profileutil.ProvisioningProfileInfoModel
15+
}
16+
17+
// BuildFilterableList ...
18+
func BuildFilterableList(installedCertificates []certificateutil.CertificateInfoModel, profiles []profileutil.ProvisioningProfileInfoModel, bundleIDs []string) []SelectableCodeSignGroup {
19+
var groups []SelectableCodeSignGroup
20+
21+
serialToProfiles := map[string][]profileutil.ProvisioningProfileInfoModel{}
22+
serialToCertificate := map[string]certificateutil.CertificateInfoModel{}
23+
for _, profile := range profiles {
24+
for _, certificate := range profile.DeveloperCertificates {
25+
if !containsCertificate(installedCertificates, certificate) {
26+
continue
27+
}
28+
29+
serialToProfiles[certificate.Serial] = append(serialToProfiles[certificate.Serial], profile)
30+
serialToCertificate[certificate.Serial] = certificate
31+
}
32+
}
33+
34+
for serial, profiles := range serialToProfiles {
35+
certificate := serialToCertificate[serial]
36+
37+
bundleIDToProfiles := map[string][]profileutil.ProvisioningProfileInfoModel{}
38+
for _, bundleID := range bundleIDs {
39+
var matchingProfiles []profileutil.ProvisioningProfileInfoModel
40+
for _, profile := range profiles {
41+
if !glob.Glob(profile.BundleID, bundleID) {
42+
continue
43+
}
44+
45+
matchingProfiles = append(matchingProfiles, profile)
46+
}
47+
48+
if len(matchingProfiles) > 0 {
49+
slices.SortFunc(matchingProfiles, func(a, b profileutil.ProvisioningProfileInfoModel) int {
50+
return len(b.BundleID) - len(a.BundleID)
51+
})
52+
bundleIDToProfiles[bundleID] = matchingProfiles
53+
}
54+
}
55+
56+
if len(bundleIDToProfiles) == len(bundleIDs) {
57+
group := SelectableCodeSignGroup{
58+
Certificate: certificate,
59+
BundleIDProfilesMap: bundleIDToProfiles,
60+
}
61+
groups = append(groups, group)
62+
}
63+
}
64+
65+
return groups
66+
}
67+
68+
func containsCertificate(list []certificateutil.CertificateInfoModel, item certificateutil.CertificateInfoModel) bool {
69+
return slices.ContainsFunc(list, func(cert certificateutil.CertificateInfoModel) bool {
70+
return cert.Serial == item.Serial
71+
})
72+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package codesigngroup_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/bitrise-io/go-xcode/certificateutil"
7+
"github.com/bitrise-io/go-xcode/exportoptions"
8+
"github.com/bitrise-io/go-xcode/profileutil"
9+
"github.com/bitrise-io/go-xcode/v2/exportoptionsgenerator/internal/codesigngroup"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestCreateSelectableCodeSignGroups(t *testing.T) {
14+
certDev := certificateutil.CertificateInfoModel{
15+
CommonName: "iPhone Distribution: Bitrise Test (ABCD1234)",
16+
TeamID: "ABCD1234",
17+
}
18+
profileDev := profileutil.ProvisioningProfileInfoModel{
19+
Name: "Bitrise Test Profile",
20+
UUID: "PROFILE-UUID-1234",
21+
TeamID: "ABCD1234",
22+
BundleID: "io.bitrise.testapp",
23+
ExportType: exportoptions.MethodAppStore,
24+
DeveloperCertificates: []certificateutil.CertificateInfoModel{certDev},
25+
}
26+
27+
tests := []struct {
28+
name string
29+
certificates []certificateutil.CertificateInfoModel
30+
profiles []profileutil.ProvisioningProfileInfoModel
31+
bundleIDs []string
32+
filter codesigngroup.SelectableCodeSignGroupFilter
33+
want []codesigngroup.SelectableCodeSignGroup
34+
}{
35+
{
36+
name: "empty inputs",
37+
certificates: []certificateutil.CertificateInfoModel{},
38+
profiles: []profileutil.ProvisioningProfileInfoModel{},
39+
bundleIDs: []string{},
40+
want: []codesigngroup.SelectableCodeSignGroup(nil),
41+
},
42+
{
43+
name: "single matching profile and certificate",
44+
certificates: []certificateutil.CertificateInfoModel{certDev},
45+
profiles: []profileutil.ProvisioningProfileInfoModel{profileDev},
46+
bundleIDs: []string{"io.bitrise.testapp"},
47+
want: []codesigngroup.SelectableCodeSignGroup{
48+
{
49+
Certificate: certDev,
50+
BundleIDProfilesMap: map[string][]profileutil.ProvisioningProfileInfoModel{
51+
"io.bitrise.testapp": {profileDev},
52+
},
53+
},
54+
},
55+
},
56+
{
57+
name: "filter by team ID, no match",
58+
certificates: []certificateutil.CertificateInfoModel{
59+
certDev,
60+
},
61+
profiles: []profileutil.ProvisioningProfileInfoModel{
62+
profileDev,
63+
},
64+
bundleIDs: []string{"io.bitrise.testapp"},
65+
filter: codesigngroup.CreateTeamSelectableCodeSignGroupFilter("WRONGID"),
66+
want: []codesigngroup.SelectableCodeSignGroup(nil),
67+
},
68+
{
69+
name: "filter by team ID, match",
70+
certificates: []certificateutil.CertificateInfoModel{
71+
certDev,
72+
},
73+
profiles: []profileutil.ProvisioningProfileInfoModel{
74+
profileDev,
75+
},
76+
bundleIDs: []string{"io.bitrise.testapp"},
77+
filter: codesigngroup.CreateTeamSelectableCodeSignGroupFilter("ABCD1234"),
78+
want: []codesigngroup.SelectableCodeSignGroup{
79+
{
80+
Certificate: certDev,
81+
BundleIDProfilesMap: map[string][]profileutil.ProvisioningProfileInfoModel{
82+
"io.bitrise.testapp": {profileDev},
83+
},
84+
},
85+
},
86+
},
87+
{
88+
name: "filter out app store distribution",
89+
certificates: []certificateutil.CertificateInfoModel{
90+
certDev,
91+
},
92+
profiles: []profileutil.ProvisioningProfileInfoModel{
93+
profileDev,
94+
},
95+
bundleIDs: []string{"io.bitrise.testapp"},
96+
filter: codesigngroup.CreateExportMethodSelectableCodeSignGroupFilter(exportoptions.MethodAdHoc),
97+
want: []codesigngroup.SelectableCodeSignGroup(nil),
98+
},
99+
}
100+
for _, tt := range tests {
101+
t.Run(tt.name, func(t *testing.T) {
102+
got := codesigngroup.BuildFilterableList(tt.certificates, tt.profiles, tt.bundleIDs)
103+
got = codesigngroup.Filter(got, tt.filter)
104+
require.Equal(t, tt.want, got)
105+
})
106+
}
107+
}

0 commit comments

Comments
 (0)