/
devices.go
117 lines (94 loc) · 4.04 KB
/
devices.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package autocodesign
import (
"errors"
"fmt"
"github.com/bitrise-io/go-utils/log"
"github.com/bitrise-io/go-xcode/devportalservice"
"github.com/bitrise-io/go-xcode/v2/autocodesign/devportalclient/appstoreconnect"
)
// EnsureTestDevices fetches devices from Apple, and register missing devices.
// Leave testDevices empty, to skip device registration.
func EnsureTestDevices(deviceClient DevPortalClient, testDevices []devportalservice.TestDevice, platform Platform) ([]appstoreconnect.Device, error) {
fmt.Println()
log.Infof("Fetching Apple Developer Portal devices")
// IOS device platform includes: APPLE_WATCH, IPAD, IPHONE, IPOD and APPLE_TV device classes.
devPortalDevices, err := deviceClient.ListDevices("", appstoreconnect.IOSDevice)
if err != nil {
return nil, fmt.Errorf("failed to fetch devices: %s", err)
}
log.Printf("%d devices are registered on the Apple Developer Portal", len(devPortalDevices))
for _, devPortalDevice := range devPortalDevices {
log.Debugf("- %s, %s, UDID (%s), ID (%s)", devPortalDevice.Attributes.Name, devPortalDevice.Attributes.DeviceClass, devPortalDevice.Attributes.UDID, devPortalDevice.ID)
}
if len(testDevices) != 0 {
fmt.Println()
log.Infof("Checking if %d Bitrise test device(s) are registered on Developer Portal", len(testDevices))
for _, d := range testDevices {
log.Debugf("- %s, %s, UDID (%s), added at %s", d.Title, d.DeviceType, d.DeviceID, d.UpdatedAt)
}
newDevPortalDevices, err := registerMissingTestDevices(deviceClient, testDevices, devPortalDevices)
if err != nil {
return nil, fmt.Errorf("failed to register Bitrise Test device on Apple Developer Portal: %s", err)
}
devPortalDevices = append(devPortalDevices, newDevPortalDevices...)
}
devPortalDevices = filterDevPortalDevices(devPortalDevices, platform)
return devPortalDevices, nil
}
func registerMissingTestDevices(client DevPortalClient, testDevices []devportalservice.TestDevice, devPortalDevices []appstoreconnect.Device) ([]appstoreconnect.Device, error) {
if client == nil {
return []appstoreconnect.Device{}, fmt.Errorf("the App Store Connect API client not provided")
}
var newDevPortalDevices []appstoreconnect.Device
for _, testDevice := range testDevices {
log.Printf("checking if the device (%s) is registered", testDevice.DeviceID)
devPortalDevice := findDevPortalDevice(testDevice, devPortalDevices)
if devPortalDevice != nil {
log.Printf("device already registered")
continue
}
log.Printf("registering device")
newDevPortalDevice, err := client.RegisterDevice(testDevice)
if err != nil {
var registrationError appstoreconnect.DeviceRegistrationError
if errors.As(err, ®istrationError) {
log.Warnf("Failed to register device (can be caused by invalid UDID or trying to register a Mac device): %s", registrationError.Reason)
continue
}
return nil, err
}
if newDevPortalDevice != nil {
newDevPortalDevices = append(newDevPortalDevices, *newDevPortalDevice)
}
}
return newDevPortalDevices, nil
}
func findDevPortalDevice(testDevice devportalservice.TestDevice, devPortalDevices []appstoreconnect.Device) *appstoreconnect.Device {
for _, devPortalDevice := range devPortalDevices {
if devportalservice.IsEqualUDID(devPortalDevice.Attributes.UDID, testDevice.DeviceID) {
return &devPortalDevice
}
}
return nil
}
func filterDevPortalDevices(devPortalDevices []appstoreconnect.Device, platform Platform) []appstoreconnect.Device {
var filteredDevices []appstoreconnect.Device
for _, devPortalDevice := range devPortalDevices {
deviceClass := devPortalDevice.Attributes.DeviceClass
switch platform {
case IOS:
isIosOrWatchosDevice := deviceClass == appstoreconnect.AppleWatch ||
deviceClass == appstoreconnect.Ipad ||
deviceClass == appstoreconnect.Iphone ||
deviceClass == appstoreconnect.Ipod
if isIosOrWatchosDevice {
filteredDevices = append(filteredDevices, devPortalDevice)
}
case TVOS:
if deviceClass == appstoreconnect.AppleTV {
filteredDevices = append(filteredDevices, devPortalDevice)
}
}
}
return filteredDevices
}