-
Notifications
You must be signed in to change notification settings - Fork 275
/
Copy pathlocal_provisioning_profiles.bzl
227 lines (193 loc) · 7.33 KB
/
local_provisioning_profiles.bzl
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
"""# Rules for using locally installed provisioning profiles"""
load(
"@build_bazel_rules_apple//apple:providers.bzl",
"AppleProvisioningProfileInfo",
)
def _provisioning_profile_repository(repository_ctx):
system_profiles_path = "{}/Library/MobileDevice/Provisioning Profiles".format(repository_ctx.os.environ["HOME"])
repository_ctx.execute(["mkdir", "-p", system_profiles_path])
repository_ctx.symlink(system_profiles_path, "profiles")
repository_ctx.file("BUILD.bazel", """\
filegroup(
name = "profiles",
srcs = glob(["profiles/*.mobileprovision"], allow_empty = True),
visibility = ["//visibility:public"],
)
filegroup(
name = "empty",
srcs = [],
visibility = ["//visibility:public"],
)
alias(
name = "fallback_profiles",
actual = "{}",
visibility = ["//visibility:public"],
)
""".format(repository_ctx.attr.fallback_profiles or ":empty"))
provisioning_profile_repository = repository_rule(
environ = ["HOME"],
implementation = _provisioning_profile_repository,
attrs = {
"fallback_profiles": attr.label(
allow_files = [".mobileprovision"],
),
},
doc = """
This rule declares an external repository for discovering locally installed
provisioning profiles. This is consumed by `local_provisioning_profile`.
You can optionally set 'fallback_profiles' to point at a stable location of
profiles if a newer version of the desired profile does not exist on the local
machine. This is useful for checking in the current version of the profile, but
not having to update it every time a new device or certificate is added.
## Example
### In your `MODULE.bazel` file:
You only need this in the case you want to setup fallback profiles, otherwise
it can be ommitted when using bzlmod.
```bzl
provisioning_profile_repository = use_extension("@build_bazel_rules_apple//apple:apple.bzl", "provisioning_profile_repository_extension")
provisioning_profile_repository.setup(
fallback_profiles = "//path/to/some:filegroup", # Profiles to use if one isn't found locally
)
```
### In your `WORKSPACE` file:
```starlark
load("@build_bazel_rules_apple//apple:apple.bzl", "provisioning_profile_repository")
provisioning_profile_repository(
name = "local_provisioning_profiles",
fallback_profiles = "//path/to/some:filegroup", # Optional profiles to use if one isn't found locally
)
```
### In your `BUILD` files (see `local_provisioning_profile` for more examples):
```starlark
load("@build_bazel_rules_apple//apple:apple.bzl", "local_provisioning_profile")
local_provisioning_profile(
name = "app_debug_profile",
profile_name = "Development App",
team_id = "abc123",
)
ios_application(
name = "app",
...
provisioning_profile = ":app_debug_profile",
)
```
""",
)
def _provisioning_profile_repository_extension(module_ctx):
root_modules = [m for m in module_ctx.modules if m.is_root and m.tags.setup]
if len(root_modules) > 1:
fail("Expected at most one root module, found {}".format(", ".join([x.name for x in root_modules])))
if root_modules:
root_module = root_modules[0]
else:
root_module = module_ctx.modules[0]
kwargs = {}
if root_module.tags.setup:
kwargs["fallback_profiles"] = root_module.tags.setup[0].fallback_profiles
provisioning_profile_repository(
name = "local_provisioning_profiles",
**kwargs
)
provisioning_profile_repository_extension = module_extension(
implementation = _provisioning_profile_repository_extension,
tag_classes = {
"setup": tag_class(attrs = {
"fallback_profiles": attr.label(
allow_files = [".mobileprovision"],
),
}),
},
doc = """
See [`provisioning_profile_repository`](#provisioning_profile_repository) for more information and examples.
""",
)
def _local_provisioning_profile(ctx):
if not ctx.files._local_srcs and not ctx.attr._fallback_srcs:
ctx.fail("Either local or fallback provisioning profiles must exist")
profile_name = ctx.attr.profile_name or ctx.attr.name
selected_profile_path = "{name}.mobileprovision".format(name = profile_name)
selected_profile = ctx.actions.declare_file(selected_profile_path)
args = ctx.actions.args()
args.add(profile_name)
args.add(selected_profile)
if ctx.attr.team_id:
args.add("--team_id", ctx.attr.team_id)
if ctx.files._local_srcs:
args.add_all("--local_profiles", ctx.files._local_srcs)
if ctx.files._fallback_srcs:
args.add_all("--fallback_profiles", ctx.files._fallback_srcs)
if not ctx.files._local_srcs and not ctx.attr._fallback_srcs:
fail("Either local or fallback provisioning profiles must exist")
ctx.actions.run(
executable = ctx.executable._finder,
arguments = [args],
inputs = ctx.files._local_srcs + ctx.files._fallback_srcs,
outputs = [selected_profile],
mnemonic = "FindProvisioningProfile",
execution_requirements = {"no-sandbox": "1", "no-remote-exec": "1"},
progress_message = "Finding provisioning profile %{label}",
)
return [
DefaultInfo(files = depset([selected_profile])),
AppleProvisioningProfileInfo(
provisioning_profile = selected_profile,
profile_name = profile_name,
team_id = ctx.attr.team_id,
),
]
local_provisioning_profile = rule(
attrs = {
"profile_name": attr.string(
doc = "Name of the profile to use, if it's not provided the name of the rule is used",
),
"team_id": attr.string(
doc = "Team ID of the profile to find. This is useful for disambiguating between multiple profiles with the same name on different developer accounts.",
),
"_fallback_srcs": attr.label(
default = "@local_provisioning_profiles//:fallback_profiles",
),
"_local_srcs": attr.label(
default = "@local_provisioning_profiles//:profiles",
),
"_finder": attr.label(
cfg = "exec",
default = "@build_bazel_rules_apple//tools/local_provisioning_profile_finder",
executable = True,
),
},
implementation = _local_provisioning_profile,
doc = """
This rule declares a bazel target that you can pass to the
'provisioning_profile' attribute of rules that require it. It discovers a
provisioning profile for the given attributes either on the user's local
machine, or with the optional 'fallback_profiles' passed to
'provisioning_profile_repository'. This will automatically pick the newest
profile if there are multiple profiles matching the given criteria. By default
this rule will search for a profile with the same name as the rule itself, you
can pass profile_name to use a different name, and you can pass team_id if
you'd like to disambiguate between 2 Apple developer accounts that have the
same profile name.
## Example
```starlark
load("@build_bazel_rules_apple//apple:apple.bzl", "local_provisioning_profile")
local_provisioning_profile(
name = "app_debug_profile",
profile_name = "Development App",
team_id = "abc123",
)
ios_application(
name = "app",
...
provisioning_profile = ":app_debug_profile",
)
local_provisioning_profile(
name = "app_release_profile",
)
ios_application(
name = "release_app",
...
provisioning_profile = ":app_release_profile",
)
```
""",
)