Skip to content

Commit dc3e9d4

Browse files
adincebiccgrindelclaude
authored
feat: Support supplying .netrc file (#1857)
This is very useful for the packages that require form of authentication to clone or download binary artifacts. It is true that SPM and rules_swift_package_manager work without this if the `.netrc` file is in `$HOME` but there are use cases where it is desirable to have `.netrc` relative to the bazel workspace. --------- Co-authored-by: Chuck Grindel <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent e4be335 commit dc3e9d4

10 files changed

+289
-6
lines changed

docs/bzlmod_extensions_overview.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ swift_deps.configure_package(<a href="#swift_deps.configure_package-name">name</
2121
swift_deps.configure_swift_package(<a href="#swift_deps.configure_swift_package-build_path">build_path</a>, <a href="#swift_deps.configure_swift_package-cache_path">cache_path</a>, <a href="#swift_deps.configure_swift_package-config_path">config_path</a>, <a href="#swift_deps.configure_swift_package-dependency_caching">dependency_caching</a>,
2222
<a href="#swift_deps.configure_swift_package-manifest_cache">manifest_cache</a>, <a href="#swift_deps.configure_swift_package-manifest_caching">manifest_caching</a>, <a href="#swift_deps.configure_swift_package-replace_scm_with_registry">replace_scm_with_registry</a>,
2323
<a href="#swift_deps.configure_swift_package-security_path">security_path</a>, <a href="#swift_deps.configure_swift_package-use_registry_identity_for_scm">use_registry_identity_for_scm</a>)
24-
swift_deps.from_package(<a href="#swift_deps.from_package-declare_swift_deps_info">declare_swift_deps_info</a>, <a href="#swift_deps.from_package-declare_swift_package">declare_swift_package</a>, <a href="#swift_deps.from_package-env">env</a>, <a href="#swift_deps.from_package-env_inherit">env_inherit</a>,
24+
swift_deps.from_package(<a href="#swift_deps.from_package-declare_swift_deps_info">declare_swift_deps_info</a>, <a href="#swift_deps.from_package-declare_swift_package">declare_swift_package</a>, <a href="#swift_deps.from_package-env">env</a>, <a href="#swift_deps.from_package-env_inherit">env_inherit</a>, <a href="#swift_deps.from_package-netrc">netrc</a>,
2525
<a href="#swift_deps.from_package-registries">registries</a>, <a href="#swift_deps.from_package-resolve_transitive_local_dependencies">resolve_transitive_local_dependencies</a>, <a href="#swift_deps.from_package-resolved">resolved</a>, <a href="#swift_deps.from_package-swift">swift</a>)
2626
</pre>
2727

@@ -82,6 +82,7 @@ Load Swift packages from `Package.swift` and `Package.resolved` files.
8282
| <a id="swift_deps.from_package-declare_swift_package"></a>declare_swift_package | Declare a `swift_package_tool` repository named `swift_package` which defines two targets: `update` and `resolve`. These targets run can be used to run the `swift package` binary in a Bazel context. The flags used when running the underlying `swift package` can be configured using the `configure_swift_package` tag.<br><br>They can be `bazel run` to update/resolve the `resolved` file:<br><br><pre><code>bazel run @swift_package//:update&#10;bazel run @swift_package//:resolve</code></pre> | Boolean | optional | `True` |
8383
| <a id="swift_deps.from_package-env"></a>env | Environment variables that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |
8484
| <a id="swift_deps.from_package-env_inherit"></a>env_inherit | Environment variables to inherit from the external environment that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | List of strings | optional | `[]` |
85+
| <a id="swift_deps.from_package-netrc"></a>netrc | A `.netrc` file that contains authentication credentials used for fetching Swift packages and or binary artifacts.<br><br>When provided, this file will be passed to Swift Package Manager commands using the `--netrc-file` flag during package resolution and updates. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
8586
| <a id="swift_deps.from_package-registries"></a>registries | A `registries.json` file that defines the configured Swift package registries.<br><br>The `registries.json` file is used when resolving Swift packages from a Swift package registry. It is created by Swift Package Manager when using the `swift package-registry` commands.<br><br>When using the `swift_package_tool` rules, this file is symlinked to the `config_path` directory defined in the `configure_swift_package` tag. If not using the `swift_package_tool` rules, the file must be in one of Swift Package Manager's search paths or in the manually specified `--config-path` directory. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
8687
| <a id="swift_deps.from_package-resolve_transitive_local_dependencies"></a>resolve_transitive_local_dependencies | Local Swift packages that are declared directly in the `Package.swift` file can depend on other local packages. By default these transitive dependencies will be automatically resolved and made available during the build process.<br><br>The process of resolving transitive local dependencies can become time consuming as the number of local Swift packages grows. Setting this flag to `False` will skip resolving local packages and instead require every local Swift package that is required during the build to be explicitly defined in the `Package.swift` file.<br><br>This time appears as `Fetching module extension swift_deps in @@rules_swift_package_manager~//:extensions.bzl;` in the output log. | Boolean | optional | `True` |
8788
| <a id="swift_deps.from_package-resolved"></a>resolved | A `Package.resolved`. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |

docs/repository_rules_overview.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Used to build a local Swift package.
4747
<pre>
4848
load("@rules_swift_package_manager//swiftpkg:defs.bzl", "registry_swift_package")
4949

50-
registry_swift_package(<a href="#registry_swift_package-name">name</a>, <a href="#registry_swift_package-bazel_package_name">bazel_package_name</a>, <a href="#registry_swift_package-dependencies_index">dependencies_index</a>, <a href="#registry_swift_package-env">env</a>, <a href="#registry_swift_package-env_inherit">env_inherit</a>, <a href="#registry_swift_package-id">id</a>,
50+
registry_swift_package(<a href="#registry_swift_package-name">name</a>, <a href="#registry_swift_package-bazel_package_name">bazel_package_name</a>, <a href="#registry_swift_package-dependencies_index">dependencies_index</a>, <a href="#registry_swift_package-env">env</a>, <a href="#registry_swift_package-env_inherit">env_inherit</a>, <a href="#registry_swift_package-id">id</a>, <a href="#registry_swift_package-netrc">netrc</a>,
5151
<a href="#registry_swift_package-registries">registries</a>, <a href="#registry_swift_package-replace_scm_with_registry">replace_scm_with_registry</a>, <a href="#registry_swift_package-repo_mapping">repo_mapping</a>, <a href="#registry_swift_package-resolved">resolved</a>, <a href="#registry_swift_package-version">version</a>)
5252
</pre>
5353

@@ -64,6 +64,7 @@ Used to download and build an external Swift package from a registry.
6464
| <a id="registry_swift_package-env"></a>env | Environment variables that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |
6565
| <a id="registry_swift_package-env_inherit"></a>env_inherit | Environment variables to inherit from the external environment that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | List of strings | optional | `[]` |
6666
| <a id="registry_swift_package-id"></a>id | The package identifier. | String | required | |
67+
| <a id="registry_swift_package-netrc"></a>netrc | A `.netrc` file that contains authentication credentials used for fetching Swift packages and or binary artifacts.<br><br>When provided, this file will be passed to Swift Package Manager commands using the `--netrc-file` flag during package resolution and updates. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
6768
| <a id="registry_swift_package-registries"></a>registries | A `registries.json` file that defines the configured Swift package registries.<br><br>The `registries.json` file is used when resolving Swift packages from a Swift package registry. It is created by Swift Package Manager when using the `swift package-registry` commands.<br><br>When using the `swift_package_tool` rules, this file is symlinked to the `config_path` directory defined in the `configure_swift_package` tag. If not using the `swift_package_tool` rules, the file must be in one of Swift Package Manager's search paths or in the manually specified `--config-path` directory. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
6869
| <a id="registry_swift_package-replace_scm_with_registry"></a>replace_scm_with_registry | When enabled replaces SCM identities in dependencies package description with identities from the registries.<br><br>Using this option requires that the registries provide `repositoryURLs` as metadata for the package.<br><br>When `True` the equivalent `--replace-scm-with-registry` option must be used with the Swift Package Manager CLI (or `swift_package` rule) so that the `resolved` file includes the version and identity information from the registry.<br><br>For more information see the [Swift Package Manager documentation](https://github.com/swiftlang/swift-package-manager/blob/swift-6.0.1-RELEASE/Documentation/PackageRegistry/Registry.md#45-lookup-package-identifiers-registered-for-a-url). | Boolean | optional | `False` |
6970
| <a id="registry_swift_package-repo_mapping"></a>repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<br><br>For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).<br><br>This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | |
@@ -79,7 +80,7 @@ Used to download and build an external Swift package from a registry.
7980
load("@rules_swift_package_manager//swiftpkg:defs.bzl", "swift_package")
8081

8182
swift_package(<a href="#swift_package-name">name</a>, <a href="#swift_package-bazel_package_name">bazel_package_name</a>, <a href="#swift_package-branch">branch</a>, <a href="#swift_package-commit">commit</a>, <a href="#swift_package-dependencies_index">dependencies_index</a>, <a href="#swift_package-env">env</a>, <a href="#swift_package-env_inherit">env_inherit</a>,
82-
<a href="#swift_package-init_submodules">init_submodules</a>, <a href="#swift_package-patch_args">patch_args</a>, <a href="#swift_package-patch_cmds">patch_cmds</a>, <a href="#swift_package-patch_cmds_win">patch_cmds_win</a>, <a href="#swift_package-patch_tool">patch_tool</a>, <a href="#swift_package-patches">patches</a>,
83+
<a href="#swift_package-init_submodules">init_submodules</a>, <a href="#swift_package-netrc">netrc</a>, <a href="#swift_package-patch_args">patch_args</a>, <a href="#swift_package-patch_cmds">patch_cmds</a>, <a href="#swift_package-patch_cmds_win">patch_cmds_win</a>, <a href="#swift_package-patch_tool">patch_tool</a>, <a href="#swift_package-patches">patches</a>,
8384
<a href="#swift_package-publicly_expose_all_targets">publicly_expose_all_targets</a>, <a href="#swift_package-recursive_init_submodules">recursive_init_submodules</a>, <a href="#swift_package-registries">registries</a>, <a href="#swift_package-remote">remote</a>,
8485
<a href="#swift_package-replace_scm_with_registry">replace_scm_with_registry</a>, <a href="#swift_package-repo_mapping">repo_mapping</a>, <a href="#swift_package-shallow_since">shallow_since</a>, <a href="#swift_package-tag">tag</a>, <a href="#swift_package-verbose">verbose</a>, <a href="#swift_package-version">version</a>)
8586
</pre>
@@ -99,6 +100,7 @@ Used to download and build an external Swift package.
99100
| <a id="swift_package-env"></a>env | Environment variables that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |
100101
| <a id="swift_package-env_inherit"></a>env_inherit | Environment variables to inherit from the external environment that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | List of strings | optional | `[]` |
101102
| <a id="swift_package-init_submodules"></a>init_submodules | Whether to clone submodules in the repository. | Boolean | optional | `False` |
103+
| <a id="swift_package-netrc"></a>netrc | A `.netrc` file for authentication when downloading binary artifacts. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
102104
| <a id="swift_package-patch_args"></a>patch_args | The arguments given to the patch tool. Defaults to -p0, however -p1 will usually be needed for patches generated by git. If multiple -p arguments are specified, the last one will take effect.If arguments other than -p are specified, Bazel will fall back to use patch command line tool instead of the Bazel-native patch implementation. When falling back to patch command line tool and patch_tool attribute is not specified, `patch` will be used. | List of strings | optional | `["-p0"]` |
103105
| <a id="swift_package-patch_cmds"></a>patch_cmds | Sequence of Bash commands to be applied on Linux/Macos after patches are applied. | List of strings | optional | `[]` |
104106
| <a id="swift_package-patch_cmds_win"></a>patch_cmds_win | Sequence of Powershell commands to be applied on Windows after patches are applied. If this attribute is not set, patch_cmds will be executed on Windows, which requires Bash binary to exist. | List of strings | optional | `[]` |

swiftpkg/bzlmod/swift_deps.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ def _declare_pkg_from_dependency(dep, config_pkg, from_package, config_swift_pac
238238
env_inherit = from_package.env_inherit,
239239
init_submodules = init_submodules,
240240
recursive_init_submodules = recursive_init_submodules,
241+
netrc = from_package.netrc,
241242
patch_args = patch_args,
242243
patch_cmds = patch_cmds,
243244
patch_cmds_win = patch_cmds_win,
@@ -289,6 +290,7 @@ def _declare_swift_package_repo(name, from_package, config_swift_package):
289290
package = from_package.swift.package,
290291
name = from_package.swift.name,
291292
),
293+
netrc = from_package.netrc,
292294
registries = from_package.registries,
293295
**config_swift_package_kwargs
294296
)

swiftpkg/internal/swift_package.bzl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,13 @@ _ALL_ATTRS = dicts.add(
220220
_GIT_ATTRS,
221221
repo_rules.env_attrs,
222222
repo_rules.swift_attrs,
223-
{"version": attr.string(doc = "The resolved version of the package.")},
223+
{
224+
"netrc": attr.label(
225+
default = None,
226+
doc = "A `.netrc` file for authentication when downloading binary artifacts.",
227+
),
228+
"version": attr.string(doc = "The resolved version of the package."),
229+
},
224230
)
225231

226232
swift_package = repository_rule(

swiftpkg/internal/swift_package_tool.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ def _swift_package_tool_impl(ctx):
1616
cmd = ctx.attr.cmd
1717
package = ctx.attr.package
1818
package_path = paths.dirname(package)
19+
netrc = ctx.file.netrc
1920
registries = ctx.file.registries
2021
runfiles = []
2122

2223
toolchain = swift_common.get_toolchain(ctx)
2324
swift = toolchain.swift_worker
2425
runfiles.append(swift.executable)
2526

27+
if netrc:
28+
runfiles.append(netrc)
29+
2630
if registries:
2731
runfiles.append(registries)
2832

@@ -43,6 +47,10 @@ def _swift_package_tool_impl(ctx):
4347
"true" if ctx.attr.dependency_caching else "false",
4448
)
4549
template_dict.add("%(manifest_cache)s", ctx.attr.manifest_cache)
50+
template_dict.add(
51+
"%(netrc_file)s",
52+
netrc.short_path if netrc else "",
53+
)
4654
template_dict.add(
4755
"%(registries_json)s",
4856
registries.short_path if registries else "",

swiftpkg/internal/swift_package_tool_attrs.bzl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
"""Attributes shared between rules that interact with the Swift package tool."""
22

33
_swift_package_registry_attrs = {
4+
"netrc": attr.label(
5+
allow_single_file = True,
6+
doc = """
7+
A `.netrc` file that contains authentication credentials used for fetching Swift packages and or binary artifacts.
8+
9+
When provided, this file will be passed to Swift Package Manager commands using \
10+
the `--netrc-file` flag during package resolution and updates.
11+
""",
12+
),
413
"registries": attr.label(
514
allow_single_file = [".json"],
6-
cfg = "exec",
715
doc = """
816
A `registries.json` file that defines the configured Swift package registries.
917

swiftpkg/internal/swift_package_tool_repo.bzl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ def _swift_package_tool_repo_impl(repository_ctx):
3535
attrs_content = _package_config_attrs_to_content(repository_ctx.attr)
3636
package_path = repository_ctx.attr.package
3737

38+
# We copy .netrc file contents to avoid requiring users to use `exports_files(...)`
39+
netrc_attr = None
40+
if repository_ctx.attr.netrc:
41+
netrc_content = repository_ctx.read(repository_ctx.attr.netrc)
42+
repository_ctx.file(".netrc", netrc_content)
43+
netrc_attr = ' netrc = ":.netrc",'
44+
45+
attrs_lines = [line for line in attrs_content.split("\n") if "netrc =" not in line]
46+
filtered_attrs = "\n".join(attrs_lines)
47+
48+
final_attrs_parts = [filtered_attrs]
49+
if netrc_attr:
50+
final_attrs_parts.append(netrc_attr)
51+
final_attrs_content = "\n".join([p for p in final_attrs_parts if p])
52+
3853
repository_ctx.file(
3954
"BUILD.bazel",
4055
content = """
@@ -55,7 +70,7 @@ swift_package_tool(
5570
)
5671
""".format(
5772
package = package_path,
58-
attrs_content = attrs_content,
73+
attrs_content = final_attrs_content,
5974
),
6075
)
6176

@@ -74,3 +89,8 @@ swift_package_tool_repo = repository_rule(
7489
),
7590
doc = "Declares a `@swift_package` repository for using the `swift_package_tool` targets.",
7691
)
92+
93+
# Exported for testing
94+
swift_package_tool_repo_testing = struct(
95+
package_config_attrs_to_content = _package_config_attrs_to_content,
96+
)

swiftpkg/internal/swift_package_tool_runner_template.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config_path="%(config_path)s"
2727
enable_build_manifest_caching="%(enable_build_manifest_caching)s"
2828
enable_dependency_cache="%(enable_dependency_cache)s"
2929
manifest_cache="%(manifest_cache)s"
30+
netrc_file="%(netrc_file)s"
3031
registries_json="%(registries_json)s"
3132
replace_scm_with_registry="%(replace_scm_with_registry)s"
3233
security_path="%(security_path)s"
@@ -57,6 +58,11 @@ fi
5758

5859
args+=("--manifest-cache=$manifest_cache")
5960

61+
# If netrc_file is set, add the --netrc-file flag.
62+
if [ -n "$netrc_file" ]; then
63+
args+=("--netrc-file" "$(readlink -f "$netrc_file")")
64+
fi
65+
6066
# If registries_json is set, symlink the `.json` file to the `config_path/configuration` directory.
6167
if [ -n "$registries_json" ]; then
6268
mkdir -p "$config_path"

swiftpkg/tests/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ load(":resource_files_tests.bzl", "resource_files_test_suite")
1717
load(":semver_tests.bzl", "semver_test_suite")
1818
load(":starlark_codegen_tests.bzl", "starlark_codegen_test_suite")
1919
load(":swift_files_tests.bzl", "swift_files_test_suite")
20+
load(":swift_package_tool_repo_tests.bzl", "swift_package_tool_repo_test_suite")
2021
load(":swiftpkg_build_files_tests.bzl", "swiftpkg_build_files_test_suite")
2122
load(":validations_tests.bzl", "validations_test_suite")
2223

@@ -58,6 +59,8 @@ swift_files_test_suite()
5859

5960
swiftpkg_build_files_test_suite()
6061

62+
swift_package_tool_repo_test_suite()
63+
6164
validations_test_suite()
6265

6366
bzl_library(

0 commit comments

Comments
 (0)