{"action":"created","issue":{"url":"https://api.github.com/repos/bazelbuild/rules_apple/issues/226","repository_url":"https://api.github.com/repos/bazelbuild/rules_apple","labels_url":"https://api.github.com/repos/bazelbuild/rules_apple/issues/226/labels{/name}","comments_url":"https://api.github.com/repos/bazelbuild/rules_apple/issues/226/comments","events_url":"https://api.github.com/repos/bazelbuild/rules_apple/issues/226/events","html_url":"https://github.com/bazelbuild/rules_apple/issues/226","id":361947601,"node_id":"MDU6SXNzdWUzNjE5NDc2MDE=","number":226,"title":"Support custom substitutions in plists and entitlements files","user":{"login":"keith","id":283886,"node_id":"MDQ6VXNlcjI4Mzg4Ng==","avatar_url":"https://avatars3.githubusercontent.com/u/283886?v=4","gravatar_id":"","url":"https://api.github.com/users/keith","html_url":"https://github.com/keith","followers_url":"https://api.github.com/users/keith/followers","following_url":"https://api.github.com/users/keith/following{/other_user}","gists_url":"https://api.github.com/users/keith/gists{/gist_id}","starred_url":"https://api.github.com/users/keith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keith/subscriptions","organizations_url":"https://api.github.com/users/keith/orgs","repos_url":"https://api.github.com/users/keith/repos","events_url":"https://api.github.com/users/keith/events{/privacy}","received_events_url":"https://api.github.com/users/keith/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-09-19T22:12:31Z","updated_at":"2018-09-26T22:42:49Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"Currently in our app we have some custom settings that we use across code, and entitlements files. To do this we define custom build settings, and reference them from our plist, and entitlements files, and then read the plist value in code. It ends up looking something like this:\r\n\r\n```\r\n# foo.xcconfig\r\nAPP_GROUP_SUITE_NAME = some id\r\n```\r\n\r\n```\r\n# foo.entitlements\r\n<key>com.apple.security.application-groups</key>\r\n<array>\r\n  <string>$(APP_GROUP_SUITE_NAME)</string>\r\n</array>\r\n```\r\n\r\n```\r\n# info.plist\r\n<key>AppGroupSuiteName</key>\r\n<string>${APP_GROUP_SUITE_NAME}</string>\r\n```\r\n\r\n```\r\n# foo.swift\r\nlet appGroupSuiteName = Bundle.main.infoDictionary?[\"LFTAppGroupSuiteName\"] as! String\r\n```\r\n\r\nI'm wondering if there's a specific reason bazel doesn't support custom substitutions to support this use case, or if this is something we could add to some of the rules."},"comment":{"url":"https://api.github.com/repos/bazelbuild/rules_apple/issues/comments/424892945","html_url":"https://github.com/bazelbuild/rules_apple/issues/226#issuecomment-424892945","issue_url":"https://api.github.com/repos/bazelbuild/rules_apple/issues/226","id":424892945,"node_id":"MDEyOklzc3VlQ29tbWVudDQyNDg5Mjk0NQ==","user":{"login":"keith","id":283886,"node_id":"MDQ6VXNlcjI4Mzg4Ng==","avatar_url":"https://avatars3.githubusercontent.com/u/283886?v=4","gravatar_id":"","url":"https://api.github.com/users/keith","html_url":"https://github.com/keith","followers_url":"https://api.github.com/users/keith/followers","following_url":"https://api.github.com/users/keith/following{/other_user}","gists_url":"https://api.github.com/users/keith/gists{/gist_id}","starred_url":"https://api.github.com/users/keith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keith/subscriptions","organizations_url":"https://api.github.com/users/keith/orgs","repos_url":"https://api.github.com/users/keith/repos","events_url":"https://api.github.com/users/keith/events{/privacy}","received_events_url":"https://api.github.com/users/keith/received_events","type":"User","site_admin":false},"created_at":"2018-09-26T22:42:49Z","updated_at":"2018-09-26T22:42:49Z","author_association":"CONTRIBUTOR","body":"Using the change here https://github.com/bazelbuild/rules_apple/pull/230 I was able to implement a simple custom rule for this:\r\n\r\n```python\r\ndef _replace_plist_variables(ctx):\r\n    input_file = ctx.file.plist\r\n    output_plist = ctx.outputs.out\r\n\r\n    control = struct(\r\n        output = output_plist.path,\r\n        plists = [input_file.path],\r\n        target = str(ctx.label),\r\n        variable_substitutions = struct(**ctx.attr.replacements),\r\n        allow_missing_variables = True,\r\n    )\r\n\r\n    control_file = ctx.actions.declare_file(\r\n        \"%s-control\" % output_plist.basename,\r\n        sibling = output_plist,\r\n    )\r\n    ctx.actions.write(\r\n        output = control_file,\r\n        content = control.to_json(),\r\n    )\r\n\r\n    apple_action(\r\n        ctx,\r\n        inputs = [input_file, control_file],\r\n        outputs = [output_plist],\r\n        executable = ctx.executable._plisttool,\r\n        arguments = [control_file.path],\r\n        mnemonic = \"ReplacePlistVariables\",\r\n    )\r\n\r\n\r\nprocess_plist_vars = rule(\r\n    attrs = {\r\n        \"plist\": attr.label(\r\n            mandatory = True,\r\n            allow_files = [\".plist\"],\r\n            single_file = True,\r\n        ),\r\n        \"replacements\": attr.string_dict(allow_empty = False),\r\n        \"_plisttool\": attr.label(\r\n            cfg = \"host\",\r\n            default = Label(\"@build_bazel_rules_apple//tools/plisttool\"),\r\n            executable = True,\r\n        ),\r\n    },\r\n    outputs = {\"out\": \"%{plist}-replaced.plist\"},\r\n    implementation = _replace_plist_variables,\r\n)\r\n```"}}
{"actor":{"display_login":"keith"}}